Go language is getting increasingly popular when it comes to writing microservices and commmand-line tools. It easily lets you compile a complicated application into a single binary, it can cross-compile from any OS to any other OS the Go compiler supports.

Go compiler has this nice LDFLAGS trick to assign values to the variables in the program at the compile time. So if you have a Version variable in your program you can compile it as:

 $ go build -ldflags "-X main.Version=2.0.0"

This trick is really popular that pretty much everybody distributing Go binaries are using it to embed app version, git commit number etc. to the binaries. Learn more about it here and here.

Problem is, you will easily end up with the following command:

$ go build -ldflags "-X main.BuildDate=`date -u --rfc-3339=seconds | sed -e 's/ /T/'` \
      -X main.GitCommit=`git rev-parse --short HEAD` \
      -X main.GitBranch=`git symbolic-ref -q --short HEAD` \
      -X main.State=`if [ -n "$(git status --porcelain)" ]; then echo 'dirty'; fi` \
      -X main.Version=`<./VERSION`"

and find yourself creating a Makefile for it. Ugh…

Enter govvv

I wrote this go build wrapper that handles all this jazz for you. It’s called govvv. Check it out on GitHub.

You just call govvv build instead of go build without an -ldflags argument and it handles it all for you:

govvv is a very-opinionated take on Go binary versioning problem. It offers you various variables, some of them are:

  • main.BuildDate
  • main.GitCommit+main.GitState (e.g. 85f5a13-dirty)
  • main.GitBranch
  • main.Version if there is a ./VERSION file in your repo

Read the documentation to learn more.

Why govvv?

Well, mostly because repeating the same go build -ldflags ... over and over again sucks. govvv gives you a predefined set of variables that will be provided to your program at compile-time.

govvv honors your existing -ldflags and works well with them.

Also, govvv itself is compiled with govvv. What’s more to say?

Why not govvv?

govvv will be yet another external depdency to your project. It is not a package you import, but it is a tool like go lint that you go get in your build jobs.

I know, it sucks, and you should decide whether it is better than copypasting the same Makefile around. You can download a binary release or just vendor the code into your build environment to build it offline.


Let me know in the comments what you think, how govvv can be better and don’t forget to check out govvv on GitHub: