Deploying Jekyll GitHub Pages with Travis CI
By Andrew Kulpa on May 6, 2019
Modified on October 28, 2021
Overview
GitHub Pages are a free and great way to setup and maintain a website for a personal, organizational, or project website. In addition to plain HTML content Github Pages also supports a popular ruby-based static site generator called Jekyll. There are many advantages to using Jekyll including:
- Using Markdown instead of HTML
- Using Jekyll themes instead of copying CSS
- Incorporating templating for website parts like the head, headers, and footers.
- Simplified local development using commands such as
jekyll build
andjekyll serve
GitHub Pages integrates seamlessly by simplifying the build process. Unfortunately, this simplification is not without its limitations. For instance, GitHub Pages builds with the --safe
flag, which according to Jekyll documentation disables custom plugins and ignores symbolic links. Thankfully, by using Travis CI, we can build the pages ourselves and publish to GitHub Pages.
Develop Jekyll Site
I am assuming we have already setup a Jekyll site locally, pushed to GitHub repository, and have determined a location for our GitHub Page. Instead, this tutorial will focus upon the deployment of a Jekyll site. Deploying Jekyll sites is easy once we have the basic pipeline setup. To get to that point, there are two steps:
- Setup the source repository with Travis CI
- Setup deployment to destination repository & branch
Setup Source Repository with Travis CI
The first thing that we need to do is sign-up and connect Travis CI to your GitHub account. To do this, go to travis-ci.org and sign-up with GitHub. Accept the authorization and activate it following a redirect to GitHub. Then, go to your repositories at https://travis-ci.org/account/repositories. Lastly find the source repository for your Jekyll site and flick the repository switch on.
Setup Deployment to Destination Repo & Branch
The second step to setting up an automatic deployment pipeline for your Jekyll site is much more involved. We can break this down into a few easily chewed parts.
Getting Us All on the Same Page
First, we need to make sure our repository is configured correctly. If there is anything stored in the vendor
directory, make sure to exclude it from the build process by adding the following line to your Jekyll _config.yml
file:
exclude: [vendor]
Next, we need to determine where exactly the Jekyll site should be deployed to. With the pages
provider for the deployment process of the Travic CI configuration, we can define this quite easily. If this is a GitHub Page for a project, the destination by default would be the gh-pages
branch. For user and organization GitHub Pages, the resulting site would need to be located at the master
. Its worth noting that normal project pages also support a third option: a docs
folder.
Create deployment .travis.yml
Now that we’ve determined where the site is to be deployed to, we can finally make the Travis CI .travis.yml
configuration file. First, create a blank .travis.yml
file. Then, paste the following configuration:
language: ruby
rvm:
- 2.5.1
cache: bundler # caching bundler gem packages will speed up build
before_script:
script:
- set -e
- bundle exec jekyll build
- bundle exec htmlproofer --http-status-ignore "999" ./_site # test site, but ignore any 999 errors (e.g. LinkedIn checks)
branches: # branch whitelist, only for GitHub Pages
only:
- master
env:
global:
- NOKOGIRI_USE_SYSTEM_LIBRARIES=true # faster html-proofer install
addons:
apt:
packages:
- libcurl4-openssl-dev
sudo: false
notifications: # Optionally disable build email notifications
email: false
deploy:
provider: pages
local-dir: ./_site
skip_cleanup: true
name: Deployment Bot
github_token: $GITHUB_TOKEN # Set in the settings page of your repository, as a secure variable
repo: $REPOSITORY # Set in the settings page of your repository, as a secure variable
keep_history: true
target-branch: master
on:
branch: master
Deployment Breakdown
This configuration does quite a bit, so I’ll break it down.
First, we tell Travis CI to use Ruby and Bundler during the build process.
language: ruby
rvm:
- 2.5.1
cache: bundler # caching bundler gem packages will speed up build
Then, we want to halt the build upon error, in case later script parts fail to process as expected. After this, we can build the site and use htmlproofer
to test the rendered HTMLfiles to sure the quality of the site.
before_script:
script:
- set -e
- bundle exec jekyll build
- bundle exec htmlproofer --http-status-ignore "999" ./_site # test site, but ignore any 999 errors (e.g. LinkedIn checks)
We also only want to automatically generate site content from the master
branch and speed up the html-proofer
installation.
branches: # branch whitelist, only for GitHub Pages
only:
- master
env:
global:
- NOKOGIRI_USE_SYSTEM_LIBRARIES=true # faster html-proofer install
We then make sure that the development files for the OpenSSL flavor of libcurl are available. Optionally, we also disable the email notifications for the build process.
addons:
apt:
packages:
- libcurl4-openssl-dev
notifications: # Optionally disable build email notifications
email: false
In the last part of the .travis.yml
we use the Github Pages Deployment Provider. The site by default is built to the ./_site
local directory. A personal access token is needed at this point too. Once you have created your personal access token and determined the target repository, this information can easily be defined using secure variables in Travis CI. The last few lines determine the source and target branches. As the example repository is a master to master deployment from two different repositories, the configuration is as demonstrated, but your configuration may differ.
deploy:
provider: pages
local-dir: ./_site
skip_cleanup: true
name: Deployment Bot
github_token: $GITHUB_TOKEN # Set in the settings page of your repository, as a secure variable
repo: $REPOSITORY # Set in the settings page of your repository, as a secure variable
keep_history: true
target-branch: master
on:
branch: master
Update Gemfile
Finally, after we have completed the Travis CI configuration we can add the gem dependency for html-proofer
to the Gemfile
.
gem "html-proofer"
Wrapping Up
In this tutorial we walked through setting up the source repository for your Jekyll site and deploying it to a target repository. While GitHub Pages supports basic deployments, the --safe
building of Jekyll sites can be rather limiting. Through switching to a Travis CI based deployment process, you may further improve your site without limitation through the newfound freedom of using Jekyll Plugins.
Update (Oct. 2021)
Github Actions has improved substantially since the early beta days. Given I feel it has better integration with GitHub, I have switched away from this process and am now exclusively using GitHub Pages and branch-based deployments.