Configure CircleCI for Go

Bernerd Schaefer

One of the things I love about CircleCI is how easy it is to get started with any language: just turn it on!

But for working with Go, like with Travis CI, I find that a bit of customization creates an even better CI experience.

For reference, here’s a complete circle.yml configuration which should work well for any project using godep.

machine:
  environment:
    IMPORT_PATH: "github.com/$CIRCLE_PROJECT_USERNAME/$CIRCLE_PROJECT_REPONAME"

dependencies:
  pre:
    - go get github.com/tools/godep

  override:
    - mkdir -p "$GOPATH/src/$IMPORT_PATH"
    - rsync -azC --delete ./ "$GOPATH/src/$IMPORT_PATH/"

test:
  pre:
    - go vet ./...

  override:
    - godep go test ./...

Environment setup

We augment our build environment, by setting up an environment variable (IMPORT_PATH) for use in later steps.

We want IMPORT_PATH to match our project’s canonical import path, for example github.com/foo/bar; rather than hard-code this in the configuration, we can build it from some [standard environment variables] provided in the CircleCI environment.

Dependencies

The default dependency step for a Go project is to run go get -d -u ./....

Since we’re using godep to manage our dependencies, we’ll need to override the default steps.

As a prerequisite, then, of setting up our dependencies, we’ll need godep:

dependencies:
  pre:
    - go get github.com/tools/godep

Then we want to override the installation step; because our dependencies are already vendored, we don’t need to install anything. This keeps our builds speedy and reliable and is also recommended for Heroku deployment.

But we do need to move the current repository into the right location in the GOPATH which we do with the following steps:

    - mkdir -p "$GOPATH/src/$IMPORT_PATH"
    - rsync -azC --delete ./ "$GOPATH/src/$IMPORT_PATH/"

The rsync command will synchronize the current repository into the correct location in the import path. The options passed mean:

  • -a (--archive) is shorthand for a number of other arguments, but most importantly makes the sync recursive and preserves permissions, owners, etc.
  • -z (--compress) compresses data during transfer.
  • -C (--cvs-exclude) excludes various unneeded files.
  • --delete removes files in the import path which have been deleted.

At this point, the repository is fully installed into the GOPATH.

Testing

For running tests, we’re going to make two changes from the default, which by default runs go test ./....

First, we want to make sure that that the code passes go vet without error. We’re able to wire that in with:

test:
  pre:
    - go vet ./...

Then we override the test command, to make it aware of godep:

  override:
    - godep go test ./...

Great! Now when we open a pull request for our project, CircleCI will check our program for correctness and then run the tests using our vendored dependencies.