<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Matthew Dailey</title>
    <description>The latest articles on DEV Community by Matthew Dailey (@mtdailey).</description>
    <link>https://dev.to/mtdailey</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F425598%2F0b1040c6-eae0-4910-907b-d28fdf8ca498.jpg</url>
      <title>DEV Community: Matthew Dailey</title>
      <link>https://dev.to/mtdailey</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mtdailey"/>
    <language>en</language>
    <item>
      <title>Easily enforce git branch naming conventions</title>
      <dc:creator>Matthew Dailey</dc:creator>
      <pubDate>Sat, 09 Apr 2022 14:03:45 +0000</pubDate>
      <link>https://dev.to/mtdailey/easily-enforce-git-branch-naming-conventions-583o</link>
      <guid>https://dev.to/mtdailey/easily-enforce-git-branch-naming-conventions-583o</guid>
      <description>&lt;p&gt;In many software development projects there is often some kind of branch naming conventions the developers follow. What if not all developers follow the naming rules? This has been a recurring problem at my work. I came up with a solution that was the easiest to implement.&lt;/p&gt;

&lt;p&gt;I created a githooks script that will run right before the &lt;code&gt;git push&lt;/code&gt; command. For the script to automatically run, a new .githooks folder needs to be created in the Git repository's root folder. Git needs to know it exists so run &lt;code&gt;git config core.hooksPath .githooks&lt;/code&gt; while in the repository root folder. The script needs to be named &lt;code&gt;pre-push&lt;/code&gt; with no file extension.&lt;/p&gt;

&lt;p&gt;My githooks script is set up so if the git branch being pushed doesn't start with certain words and contains more than 10 characters, an error message is thrown and the push doesn't occur. &lt;/p&gt;

&lt;p&gt;Here is the script and &lt;a href="https://gist.github.com/mdailey77/fd6ba0121854c511395607ac902f330e" rel="noopener noreferrer"&gt;GitHub Gist link&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#!/usr/bin/env bash
LC_ALL=C

local_branch="$(git rev-parse --abbrev-ref HEAD)"

valid_branch_regex="^(task|master|develop|qa|tb|bug|story)[a-z0-9._-]{2,10}$"

message="This branch violates the branch naming rules. Please rename your branch."

if [[ ! $local_branch =~ $valid_branch_regex ]]
then
    echo "$message"
    exit 1
fi

exit 0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>git</category>
      <category>githooks</category>
    </item>
    <item>
      <title>Bulk delete stored npm packages from Azure Artifacts</title>
      <dc:creator>Matthew Dailey</dc:creator>
      <pubDate>Sat, 09 Apr 2022 13:32:26 +0000</pubDate>
      <link>https://dev.to/mtdailey/bulk-delete-stored-npm-packages-from-azure-artifacts-3879</link>
      <guid>https://dev.to/mtdailey/bulk-delete-stored-npm-packages-from-azure-artifacts-3879</guid>
      <description>&lt;p&gt;At my work we used to store our npm packages in an Azure Artifacts feed. We realized this was no longer necessary since we didn't publish our own custom packages anymore. Plus, over time all the different versions of the stored npm packages were taking up a large amount of space, close to 3GB in our cloud instance.&lt;/p&gt;

&lt;p&gt;Using the Azure DevOps REST API, I came up with a Powershell script that will bulk delete all npm packages from an Azure Artifacts feed. You will need to generate a PAT (Personal Access Token) with full privileges regarding packages and paste it into the script code. The organization name and feed id also needs to be added.&lt;/p&gt;

&lt;p&gt;If there is a large amount of packages with accompanying versions, the script will need to run multiple times. There is a limit to the number of stored package versions that can be retrieved at one time.&lt;/p&gt;

&lt;p&gt;The way the script works is it retrieves all the versions of the stored npm packages, loops through the versions and deletes them. In order to delete any package in Azure Artifacts, be it npm or NuGet, you have to delete the specific package version. The script can be modified in case you want to only delete certain versions of packages by changing the url that retrieves the package versions.&lt;/p&gt;

&lt;p&gt;Here is the script. Run it on your local machine.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;# Azure DevOps REST API #&amp;gt;
$url1 = 'https://feeds.dev.azure.com/{organization}/_apis/packaging/Feeds/{feed_id}/packages?protocolType=npm&amp;amp;includeAllVersions=true&amp;amp;api-version=7.1-preview.1'

$Token = '{Personal_Access_Token}'

if ($Token -eq "") {
    Write-Host 'PAT not set'
    exit 1
}
$AzureAuthHeader1 = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f "", $Token)))

$headers1 = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$headers1.Add("Authorization", ("Basic {0}" -f $AzureAuthHeader1))
$headers1.Add("Content-Type", "application/json")

$response1 = Invoke-RestMethod -Uri $url1 -Method GET -Headers $headers1

$packages = $response1.value

&amp;lt;# Loops through returned npm package versions and deletes them #&amp;gt;
Foreach ($i in $packages)
{
    $packageName = $i.name
    Write-Host $i.name -BackgroundColor cyan
    $allversions = $i.versions
    Foreach ($v in $allversions) {
        $packageVersion = $v.version
        $url2 = 'https://pkgs.dev.azure.com/{organization}/_apis/packaging/feeds/{feed_id}/npm/{0}/versions/{1}?api-version=7.1-preview.1' -f $packageName, $packageVersion
        $AzureAuthHeader2 = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f "", $Token)))

        $headers2 = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
        $headers2.Add("Authorization", ("Basic {0}" -f $AzureAuthHeader2))
        $headers2.Add("Content-Type", "application/json")

        $response2 = Invoke-RestMethod -Uri $url2 -Method DELETE -Headers $headers2
        Write-Host 'deleted' + $response2.value
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;a href="https://gist.github.com/mdailey77/adaf4c7acf24836a9f2c3a3346a9a4da" rel="noopener noreferrer"&gt;GitHub Gist link&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>azure</category>
      <category>devops</category>
      <category>azureartifacts</category>
      <category>powershell</category>
    </item>
    <item>
      <title>Adding Docker image to Docker Hub private repository</title>
      <dc:creator>Matthew Dailey</dc:creator>
      <pubDate>Sat, 21 Nov 2020 20:22:40 +0000</pubDate>
      <link>https://dev.to/mtdailey/adding-docker-image-to-docker-hub-private-repository-8b9</link>
      <guid>https://dev.to/mtdailey/adding-docker-image-to-docker-hub-private-repository-8b9</guid>
      <description>&lt;p&gt;I've learned something as straightforward as adding a Docker image to a repository can be somewhat frustrating. When I say private repository I mean a private repository hosted on Docker Hub. &lt;/p&gt;

&lt;p&gt;Here are the steps I had to take to successfully push a Docker image:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;If you recently created a private repo, log out of Docker and then login back in by running &lt;code&gt;docker logout&lt;/code&gt; and &lt;code&gt;docker login&lt;/code&gt; commands. The reason behind this is to make sure Docker is aware that the private repo exists. &lt;/li&gt;
&lt;li&gt;This is very important. The Docker image has to be named exactly the same as the private repo. If it is not named the same, you will get a &lt;code&gt;requested access to the resource is denied&lt;/code&gt; error. To change the Docker image name, run 'docker tag [current image name] [dockerhub username/private repo name:tag]. You can add whatever you want for the tag, I added '1.0'.&lt;/li&gt;
&lt;li&gt;Now with the Docker image having the correct name, you can add it to the private repository. Run &lt;code&gt;docker push [username/private repo name:tag]&lt;/code&gt;. For example &lt;code&gt;docker push johnsmith/demorepo:1.0&lt;/code&gt;. &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You're done. &lt;/p&gt;

</description>
      <category>docker</category>
    </item>
    <item>
      <title>How to fix extra list bullet in Outlook</title>
      <dc:creator>Matthew Dailey</dc:creator>
      <pubDate>Mon, 06 Jul 2020 20:24:12 +0000</pubDate>
      <link>https://dev.to/mtdailey/how-to-fix-extra-list-bullet-in-outlook-51lm</link>
      <guid>https://dev.to/mtdailey/how-to-fix-extra-list-bullet-in-outlook-51lm</guid>
      <description>&lt;p&gt;Even though I don't code emails anymore, I wanted to share a fix for an Outlook bug I encountered awhile back. An extra unordered list bullet appears at the end of the list even though the code itself is correct and no empty &lt;code&gt;&amp;lt;li&amp;gt;&lt;/code&gt; elements are present. I learned this particular bug happens when the unordered list is the last element in an editable region, say a table cell. A situation where an unordered list is the last element doesn't happen often, hence why I hadn't encountered it before. The workaround is to trick Outlook in thinking there is another element after the unordered list. Insert this code snippet directly after the closing &lt;code&gt;&amp;lt;/ul&amp;gt;&lt;/code&gt; tag: &lt;code&gt;&amp;lt;div style="display:none;"&amp;gt;&amp;amp;nbsp;&amp;lt;/div&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Here's an example:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;p&amp;gt;Here is some text inside a paragraph tag&amp;lt;/p&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;List bullet 1&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;List bullet 2&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;List bullet 3&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;div style="display:none;"&amp;gt;&amp;amp;nbsp;&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;I hope this saves someone some time.&lt;/p&gt;

</description>
      <category>outlook</category>
    </item>
    <item>
      <title>Adding virtual hosts in WAMP</title>
      <dc:creator>Matthew Dailey</dc:creator>
      <pubDate>Mon, 06 Jul 2020 20:13:41 +0000</pubDate>
      <link>https://dev.to/mtdailey/adding-virtual-hosts-in-wamp-2m2a</link>
      <guid>https://dev.to/mtdailey/adding-virtual-hosts-in-wamp-2m2a</guid>
      <description>&lt;p&gt;The ability to have multiple domains running on a local server can be accomplished with virtual hosts. Setting up a virtual host in the past was tedious and time-consuming. The process involved updating multiple files that were hard to find. One of the reasons why MAMP Pro has become so popular is it automates the task of adding virtual hosts. Naturally you have to buy a license. Now WAMP makes it easy to add virtual hosts and its free. This feature is barely mentioned on WAMP's website. Googling how to add a virtual host in WAMP turns up outdated instructions. I thought I share these instructions for those who weren't aware WAMP can add a virtual host in a couple of steps.&lt;/p&gt;

&lt;p&gt;Start WAMP and left-click the green WAMP desktop icon. If the icon is red then WAMP is not running correctly and you will need to troubleshoot the issue before continuing.&lt;br&gt;
Click on Localhost. A new browser tab should open. The heading at the top of the page will say 'Server Configuration'. Scroll down to the bottom of the page and look for the subheading 'Tools'. See the screenshots below.&lt;br&gt;
Click on 'Add a virtual host'. On the next page you need to fill out two fields. First type in the name of the virtual host you want to add. Whatever you type in will serve as the URL. For example if you type in 'newwebsite' as the name then the new domain's URL will be: &lt;a href="http://newwebsite" rel="noopener noreferrer"&gt;http://newwebsite&lt;/a&gt;&lt;br&gt;
In the second field put in the location where the website files reside on your computer. It has to be the complete file path. The files can be anywhere on your computer; they don't necessarily need to be inside the wamp folder. For myself I have one of my virtual hosts pointed to my git repository.&lt;br&gt;
The third field you can leave blank. Click on the 'Start the creation of the VirtualHost' button. After a few minutes you will see the newly created virtual host listed near the top of the page.&lt;/p&gt;

&lt;p&gt;There is no limit to the number of virtual hosts that can be added. To add another virtual host, just go back to the 'Add a virtual host' page and fill out the first two fields. To access the virtual hosts, left-click on the WAMP desktop icon, hover over 'My VirtualHosts', then choose which one to load.&lt;/p&gt;

</description>
      <category>virtualhost</category>
      <category>wamp</category>
    </item>
    <item>
      <title>"Family count" error when trying to restore database in SQL Server</title>
      <dc:creator>Matthew Dailey</dc:creator>
      <pubDate>Mon, 06 Jul 2020 20:02:09 +0000</pubDate>
      <link>https://dev.to/mtdailey/family-count-error-when-trying-to-restore-database-in-sql-server-25ai</link>
      <guid>https://dev.to/mtdailey/family-count-error-when-trying-to-restore-database-in-sql-server-25ai</guid>
      <description>&lt;p&gt;In the process of migrating a SQL Server LocalDB database to MySQL, one of the steps involves restoring the database in SQL Server Management Studio. The LocalDB database was first created in Visual Studio and to migrate it over to MySQL the database had to be setup in SQL Server Management Studio beforehand. Initially I recreated the database in Management Studio by using the T-SQL generated in Visual Studio. Along the line I had to move the database from my work computer to my home computer due to needing admin privileges to run certain tasks.&lt;/p&gt;

&lt;p&gt;This is when I encountered an error of "Family count:2. Missing family sequence number:1" when in the middle of the restore process. After some digging, the cause was from having more than one file path listed when performing the backup. I backed up the database a second time with just one file path listed under the Destination section and the Backup Type set to 'Full'. The database was restored with no errors. Success! Here is a &lt;a href="https://sql-compass.blogspot.com/2015/05/sql-server-media-set-has-2-media.html" rel="noopener noreferrer"&gt;blog post&lt;/a&gt; from SQL Compass with some helpful screenshots.&lt;/p&gt;

</description>
      <category>sqlserver</category>
      <category>database</category>
    </item>
    <item>
      <title>How to add free SSL certificate to GoDaddy shared hosting</title>
      <dc:creator>Matthew Dailey</dc:creator>
      <pubDate>Mon, 06 Jul 2020 19:41:31 +0000</pubDate>
      <link>https://dev.to/mtdailey/how-to-add-free-ssl-certificate-to-godaddy-shared-hosting-4gag</link>
      <guid>https://dev.to/mtdailey/how-to-add-free-ssl-certificate-to-godaddy-shared-hosting-4gag</guid>
      <description>&lt;p&gt;I began researching adding a SSL certificate to my personal website after founding out Google would start flagging HTTP sites as 'not secure' back in 2018. Naturally GoDaddy offers their own SSL certificate for 79 dollars a year. You can install your own SSL certificate but GoDaddy offers very little help. I called them to ask questions about how to do it and they tried to discourage me from going on my own. The customer support rep reminded me if I install my own SSL certificate I would have to  manually renew it every 90 days. This was after they said they weren't sure if it was possible on my plan. The rep was correct about the manual renewal although a CRON job can be set up to automatically renew the certificate.&lt;/p&gt;

&lt;p&gt;After going through multiple tutorials that didn't apply to my particular situation I found an easy-to-follow post by Steve Phillips. It covered everything on how to install a SSL certificate on GoDaddy shared hosting using a Windows machine and even how to have the certificate automatically renew. It can be found &lt;a href="https://tryingtobeawesome.com/encryptdaddy/" rel="noopener noreferrer"&gt;here&lt;/a&gt;. The hard part was enabling the SSH access and configuring PuTTy, an SSH client. I used a different way in generating the SSH keys than what is described in Steve Phillips' post. I used PuTTy's built-in key generator. I completed the entire process, including setting up PuTTy in about an hour.&lt;/p&gt;

</description>
      <category>sslcertificate</category>
    </item>
    <item>
      <title>Using WP-CLI and Composer to migrate a WordPress site</title>
      <dc:creator>Matthew Dailey</dc:creator>
      <pubDate>Mon, 06 Jul 2020 19:25:33 +0000</pubDate>
      <link>https://dev.to/mtdailey/using-wp-cli-and-composer-to-migrate-a-wordpress-site-1603</link>
      <guid>https://dev.to/mtdailey/using-wp-cli-and-composer-to-migrate-a-wordpress-site-1603</guid>
      <description>&lt;p&gt;In a recent project, I had to convert a single WordPress site to a multisite for a client. The approach I took was to create a new multisite install locally and import the content from the existing database. With the newly created WordPress multisite up and running locally on my computer, the next step was to migrate the site to a subdomain. &lt;/p&gt;

&lt;p&gt;Migrating a WordPress multisite from localhost to a test site can feel daunting but this is where WP-CLI (WordPress command-line) and Composer can save a considerable amount of time. I maintain my plugins using Composer. Rather than commit all of my plugins to a Git repository I list the plugins in a composer.json file and install them from &lt;a href="https://wpackagist.org/" rel="noopener noreferrer"&gt;WordPress Packagist&lt;/a&gt;, a composer repository for themes and plugins. Only custom or propriety themes and plugins are committed to a Git repository. &lt;/p&gt;

&lt;p&gt;Using both WP-CLI and Composer you can save time from having to upload plugins and WordPress core files. Using SSH access, go into the folder on the server where the WordPress install will reside. Since I'm on Windows I used &lt;a href="https://www.putty.org/" rel="noopener noreferrer"&gt;Putty&lt;/a&gt; for SSH access to the server. Run the wp-cli command: &lt;code&gt;wp core download&lt;/code&gt;. If you don't have WP-CLI installed, go to the &lt;a href="https://wp-cli.org/" rel="noopener noreferrer"&gt;documentation&lt;/a&gt; for instructions on how to install. This command will download the latest version of WordPress. Next run this command: &lt;code&gt;wp config create --dbname=testing --dbuser=wp --dbpass=securepswd&lt;/code&gt; to create a wp-config file. Make sure to put in your actual database credentials. Or you can upload your existing wp-config file and change the database credentials. With a multisite the install command is slightly different. The command would be as follows:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;wp core multisite-install --title="Welcome to the WordPress" --admin_user="admin" --admin_password="password" --admin_email="user@example.com"&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Import your database into the server. I'm not going to go into detail on how to do this as it it's outside the scope of this post. The URLs in the database need to be changed. Using WP-CLI, run command: &lt;code&gt;wp search-replace 'http://example.com' 'http://example.dev' --recurse-objects --skip-columns=guid --skip-tables=wp_users&lt;/code&gt; This will replace the localhost urls with the live server urls but skip the users table and any entries that have a guid. &lt;/p&gt;

&lt;p&gt;We will use Composer to install all plugins and themes at once. Move the composer.json file to the server if it's not already there. Using SSH access, run 'composer update' while in the WordPress folder on the server. This will install all the plugins and themes listed in the composer.json. You can use FTP to move over any custom plugins or themes not listed in the composer.json. You now have migrated a WordPress multisite.&lt;/p&gt;

&lt;p&gt;There are steps I purposely left out, like moving over images or importing a database. I wanted this to be a general overview. Hope you found it helpful. For a list of WP-CLI commands check out this &lt;a href="https://developer.wordpress.org/cli/commands/" rel="noopener noreferrer"&gt;page&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>wordpress</category>
      <category>composer</category>
    </item>
  </channel>
</rss>
