Moving A Github Tag With Travis

Sam Pikesley

In the ODI tech team, we are deeply devoted followers of the dual canons of Continuous Integration and Continuous Deployment. This means that once our code is pushed into Github, we run the tests on our Jenkins server, and if the tests pass on the master branch, it moves a Github tag called CURRENT to that point. Our Chef server then picks it up and deploys the code to production. No humans are involved in the process. It’s robots all the way down.

We’ve recently been experimenting with using Travis-CI to run our tests, and wanted to know if we could do the same thing using Travis.

Turns out we can, but it involves a certain amount of hoop-jumping. Presuming you’ve got your project currently building in Travis, the steps are:

Encrypt your Github login (from inside your local repo):

travis login
travis encrypt GITHUB_USER=odi-robot
travis encrypt GITHUB_PASSWORD=thisisareallyreallylonggithubpassword

This will give you a couple of strings, which you need to paste into your .travis.yml to make it look like this:

---
after_success:
  - "[ \"$TRAVIS_BRANCH\" == \"master\" ] && curl -v -X DELETE -u $GITHUB_USER:$GITHUB_PASSWORD \"https://api.github.com/repos/$TRAVIS_REPO_SLUG/git/refs/tags/CURRENT\""
  - "[ \"$TRAVIS_BRANCH\" == \"master\" ] && curl -v -X POST -d '{\"ref\":\"refs/tags/CURRENT\",\"sha\":\"'$TRAVIS_COMMIT'\"}' --header \"Content-Type:application/json\" -u $GITHUB_USER:$GITHUB_PASSWORD \"https://api.github.com/repos/$TRAVIS_REPO_SLUG/git/refs\""
env:
  global:
    -
      secure: longuglyencryptedstringnumber1=
    -
      secure: longuglyencryptedstringnumber2=
language: ruby
rvm:
  - "2.0.0"

It’s probably best if you avert your gaze from those after_success lines, lest you be turned to stone. The real trick is interpolating that $TRAVIS_COMMIT into the single-quoted JSON payload. If there’s a less-hideous way of doing this, I’d really like to hear about it.

In the course of debugging this (which took way longer than it should have), I was pointed towards the brilliant requestb.in HTTP-request-inspection tool (thanks James), without which I may have simply thrown in the towel. Also, YAMLlint is pretty nice.

Hope this spares somebody else the pain I’ve been through this morning.