Deploying a Gatsby site to Azure Storage via GitHub

by Kristian Ranstrom
October 5, 2021
5 min read

GitHub has become a very powerful code repository and one aspect that makes it so powerful are it's CI/CD capabilities.  Let's say you have a great little Gatsby site and want to host it in Azure Storage. In a matter of minutes, you can have your repo automatically build upon check-in to your master branch and push out to your Azure Storage account.  Here's how to do it.

Azure Setup

  1. Create a Storage Account
  2. Go to the Static Website blade and Enable the storage account's static website capabilities.
  3. Optionally, create a CDN on the $web container of the storage account, which is where your static site will live.
  4. Optionally, setup a custom domain for your CDN.
  5. Now you'll need to gather a bunch of variables from your Azure instance. We'll be using these soon when we create the GitHub workflow. Here they are:
    1. AZURE_CDN_ENDPOINT
    2. AZURE_CDN_PROFILE_NAME
    3. AZURE_CREDENTIALS
    4. AZURE_RESOURCE_GROUP
    5. AZURE_STORAGE_CONNECTION_STRING
    6. AZURE_SUBSCRIPTION_ID

GitHub

In our GitHub repository, there are 2 areas that we'll be working with, Secrets and Actions.  

Secrets

Secrets are GitHub's area to store variables that contain important data.  You can get to the Secrets area by going to the repo's Settings page and then selecting the Secrets link in the left navigation.  On that page, you will enter the Azure variables you grabbed from the previous step.

Actions

Actions are where you can define and monitor your CI/CD pipelines.  They are created by creating yaml scripts.  Yaml is capable of many things.  Today, I'm just showing how to build a Gatsby site, deploy it to Azure Storage and clear the CDN cache.  

We only want to deploy when code is checked into the master branch.  If you want the trigger to occur on a different branch, just substitute the name of your branch.

on:   
 push:  
   branches:  
     - master  

Now we're going to create a workflow with 2-steps.  Our script requires the use of an ubuntu image to run on with Node js (version 15) installed.  

runs-on: ubuntu-latest

strategy:  
 matrix:  
node-version: [15.x]  

Next, we're going to tell the script to use Node.js and install the Gatsby cli.  Once that is installed, we will do a simple build using the gatsby-cli.

- uses: actions/[email protected]  
       
- name: Use Node.js ${{ matrix.node-version }}  
 uses: actions/[email protected]  
 with:  
node-version: ${{ matrix.node-version }}

- name: Install dependencies  
 run: |  
npm install  
npm install -g gatsby-cli

- name: Build with Gatsby  
 run: gatsby build  

Once the site is built, we can now push it out to Azure using the azure-cli.  These next 2 lines first delete every file from teh $web container and then upload the new files

- name: Azure upload  
     uses: azure/[email protected]  
     with:  
       azcliversion: 2.0.72  
       inlineScript: |  
         az storage blob delete-batch -s "\$web" --connection-string "${{ secrets.AZURE_STORAGE_CONNECTION_STRING }}"  
         az storage blob upload-batch -d "\$web" -s public --connection-string "${{ secrets.AZURE_STORAGE_CONNECTION_STRING }}"  

Now if you're using an Azure CDN to front the site, you should purge the cache or else it could take a long time for the site to reflect the changes.  We do that with a purge job.  As you can see below, it's waiting until the build job finishes first, then it logs into Azure, purges the CDN and logs out.  Note all the Secrets variables that are used through the script.

purge:  
   needs: build  
   runs-on: ubuntu-latest

   steps:  
       
   - name: Azure service principal login  
     uses: Azure/[email protected]  
     with:  
       creds: ${{ secrets.AZURE_CREDENTIALS }}  
         
   - name: Purge CDN  
     run:  
       az cdn endpoint purge -g ${{ secrets.AZURE_RESOURCE_GROUP }} -n ${{ secrets.AZURE_CDN_ENDPOINT }} --profile-name ${{ secrets.AZURE_CDN_PROFILE_NAME }} --subscription ${{ secrets.AZURE_SUBSCRIPTION_ID }} --content-paths "/\*" --no-wait  
         
   - name: Azure service principal logout  
     run: |  
       az logout  

Here's the entire yaml script in its entirety.

name: Deploy Gatsby to Azure Storage

on:   
 push:  
   branches:  
     - master

jobs:  
 build:

   runs-on: ubuntu-latest

   strategy:  
     matrix:  
       node-version: [15.x]

   steps:  
       
   - uses: actions/[email protected]  
       
   - name: Use Node.js ${{ matrix.node-version }}  
     uses: actions/[email protected]  
     with:  
       node-version: ${{ matrix.node-version }}  
   
   - name: Install dependencies  
     run: |  
       npm install  
       npm install -g gatsby-cli  
         
   - name: Build with Gatsby  
     run: gatsby build  
     
   - name: Azure upload  
     uses: azure/[email protected]  
     with:  
       azcliversion: 2.0.72  
       inlineScript: |  
         az storage blob delete-batch -s "\$web" --connection-string "${{ secrets.AZURE_STORAGE_CONNECTION_STRING }}"  
         az storage blob upload-batch -d "\$web" -s public --connection-string "${{ secrets.AZURE_STORAGE_CONNECTION_STRING }}"  
                       
 purge:  
   needs: build  
   runs-on: ubuntu-latest

   steps:  
       
   - name: Azure service principal login  
     uses: Azure/[email protected]  
     with:  
       creds: ${{ secrets.AZURE_CREDENTIALS }}  
         
   - name: Purge CDN  
     run:  
       az cdn endpoint purge -g ${{ secrets.AZURE_RESOURCE_GROUP }} -n ${{ secrets.AZURE_CDN_ENDPOINT }} --profile-name ${{ secrets.AZURE_CDN_PROFILE_NAME }} --subscription ${{ secrets.AZURE_SUBSCRIPTION_ID }} --content-paths "/\*" --no-wait  
         
   - name: Azure service principal logout  
     run: |  
       az logout  

Try to check in some code to the master branch and watch the new workflow work.  This is just one possibility of what GitHub Actions can do.  If this isn't exactly what you're looking for, hopefully it'll get you part of the way.