-
Notifications
You must be signed in to change notification settings - Fork 17.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
proposal: start using semantic versions for Go releases #32450
Comments
I don't see anything "Go 2" about this proposal. It's not a language or library change, and could presumably take effect immediately. Any reason to keep the |
I love this proposal. I happened to have a problem with the However, I think we also need to pay attention to the Go versions without tags. According to the comment of the
The "commit hash" will disrupt the new naming rules you proposed. So, I think we can use some credits of Go modules. We can rename the original "commit hash" to "v0.0.0-20060102150405-0123456789ab". Then we can do something like |
Do you mean retroactively changing all previous releases to start using a new version scheme, or to start using it for new releases only? I proposed this for Go 2 in the sense we can consider starting to do this as of Go v2.0.0 release. I didn't think it was possible to retroactively change previous releases, and mixing-and-matching different versioning schemes within v1.x.x releases didn't seem great either. However, we can consider those options too. In that case, the Go 2 label isn't necessary. Edit: As @aofei mentioned, there are additional considerations such as output from |
As discussed at https://github.com/golang/proposal/blob/master/design/28221-go2-transitions.md, it is, I think, unlikely that there will ever be a Go v2.0.0 release. But if you want to wait for that in case it happens, that is OK with me, in which case we should put this proposal on hold for now. |
I think keeping it targeted at Go 2 and putting on hold for now is okay. I wanted to write up this initial proposal to have a proposal to reference and gather initial feedback. For now, it can continue to target a hypothetical v2.0.0 release. I can take the time to flesh out the details and see what would it take to implement this concretely in an earlier v1.x.x release, and then we can re-consider it for that. |
Wait until I agree with @ianlancetaylor, there should be no "Go2". If this proposal is to be adopted, then it should take effect immediately. In fact, I think we should have done this long ago. I mean this proposal should be proposed along with the Go modules proposal. Unfortunately, it does not. Why is Go urging everyone to strictly follow the semver, but Go itself doesn't do it? This should not happen. |
See #27255. |
Thanks for pointing out #27255 to me. I hadn't found it when I was doing a search to see if this was proposed in the past. It covers an important subset of this proposal, so I plan to read through it and take the information there into account. |
It would be a service to the community at large to have Go's module system use the strict semver model (https://semver.org/), which is three numeric fields separated by periods, followed by optional prerelease and build tags. There should always be 3 numbers and the 'v' prefix is spurious. The argument for rejection in #27255 was, in essence, it's only us so it doesn't matter. But Go is part of a larger world and there are tools that work across languages. Also, large systems often contain many languages and consistency across their handling eases development. It would be better to lead by following the proposed standard than to stick to the unique form it has now. |
We have a lovely consistent set of versions dating all the way back to Go 1. If we change the way Go version strings are written then anything that consumes such strings needs to consume both the old format and the new one. Or am I missing something? |
@adg I didn't include a section talking about the costs of implementing this proposal; perhaps I should have. You're absolutely right, that is one of the disadvantages of changing the version format. I can think of some ways of dealing with it:
|
I found these for you @robpike, and I think their discussions may be helpful in determining whether there should be a "v" prefix: semver/semver#204 semver/semver#235 especially semver/semver#424 (comment) And BTW, semver itself is using the "v" prefix. See https://github.com/semver/semver/releases. |
After all, I think it's okay to use What @rsc mentioned in #27255 (comment) seems that he sees this kind of changes as incompatible. I don't know, maybe. For me, I can only find one incompatible change at the moment, which is the output style of the Edit: In my opinion, implementing this new Go version naming convention from |
Whoever (edit: to clarify: distributors, packagers, etc) has an update mechanism for Go in place today, will be able to make a small change by saying "this range follows what we previously defined for Go" and "everything else follows semantic versioning". |
@ng-0 yes, precisely my point. |
There would be some advantages to having the Go tool itself following semver, but I would be OK if that doesn't happen, including because there are a different set of goals, constraints and possible mistakes that are in play for versioning an API or program (which is arguably what semver is most targeting), vs. versioning a programming language. As I understand it, there is an option and likely plan to introduce breaking changes without incrementing the 1 for Go, but to do so carefully, and without redefining the meaning of any current programs, and while still allowing for example the removal of capabilities. For example, from the "Go 2 transition" proposal
and
Perhaps one could argue that the That said, a narrower version of this proposal would be to always have the last dot for any future initial major release, such as Of all the flavors of version strings @dmitshur listed in his opening comment, I think versions like @bcmills wrote in #29984 (comment):
@mvdan wrote:
@dmitshur, I am guessing you would view that as a completely separate proposal rather than a variation of your current proposal, but wanted to at least mention it, including it could be viewed as a smaller but useful step towards your proposal. |
@thepudds Thanks for surfacing that information, it's helpful to see that more people have voiced a desire for the ".0" suffixes to not be omitted.
This proposal does not have a very specific implementation plan attached to it yet, and so I view a proposal to include trailing zero version components as closely related to this proposal. To repeat and summarize my proposal at a high level, it is "use semver for Go release versions". The three benefits I'm looking to achieve are:
To me, both 1 and 2 are very important goals. 3 is nice but much less important. As a result, a proposal/solution that resolves 1 would be a great win to me. However, I suspect the cost of making any change, regardless of how small or trivial, to the version scheme used by Go releases is quite high. As a result, if we're going to change it from just go "go1.12" -> "go1.12.0", then I suspect the additional cost of changing prefix from "go" to "v" and doing the minor "beta1" -> "-beta.1" change to make it fully semver compliant would be relatively small that it'd be better to do it all at once rather than not. This is why I framed this proposal about moving completely to semver, rather than a smaller "go1.12" -> "go1.12.0" change. |
Change https://golang.org/cl/229481 mentions this issue: |
Make it more clear that this type represents a Go-specific version, rather than a version that follows the Semantic Versioning 2.0.0 specification. The type already has Go-specific methods, for example IsMajor reports true for "1.14" and IsMinor reports true for "1.14.1". This is consistent with the terminology used by Go releases, but very surprising if considered from the perspective of semver. Document some differences of the Go-specific version convention compared to semver, and describe the X, Y, Z fields in more detail. This change makes it viable to add a String method to GoVer type documented to print a Go-specific version string, which will be useful in more places in CL 229483. For golang/go#32450. Change-Id: If7482fdb4a739ff5b89b7133402d94412057f590 Reviewed-on: https://go-review.googlesource.com/c/website/+/229481 Reviewed-by: Carlos Amedee <carlos@golang.org>
One way of dealing with this, regardless of whether the Go project does switch to semver or not, would be to provide a simple utility function that translates from a Go version (e.g. |
Make it more clear that this type represents a Go-specific version, rather than a version that follows the Semantic Versioning 2.0.0 specification. The type already has Go-specific methods, for example IsMajor reports true for "1.14" and IsMinor reports true for "1.14.1". This is consistent with the terminology used by Go releases, but very surprising if considered from the perspective of semver. Document some differences of the Go-specific version convention compared to semver, and describe the X, Y, Z fields in more detail. This change makes it viable to add a String method to GoVer type documented to print a Go-specific version string, which will be useful in more places in CL 229483. For golang/go#32450. Change-Id: If7482fdb4a739ff5b89b7133402d94412057f590 Reviewed-on: https://go-review.googlesource.com/c/website/+/229481 Reviewed-by: Carlos Amedee <carlos@golang.org>
At some point between filing this proposal and now, I've realized that the "v" part in a string like "v1.2.3" is not a part of SemVer 2.0.0. See https://semver.org/spec/v2.0.0.html#is-v123-a-semantic-version. So any semver parser would only see the "1.2.3" substring. That means there's no good reason to change the "go" prefix to "v". I think keeping "go" prefix is a good idea, I withdraw the suggestion to change that. I've updated this detail in the original proposal for better visibility. (I would've done this much earlier, but this proposal was on Hold so I left it for later. But it's more relevant now given discussion in #57631.) |
I just wrote a lot of new version code for the GOTOOLCHAIN work (#57001). The extra zero digit on major releases turned out to be a great help - if we hadn't already accepted #57631 we'd have had to add it anyway, so thanks to @thepudds for anticipating that. The extra zero digit helps because it solves a real problem: distinguishing between the Go 1.21 language definition + release family and the Go 1.21.0 release. In contrast, changing to semver does not solve a problem. It just changes syntax in a way that people have to learn. Yes, it would use a semi-standard syntax, but it would still be our own defined subset of Semver, not complete Semver. That would be significant churn without significant benefit. When I first started working on the GOTOOLCHAIN code, I handled Go versions in MVS by defining conversion functions from Go version syntax -> Semver and then Semver -> Go version syntax. That was pretty tricky and annoying, and it was difficult to catch all the places where the "internal" Semver form might leak out. @bcmills pointed out to me that the MVS library did not assume Semver at all, and that by making a minor adjustment I could let it operate directly on the Go version syntax. That was an enormous simplification and cleaned up tons of rough edges. We could in theory switch from Go versions to semver, but:
The code is written and everyone understands the current syntax. Most importantly, the GOTOOLCHAIN code understands the current syntax. If we switched to semver in the future, that would invalidate all the old toolchains being used perfectly well to run newer versions of Go. At this point I think the ship has sailed, and the island it landed on is Go's version syntax, not semver. |
This proposal has been added to the active column of the proposals project |
I would argue it's the opposite. It isn't obvious that the version of go1.21rc2 is "go1.21rc2" without being familiar with Go versions, but most people who know semver (which is most people) would guess "1.21.0-rc2".
What do you mean?
It sounds like all of that complexity would be avoided by using the same versioning scheme, as you described at the end here. Using semver for modules and the language would have the same simplification, right?
Couldn't the toolchain map old version strings to their semver equivalents? There are maybe a hundred of them? There's no need to parse the old versions.
"-rc2" vs. "rc.2" doesn't seem that complicated to learn. Only a small minority of Gophers work with RC releases anyway.
In my opinion, this would quickly pass, and wouldn't even be a big deal when it happens. "brew upgrade go" doesn't deal with Go versions at all. Most users are on a recent, supported version.
Why wouldn't 1.21 work? It's obvious it's not a semver.
It can be written again, right?
It can be written to understand the new syntax, right?
I don't understand what this is saying. The old and new version schemas can coexist.
It doesn't seem that way to me. We've added the patch version, and now we could go the rest of the way. |
People who know semver might guess 1.21.0-2 or 1.21.0-releasecandidate.2 or 1.21.0-pre.2 or any number of other possibilities. Nothing about semver dictates the specific syntax 1.21.0-rc.2. Also note that you used the wrong semver syntax in this reply: we would surely use 1.21.0-rc.2 not 1.21.0-rc2. This only proves the point that there's not one obvious semver answer. We can't help "people who know semver" because semver does not constrain the space. People who have used previous Go release candidates know the numbering already. We can help those people by continuing to use the same syntax.
I meant that we'd be using 1.21.0-rc.2 not 1.21.0-rc2 or 1.21.0-pre.2 or 1.21.0-rc.2+foo or any other number of valid semver syntaxes that would not be valid Go syntaxes.
Maybe but it doesn't really seem like a simplification.
I suppose.
It would be "-rc.2" vs "rc2". Another mistake using the syntax, which proves my point that we should not try to teach people a different syntax. Let's keep using the one we have.
History matters (in my opinon of course). Not everyone updates frequently or keeps up with the issue tracker like you do. Churn is painful.
In go.mod files, for require lines, if you write v1.21 it means v1.21.0.
Not really, no. Go 1.21 is in the release freeze. We are not going to rewrite the code at this point.
Again, no. Go 1.21 is in the release freeze.
It is an explicit goal that Go 1.21 can invoke future toolchains based on the go line in the go.mod file. When Go 1.22rc1 comes out, Go 1.21 will work fine with things like
We will have to disagree on that. |
Based on the discussion above, this proposal seems like a likely decline. |
No change in consensus, so declined. |
At this time, the Go distribution uses versions that look like this:
Those version strings are used both in the output of
go version
command, and as tag names in the source code repository.Semantically, each version encodes a major, minor, and patch component, as well as optional pre-release metadata. However, the exact version string differs from semantic versions as defined by Semantic Versioning 2.0.0 specification in the following ways:
Differences
4. The prefix is "go" rather than "v".Go's current version strings are nice-looking and familiar, and this scheme was created before the existence and proliferation of https://semver.org. However, there are some disadvantages compared to following semver:
When someone talks about a "minor release" of Go, it's sometimes hard to know if they mean "x.Y.z" minor, or "x.y.Z" minor.
For people who are familiar with semver, it's difficult to refer versions such as 1.12.6 as "minor releases" because semver refers to the increased version component as "patch", and it's hard to know if the target audience will understand what you actually meant.
Following semver conventions, being as widespread as it is today, makes it possible to refer to all 3 version components without ambiguity or confusion.
Omitting the trailing version component makes it difficult to have clear conversation about those versions of Go releases.
For example, when someone says "I was able to reproduce the problem with go1.12", it's hard to tell if they mean it happens only the exact version
go1.12[.0]
only, or if they mean any patch version, including go1.12, go.1.12.1, go1.12.2, go1.12.3, etc.Similarly, it's hard to refer to the initial release version with a trailing zero version component. It can be temping to explicitly say "try it with go1.12.0" in order to be clear you mean that exact version and not any other.
Modules have adopted semver, and many people are familiar with semver. Right now, the Go project uses two different version string schemes. By adopting semver for Go release versions, we can reduce it from two schemes to just one scheme. It's simpler, more consistent and fewer things for users to learn and keep in their head.
Performing any change to the existing version scheme has transitional costs. However, I think the medium- and long-term benefits will outweigh the costs by a wide enough margin to consider this.
This proposal is to consider changing the Go release version format to match that of Go module versions, which is semver-compliant. Specifically, the trailing zero version components should always be included,
the "go" prefix changed to "v",and beta/RC pre-release suffixes represented in a way that satisfies semver.The proposed version strings can look like this:
Update on 2023-03-01: withdrew the suggestion to change the "go" prefix to "v". See #32450 (comment) for my rationale.
The text was updated successfully, but these errors were encountered: