arun thampi  /  writing  / 

is it still time to build?

Move Fast & Ship Things with Go & Equinox

Originally posted on Medium

One of my favorite features of the Go programming language is that you can distribute executable binaries of your software that users can download and run without installing huge VMs such as Ruby, Python and Node.JS; thus removing huge barriers for adoption.

With Go 1.5, cross-compilation is built in to the compiler which means that you can compile your Go program on OS X for Windows, Linux and of course OS X.

But this is just one piece of the puzzle — what happens when you need to provide over-the-air software updates and nightly builds?

Enter Equinox

Equinox is a service built by Alan Shreve and Kyle Conroy that lets you easily package and distribute your Go apps. (As an aside, you should check out ngrok by the same folks which is another super useful piece of software and a required part of any developer’s toolbox). With Equinox you can cross-compile your Go program for multiple operating systems and architectures, upload your binaries to a well-known URL that your users can download from and provide software updates to all your users with very few lines of code. You can also provide multiple release channels for your program: so a “stable” channel where you only upload point releases and a “beta” channel where a release is made for every commit made to the master branch.

Additionally, Equinox also provides with you .pkg and .msi installers for OS X and Windows respectively, making your apps just that little bit easier to install for users.

Relax & Equinox

When I first released Relax as an open-source project, I thought the installation process was fairly straightforward — download the Go toolchain (which in itself is more straightforward than a lot of other languages), run go get github.com/zerobotlabs/relax and you’re done.

Turns out this was a stumbling block for quite a few users who were not familiar with Go at all and didn’t want to have to install it (especially since one of the stated benefits of using Relax was that you didn’t have to know Go to have to operate it). That’s when I stumbled on Equinox and decided that Relax needed its own pre-built binaries.

The setup process for Equinox is fairly simple and the docs are great.

Since relax already had a Makefile, all I had to do was add a command to perform an Equinox release and appropriately, I called it make release. Release calls ./script/release which then internally calls go build and uploads the binary to Equinox.

Couple of things to note here:

$EQUINOX_SIGNING_KEY_FILE is the path to the private key used to sign your uploads. According to the Equinox docs:

Cryptographically signing your releases with a private key allows untrusted third parties to distribute your updated code while providing end-to-end guarantees that updates come only from you, the developer, and no one else.

$EQUINOX_CREDENTIAL contains your credential token which is used to authenticate and authorize the release tool to upload builds to your Equinox account. Your credential can be generated like so.

Before running make release, I ensure that those two environment variables are set and boom, I have my Equinox releases set up.

You then get a nice downloads page for your project.

Automating Builds with Travis

So manually releasing of your Go apps is great and is a huge step forward but what if you wanted to automate this? Relax already had a pretty comprehensive test suite so I wanted an Equinox release to happen every time a successful Travis build was completed.

(Travis of course is an awesome continuation integration service that is well suited for open-source projects).

With automated builds, it probably is a good idea to use a separate channel since not all users would want to use the bleeding edge of your software. In Relax’s case, I created a beta channel.

The first step is to add a .travis.yml file to your project. This is what Relax’s .travis.yml file looks like:

The script to run the test itself is make test and once a successful build is completed, two commands are executed:

  • make install_equinox: Installs Equinox within the Travis build environment. This make command calls ./script/install_equinox which installs equinox in a cross-platform way (at least cross platform to OS X and Linux):

  • make release: Builds and uploads binaries to Equinox. The release command calls ./script/release which looks like this:

The release script is a slight modification from the earlier one in this post in that there is an environment variable that is used to decide whether to publish to the “stable” channel or the “beta” channel. The variable EQUINOX_BETA is set to true in Travis so that Travis only publishes to the beta channel.

Keeping Secrets Safe in Travis

As described earlier, both $EQUINOX_SIGNING_KEY_FILE and $EQUINOX_CREDENTIAL contains information that must not be publicly shared. Luckily Travis lets us use encrypted files and environment variables to keep these secrets away from prying eyes.

The $EQUINOX_SIGNING_KEY_FILE variable is set to script/equinox.key in Travis but the file itself is encrypted using the Travis CLI tool and is uploaded to Github. The encrypted file can be seen in Github as script/equinox.key.enc and is decrypted by Travis with the command specified in the before_install stanza in .travis.yml:

More information on how you can set up encrypted files in Travis can be found here.

The $EQUINOX_CREDENTIAL again is another encrypted environment variable set in Travis.

Ta Da!

With this setup, every time there is a successful Travis build a new release is made to the Equinox beta channel for Relax and you can download beta releases here.

So what is Relax anyway?

Relax is a Go-based message broker used to make Slack bots as a service. It is used to power my day job Nestor — which is a programmable Slack bot that can be used to automate all the mundane parts of your company and becomes your go-to ChatOps bot.

Coincidentally, the nestor CLI is another Go software tool that uses Equinox but that’s a topic for another post.