In my previous post on Travis, I explained how it can be used to easily test OCaml packages on GitHub without having to host any infrastructure yourself.
The next step I wanted to investigate was how to use Travis to trigger service deployments after a successful build. One nice feature that Travis has is support for encrypted environment variables. The basic workflow is that you encrypt key/value pairs using a public key that they publish per GitHub repository. Once registered, this is made available as a decrypted environment variable within the Travis worker. You can use this to transmit API keys or other authentication data that you need to commit to the
travis.yml file, but obviously can’t leave on a public repository for the world to see.
The small hitch with this whole scheme is that there’s a very small limit of about 90 bytes or so for the size of each individual environment variable that’s exported, and so you can’t just stash an SSH private key in there. Instead, it needs to be Base64 encoded, split it up into multiple environment variables of the right size, and then reassembled within the Travis VM. Rather than deal with importable shell scripts between MacOS X and Linux, I created a small
travis-senv command-line binary to make this easier.
To use it, just
opam install travis-senv and follow the instructions on the README at the homepage. Here’s the fragment of shell script that pushes the build output to another GitHub repository:
if [ "$DEPLOY" = "1" ]; then # get the secure key out for deployment opam install travis-senv mkdir -p ~/.ssh SSH_DEPLOY_KEY=~/.ssh/id_dsa travis-senv decrypt > $SSH_DEPLOY_KEY chmod 600 $SSH_DEPLOY_KEY echo "Host mirdeploy github.com" >> ~/.ssh/config echo " Hostname github.com" >> ~/.ssh/config echo " StrictHostKeyChecking no" >> ~/.ssh/config echo " CheckHostIP no" >> ~/.ssh/config echo " UserKnownHostsFile=/dev/null" >> ~/.ssh/config git config --global user.email "firstname.lastname@example.org" git config --global user.name "Travis the Build Bot" git clone git@mirdeploy:mirage/mirage-www-deployment cd mirage-www-deployment mkdir -p xen/$TRAVIS_COMMIT cp ../src/mir-www.xen ../src/mir-www.map ../src/www.conf xen/$TRAVIS_COMMIT bzip2 -9 xen/$TRAVIS_COMMIT/mir-www.xen git pull --rebase git add xen/$TRAVIS_COMMIT git commit -m "adding $TRAVIS_COMMIT" git push fi
I’ve been using this to automate the construction of the Mirage Xen unikernel homepage. Every time there’s a push to the mirage-www, the Travis scripts now retrieve an SSH deployment key using
travis-senv, and push the results of the build to the mirage-www-deployment repository that stores the build output. This repository is polled by the hosting machines we have to look for new kernels and rotate the website (but more on this later – I’m just integrating the EC2 and Rackspace scripts to remove this step entirely next!)