← Home

Automatic Versioning of Go Code

6 months ago, I read a blog post from the Go package management team [0] which asked for the community to build a tool which would automatically suggest the next version to use for Go code, so I decided to build something based on a simple algorithm:

  • For each git commit, increment the build number (0.0.1).
  • For each additional exported (public) function, struct or field, increment the minor number (0.1.0).
  • For each removal of a previously exported function, struct or field, or where a function signature has changed, increment the major number (1.0.0), since this could break compatibility.

To do it, I wrote some code to take in a path to remote git repository, clone it and use the experimental [1] code to parse the Go code and extract features into a struct which defined the features:

type PackageDiff struct {
	PackageName string `json:"packageName"`
	Functions   Diff   `json:"functions"`
	Fields      Diff   `json:"fields"`
	Constants   Diff   `json:"constants"`
	Structs     Diff   `json:"structs"`
	Interfaces  Diff   `json:"interfaces"`
}

It was then a case of creating a diff between versions and updating the version according to the rules.

type Signature struct {
	Functions  []string `json:"functions"`
	Fields     []string `json:"fields"`
	Constants  []string `json:"constants"`
	Structs    []string `json:"structs"`
	Interfaces []string `json:"interfaces"`
}

So far so good, but then I needed to test it on a wide range of repositories.

Early feedback from the team was that it didn’t run in a Docker container, which actually turned out to be that the git log command I’d used contained an ISO 8601 compatible date format specifier, which wasn’t present in the older version of git that ships with the Go 1.7 Docker container, so once I’d changed that code to use a Unix timestamp instead, I had a container ready to set loose to version Go code.

The tool is up at [2] I just forgot to post about it earlier.

Maybe you might find it useful for determining whether your code or external code has broken binary compatibility.