Uptonian Thoughts

Installing the Latest ZSH on Travis CI

· ·

I recently thought it might be a good idea to start using Travis CI to run builds of my personal repositories on a regular basis. A lot of my repositories are pet projects, but that doesn’t mean that I don’t depend on them on a daily basis.

That couldn’t be more true of my dotfiles. My zshrc and my vimrc get exercised tens if not hundreds of times per day. Sometimes I’ll make a change to test out something new, verify that it doesn’t blow up, commit it, and move on. That’s probably not the best way to do things, but I figure that I’ll never start using the new hotness if I don’t jump in and start using it right away. Usually this works out well and I’ve simply added a new tool to my repertoire, but it can potentially break my environment in subtle ways. Continuous integration can help with that: if I commit a breaking change, I can get an email when the “build” breaks. I’ll immediately know which commit broke something without having to resort to git blame or something similar.

Travis CI offers a fantastic free service, but I haven’t really had a chance to use it yet.1 I figured that setting up CI for my small dotfiles repository would be a great way to learn a tool that many open source projects use today.

There was one huge hurdle: I use zsh, and most of my dotfile setup scripts are written in zsh, but the Travis environment only comes with the bash shell installed.2

Some existing open source projects use Travis with zsh, but they all use the legacy environment that still allows sudo, not the newer container-based environment. The apt addon can help install packages in containers, but the latest version of zsh on Ubuntu 12.04 is 4.3.17. zsh 5 is a requirement for most modern usages, so that’s a non-starter. I thought that someone would have come across this already and solved it, and maybe they have, but I couldn’t easily find a solution.

We need to build and install zsh, and we need to do it without sudo. build-essential is already available on the Travis CI virtual machines, and we could use the aforementioned apt addon if it wasn’t.

After much trial and error, I finally got a Travis config that makes sure a recent version of zsh is set up before running the build. I chose to do this in the before_install step because that seems to be where additional dependencies should be installed, but I suppose it could be done anywhere in the build lifecycle before script runs the actual tests.

The full Travis config follows, but the before_install step is what really matters:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
language: sh
addons:
  apt:
    packages:
    - build-essential
before_install:
- export LOCAL="$(mktemp --directory --tmpdir=${TMPDIR:/tmp} local.bin.XXXXXX)"
- curl -L http://downloads.sourceforge.net/zsh/zsh-5.0.7.tar.gz | tar zx
- cd zsh-5.0.7
- ./configure --prefix=$LOCAL
- make
- make install
- cd -
- export PATH="$LOCAL/bin:$PATH"
script: make test

First, we make a temporary directory to install zsh to. Remember, no sudo means no access to /usr/bin/local, so we need to choose a safe location to install.

Next, we download the latest version of zsh. If you want to use a different mirror or download an archive with a different compression, you just need to change this line to handle that and the rest should work. If you change the version, make sure to update the following line that changes directories to the archive you just decompressed.

Then we build zsh: configure with the prefix set to the directory we created earlier, then make it and make install it to the prefixed directory.

Finally, we cd back to the directory we were in – these build lifecycle steps are run in series so we need to hop back to the directory we were in before building zsh – and, more importantly, we add the temporary directory to the beginning of our path so that zsh can be found.

These before_install steps could probably be extracted into a script, but I wanted to go with the simplest Travis config with the least overhead to get up and running with zsh. Now, when the test script runs, zsh is available and we can check our scripts for errors!

I look forward to exploring more of what is possible with Travis. On my horizon: using vint to lint my vimrc and writing tests for the majority of my private repositories that don’t currently have any verification.

  1. We use Jenkins at work, which is a blessing and a curse. Mostly the latter, but the sheer number of plugins available coupled with the fact that I work with some awesome people who know Jenkins better than I ever will makes it ok.

  2. Really, it comes with whatever shell is default for the operating system that Travis VMs use. Since they run Ubuntu 12.04, that means that bash is available but zsh is not. It seems like Travis didn’t set out to explicitly support shell-based projects, but because their machines are (mostly) Linux, that comes for “free” if you know how to configure things.