Blog / Using GitHub Actions to Publish Static Sites to Azure

This site is hosted on Microsoft Azure. Its source code is stored in GitHub on a free tier, which allows me to run GitHub actions to publish the site whenever I merge any code into my main branch. Last week I ran into an issue publishing Xenobell and wanted to share the solution I discovered.

What went wrong

  1. The “latest” version of azcliversion had a bug (… and then today it didn’t)
  2. Something happened with permissions such that the “Contributor” role didn’t cover blog storage and CDN

Generating credentials

This is the command I use in Azure Shell to generate credentials for the AZURE_CREDENTIALS_STORAGE secret. Replace the all-caps sections with your own subscription ID and resource name.

az ad sp create-for-rbac --name "GitHubStorage" --role "Storage Blob Data Contributor" --scopes /subscriptions/MY-SUBSCRIPTION-GUID/resourceGroups/MY-RESOURCE-GROUP --sdk-auth

Same here for the AZURE_CREDENTIALS_CDN secret.

az ad sp create-for-rbac --name "GitHubCDN" --role "CDN Endpoint Contributor" --scopes /subscriptions/MY-SUBSCRIPTION-GUID/resourceGroups/MY-RESOURCE-GROUP --sdk-auth

GitHub action

I know, I know, it’s terrible to delete all my content before uploading new stuff. I haven’t figured out how to delete only files older than X minutes. Plus, this site has very little traffic and I don’t publish that often.

Want to hear something funny? I was all set to publish this article, but it turns out the 2.29.2 version didn’t work today! After a few attempts I went back to the latest version and it’s working again! Ugh. Be careful with your azcliversion numbers, everyone.

# .github/workflows/actions.yml
on:
    push:
        branches:
            - main

jobs:
    upload:
        runs-on: ubuntu-latest
        steps:
            - name: Checkout repository
              uses: actions/checkout@v2

            - name: Setup Node.js
              uses: actions/setup-node@v1
              with:
                  node-version: "12.x"

            - name: NPM install
              run: npm install

            - name: Build
              run: npm run build

            - name: Login to Azure Storage
              uses: Azure/login@v1
              with:
                  creds: ${{ secrets.AZURE_CREDENTIALS_STORAGE }}

            - name: Delete blob files
              uses: Azure/cli@v1
              with:
                  azcliversion: latest
                  inlineScript: |
                                            az storage blob delete-batch -s \$web --account-name ${{ secrets.AZURE_STORAGE_ACCOUNT_NAME }} --auth-mode login

            - name: Upload to blob storage
              uses: Azure/cli@v1
              with:
                  azcliversion: latest
                  inlineScript: |
                                            az storage blob upload-batch -s $GITHUB_WORKSPACE/public -d \$web --account-name ${{ secrets.AZURE_STORAGE_ACCOUNT_NAME }} --auth-mode login

            - name: Login to Azure CDN
              uses: Azure/login@v1
              with:
                  creds: ${{ secrets.AZURE_CREDENTIALS_CDN }}

            - name: Purge CDN
              uses: Azure/cli@v1
              with:
                  azcliversion: latest
                  inlinescript: |
                                            az cdn endpoint purge -g ${{ secrets.AZURE_RESOURCE_GROUP_NAME }} -n ${{ secrets.AZURE_ENDPOINT_NAME }} --profile-name ${{ secrets.AZURE_CDN_NAME }} --content-paths '/*'