Michael Hausenblas

@mhausenblas

Using Go dep as a project maintainer

A Go dependency graph, generated using https://github.com/davecheney/graphpkg.

Managing dependencies in Go might not be the first thing you’d be paying attention to but there comes the time when you likely have to face the task. In this post I’ll share some observations with my first steps using Go dep from a project maintainer perspective.

Go dependency management, or vendoring as we Gophers say, has a rather longish and slightly complicated history. With Go dep the community now seems to slowly (?) but surely converge on a standard. Since I need it anyway in one of the projects I contribute to I thought it makes sense to get some hands-on knowledge under my belt, in a sandboxed environment, before I apply it ‘for real’.

OK, let’s jump right into it: first, we have to install Go dep, which assumes a more recent version of Go installed (I’m using 1.8):

$ go get -u github.com/golang/dep/cmd/dep

Next, we’ll need a program we want to vendor, so here’s a simple example using amongst other things the Kubernetes Go client to create a primitive version of a cluster shell (side note I’m using Minishift to set up and run Kubernetes):

The goal is to vendor the packages imported in line 7 to 10. So, in order to do this, I executed in the directory where the main.go file is located these commands:

$ dep init
$ dep ensure k8s.io/client-go@^2.0.0
$ dep ensure github.com/chzyer/readline@1.4

Note that the last two lines are not strictly required, since dep is smart enough to figure out the versions needed itself. In my case I needed to pin the client-go package to the 2.0.0version to make sure it works against the Kubernetes version I’m using.

After that step, the directory layout looks like in the following:

.
├── Gopkg.lock
├── Gopkg.toml
├── main.go
└── vendor
├── cloud.google.com
├── github.com
├── golang.org
├── google.golang.org
├── gopkg.in
└── k8s.io

Now I’m in the position to go build or go install the program and execute it. On important note and a potential pitfall at this point: unless you actually import a certain package in your source code, a dep ensure won’t actually download the version into the vendor/ sub-directory.

Coming back to the initial question: what do I need to do now as a project maintainer to make this vendored setup available in a repo for others to use? Since I wasn’t able to find best practices around this topic, I jumped on the #vendor channel in the Go Slack community and the friendly people (special kudos to Peter Bourgon) provided guidance:

  1. In your repo you should at least include Gopkg.toml and Gopkg.lock.
  2. You can include the vendor/ subdirectory, and …
  3. … if you include the vendor/ subdirectory:
  • your repo gets bigger :(
  • pull request diffs can get more complicated to deal with :(
  • guarantees reproducible builds as it decouples you from upstream changes :)
  • it doesn’t require the user of your repo to execute an additional dep ensure in order to be able to build the program :)

Summing up: while Go dep is still early days and lacks some documentation around best practices (apparently a FAQ is coming soon) I found it simple to use and feel like I’m ready to use it in anger now.

EDIT: As pointed out by Ahmet Alp Balkan, you can generate visualizations of dependency graphs for packages via godoc.org, for example, https://godoc.org/github.com/mhausenblas/cinf?import-graph&hide=1

More by Michael Hausenblas

Topics of interest

More Related Stories