Proposal: A minimal release process for Go repositories
Author: Dave Cheney <firstname.lastname@example.org>
Last updated: 03 December 2015
Discussion at https://golang.org/issue/12302.
In the same way that gofmt defines a single recommended way to format Go source code, this proposal establishes a single recommended procedure for releasing the source code for Go programs and libraries.
This is intended to be a light weight process to facilitate tools that automate the creation and consumption of this release information.
Releasing software is useful. It separates the every day cut and thrust of software development, patch review, and bug triage, from the consumers of the software, a majority of whom are not developers of your software and only wish to be concerned with the versions that you tell them are appropriate to use.
For example, the Go project itself offers a higher level of support to users who report bugs against our released versions. In fact we specifically recommend against people using unreleased versions in production.
A key differentiator between released and unreleased software is the version number. Version numbers create a distinct identifier that increments at its own pace and under different drivers to the internal identifier of the version control system (VCS) or development team.
This proposal describes a minimal release procedure of tagging a repository which holds the source of one or more Go packages.
This proposal recommends that repository owners adopt the Semantic Versioning 2.0 standard (SemVer) for their numbering scheme.
Source code is released by tagging (eg.
git tag) the VCS repository with a
string representing a SemVer compatible version number for that release.
This proposal is not restricted to git, any VCS that has the facility to assign a tag-like entity to a revision is supported.
The format of the VCS tag is as follows:
That is, the character
v, U+0075, followed directly by a string which is
compliant with the Semantic Versioning 2.0 standard.
When inspecting a repository, tags which do not fit the format described above must be ignored for the purpose of determining the available release versions.
SemVer requires that a once a version number has been assigned, it must not change, thus a tag, once assigned must not be reused.
Go libraries and programs do not have version numbers in the way it is commonly understood by our counterparts in other languages communities. This is because there is no formalised notion of releasing Go source code. There is no recognised process of taking an arbitrary VCS commit hash and assigning it a version number that is meaningful for both humans and machines.
Additionally, operating system distributors such as Debian and Ubuntu strongly prefer to package released versions of a library or application, and are currently reduced to doing things like this.
Who benefits from adopting this proposal ?
This proposal will immediately benefit the downstream consumers of Go libraries and programs. For example:
- The large ecosystem of tools like godeps, glide, govendor, gb, the vendor-spec proposal and dozens more, that can use this information to provide, for example, a command that will let users upgrade between minor versions, or update to the latest patch released of their dependencies rather than just the latest HEAD of the repository.
- Operating system distributions such as Debian, Fedora, Ubuntu, Homebrew, rely on released versions of software for their packaging policies. They don't want to pull random git hashes into their archives, they want to pull released versions of the code and have release numbers that give them a sense of how compatible new versions are with previous version. For example, Ubuntu have a policy that we only accept patch releases into our LTS distribution; no major version changes, no minor version changes that include new features, only bug fixes.
- godoc.org could show users the documentation for the version of the package they were using, not just whatever is at HEAD.
go get cannot consume this version information today should not be an
argument against enabling other tools to do so.
Why recommend SemVer ?
Applying an opaque release tag is not sufficient, the tag has to contain enough semantic meaning for humans and tools to compare two version numbers and infer the degree of compatibility, or incompatibility between them. This is the goal of semantic versioning.
To cut to the chase, SemVer is not a magic bullet, it cannot force developers to not do the wrong thing, only incentivise them to do the right thing. This property would hold true no matter what version numbering methodology was proposed, SemVer or something of our own concoction.
There is a lot to gain from working from a position of assuming Go programmers want to do the right thing, not engineer a straight jacket process which prevents them from doing the wrong thing. The ubiquity of gofmt'd code, in spite of the fact the compiler allows a much looser syntax, is evidence of this.
Adherence to a commonly accepted ideal of what constitutes a major, minor and patch release is informed by the same social pressures that drive Go programmers to gofmt their code.
Why not allow the v prefix to be optional ?
The recommendation to include the
v prefix is for compatibility with the
three largest Go projects, Docker, Kubernetes, and CoreOS, who have already
adopted this form.
v prefix to be optional would mean some authors adopt it, and
others do not, which is a poor position for a standard.
In the spirit of gofmt, mandating the
v prefix across the board means there
is exactly one tag form for implementations to parse, and outweighs the
personal choice of an optional prefix.
There is no impact on the compatibility guidelines from this proposal.
However, in the past, members of the Go team have advocated that when a libraries' API changes in an incompatible way, the import path of the library should be changed, usually including a version number as a component of the import path. This proposal deprecates this recommendation.
Authors of Go libraries should follow these two maxims:
- Packages which are the same, must share the same import path. This proposal provides the mechanism for consumers to identify a specific release version without the requirement to encode that information in the import path.
- Packages which are not the same, must not have the same import path. A clone or fork of a library or project is not the same as its parent, so it should have a new name -- a new import path.
Authors who wish to release their software must use a tag in the form described above. An example would be:
% git tag -a v1.0.0 -m "release version 1.0.0" % git push --tags
Authors are not prohibited from using other methods of releasing their software, but should be aware that if those methods do not conform to the format described above, those releases may be invisible to tools confirming to this proposal.
There is no impact on the Go release cycle, this proposal is not bound by a deliverable in the current release cycle.
Out of scope
The following items are out of scope of this proposal:
- How libraries and applications can declare the version numbers or ranges for their dependencies.
- How go get may be changed to consume this version information.
Additionally, this proposal not seek to change the release process, or version numbering scheme for the Go (https://golang.org) distribution itself.