Use GitHub Actions to a publish a static site with hugo and azcopy
In a previous post I shared how I build this site using Hugo and serve it from Azure Blob Storage using Cloudflare Workers. In other scenarios (such as content for workshops, etc) I also use the Static Websites feature of Azure Blob Storage paired with Azure Front Door for its Custom Domain and free and automatic SSL support. In this post I’ll cover how I automate my static site’s deployment using the new GitHub Actions, Hugo, and AzCopy.
I have used GitHub Actions since its initial launch in October 2018. The initial release of GitHub Actions was focused on container-based workflows and used the HCL syntax to define them. My hugo-azcopy
action that built this site was defined via an HCL file, main.workflow
, a Dockerfile
and a bash script, entrypoint.sh
that lived in a .github/hugo-azcopy/
directory in my repo.
This month GitHub released a major update to Actions, which included built-in CI/CD, YAML syntax, cross-platform (Linux, macOS and Windows) support, live logs, built-in secret handling, multi-container docker support, and straightforward pay-as-you-go pricing (from 2,000 minutes a month on free plans with per-minute billing thereafter).
This weekend I re-wrote my hugo-azcopy
action from HCL syntax to the new YAML powered Actions, which now lives in a single file, .github/workflows/main.yml
(example). I took the opportunity to bump the Hugo version I use, and choose a new template which I continue to tweak. HCL actions are deprecated but continue to work, even side-by-side with YAML actions. After migrating myself I discovered my colleague Den Delimarschi on the docs team just published a post on how he migrated his own GitHub Action for publishing his Hugo site to GitHub pages from HCL to YAML in less than 10 minutes!
I was very pleased to see YAML actions continue to support a Docker container image on Docker Hub. This might be helpful if you have many dependencies you want to bundle into a single immutable container image. But since both Hugo and AzCopy v10 are self-contained Go binaries that take mere seconds to download via curl
, I found it easier to ditch the Dockerfile and use the standard checkout action that is already required for every workflow.
If you click on the Actions
tab of your GitHub repo, you will see dozens of pre-built Actions from Python and Docker to Go and Rust. However, if you click Skip this: Set up a workflow yourself
you will see a default workflow, main.yml
, that uses the actions/checkout@v1
Action as follows:
name: CI
on: [push]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: Run a one-line script
run: echo Hello, world!
- name: Run a multi-line script
run: |
echo Add other actions to build,
echo test, and deploy your project.
Here we have sensible defaults for the name (CI
) of the workflow, the event (push
), that triggers your action, the virtual environment (ubuntu-latest
– currently Ubuntu 18.04), and a build
job with steps that include examples of one-line and multi-line scripts.
I added two steps to my main.yml. The first, Install hugo + azcopy
, downloads these CLI tools using curl
. The second, Run hugo + azcopy
, is as follows:
- name: Run hugo + azcopy
env:
SOURCE_DIRECTORY: aaronmsft-com/
AZURE_STORAGE_CONTAINER_URL: https://180300static.blob.core.windows.net/aaronmsft-com/
AZURE_STORAGE_SAS_TOKEN: ${{ secrets.AZURE_STORAGE_SAS_TOKEN }}
run: |
echo $PWD
cd $SOURCE_DIRECTORY
export HUGO_ENV='production'
hugo -v
azcopy sync public/ "${AZURE_STORAGE_CONTAINER_URL}${AZURE_STORAGE_SAS_TOKEN}" --delete-destination=true
Here I have created an array of environment variables under env
. The AZURE_STORAGE_SAS_TOKEN
references a secret which I added to my GitHub repo under Settings > Secrets
. I retrieved the AZURE_STORAGE_CONTAINER_URL
and a container-level Shared Access Signature (SAS) for AZURE_STORAGE_SAS_TOKEN
using the Storage Explorer (preview) in the Azure Portal (the SAS can also be generated using the Azure CLI via the az storage container generate-sas command).
Finally, we run hugo
to build the site and the azcopy sync command to sync the contents of the public/
directory to Blob Storage, using the --delete-destination
flag to clean up any extra files.
I put my sites in a sub-folder of my repo so that I can build and manage multiple sites per repo. Using Cloudflare Workers or Azure Front Door enables me to build and serve multiple sites per Azure Storage account.
I also amend the on: [push]
section in my YAML file so that it is only triggered on push to the master
branch:
on:
push:
branches:
- master
I could even restrict its execution based on a push to a specific path so only one action would be triggered if I want to build several sites out of the same repo. My new YAML action is much faster than my already-fast HCL action. Hugo is blazingly fast, so the cost of building even multiple sites is tiny, and azcopy sync is also efficient enough that I won’t need to use multiple actions in the forseeable future.
If you think this looks like a fair few steps for a static site, you’re right! Static sites are just one simple workflow that showcases GitHub, Actions, and efficient CLI tools, but Actions can be used for almost everything from continuous integration and deployment, to GitHub-powered workflows for your personal, team, or community projects. Almost every major language and platform is represented – and if yours isn’t, you can create a public one today. We released Azure actions (github) for Azure, Web Apps, Containers and Kubernetes just last week. One of my favorite features of Actions is that they are completely declarative, which means anyone can clone a repo with an Action, set some environment variables and/or drop in a secret, and perform the same steps without pages of point and click, or new accounts to setup.
As always, feel free to reach out any time! I’d love to hear any feedback on Actions, whether have signed up for the beta but don’t have access yet (prior to their General Availability this November), or are building something interesting already. My twitter direct messages (@as_w) are always open!
Use GitHub Actions to a publish a static site with hugo and azcopy https://t.co/fVKk9ywnAh by @as_w pic.twitter.com/eVVCHTTUqs
— Aaron W ☁️ (@as_w) August 20, 2019