Deploy Hugo sites on GitHub Pages using Travis CI

Hugo-Travis-GitHub

Recently, I have started to play around with Hugo. In a single word, my experience was awesome. The only thing that I found a little bit uneasy was deploying the site to GitHub Pages. Of course, it’s possible to publish the site with running commands manually. But I wanted to have the entire process automated. Hence, I’ve done some research and came up with the simplest approach. In this post, I share how to automatically deploy Hugo sites on GitHub Pages using Travis CI.

Workflow explanation

The idea is very simple. We want to add or modify some contents on a Hugo site which then we push the changes to GitHub. And we are expecting after that the changes to be published automatically. This means that Travis CI should pick up the changes, generates the site and publish it to GitHub pages by pushing the generated content to the gh-pages branch. See the below picture,

Hugo, Travis CI, and GitHub pages workflow
Hugo, Travis CI, and GitHub pages workflow

This way with kill two birds with one stone. First, we just change the .md file content and push the changes and Travis takes care of the rest. Second, we keep both original contents and generated ones in a single neat repository. Thirdly, we don’t need to pay a single cent to have a gorgeous website. Last but not least, the workflow works for any static site generator.

Publish a Hugo site to GitHub Pages with Travis CI

Now that we know our objective, it’s time to implement what we need. The good thing is we just deal with a single file, .travis.yml.

The first step is to download the Hugo binary before running the build process. For that we can something like this:

dist: bionic
sudo: true
install:
  - curl -LO https://github.com/gohugoio/hugo/releases/download/v0.58.3/hugo_extended_0.58.3_Linux-64bit.deb
  - sudo dpkg -i hugo_extended_0.58.3_Linux-64bit.deb

That’s because most of the Travis slaves have an old version of Hugo which may fail to generate the site.

After that, we have to pull the submodule Git repository, if we have. I personally add Hugo themes as submodules to my repository. If you are not doing that, feel free to skip it. To pull the submodule to the repository, we need to add the following lines to the script section of .travis.yml file,

dist: bionic
sudo: true
install:
  - curl -LO https://github.com/gohugoio/hugo/releases/download/v0.58.3/hugo_extended_0.58.3_Linux-64bit.deb
  - sudo dpkg -i hugo_extended_0.58.3_Linux-64bit.deb
script:
  - git submodule update --init
  - git submodule update --remote --merge

And then the last step before deploying the Hugo site is to build it. I highly recommend to not generate the site in the repository directory. To do that, we add the following line to the script section,

dist: bionic
sudo: true
install:
  - curl -LO https://github.com/gohugoio/hugo/releases/download/v0.58.3/hugo_extended_0.58.3_Linux-64bit.deb
  - sudo dpkg -i hugo_extended_0.58.3_Linux-64bit.deb
script:
  - git submodule update --init
  - git submodule update --remote --merge
  - hugo -d ../generated

Now everything is ready to deploy the site. For the deployment, we rely on the Travis CI GitHub pages deploy process which is very handy. The only thing that we need to configure is on which branch this process should be triggered, provide the generated content path, and pass GitHub token. So essentially we will have something like this,

deploy:
  provider: pages
  skip_cleanup: true
  github_token: $GITHUB_TOKEN
  keep_history: true
  local_dir: ../generated
  on:
    branch: master

Keep in mind that the $GITHUB_TOKEN variable should be set in the setting section of Travis CI.

Our .travis.yml file is finished and ready as follows,

dist: bionic
sudo: true
install:
  - curl -LO https://github.com/gohugoio/hugo/releases/download/v0.58.3/hugo_extended_0.58.3_Linux-64bit.deb
  - sudo dpkg -i hugo_extended_0.58.3_Linux-64bit.deb
script:
  - git submodule update --init
  - git submodule update --remote --merge
  - hugo -d ../generated
  
deploy:
  provider: pages
  skip_cleanup: true
  github_token: $GITHUB_TOKEN
  keep_history: true
  local_dir: ../generated
  on:
    branch: master

Have a look at the following GitHub repository to see a fully functional example,

https://github.com/kasramp/outOfUniverse

If you are interested in GitHub pages stuff, check my previous post how to enforce HTTPS on GitHub pages,

https://geekyhacker.com/2018/10/16/how-to-set-https-on-github-pages-with-a-custom-domain-for-free/

Inline/featured images credits