Versiongen is an opinionated approach to a common problem: how to add to your go software's build information about its version / repository commit.
It is opinionated because:
- It works via go generate
- Expects you to use git
- Expects you to have tags (at least one) in your repository
The use is pretty simple. You add a go program to run via go generate:
package main
import (
"log"
"github.com/andmarios/go-versiongen"
)
func main() {
err := versiongen.Create()
if err != nil {
log.Fatalln(err)
}
}
This will add a version.go
file in the directory you ran go generate
that will include 3 constants: vgVersion, vgHash and vgClean. It will
look like:
package main
// auto generated by github.com/andmarios/go-versiongen
const (
vgVersion = "v0.1-2-g7665642+"
vgHash = "7665642a17cecca2693d48276b07c28bd29cda06"
vgClean = "false"
)
vgVersion is the version of your program as provided by git describe --tags
.
If you have uncommited changes, the DirtyString
will be appended to the
version. It is by default +
but can be changed to your liking.
vgHash is the SHA1 of the current HEAD.
vgClean indicates whether your build is clean or it includes uncommited changes.
What you will do with them, is up to you. Have a look into the example directory to better understand how it works.
Other knobs include IgnoreFiles
which is an array of filenames to ignore
uncommited changes on (by default it contains version.go
). You can also create
the version file to a custom path instead of version.go
.
The solution is obviously far from perfect. In the past I used custom go generate
code, git pre-commit hooks and other methods to auto-create build
version information. None was perfect and without a standard I lost more time
than needed. Build version on runtime is very important in order to identify
which version of your application is deployed.
Versiongen is quick to setup with acceptable output for most small go programs.
The most important issue with versiongen is that Go's documentation suggests
that files created via go generate
should be commited to the repository, as
stated “it is for package authors, not clients”[^1]. This creates a conflict, as
it is practically impossible to commit a file containing its commit HASH. On the
other hand it makes go get
work as expected and if your users are serious
about their build, they still can run go generate
before build. A solution
that would always give the correct version would be to utilize another build
system, such as make, but I prefer to avoid it if I can and have my code work
with go get
.
By default, version.go
is part of the IgnoreFiles
. This is acceptable,
because if you changed any file besides version.go
your build will be
set as not clean anyway. If you only changed version.go
then your build
is actually clean since it won't affect the runtime behaviour of your file.
[^1] The Go Blog / Generating Code
License is Apache 2.0.