Automating Deployments to GitHub Pages with Middleman and Travis CI
Recently, I've been using Middleman to build static websites. I've dwelled into static site generators in the past but never really got into it until I started to build an actual website, the Unruly Tech site, which has multiple, often similar but slightly different pages. Copying and pasting became a chore and I didn't want to run a full blown server to compile templates due to the extra management. Hosting on GitHub Pages was enough.
Previously, working with GH Pages was simple enough. Just make changes to static assets and push them to
gh-pages. But now with Middleman being the middleman, I had to make changes, compile the static files locally and then push those to
gh-pages. What a chore.
Of course you could write a script to do it all in one command, but that also meant other contributors had to do the same and have a compatible environment with dependencies. That's way too much setup for a simple setup.
Now comes Travis CI. Travis is an automated build server, free for open source projects. It hooks into a repo and automatically runs scripts in a defined environment when something's pushed. With this, I now had a common environment to deploy from with minimal faff.
I know that GH Pages has Jekyll integration to ease the process, but having tried both Jekyll and Middleman, I prefer Middleman in pretty much every aspect but that's for a different blog post
There's also some other continuous integration services available but they're all somewhat similar and I'm already familiar with Travis.
Our goal is to be able to push changes to a Middleman project, let Travis pick it up, build and test it and deploy it to a GitHub Pages branch.
Setup the project on Travis
First, Make sure you have a Travis account and your project is visible to it by going to Travis CI's website.
Back in the root of your project, make sure you have Travis CLI installed and you're logged in:
gem install travis
Next you'll want to restrict your concurrent builds so only one is built at a time. This will prevent multiple commits being deploy out of order and causing race conditions. In the root of your project, run:
travis settings maximum_number_of_builds --set 1
Setup Middleman Deploy
First, you'll need to use the middleman-deploy extension if you haven't already and activate it with the following in your project's
activate :deploy do |deploy|
Here we're simply setting up
middleman-deploy to commit with the Travis Build Number as the message so we know where the commit came from.
If your GitHub Page is for the top-level (i.e. username.github.io) then you'll want to set
master and commit your Middleman project to a different branch like
Give Travis commit access to your project
In order for Travis to be able to commit to your GitHub Pages branch, you need to setup an SSH key for it.
Create an SSH Key for Travis
In the root of your project, create your SSH keys by running:
ssh-keygen -q -N "" -f deploy_key
You will now have these new files:
deploy_key.enc- The encrypted private key
deploy_key.pub- The public key
Copy and paste the contents of
deploy_key.pub as a new Deploy Key in your GitHub Repo by going to
Settings > Deploy keys in GitHub. Make sure to give it write access.
Once you've save it, you can remove the public key.
rm -f deploy_key.pub
travis encrypt-file command which you ran gives you a decryption command to run later:
openssl aes-256-cbc -K $encrypted... etc.
Keep note of this! We'll be using it later.
Setup the Deploy Script for Travis
Now that we have the SSH key setup, we need to use it when we deploy from Travis.
Create a new script called
travis-deploy.sh at the root of your project and give it execution rights:
Set the contents of the script to be as follows:
This script will decrypt the encrypted private key, give it safe permissions and add it to the script's session. It then sets up the git repo to use SSH and runs the
deploy task in the same session via Rake which we'll get to next.
Make sure you've replaced the line with the comment with the output
travis encrypt-file gave you before.
Setup some Rake tasks
task default: %w[test]
Here we're defining two tasks for Travis:
Test task for the Travis build. If this fails, no deploy happens. Our test case is if the Middleman build succeeds, relying on Middleman to tell us if something's wrong.
Deploy task after the test task succeeds. In our case, we'll run the
travis-deploy.sh script we created earlier.
Now that we have our Rake tasks, it's just a matter of plugging them in.
Pretty self-explanatory. It will run our test task first (
script), then on success it will deploy it (
You'll want to only run the build on the
branches holding your unbuilt Middleman project, whether it's
develop or whatever.
You'll also want to setup some environment variables which
$GH_COMMIT_AUTHOR- The name Travis will use commit to your GitHub Pages branch.
$GH_COMMIT_EMAIL- The email Travis will use commit to your GitHub Pages branch.
Make sure everything's ready
By the end of all this, you should have at least the following files committed in the root of your project:
config.rb- Your Middleman configuration, including
.travis.yml- Your Travis configuration.
travis-deploy.sh- The deploy script for Travis to run.
deploy_key.enc- The encrypted SSH key for Travis to use
Ensure no private details are committed such as unencrypted private keys and tokens.
That should be it. Commit a change to your Middleman project and watch Travis pick it up and deploy it. Watch the build and check the logs to see if anything goes wrong or any secrets are leaked.
Now you have a Middleman project setup to use GitHub Pages with automated deployment and reduced chance to publish a broken build.