A common use-case for build-time variables is to inject the Git version information in the binary. There are several approaches on how to do this, but this one is the one I found the most useful one.
Let's start with creating a sample project using Go modules:
$ mkdir example-go-build-time-variables $ cd example-go-build-time-variables $ go mod init github.com/pieterclaerhout/example-go-build-time-variables go: creating new go.mod: module github.com/pieterclaerhout/example-go-build-time-variables
As we want to play with the Git revision and branch info, let's also initialize it as a Git repository:
$ echo "# example-go-build-time-variables" >> README.md $ git init Initialized empty Git repository in ~/example-go-build-time-variables/.git/ $ git add . $ git commit -m "first commit" [master (root-commit) 47c55c2] first commit 2 files changed, 4 insertions(+) create mode 100644 README.md create mode 100644 go.mod
Let's start with creating the most simple app we can think of by adding a main.go
file with the following contents:
main.go
package main import ( "fmt" ) func main() { fmt.Println("Hello stranger!") }
Let's also create a package called version
in which the version information is going to be stored:
version/version.go
package version // GitRevision will be injected with the current git commit hash var GitRevision string // GitBranch will be injected with the current git branch name var GitBranch string
I prefer to create a non-related package just containing this information. This makes it easy to access the version information from anywhere.
We can then update the main.go
file to use this information:
main.go
package main import ( "fmt" "github.com/pieterclaerhout/example-go-build-time-variables/version" ) func main() { fmt.Println("Git Revision:", version.GitRevision) fmt.Println("Git Branch:", version.GitBranch) }
If we build and run it, you'll get the following output:
$ go build -o example-go-build-time-variables . $ ./example-go-build-time-variables Git Revision: Git Branch:
That's the expected behaviour as we didn't inject the version information yet.
To inject the information, you need to specify the -ldflags
option during the go build
process. You can test it manually by changing the build command to:
$ go build -o example-go-build-time-variables -ldflags "-X github.com/pieterclaerhout/example-go-build-time-variables/version.GitRevision=revision -X github.com/pieterclaerhout/example-go-build-time-variables/version.GitBranch=branch" . $ ./example-go-build-time-variables Git Revision: revision Git Branch: branch
Now, the only thing we need to do is to get the proper Git revision and branch name. The revision can be found with the following command:
$ git rev-parse --short HEAD 47c55c2
The branch name is obtained by the following command:
$ git rev-parse --abbrev-ref HEAD | tr -d '\040\011\012\015\n' master
To make it easier, I usually combine everything in a simple Makefile
which looks as follows:
APPNAME := example-go-build-time-variables PACKAGE := github.com/pieterclaerhout/example-go-build-time-variables/version REVISION := $(shell git rev-parse --short HEAD) BRANCH := $(shell git rev-parse --abbrev-ref HEAD | tr -d '\040\011\012\015\n') build: go build -ldflags "-X $(PACKAGE).GitRevision=$(REVISION) -X $(PACKAGE).GitBranch=$(BRANCH)" -o $(APPNAME) run: build ./$(APPNAME)
You can then simply run either make build
to create the build or make run
to build and run the application:
make run go build -ldflags "-X github.com/pieterclaerhout/example-go-build-time-variables/version.GitRevision=47c55c2 -X github.com/pieterclaerhout/example-go-build-time-variables/version.GitBranch=master" -o example-go-build-time-variables ./example-go-build-time-variables server Git Revision: 47c55c2 Git Branch: master
The complete source code for this example can be found here.