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
Could we clarifies better in the semver doc PATCH releases and initial development? #915
Comments
Proposed suggestion to bring clarifications to do the doc: #916 |
What it means is that in |
Hi @ljharb, The whole point of the convention is to have clear and defined criteria/rules to address the expectations of those that will consume the API and keep the solution maintained. Sorry, but your comments and arguments do not seem consistent with the info provided in the doc https://semver.org/ and real scenarios. Therefore, I hope we agree that the https://semver.org/ shows need to adequately cover the stage where the project version is < 1.0.0 at least. Otherwise, we would not have this discussion with very different points of view. Now, following some comments inline about your replies so far:
That seems inaccurate and contrary to the points described in this doc. If so, why do we have in the doc: If you are right here, then:
Sorry, but that does not make sense to me. Before becoming stable, an API must have many lifecycles and interactions with those users, resulting in incompatible changes. I can share with you that, for example, many Kubernetes projects are < 1.0.0 for those reasons. This convention could not be valid and valuable to many factual scenarios if you think this way. In the real world is a big deal to have so many releases and become 100.0.2 very soon. Indeed that is also a point highlighted in the document. PS: The doc highlighted this point and considered this real case scenario and requirements.
At the top of the document, we have the following: Also, we have:
It is clear to me that we cannot expect a project that is < 1.0.0 need to make a MAJOR bump release to breaking changes because no MAJOR releases will be produced at all in this case. However,
I hope that the comments and arguments above make sense. |
I agree there's confusion there - i think the document mistakenly conflates, at times, first/second/third for major/minor/patch, since those are only the same at v1+. |
Reading and writing technical specs is as much an art form as it is an engineering practice. The language can be particularly terse with respect to "normal" communications. The goal is to produce a document that can hold up to formal logic and the later requires extra attention on the part of the reader. The SemVer spec does a pretty good job of this on whole, but doc is also cluttered with some non-formal language that tends to be the prime source of confusion. It's also attempting to simultaneously codify and extend a certain pre-existing convention that was also likely in use right here at github before the author checked in the original proposal.
Because during initial development, lots of things are broken and unpredictable and the standard would not have been adopted if it did not include the prerelease loop holes. First, the 0.y.z form was a common convention prior to the writing of SemVer and second, there had to be a get out of jail free card for already released software, to allow for additional prerelease cycles. If not for the allowance of these two conventions, SemVer would never have been adopted, as it would be deemed too restrictive. There's nothing in the spec that prevents you from using the full major.minor.patch-prereleaseTag semantics for initial development. The 0.y.z prerelease form is there because some developers and probably some marketing departments didn't like the idea of their first official non alpha/beta/dog-food release being very much higher than 1.0.0. In the CI/CR we live in today, best engineering practices mostly prevail, so marketing and developer predilections and superstitions are a little less dominate, and we're seeing a lot more of those higher major version numbers than in the past. If you start at 1.y.z-pr, you should use an informative tag of the form -a.Dev or my favorite -a.Experimental. Note the 'a.' prefix on the tag. That's there so my Experimental tag doesn't sort higher than -Beta. Alternatively you could use -alpha. Nothing in the SemVer spec prevents you from layering your own compatible conventions over the top of it.
There's six parts to the SemVer doc:
The spec and the BNF grammar say everything you need to know. The rest is there for for anyone initially unable to grok those two parts or unwilling to read them carefully enough. There is much that can be derived from them. Almost as important as what they say is what they don't say. The spec is not over-engineered to the point of being difficult to implement or use. If you spend some time researching through some of the discussions that have taken place here (closed as well as open), you will get a better impression of how we interpret the spec and why some of it's apparent vagaries are allowed to stand without comment in the FAQ.
Why indeed? Where in the spec does it say you cannot do that? There's two common conventions allowed under the initial prerelease phase, either drop the major version entirely and continue using the minor and patch as intended (0.minor.patch), or shift the meaning of the triple to the right (0.major.minor). And even though the spec doesn't say anything about the 0.m.y convention, it is certainly allowed due to the phrases "Anything MAY change at any time. The public API SHOULD NOT be considered stable". One problem I have with these to two initial release conventions, is that there is no formal way to distinguish between them, but then we don't have to because we have the phrases "Anything MAY change at any time. The public API SHOULD NOT be considered stable". In this case the publishers intent is not relevant. The consumers of the initial release had better take head of the phrases "Anything MAY change at any time. The public API SHOULD NOT be considered stable".
Unless I am misunderstanding the question, I think the spec says exactly that. The Y part of the triple is the Minor field and the fact that it's a prerelease version means that breakage is allowed. So now we come to the realization that the spec never says "MAJOR.MINOR.PATCH" (it's in the summary, not the spec), it uses the "X.Y.Z" notation everywhere and applies the labels Major (X.y.z), Minor (x.Y.z), Patch (x.y.Z) instead. Why is this? Because the original convention that was being extended with the proposed semantics commonly used the X.Y.Z pattern (there were others, but they weren't triples). In some cases X was the "major" thing that marketing was promoting as the next best thing, and the Y.Z parts were left for whatever willy-nilly thing the developers wanted to cram into them (like dates!). In other cases it was X => Year, Y => Month, etc. All of those other conventions are still quite commonly used, but many of them already have their own set of explicit or implied semantics. |
I should note that I have also seen the 0.YYYYM.DRR convention is used internally in many places. You can't have leading zeros in the triple, so the year and revision parts must be fixed length so you can drop the leading zeros for month and day fields as needed and still parse the thing in your head. I don't see any reason why you couldn't release those to early adopters. The semantics are obvious when you see them in the wild and the Y and Z fields will get reset when you finally get around to bumping the major version. Since both prerelease forms absolve the publisher from semantic correctness with regard to the triple values, they lose their intended meanings from the perspective of the consumer anyway, so why not lay in some useful information instead? You may encounter some tooling that won't accept large numeric field values because the implementers either misinterpreted the spec to mean integer in whatever their programming language was (8, 16, 32, 64 bits, etc) or they were just to lazy to figure out that an integer string without leading zeros will sort correctly if you take account of the string length (simple algorithm takes less time to sort than converting to int and then comparing, in the vast majority of real world version strings). |
For whatever it's worth, I see this line as the worst line in the semver spec
And would like to see it removed. Nobody who implements semver actually respects this; they all implement the same ranges as everyone else, some of which have semantic meaning for the relationships between x=0 versions. I just have not had the energy to try and get it done. Maybe I will. |
@steveklabnik do you mean to enshrine the way npm treats v0 versions? If that's the case and you'd accept the PR, I'm happy to take a crack at authoring it. |
I think "the way npm treats v0 versions" is too broad for me to know what specifically you mean; I'm referring to the "the ^ matcher treats y as x and z as y when x = 0" semantics. But part of the reason that I haven't done it, and maybe you're interested in this too, is that IMHO the spec is poorly organized. That's nobody's fault, really. But at the very least, the "what versions mean" bits and the "how versions relate to each other" bits should be separated out cleanly. Part of the issue here is that #584 has still not landed; I think ideally this would all be under a "how versions relate to each other" bit. But that's not all fully thought through, and a bit rambly. Needs more work, heh. |
Gotcha, I think that aligns :-) I'll see if I can find some time this week. While I'd love to see #584 land, that seems like a larger change and i don't think this needs to wait on it. |
Cool cool. I agree that it's not blocking, for sure. |
Reducing to only one prerelease form would help. But that's a breaking change, so how do you disambiguate between SemVer 2 and 3? I strongly recommend that you resolve that problem first. |
That is not what I would advocate. Pre-release versions are still pre-release versions. |
@steveklabnik I meant that the 0.y.z form of prerelease is redundant. I had thought you were in agreement with that, or were you objecting to the "Anything MAY change at any time. The public API SHOULD NOT be considered stable" phrasing of the 4th clause? |
I am not. People use this, massively, in the real world. There's no advantage to getting rid of this. In fact, in some ways, the point is the opposite: people don't necessarily view x=0 as a prerelease.
That is correct. Things like the |
I am not familiar with how that operator is applied to version ranges in whatever tool chain(s) you are referring to. Stricter in what way? |
@jwdonahue in npm, (Additionally, semver ranges by default ignore prereleases, unless the root version of the range is itself a prerelease) |
(not only npm, but cargo, and iirc bundler with |
Ah, the never defined in the SemVer spec convention of slipping the Major version number to the right. Ya, I would object to making that part of the standard, but it's not my call. I see that as pointless because by definition, breaking changes can and often are, slipped into a prerelease code base. So why pretend otherwise? I don't object to the practice however, I think it's a perfectly valid workflow that is well within the bounds of the spec, along with a couple others I've seen in use. I was also one of three creators of a packaging tool, built on the same tech that Microsoft's Universal Packages are based on, that is used in the Windows build system that uses proper range notation of the form (VL, VH), (VL, VH], etc. Not my tool anymore since I moved on, but last time I was there, they were still using it to populate tooling and other binary bits that are used in the Window build. I agree the "0.y.z" form is commonly supported by all semver compliant tools. That's why I think mucking around with it is going to break somebody. |
@steveklabnik filed #923, lmk your thoughts! |
I just stumbled across a related comment of old: #127 (comment) We now have multiple PR's that are related to this topic. |
If that is true, then NPM is not SemVer compliant if the ^ operator accepts any 0.x.y versions. The 0.y.z form comes with the caveat that "Anything MAY change at any time. The public API SHOULD NOT be considered stable", therefore the ^ operator should exclude all 0.y.z forms if it claims to be SemVer compliant. But NPM is free to innovate however it sees fit to satisfy it's customers. If the ^ operator behaves as you say it does, then it is innovating beyond the bounds of the SemVer spec and should make that clear in the documentation. As I stated earlier, the 0.major.minor convention is compatible with SemVer because consumers and publishers understand that any 0.x.y form or N.x.y form come with the prerelease caveat that "Anything MAY change at any time. The public API SHOULD NOT be considered stable". |
@jwdonahue npm isn't semver v2 compliant, because npm existed before the current version of the semver spec. #932 and #584, however, would change the semver spec so that it fully matches npm. |
Are you saying that NPM cannot be used in its current form in a SemVer compliant way? Does it not have a -SemVer mode? That would be a sad situation to be in. I am sure there are other packaging tools out there who's owners wish they could bend the SemVer spec to validate their current product behaviors. This is one reason why I have always argued that the spec should steer clear of the range specification and dependency tree problems. SemVer as it is, is a simple convention to follow. Adding range spec behavior and dependency tracking to it, will constrain innovation and severely complicate the spec. Better to layer-on whatever flavor of range spec you prefer to use in a separate document. In the case of the ^ operator, it sounds like you also have non SemVer compliant semantics of your own. I don't see any problem with the various packaging schemes applying their preferred semantics, provided they are clear that theirs are not SemVer semantics. SemVer is a specific kind of semantic versioning that is very simple, easy to implement and programming language/tool-chain agnostic. Other than specifying how to sort a list of SemVer version strings, it is entirely agnostic on the subject of range specifications and other implementation details. Tool owners and development communities may choose to support SemVer or any other form of semantic versioning that they see fit. Claiming to use a form of semantic versioning is not the same thing as claiming SemVer compliance. A tool need not promote any of the semantic forms it supports. I know there are many that predate SemVer which also currently support it while allowing for other forms to be used. It sounds like NPM promotes another form by implication of its range operator specifications. |
I'm saying that "what semver is" changed after npm had already cemented its semantics, and no, there couldn't possibly be any mode to give it different semantics. Your argument already doesn't work because this spec already changed (widening what changes are expected in v0) in a way that conflicted with existing implementations. #923 fixes that. |
Emphasis added by me. Also, that's not a valid link at the end:
Hence the SemVer version bump from 1.0.0 to 2.0.0. My argument holds in any case, in fact, I think we should have a 3.0.0 of the spec where we finally deal with the version string disambiguation problem, and only that problem. Some form of VersionMeta would provide a means to disambiguate between the various semantic forms currently in existence. That would give us a solid base to work from, that would not stifle innovation or break existing conventions. And a quick check of the v1 and v2 specs yields exactly the same language wrt to the 0.y.z form:
Other than the added emphasis in v2, they look the same to me. Notice that nowhere in the history of SemVer does it refer to the 0.x.y form? If NPM cannot support SemVer in it's current or past forms, then why are they even involved in maintaining this spec? I would be surprised if NPM is truly non-SemVer compliant. It may have non-SemVer features, but those don't have top be used. |
The purpose of specs is to document reality, not to dictate it. The spec should match what major implementations are already doing. |
Then we'd need 10 of them. |
Or, we'd need one with sufficient minimal union semantics that all 10 can be considered compliant. |
There are literally thousands of bespoke tools out there that implement SemVer 2.0.0 as it is. Why break it for a handful of tools that are getting by just fine without it? |
No, that's what your product docs are for. This spec was intended by mojombo to be a proposal for a specific form of semantic versioning. I think NPM predates the spec and since https://semver.org/spec/v1.0.0-beta.html, the language regarding the 0.y.z form has been very clear that "The public API should not be considered stable" and was then changed to "Anything may change at any time. The public API should not be considered stable" in the v1 spec.. I don't see anything in Preston's LinkedIn profile indicating that he's ever had anything to do with NPM. I have always suspected that he wrote it in response to dependency issues experienced during the development of GitHub, caused by the subjective use of major.minor.patch versioning that was still common at the time. It's obvious the proposal simply layered tighter semantics on meanings of each of those fields. I would add that most specifications are written prior to implementation. The general purpose of writing specs is to make it clear how the implementation should behave or what it should look like. I would also add that there are packaging and other versioning related tools out there that do adhere to the spec as written (Nuget for instance). |
Originalism isn't really useful or realistic - the value of the spec now is that it's what people look to when they want to mirror existing implementations, and if it doesn't match those, it's not doing its job. |
There are plenty of implementations that hone to the current spec. Many that are mostly compatible, plus support for other semantics as well. Tweaking the spec to match NPM behavior will break it and render many tools incompatible. From that point on, the spec won't be relevant to anybody but the NPM community and yet another fork will follow. I think the main variance between all of the tool chains is in their range specifiers and selectors used for defining dependencies. It's already pretty obvious that not even the tools represented by the maintainers can agree how those should operate and they may represent a majority of the package repositories, they are a minority in terms of CI/CD tooling however. There are literally thousands of other tools, some of them representing large vertical segments that reference this spec. I think the whole point of having a very narrowly defined spec is to clarify the gist of semantic versioning (not really invented by mojombo btw) and leave some space to innovate. |
By reading the doc https://semver.org/ is clear for me that:
However, the text:
Major version zero (0.y.z) is for initial development. Anything MAY change at any time. The public API SHOULD NOT be considered stable.
Brings the idea that new features (api changes) would be fine in PATCH releases with
Anything MAY change at any time.
The text was updated successfully, but these errors were encountered: