Using Travis CI with Github Pages
12 Jun 2015
I’ve been using GitHub Pages for my personal website for some time now. Since I’ve never needed dynamic content, GitHub has been a perfect solution. It’s simple to use and free. GitHub will either serve a completely static site or a Jekyll site, which it automatically generates.
Travis CI is a popular testing and deployment service. You can use it to generate and deploy your website to GitHub Pages instead of using GitHub’s automatic Jekyll generator.
Why use Travis?
Most of the time, using Travis is not necessary. Vanilla Jekyll works quite well and has most of the features that you’d want out of a static site generator. However, GitHub Pages only allows the use of a limited number of Jekyll plugins and runs Jekyll builds in safe mode. If you want to use Jekyll plugins other than the ones available on GitHub Pages, use your own custom plugins, or generate parts of your site by non-Jekyll means, then you should consider using Travis to automatically do the job.
My original impetus for switching to Travis was that I wanted the generation process for my website to generate my resume automatically, which gets built from a YAML file using LaTeX and a Python script. However, now that I’m free from GitHub Pages’ limitations, I’m considering switching from Jekyll to Pelican because I like Jinja templates better than Liquid.
Making the Switch
The first thing you need to do is create a new branch, as the generated site
will eventually get put into the GitHub Pages branch (either gh-pages
or
master
depending on the type of repo). Call the new branch source
(or maybe
pages-source
if you prefer).
$ git checkout -b source
Next, you’ll want to enable Travis for the repo. You can do so here.
You should then create a file called .travis.yml
in the root of your
repository in the new source
branch.
Configuring Travis
Your .travis.yml
file tells Travis what to do. You’ll use it to install your
site’s dependencies, build your site, and then push the generated site back to
GitHub.
Authenticating Travis with GitHub
In order for Travis to be able to push your site to GitHub, it will need to authenticate with GitHub. Travis has built in encryption tools which allow you to encrypt some secret which only the Travis build agent for your repo will be able to decrypt. Then, you can upload the encrypted secret to a public repo without fear that you’re giving everyone access they shouldn’t have.
Some people have suggested using an encrypted GitHub Personal Access Token. This is a decent solution, but the problem is that the permissions settings for access tokens are too coarse. They only allow you to determine whether or not the token has access to all your public repos and all your private repos. Instead, a better solution is using a deploy key on the repository. If that key somehow gets compromised, the most anyone will have access to is a single repo.
First, you’ll have to generate the key.
$ ssh-keygen
Name the file .travisdeploykey
and do not put a password on the key. Upload
the public key (in .travisdeploykey.pub
) to your repo (Settings > Deploy
keys). Now, encrypt the private key. You’ll need the Travis client installed to
do that.
$ gem install travis
Then, encrypt the file.
$ travis encrypt-file .travisdeploykey
This will output the .travisdeploykey.enc
file and print out a command to be
added to the build script. Save that print out and add .travisdeploykey.enc
to
your repo. Do NOT add the unencrypted private key to the repo. If you already
did, remove the public key from the repo, and start over with a new key. If not,
you can go ahead and delete the private key as well as the public key.
The Build Script
Copy the following to .travis.yml
install:
- gem install jekyll
before_script:
# Replace with the line that travis encrypt-file printed out
- openssl aes-256-cbc ...
- chmod go-rwx .travisdeploykey
- eval `ssh-agent -s`
- ssh-add .travisdeploykey
- git config user.name "Travis-CI"
- git config user.email "noreply@travis-ci.org"
- COMMIT_MESSAGE="Publishing site on `date "+%Y-%m-%d %H:%M:%S"` from
`git log -n 1 --format='commit %h - %s'`"
script:
- set -e
- make # Or jekyll build or whatever command you use to generate your site
- git checkout -b master # Replace master with gh-pages if applicable
- git add -f _site/ # Replace _site/ with the build's output directory
- 'git commit -m "${COMMIT_MESSAGE}"'
- git filter-branch -f --subdirectory-filter _site/ # Again, replace _site/
# Obviously, replace with your repo's SSH URL and the appropriate branch
- git push -f YOUR_REPOS_SSH_URL master:master
branches:
only:
- source
If you have any other dependencies to install (e.g. Python packages), you should
add the necessary commands under install
. Otherwise, once you make the
appropriate adjustments to .travis.yml
, you should be good to go!
Final Notes
Caveat user: debugging your install script and adding all of the dependencies can be a somewhat frustrating process, especially if the dependencies take a while to install. You might find yourself making a change, pushing that change to the repo to kick off a Travis build, and then waiting 5 minutes only to find out that something else went wrong.
Now that you’re building your site with Travis, you don’t need GitHub to build
it with it’s built-in Jekyll support. By default, GitHub will only invoke Jekyll
if there is a _config.yml
file present, but if you want, you can go one step
further and add a .nojekyll
file to the site. If you’re still using Jekyll,
then you’ll need to add the following to _config.yml
.
include:
- .nojekyll