Gunnar Morling

Gunnar Morling

Random Musings on All Things Software Engineering

Gunnar Morling

Gunnar Morling

Random Musings on All Things Software Engineering

Automatically Deploying a Hugo Website via GitHub Actions

Posted at Dec 26, 2019

As a software engineer, I like to automate tedious tasks as much as possible. The deployment of this website is no exception: it is built using the Hugo static site generator and hosted on GitHub Pages; so wouldn’t it be nice if the rendered website would automatically be published whenever an update is pushed to its source code repository?

With the advent of GitHub Actions, tasks like this can easily be implemented without having to rely on any external CI service. Instead, many ready-made actions can be obtained from the GitHub marketplace and easily be configured as per our needs. E.g. triggered by a push to a specified branch in a GitHub repository, they can execute tasks like project builds, tests and many others, running in virtual machines based on Linux, Windows and even macOS. So let’s see what’s needed for building a Hugo website and deploying it to GitHub Pages.

GitHub Actions To the Rescue

Using my favourite search engine, I came across two GitHub actions which do everything we need:

There are multiple alternatives for GitHub Pages deployment. I chose this one basically because it seems to be the most popular one (as per number of GitHub stars), and because it’s by the same author as the Hugo one, so they should nicely play together.

Registering a Deploy Key

In order for the GitHub action to deploy the website, a GitHub deploy key must be registered.

To do so, create a new SSH key pair on your machine like so:

ssh-keygen -t rsa -b 4096 -C "$(git config user.email)" -f gh-pages -N ""

This will create two files, the public key (gh-pages.pub) and the private key (gh-pages). Go to https://github.com/<your-user-or-organisation>/<your-repo>/settings/keys and click "Add deploy key". Paste in the public part of your key pair and check the "Allow write access" box.

Now go to https://github.com/<your-user-or-organisation>/<your-repo>/settings/secrets and click "Add new secret". Choose ACTIONS_DEPLOY_KEY as the name and paste the private part of your key pair into the "Value" field.

The key will be stored in an encrypted way as per GitHub’s documentation Nevertheless I’d recommend to use a specific key pair just for this purpose, instead of re-using any other key pair. That way, impact will be reduced to this particular usage, should the private key get leaked somehow.

Defining the Workflow

With the key in place, it’s time to set up the actual GitHub Actions workflow. This is simply done by creating the file .github/workflows/gh-pages-deployment.yml in your repository with the following contents. GitHub Actions workflows are YAML files, because YOLO ;)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
name: GitHub Pages

on:                                              (1)
  push:
    branches:
    - master

jobs:
  build-deploy:
    runs-on: ubuntu-18.04
    steps:
    - uses: actions/checkout@v1                  (2)
      with:
        submodules: true

    - name: Install Ruby Dev                     (3)
      run: sudo apt-get install ruby-dev

    - name: Install AsciiDoctor and Rouge
      run: sudo gem install asciidoctor rouge

    - name: Setup Hugo                           (4)
      uses: peaceiris/actions-hugo@v2
      with:
        hugo-version: '0.62.0'

    - name: Build                                (5)
      run: hugo

    - name: Deploy                               (6)
      uses: peaceiris/actions-gh-pages@v2
      env:
        ACTIONS_DEPLOY_KEY: ${{ secrets.ACTIONS_DEPLOY_KEY }}
        PUBLISH_BRANCH: gh-pages
        PUBLISH_DIR: ./public
1 Run this action whenever changes are pushed to the master branch
2 The first step in the job: check out the source code
3 Install AsciiDoctor (in case you use Hugo with AsciiDoc files, like I do) and Rouge, a Ruby gem for syntax highlighting; I’m installing the gems instead of Ubuntu packages in order to get current versions
4 Set up Hugo via the aforementioned GitHub Actions for Hugo
5 Run the hugo command; here you could add parameters such as -F for also building future posts
6 Deploy the website to GitHub pages; the contents of Hugo’s build directory public will be pushed to the gh-pages branch of the upstream repository, using the deploy key configured before

And that’s all we need; once the file is committed and pushed to the upstream repository, the deployment workflow will be executed upon each push to the master branch.

You can find the complete workflow definition used for publishing this website here. Also check out the documentation of GitHub Actions for Hugo and GitHub Actions for GitHub Pages to learn more about their capabilities and the options they offer.