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
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
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 "email@example.com" 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
retrieve an SSH deployment key using
travis-senv, and push the results of the
build to the
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!)