go icon indicating copy to clipboard operation
go copied to clipboard

proposal: cmd/go should output structured version information usable by development tools (and go itself)

Open willhughes-au opened this issue 3 years ago • 2 comments

Background

Issue #21207 describes an effectively similar problem, but was closed without actually resulting in a structured version output.

Problem

When using CI Tools and pipelines, it is often required to know the major/minor version of Go.

Not least of which for passing into go commands such as go mod tidy which has a -compat argument, which requires just the major.minor version number.

Current Work-Arounds

As best as I can tell, everyone seems to be using some kind of regex against the output of go version.

Proposal

An argument for go version which will output a structured format of some kind, or perhaps just the version elements requested.

willhughes-au avatar Sep 19 '22 06:09 willhughes-au

CC @bcmills @matloob

ianlancetaylor avatar Sep 20 '22 02:09 ianlancetaylor

You're somewhat there already via go env -json. For example:

$ go1.18.5 version
go version go1.18.5 linux/amd64
$ go1.18.5 env -json GOVERSION GOOS GOARCH
{
	"GOARCH": "amd64",
	"GOOS": "linux",
	"GOVERSION": "go1.18.5"
}

or with tip:

$ go version
go version devel go1.20-1eeb257b88 Tue Sep 20 02:58:09 2022 +0000 linux/amd64
$ go env -json GOVERSION GOOS GOARCH
{
	"GOARCH": "amd64",
	"GOOS": "linux",
	"GOVERSION": "devel go1.20-1eeb257b88 Tue Sep 20 02:58:09 2022 +0000"
}

mvdan avatar Sep 20 '22 13:09 mvdan

@mvdan Thanks for pointing out the -json args and options, however GOVERSION still requires parsing out the actual version numbers from the returned text. Perhaps more options could be added for the major, minor and point version (or use whatever terms that Go normally uses)?

Perhaps for tip/non-official releases there could be another option for what git rev it was built from or something like that.

For example, to take your two examples, it would be good to have these values output independently.

$ go1.18.5 env -json GOVERSION GOOS GOARCH GOMAJORVERSION GOMINORVERSION GOPOINTVERSION
{
	"GOARCH": "amd64",
	"GOOS": "linux",
	"GOVERSION": "go1.18.5", 
        "GOMAJORVERSION": 1, 
        "GOMINORVERSION": 18,
        "GOPOINTVERSION": 5
}

and

$ go env -json GOVERSION GOOS GOARCH GOMAJORVERSION GOMINORVERSION GOPOINTVERSION GOTIPCOMMIT
{
	"GOARCH": "amd64",
	"GOOS": "linux",
	"GOVERSION": "devel go1.20-1eeb257b88 Tue Sep 20 02:58:09 2022 +0000",
        "GOMAJORVERSION": 1, 
        "GOMINORVERSION": 20,
        "GOPOINTVERSION": 0, 
        "GOTIPCOMMIT": "1eeb257b88"
}

willhughes-au avatar Sep 29 '22 23:09 willhughes-au

For actual releases, it seems to me like you can extract the semver-like numbers with a fairly simple regular expression. I've done that in a couple of places and it doesn't seem particularly difficult.

For "devel" versions, note that they don't need to follow a specific format. A build can end up with any version string placed in the VERSION file when running make.bash. It's true that builds by default end up with a format that includes a commit hash and a timestamp, but - again those feel rather easy to extract via a regular expression or string handling.

Not least of which for passing into go commands such as go mod tidy which has a -compat argument, which requires just the major.minor version number.

Note that if this is your use case, you likely don't want to obey go env GOVERSION if it is not a proper stable release. The current master, even though it's 1.20-somecommit, is very different from what the final Go 1.20 will be like.

It sounds to me like you only want to use GOVERSION when it's a stable version - in which case you only need to trim the bugfix release if there is one.

mvdan avatar Sep 30 '22 22:09 mvdan

I can use a regex, that's what all the search results for "How to get Go version" do. Some of them are broken in various ways, need maintenance, or assume access to certain tooling or a particular regex implementation.

The point of the proposal is to do away with this. It's information that the Go binary already has, why not make it available in a structured way rather than making everyone re-implement the wheel in various broken ways?

willhughes-au avatar Oct 04 '22 00:10 willhughes-au

When using CI Tools and pipelines, it is often required to know the major/minor version of Go.

I'm not sure I understand when this would happen at all, certainly not "often".

Not least of which for passing into go commands such as go mod tidy which has a -compat argument, which requires just the major.minor version number.

The -compat argument predates the work on forward compatibility (respecting the go version in the go.mod file) and basically should not be used anymore.

Are there other contexts where this information is needed?

rsc avatar Dec 04 '23 16:12 rsc

This proposal has been added to the active column of the proposals project and will now be reviewed at the weekly proposal review meetings. — rsc for the proposal review group

rsc avatar Dec 04 '23 16:12 rsc

Talked to @bcmills and @matloob, and we think probably if this information is anywhere it would be in go list -f context.something, but it's unclear why it's necessary so we should establish a use case first.

rsc avatar Dec 06 '23 18:12 rsc

With the compatibility work that has landed since this issue was filed in 2022, it seems like this may not be necessary anymore.

rsc avatar Dec 13 '23 18:12 rsc

Based on the discussion above, this proposal seems like a likely decline. — rsc for the proposal review group

rsc avatar Dec 14 '23 04:12 rsc

No change in consensus, so declined. — rsc for the proposal review group

rsc avatar Dec 21 '23 04:12 rsc