Using Go modules with Travis CI
In my previous post I converted httpstat to use Go 1.11’s upcoming module support. In this post I continue to explore integrating Go modules into a continuous integration workflow via Travis CI.
Life in mixed mode
The first scenario is probably the most likely for existing Go projects, a library or application targeting Go 1.10 and
GO111MODULE
The straddling of two worlds is best accomplished via the GO111MODULE
environment variable. GO111MODULE
vendor/
directory behaviour. In Go 1.11 the Go module behaviour is disabled by default for packages within $GOPATH
(this also includes the default $GOPATH
introduced in Go1.8). Thus, without additional configuration, Go1.11 inside Travis CI will behave like Go 1.10.In my previous post I chose the working directory ~/devel/httpstat
to ensure I was not working within a $GOPATH
workspace. However CI vendors have worked hard to make sure that their CI bots always check out of the branch under test inside a working $GOPATH
.
Fortunately there is a simple workaround for this, add env GO111MODULE=on
before any go build
or test
invocations in your .travis.yml
to force Go module behaviour and ignore any vendor/
directories that may be present inside your repo.1
language: go go: - 1.10.x - master os: - linux - osx dist: trusty sudo: false install: true script: - env GO111MODULE=on go build - env GO111MODULE=on go test
Creating a go.mod on the fly
You’ll note that I didn’t check in the go.mod
module manifest I created in my previous post. This was initially an accident on my part, but one that turned out to be beneficial. By not checking in the go.mod
file, the source of truth for dependencies remained httpstat’s Gopkg.toml
file. When the call to env GO111MODULE=on go build
executes on the Travis CI builder, the go
tool converts my Gopkg.toml
on the fly, then uses it to fetch dependencies before building.
$ env GO111MODULE=on go build go: creating new go.mod: module github.com/davecheney/httpstat go: copying requirements from Gopkg.lock go: finding github.com/fatih/color v1.5.0 go: finding golang.org/x/sys v0.0.0-20170922123423-429f518978ab go: finding golang.org/x/net v0.0.0-20170922011244-0744d001aa84 go: finding golang.org/x/text v0.0.0-20170915090833-1cbadb444a80 go: finding github.com/mattn/go-colorable v0.0.9 go: finding github.com/mattn/go-isatty v0.0.3 go: downloading github.com/fatih/color v1.5.0 go: downloading github.com/mattn/go-colorable v0.0.9 go: downloading github.com/mattn/go-isatty v0.0.3 go: downloading golang.org/x/net v0.0.0-20170922011244-0744d001aa84 go: downloading golang.org/x/text v0.0.0-20170915090833-1cbadb444a80
If you’re not using a dependency management tool that go mod
knows how to convert from this advice may not work for you and you may have to maintain a go.mod
manifest in parallel with you previous dependency management solution.
A clean slate
The second option I investigated, but ultimately did not pursue, was to treat the Travis CI builder, like my fresh Ubuntu 18.04 install, as a blank canvas. Rather than working around Travis CI’s attempts to check the branch out inside a working $GOPATH
I experimented with treating the build as a C project2 then invoking gimme
directly. This also required me to check in my go.mod
file as without Travis’ language: go
support, the checkout was not moved into a $GOPATH
folder. The latter seems like a reasonable approach if your project doesn’t intend to be compatible with Go 1.10 or earlier.
language: c os: - linux - osx dist: trusty sudo: false install: - eval "$(curl -sL https://raw.githubusercontent.com/travis-ci/gimme/master/gimme | GIMME_GO_VERSION=master bash)" script: - go build - go test
Sadly when run in this mode gimme
is unable to take advantage of the caching provided by the language: go
environment and must build Go 1.11 from source, adding three to four minutes delay to the install phase of the build. Once Go 1.11 is released and gimme
can source a binary distribution this will hopefully address the setup latency.
Ultimately this option may end up being redundant if GO111MODULE=on
becomes the default behaviour in Go 1.12 and the location Travis places the checkout becomes immaterial.
- I tried setting
GO111MODULE=on
using theenv:
key as documented here, but this caused a strange error wheregimme
would forget whatmaster
meant and fell back to Go 1.7.4. - This is the closest I could find to a generic
bash
builder