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 Go 1.11. httpstat has an existing CI story–I’m using Travis CI for my examples, if you use something else, please blog about your experience–and I wanted to test against the current and development versions of Go.
The straddling of two worlds is best accomplished via the
GO111MODULE environment variable.
GO111MODULE dictates when the Go module behaviour will be preferred over the Go 1.5-1.10’s
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
Fortunately there is a simple workaround for this, add
env GO111MODULE=on before any
test invocations in your
.travis.yml to force Go module behaviour and ignore any
vendor/ directories that may be present inside your repo.
- 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 project
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.
- eval "$(curl -sL https://raw.githubusercontent.com/travis-ci/gimme/master/gimme | GIMME_GO_VERSION=master bash)"
- go build
- go test
You can see the output from this branch here.
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
env:key as documented here, but this caused a strange error where
gimmewould forget what
mastermeant and fell back to Go 1.7.4.
- This is the closest I could find to a generic