The Setup

It has been years since I’ve modified how I deploy this blog. The last time I wrote about it was back in 2021. Since then, one of the Github Action components I relied on peaceiris/actions-hugo has stopped being actively developed. Hugo later made a change that removed the withdeploy feature from it’s default builds, such that when downloading Hugo binaries you needed to specify you wanted the withdeploy capability. That capability let’s me deploy the site to AWS nice and easy. Since peaceiris/actions-hugo was never updated to support this change, I had to consider my options.

First, I could fork peaceiris/actions-hugo and go my own route. I gave this an attempt, but ultimately that action has much more functionality than I need to support the deployment of this site. And maintaining my own fork would create extra work over time.

Second, I could find a different Github Action to handle Hugo. I may have spent 15 minutes looking into alternatives, but a different idea was nagging at me.

Third, I could just build my own container to run as a Github Action step. I only needed to run the hugo command using the hugo binary containing withdeploy. That should be easy.

Building a Container

The bare bones of this are quite simple. I need:

  • A Dockerfile
  • An entry point script
  • An action script

The Dockerfile simply starts with an Ubuntu base and adds a few common tools I will use to download the Hugo binary.

# Container image that runs your code
FROM ubuntu:latest

RUN apt-get update && \
    apt-get install -y wget gzip curl jq sed

# Copies your code file from your action repository to the filesystem path `/` of the container
COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh

# Code file to execute when the docker container starts up (`entrypoint.sh`)
ENTRYPOINT ["/entrypoint.sh"]

Then the entrypoint.sh script needs to download the Hugo binary. There is a bit of logic here that lets me choose which Hugo version, if I wanted the extended Hugo binary, and if I want deploy capabilities (I do!). My site deploy never changes these parameters, but maybe I’ll recycle this thing in the future to a different use and it’s nice to have a couple of flags to make it more flexible.

#!/bin/bash -l

echo "Hugo Version: $INPUT_HUGOVERSION"
echo "Extended: $INPUT_EXTENDED"
echo "With Deploy: $INPUT_WITHDEPLOY"

EXT_STR=""
if [ "$INPUT_EXTENDED" = true ]; then
    EXT_STR="extended_"
fi

WD_STR=""
if [ "$INPUT_WITHDEPLOY" = true ]; then
    WD_STR="withdeploy_"
fi

VERSION_STR=""
if [ "$INPUT_HUGOVERSION" = "latest" ]; then
    # Get latest version, and remove any leading "v" a la "v0.143.1"
    VERSION_STR=$(curl --silent https://api.github.com/repos/gohugoio/hugo/releases/latest | jq --raw-output '.tag_name' | sed -r 's/v(.*)/\1/g')
else
    VERSION_STR="$INPUT_HUGOVERSION"
fi

# Change to check out directory
cd $GITHUB_WORKSPACE

# Echo version to download
echo "Will download hugo: hugo_${EXT_STR}${WD_STR}${VERSION_STR}_Linux-64bit.tar.gz"

# Install hugo
wget -qO- "https://github.com/gohugoio/hugo/releases/download/v${VERSION_STR}/hugo_${EXT_STR}${WD_STR}${VERSION_STR}_Linux-64bit.tar.gz" | gunzip | tar xf -

Finally, I need an action.yml so Github Actions knows what to do with this thing.

name: 'Publish blog using hugo to AWS'
description: 'Publish my blog'
inputs:
  hugoVersion:
    description: 'The Hugo version to download and use. Example: 0.142.0'
    required: false
    default: 'latest'
  extended:
    description: 'Download and use Hugo extended version. Example: true'
    required: false
    default: 'false'
  withDeploy:
    description: 'Include ability to deploy to AWS'
    required: false
    default: 'false'
runs:
  using: 'docker'
  image: 'Dockerfile'
  args:
    - ${{ inputs.hugoVersion }}
    - ${{ inputs.extended }}
    - ${{ inputs.withDeploy }}

Define my input variables and add some metadata. Simple.

The above all sits in a private Github repo of mine. I also need to modify a Setting to ensure it can be invoked from an Actions runner, link to Github docs for doing that.

Updating my site actions config

To reference my private repo Action when running a build of my site via Github Actions, I need to include a specific commit hash in the uses: clause. Github documentation tells me it’s a security best-practice to always reference a specific commit SHA hash, and if I recall right I needed to use a specific commit hash to reference a private repo action.

- name: Hugo setup
# You may pin to the exact commit or the version.
uses: leafonthewind/hugo-publish-github-action@81c9d9ccca240d4ba07e17f7de34a777605c5380
with:
    # The Hugo version to download (if necessary) and use. Example: 0.142.0
    # 'latest' also works!
    hugoVersion: 'latest'
    # Download (if necessary) and use Hugo extended version. Example: true
    extended: true
    withDeploy: true

I set my variables such that it pulls withDeploy: true. Later in the actions script, I use that capability to deploy the generated site to AWS.

- name: Hugo deploy static site to S3 bucket
  run: ./hugo deploy --maxDeletes -1 --environment production

Reference my original post for full details on how I deploy the entire site using Github actions. Not much else has changed in the last 4 years, which has been a nice surprise! (I upgraded some version numbers for other actions, but that’s it.)

For a free user of Github like me, it’s really, really nice to be able to deploy this site from anywhere in the world using Github Actions. Each deploy takes ~1 minute of runner time, so the 2,000 minutes of free time I get per month is absolutely enough to cover my use case.