This post describes how to integrate a Hugo project repo with Gitlab CI and deploy the built site on Gitlab Pages automatically. If you host your static site on another platform/server, the actions you’ll need to do might be slightly different. In all cases, the major thing is to specify how the public
folder of the project will be uploaded to the frontend server. These configurations are declarative and abide to the rules of the .gitlab-ci.yml specification.
Gitlab Pages is a free service to host one static web site per Gitlab project. The site will have a default domain consisting of our Gitlab username and project name: https://myusername.gitlab.io/myproject
Custom domains are supported.
Create .gitlab-ci.yml file
Gitlab CI recipes are declared in the .gitlab-ci.yml
located in the root folder of the project. We must create it, if it doesn’t exist.
Below are the file contents from my blog.
On line 1 we say what docker image we’d like to use as a base for the container that will be created for us and started by the Gitlab runners. I use a predefined container with a fixed Hugo version (0.54.0), as I’d like to have reproducible builds and be sure that the container will be baked with exactly the same Hugo version, that I’m using locally for development.
On line 3 we define a git resolving strategy for submodules in case our theme is downloaded as a git submodule. In my case, I have followed the tutorial and added the theme as a submodule.
Next we define two CI jobs.
CI job test
On line 6 we start the definition of a job named test
. The name test
is an arbitrary string that we’ve chosen, it may be something else.
The script
part on line 7 contains the commands that will be executed inside the container shell. There may be multiple commands on each new line, but for our current needs we only run hugo
.
This has the same effect as running the hugo
command locally inside the root folder of our project. The command will build our static web site and put it inside a public
folder (will create it if doesn’t exist). If the build completes successfully, the command will terminate with exit code 0
and the job will pass ✅. It the build process fails, the command will terminate with exit code > 0
and the CI job will fail ❌.
In reality, with the test
job just described, we haven’t really written any tests for our project (e.g. unit, intergration, etc.), but we implicitly say that if the build process of our static site succeeds, we consider the site OK and tested.
On line 9 we use the except
word to specify when the job should not be executed. The master
value says that the job should not be executed for a branch called master
. Instead, it will be executed for all other branches that we may have and push commits to.
CI job pages
The CI job pages
is more magical and subtle as it not only tests our site in the same way as we did in the test
job, but it also automatically deploys the site to Gitlab Pages, if the build process is successful.
On line 14 we run the hugo
command again, but this time with a flag to specify the environment configuration. The flag tells hugo
to look for config.toml
file inside the /config/production/
folder. We need this so we can specify different variables for production. For example, the baseURL
variable may point to a real domain name like https://myusername.gitlab.io/myproject
, while the default config.toml
may set baseURL = "http://localhost:1313"
.
The magic with the automatic deployment happens on line 15 with the word artifacts
. It says that the public
folder (which was generated during the run of script
), must not be deleted after the job is completed, but instead will be available afterwards. Whenever the Gitlab system finds this folder after the job completes, it will deploy it to the Gitlab Pages for our project. And bam… we have our site online.
404 Page Not Found
error. We should wait for some time until the site goes live.The last declaration in our .gitlab-ci.yml
file is the word only
. It defines another value which tells that the job should be executed only for commits in the master
branch. So whenever we merge a branch to master
or directly push commits to master
the site will be redeployed to Gitlab Pages.