
Happy Gopher on CircleCI
CircleCI is one of the best CI providers nowadays. It has many features that many users love, what features? please go read all the stuffs . For freebies hunter, in addition of 3 free containers for public projects, it is also have one container free for private projects, as long as you… ahh, Okay, I will not talking about marketing stuff here, just go ahead to https://circleci.com and happy link surfing!. Oh, I will be waiting for you, don’t worry.
Okay, you’re already came back? Great, now let’s continue!
L et’s say we have a brand new Go library, a very small library actually, the library usually will looks like:
$ tree.
├── README.md
├── hello.go
└── hello_test.go 0 directories, 3 files
With this typical library structure, CircleCI is automatically detect the project type and run proper tests when you add your library repository as CircleCI project. Yes, no configuration needed. It just works!
## CircleCI build output $ go get -t -d -v ./...$ go build -v
$ go test -v -race ./... === RUN TestSay
--- PASS: TestSay (0.00s)
PASS
ok github.com/subosito/hello-circle 1.008s Dependencies? Vendor!
To improve the ability of your library, you decided to add some external libraries to it and use vendor tool, like govendor to manage the dependencies. Now, library directories will looks like:
$ tree -L 4.
├── README.md
├── hello.go
├── hello_test.go
└── vendor
├── bitbucket.org
│ └── pkg
│ └── inflect
├── github.com
│ ├── davecgh
│ │ └── go-spew
│ ├── pmezard
│ │ └── go-difflib
│ └── stretchr
│ └── testify
└── vendor.json 11 directories, 4 files
Does CircleCI automatically support dependencies on vendor directory? Oops, unfortunately not.
$ go get -t -d -v ./...$ go build -v
bitbucket.org/pkg/inflect
github.com/subosito/hello-circle
Ohh, that’s because CircleCI by default using old Go version isn’t? yeah, correct!. When you add project to CircleCI, it’s automatically use:
CIRCLE_BUILD_IMAGE=ubuntu-12.04According to the CircleCI documentation about Ubuntu 12.04 environments . It’s still using Go 1.5.3. So vendor directory is not supported by default. There are two ways for handle this issue:
Keep using Ubuntu 12.04 and set `GO15VENDOREXPERIMENT=1 ` environment variable Use newer image Ubuntu 14.04 which has Go 1.6.2 installedLet’s play with each option:)
Ubuntu 12.04 with GO15VENDOREXPERIMENT=1To add `GO15VENDOREXPERIMENT=1` environment variable you can create custom CircleCI configuration, called `circle.yml`:
$ cat circle.ymlmachine:
environment:
GO15VENDOREXPERIMENT: 1
Now, CircleCI is using dependencies on vendor directory instead of remote ones:
$ go get -t -d -v ./...$ go build -v
github.com/subosito/hello-circle/vendor/bitbucket.org/pkg/inflect
github.com/subosito/hello-circle
But, but, CircleCI looks like still fetching perform `go get` to fetch dependencies although it’s already on vendor directory. Yeah, let’s try to fix that.
$ cat circle.ymlmachine:
environment:
GO15VENDOREXPERIMENT: 1
dependencies:
override:
- go get -u github.com/kardianos/govendor
- go build -v
and.. build output from CircleCI is, uh oh, FAILED:
$ go test -v -race ./... # _/home/ubuntu/hello-circlehello_test.go:7:2: cannot find package "github.com/subosito/hello-circle" in any of:
/usr/local/go/src/github.com/subosito/hello-circle (from $GOROOT)
/home/ubuntu/.go_workspace/src/github.com/subosito/hello-circle (from $GOPATH)
/usr/local/go_workspace/src/github.com/subosito/hello-circle
FAIL _/home/ubuntu/hello-circle [setup failed]
CircleCI is not able to setup Go environment, which basically set GOPATH, move files to proper location, etc. So, it’s broken. Broken dude.
Ok, let’s change configuration a bit. Seems override dependencies makes CircleCI failed to setting up Go environment properly. I think it’s a bug that CircleCI needs to dig through.
Here’s the updated circle.yml:
$ cat circle.ymlmachine:
environment:
GO15VENDOREXPERIMENT: 1
dependencies:
pre:
- go get -u github.com/kardianos/govendor
Well, because our attempt to remove default go get failed, we can skip that for later. Let’s take a look at another area which can be improved, which is test runner.
$ go test -v -race ./...=== RUN TestSay
--- PASS: TestSay (0.00s)
PASS
ok github.com/subosito/hello-circle 1.012s
? github.com/subosito/hello-circle/vendor/bitbucket.org/pkg/inflect [no test files]
? github.com/subosito/hello-circle/vendor/github.com/davecgh/go-spew/spew [no test files]
? github.com/subosito/hello-circle/vendor/github.com/pmezard/go-difflib/difflib [no test files]
? github.com/subosito/hello-circle/vendor/github.com/stretchr/testify/assert [no test files]
By default, CircleCI run the tests recursively. So, any package that lives on vendor directory also tried to be tested. To change the behaviour, we can tweak circle.yml again:
$ cat circle.ymlmachine:
environment:
GO15VENDOREXPERIMENT: 1
dependencies:
pre:
- go get -u github.com/kardianos/govendor
test:
override:
- govendor test -v +local
Now, CircleCI build output is great again! eh.
$ govendor test -v +local === RUN TestSay--- PASS: TestSay (0.00s)
PASS
ok github.com/subosito/hello-circle 0.005s
We are done for Ubuntu 12.04, let’s handle Ubuntu 14.04.
Ubuntu 14.04 with Go 1.6There is only few steps involved for this. First, change default OS for build in Project settings > Build environments.

Second, remove unused environment variable GO15VENDOREXPERIMENT from circle.yml:
$ cat circle.ymldependencies:
pre:
- go get -u github.com/kardianos/govendor
test:
override:
- govendor test -v +local
That’s it.
# CIRCLE_BUILD_IMAGE=ubuntu-14.04 $ govendor test -v +local=== RUN TestSay
--- PASS: TestSay (0.00s)
PASS
ok github.com/subosito/hello-circle 0.004s Coverage Reports? Easy!
Enabling coverage reports is easy, it’s just matter of passing additional flag `-coverprofile=coverage.out`, like: