For Resultra, I recently migrated the project from Go’s dep dependency management to Go modules. The primary motivations for transitioning to modules were to allow the project to be built outside the $GOPATH and work with GitHub’s fork and pull request model.
The project is currently using Go version 1.12. In version 1.12, module support is only triggered when a repository is not below the $GOPATH directory. To override this, the project’s Makefiles currently set the
GO111MODULE environment variable to
on. This transition went very smoothly in my local development environment.
Fixing Travis CI Builds to Work with Modules
When changes to incorporate Go modules were first pushed to GitHub, the Travis CI builds began to fail. By default, Travis CI is configured with the environment variable
GO111MODULE environment variable set to
auto, which disables modules when the build occurs inside $GOPATH.
My first attempt was to change GO111MODULE to
on in the environment section of the
.travis.yml config file. This potentially could have worked, except there was a conflict with a
go get from inside the project’s build script; an error message like the following was generated:
The command "eval go get -v -t ./... " failed. Retrying, 3 of 3. go get: -t flag is a no-op when using modules
The project does use
go get to install the yacc tools for an equation compiler. However, the command is not invoked with the
-t option; perhaps Travis CI’s Go environment is overriding how
go get is invoked? At any rate, without this being part of the project’s build, I suspect Travis CI likely would have worked right away. Before spending too much time investigating this specific build failure, I decided to try other potential solutions.
Further researching possible solutions to this, I found a couple of good blog posts on the topic:
- “Using Go modules with Travis CI” by Dave Cheney
- “Using Go modules with vendor support on Travis CI by Fatih Arslan
These posts discuss a number of solutions, but the 2nd solution I tried and succeeded with was a variation of Dave Cheney’s “A clean slate” option; in particular:
- In the
.travis.ymlconfig file, remove the configuration for default Golang language support; i.e., remove
language: minimal. The minimal option tells Travis to start with an image that is not tailored to any specific programming language.
- During the
installphase, configure Travis to directly install Go.
- Before launching the build, configure the
$PATHenvironment variable to reference the correct version of Go.
It only takes a few lines in the Travis config file to directly install and configure Go tools. The resulting Travis config file allowed the project to build successfully while using Go’s module support.
Minimal Language Configuration for Travis CI Builds
The major change to fix the Travis CI builds was to abandon Travis CI’s
language:go configuration option in favor of starting with a minimal image without Go support.
When I initially integrating the project with Travis CI, I wondered how much value Travis CI’s Go language option really added. While there is likely a performance gain for Travis to cache the environment needed for their default Go environment, it is also very straightforward to directly install the Go tools.
Moreover, starting with a minimal configuration, the environment can be setup using a command sequence which is very similar to Resultra’s development environment. In terms of maximizing parity between the development and production builds, a case can be made for the Travis CI configuration to:
- start with a minimal image; then
- install and configure Go tools directly, using the same commands used to setup the development environment.
In Go version 1.13, module support will purportedly be enabled by default. When Go 1.13 is release, it may be worth re-testing the
language:go configuration option. In my case, the initial build failure was potentially due to a conflict with the project’s own build environment; nonetheless, directly installing the Go tools fixed the build.
In terms of maximizing parity with the development environment and considering how straightforward it is to install the Go tools directly, a viable alternative is to continue using the
language:minimal configuration option; this is the most important lesson learned from this experience.