Automating Hugo build with GitLab CI
WARNING: This post contains links to content that no longer exists. Do not use this blog post as a guide. It remains for archive purposes only.
I found a ton of posts that describe how to use Hugo and GitLab CI to create and host a static site on GitLab Pages.
However, I had a different requirement: I want to use a local GitLab CE instance to store my content, use GitLab CI (locally) to build the static output and then push that output to GitHub to publish on GitHub Pages.
High-level workflow:
- spin up a Docker container
- check out the latest GitHub Pages content commit from GitHub
- run Hugo on the latest source content commit from GitLab CE
- if the content has been updated, push the changes to GitHub
The Docker container
I tried a bunch of the existing Hugo containers, but none of them had all the
components required (hugo+git+openssh) to achieve my goal. So, I shaved a few yaks
and created my own hugo-builder
1 image that has all the bits I need.
Secret stuff
In order to check out content (and later push it back) to GitHub, I need to be able to use SSH and have a keypair configured.
Using GitLab Secret Variables
I recommend creating a specific keypair for your GitLab CI instance so that it is kept separate from your main SSH keypair. This is required to pull and push from GitHub.
Also, I don’t want to store the private key anywhere visible or in a repo, so
I’m using GitLab Secret Variables
instead. Create a variable named PRIVATE_KEY
and store the content of ~/.ssh/id_rsa
in that variable.
I also created a GITHUB_KEY
variable that stores the public key of GitHub so I
can automatically add it to ~/.ssh/authorized_keys
in the build container.
Run Hugo
I had a bunch of problems with GitLab CI not properly pulling the Hugo theme I use
which is configured as a git submodule. So, I do it manually as part of the before_script
process in the CI pipeline.
Hugo stores its static output in the public/
folder. This folder is included in
.gitignore
for the source content so it is never stored on the local GitLab
instance.
GitLab CI automatically checks out the latest commit from the repo when it starts
a build, so before I run Hugo, I pull the current content from GitHub to create the public/
directory:
git clone git@github.com:username/username.github.io.git public
Setup and clone from GitLab is done in the before_script
block.
Then, when Hugo runs, it will update files in that same location, so I can use git
to check if the content has actually changed. This is done using the after_script
block.
1 |
|
If all goes well, this will be the first new post that is actually published using this automated workflow.
Obviously, if it doesn’t, I’ll have to fix it and republish this page and you won’t know anyway. Magic!
-
Image no longer available. ↩︎