GitHub, GitHub, What?
Well, I’m not affiliated, by the way ;P GitHub pages is a service freely available for all GH users to host static sites from their repositories. GH actions (also free, as in free lemonade) lets users automate software workflows (think CI/CD). What we’ll be doing is automating the deployment of a Hugo site in a GH repository to GH pages.
Setting up the source
Once we have a Hugo site set up1, we’ll need to push this to a repo in GH. This could be the same repo we’ve setup GH pages as well, but for my Hugo blog, I’ve used a different one that doesn’t use GH pages. Here, GH actions of this (source) repo needs to clone the GH pages repo to commit, and push to it whatever the changes. For git authentication in this case, a deploy key2 with write access (default is read-only) shall be created for the GH pages repo. This key shall then be added to the source repo as a repo secret (i.e. with name DEPLOY_KEY). That way, the deploy key shall be made securely accessible by GH actions of the source repo.
Actions Workflow
We may as well set up GH Actions in the same repo for GH pages, commit and push the changes to own repo on a trigger. However, following workflow3 is to be used in setting up GH actions in the source (non GH pages) repo.
# This workflow clones a repo, builds the Hugo site in it,
# and pushes the pages (/public dir) to another repo.
name: Build and Deploy Hugo site
# Controls when the action will run.
on:
# Triggers the workflow on push or pull request events but only for the main branch
push:
branches: [ main ]
pull_request:
branches: [ main ]
# Allows us to run this workflow manually from the Actions tab
workflow_dispatch:
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
# This workflow contains a single job called "build_and_deploy"
build_and_deploy:
# The type of runner that the job will run on
runs-on: ubuntu-latest
# Steps represent a sequence of tasks that will be executed as part of the job
steps:
# Checks-out our (source) repository under $GITHUB_WORKSPACE, so our job can access it
- uses: actions/checkout@v2
with:
path: <dir-to-checkout-source-repo>
# Sets up Hugo binary in environment
- run: |
mkdir -p $GITHUB_WORKSPACE/bin/hugo/
cd $GITHUB_WORKSPACE/bin/hugo/
wget https://github.com/gohugoio/hugo/releases/download/v0.83.1/hugo_0.83.1_Linux-64bit.tar.gz
tar -xzvf hugo_0.83.1_Linux-64bit.tar.gz
chmod +x hugo
# Checks-out GH pages repo, git auth with deploy key (with write-access)
- uses: actions/checkout@v2
with:
repository: <gh-username>/<gh-repo-name>
path: <dir-to-checkout-GH-pages-repo>
ssh-key: ${{ secrets.DEPLOY_KEY }}
- run: |
cd $GITHUB_WORKSPACE/<dir-to-checkout-source-repo>
$GITHUB_WORKSPACE/bin/hugo/hugo --minify
cd $GITHUB_WORKSPACE
rm -rf <dir-to-checkout-GH-pages-repo>/<path-to-hugo-site>/*
cp -r <dir-to-checkout-source-repo>/<path-to-hugo-site>/public/* \
<dir-to-checkout-GH-pages-repo>/<path-to-hugo-site>/.
cd <dir-to-checkout-GH-pages-repo>/
git config user.name github-actions
git config user.email github-actions@hsen.tech
git add .
git commit -m "Hugo site built & updated"
git push
echo Pushed at `date`.
The above workflow is set up to be triggered once every push or pull_request event, uses a specific version of Hugo binary to build the site, and is easily extensible for building multiple sites (with own-directory for each). It goes without saying that there are many ways to accomplish what we’ve just done, and each comes with it’s own tradeoffs.