Configure Travis CI for Go

Bernerd Schaefer

The fastest way to get started testing your Go application with Travis CI is to create a .travis.yml with language: go and push to your remote.

The defaults tend to work well for a broad spectrum of projects. But it’s good to understand what those defaults do, and how and why you might want to change them.

For reference, here’s a complete .travis.yml configuration which is perfect for an application deployed to Heroku. Read on for how we arrived at this, and other settings you might want to use.

language: go
sudo: false
before_script:
  - go vet ./...
install:
  # Add Godeps dependencies to GOPATH and PATH
  - export GOPATH="${TRAVIS_BUILD_DIR}/Godeps/_workspace:$GOPATH"
  - export PATH="${TRAVIS_BUILD_DIR}/Godeps/_workspace/bin:$PATH"

Inside a Go build on Travis CI

When Travis CI receives a push for a Go project, first it will prepare the environment:

  • use gimme to install Go if necessary
  • set up a working GOPATH
  • copy the app into the right place in the GOPATH

Then there’s the install phase:

  • set up GOPATH and PATH for godep if it’s detected
  • restore godep dependencies if they’re not vendored
  • run go get -t -v ./... to fetch dependencies

Finally, there’s the script phase:

  • run go test -v ./...

I’ve left out a few branches, and some less important phases, but you can learn everything that happens by reading the source for Travis CI’s Go build script generator.

Customize install and build with gobuild_args

One way to customize the install phase is by setting gobuild_args in .travis.yml. The default value is -v, but we could adjust our build behavior in the following ways:

  • Specify a build tag, like -tags ci.
  • Set a string variable, like -X main.Version $(git rev-parse --short HEAD) to set the Version string variable to the current git revision.
  • Enable the race detector with -race.

Note that the value of gobuild_args is only available to the default install and script steps. If you override one of those, you would need to specify the flags again.

Use custom install scripts

If we want more control than build flags, we’ll need to specify our own install steps.

For example, the default install steps differ from those used by Heroku’s Go buildpack. This can lead to cases where a build passes on Travis CI but fails on Heroku!

The default and recommended way to deploy to Heroku is to use godep to save the project’s dependencies. Because the dependencies are vendored with the repo, Heroku will not fetch remote dependencies when building a slug.

But we saw above that even if Travis CI detects godep, it will run go get -t -v ./..., which means it will install missing dependencies. So if we forget to run godep save, our build will be green, but we’ll be unable to deploy!

Instead we could set a new install step to export new GOPATH and PATH variables which include the godep workspace:

install:
  # Add Godeps dependencies to GOPATH and PATH
  - export GOPATH="${TRAVIS_BUILD_DIR}/Godeps/_workspace:$GOPATH"
  - export PATH="${TRAVIS_BUILD_DIR}/Godeps/_workspace/bin:$PATH"

Now if we forget to update our dependencies, the build will fail as expected.

Customize the script phase

There’s definitely much less to unpack here, since it only runs one command: go test.

In fact, it’s pretty unlikely you need to change the script.

One thing you might want to do, though, is to run some other checks in addition to your tests. The before_script phase is a great place to do this.

For example, it’s common for projects to assert that the code passes go vet without error. You can hook that in with:

before_script:
  - go vet ./...

Now the build will be rejected if go vet returns any errors!

What else?

With the tools above, we can perform conditional compilation on CI, enable Go’s race detector, use vendored dependencies, and check our code before running the tests.

If you need more than that, Building a Go Project and Customizing the Build are good sources of information provided by Travis CI.