-
Notifications
You must be signed in to change notification settings - Fork 694
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
Problems with the Magic Zero #221
Comments
You should consider that the FAQ suggest to use (this was edited) |
It basically makes I wonder if it would be better to say this is a recommendation for By that I mean the change from Of course the same is true with released software. The move from |
I love this suggestion very much. I think it accurately captures the distinction in my mind between |
I am also in favor of this change, for reasons specific to my understanding of conventional usage within the Node community (I have no numbers to back any of this up, hence the cagey phrasing). There are several large ecosystems (most notably grunt's) where versions are coupled between plugins and "master" packages (what are called Developers within these communities are using the operators provided by The Node world is particularly rife with 0.x.y-versioned packages, and while the current text (and @haacked's reasoning above) is a reasonable normative interpretation of semver, bringing the community's understanding into convergence with the standard is particularly difficult given the community's size and the inertia already accumulated by current conventional practice. I favor the approach suggested by @isaacs purely out of pragmatism – it matches what I see as the most common practice in the community I support. |
That's interesting and is in line with the philosophy of SemVer. Do you see this practiced in other communities as well? I'd really like to hear from @mojombo on this as I know he's had strong feels. I still think making it a recommendation rather than a MUST might alleviate that. I'm not sure. |
I think @othiym23 @ceejbot and I are all pretty full-time on Node and npm these days. Can't speak for other groups, but as npm becomes widely adopted for frontend stuff, we do see a lot of Java and Ruby folks picking it up.
Not quite. So, it is a smaller commitment, since additive changes can come along with bugfixes, without having to differentiate between them.
Not in my experience. It's an intermediate step that "feels" smaller. |
I am against this suggestion, because I think it stems simply from a poor quality of implementation issue in npm that has persisted until recently. That is, I think it does not reflect ipso facto author sentiment, but instead a post facto rationalization in favor of npm's formerly-broken implementation and the ecosystem that grew up around it. In contrast, from talking to @wycats and his work on the greenfield Rust/Cargo ecosystem, the differentiation that pre-1.0.0 provides seems to have proven useful and to have been accepted in that ecosystem as a good dividing line between "very early development; dependencies should be pinned exactly" and "stable enough to start automatically getting features and bug fixes." Notably the latter category can benefit from deduping, whereas the former demands separate on-disk instances for each instance of a package in the abstract dependency tree. Dividing these clearly between pre-.1.0.0 and 1.0.0 onward is very helpful, and moving that line back to 0.1.0 does not seem like a good idea. |
The majority of npm users doesn't care about semver. So you suggest to fix this by changing semver to fit existing practices... I suppose next will be breaking post-1.x.x minors, because we have tons of those. Please, just stop that already. Semver is great as it is. But it can't be used everywhere. It is meant for production-quality libraries with long iterations (like So, my suggestions are:
Let people use versioning system they want to use instead of trying to squeeze semver everywhere. You forcing people to use it, they fail to do so, and they blame the spec (1, 2, 3), while in reality it's npm at fault here. |
To be completely honest, my first choice would be to drop the magic zero entirely. SemVer should start at 0.0.0. The first breaking change should be 1.0.0. If the first "production ready" release is 10.22.0, then so what? Integers are cheap and plentiful. A period of "anything goes" versioning encourages oversized modules and poorly thought-out designs that should usually be abandoned rather than refactored. It is exactly the reason why semver is a good idea in the first place. I realize that this is a minority opinion. But that's why npm init starts at 1.0.0 by default now. 0.x versions are too hard to reason about, and encourage bad antisocial practices. |
Also, we already have "anything goes" versions with prerelease tags, which are more orderly anyway. The next version of node-semver will not let prereleases match on version ranges, so it's just as useful as 0.x is today. |
Not to diverge too much from the discussion, but I wanted to understand how NPM treats For example, by default, NuGet only displays stable packages. The non-risk-adverse user can opt into pre-release packages by specifying the I'd argue that this is a bug in NuGet. I think it should treat Does NPM work in this way? The reason I ask is another option that accomplishes much of what you propose is to allow but hide |
/cc @jeffhandley for that NuGet bug ^^^. 😄 |
I really like the idea of hiding 0.* packages. I don't think it'll work well in the Node ecosystem though---some large-ish percentage of packages would disappear from the npm website. |
I don't really know why I was invited to comment on this. My personal experiences with things like this, is that the public opinion doesn't matter as it doesn't win against conventions, which is the entire point of conventions, which is why I dislike conventions. I think that the way npm handles things currently is fine. I think complexity is evil. Semver should be advisory, not enforced, for it cannot be enforced, without a never-ending spiral of complexity, such as this. Yes. Npm has taken the stance, that npm is pro-semver, and you should follow it (not must follow it). However, changes like this, or the proposed changes in npm, make this silly, as it is we are pro-semver, except in the cases where we accept people don't follow it, so therefore we'll add an exception for that in the semver standard, so that hey, we can be pro-semver again while facing the reality that semver is an idealistic standard that can only be advised and not enforced like we want. I'd like for a liberal and caring npm (remember when npm's tagline was "npm loves you"), recently this semver debacle is more like a totalitarian npm, where npm controls you.
As one who follows the current semver spec, I have published many modules where the initial or a subsequent 0.x.y version was fine and never needed to publish more. Hiding the 0.x.y releases, means I gotta do unnecessary bumps for following the current semver spec. This also means current package consumers need to update their version ranges too. Adding this change, also invalidates the integrity of those packages where the 0 versions where fine. For the few people who hadn't caught on to the semver standard yet. If people want a playground for breaking things, use the git repo. |
Oh, sorry for spamming, I just mentioned people whose posts I was referring to earlier. I'll try to be quieter in the future. :) |
No worries at all, appreciate it even if it wasn't clear why I was invited. Having a question with the cc, or a why I was cc'd, would be useful just to reduce the confusion of such a notification. Hopefully I'm on the right track with my ramblings above. |
First, I really like the idea of hiding Second, you're not doing "unnecessary bumps". If your software is working fine and people are using it in production or anything, you should consider switching to
Why would that be a problem with semver? Atom is already at |
That's a lot of notions all based on the premise that 0. means something different than 1+, which for a lot of people, it doesn't, nor does the current semver spec indicate this. This is a new convention that is being proposed here.
Exactly the required changes to a perfectly functioning 0 version that follows the current spec. Unnecessary as without changing the spec, none of the above would be needed. |
False. The current semver spec does indicate this, and it is not a new convention. semver.org:
|
My statements are solely based on the most recent spec of semver, 2.0.0, and maybe a bit of interpretation in case the initial wording is not 100% clear. The core difference for clients depending on software 1.* and 0.* is that they can rely on 1.* versions to not break and thus specify a range selector. With 0.* versions this is not feasable because development between minor releases (which could potentially break and thus have to be checked manually for compatability) is too rapid and patch releases could (currently at least, according to the spec) contain breaking changes as well, so you can only select a specifc version as dependency instead of an entire version range. Imo, the only thing that semver currently needs regarding versions prior 1.0.0 is a mention of |
Wow my mistake. Sorry about that. Let me revaluate my position on this. |
I haven't had time to do an audit of the registry, but I'm guessing it would be a majority, and perhaps even a large majority. |
Something that just occurred to me. The problem isn't the "magic 0", but a problem of incentives. There are a group of folks who aren't ready to have their libraries subject to the constraints of SemVer and are skirting around it because it's less of a headache to do so. We have to make the benefits of SemVer outweigh that and provide incentives for embracing the constraints. Consider this, the intent of In order to change people's behavior in any given community, we need to give them an incentive to embrace the constraints. Hiding pre-release packages is one possible approach. Maybe that's too drastic for some communities. Other options might be to simply warn users when they install pre-release. Get them to tell the authors to supply a release version. Or show a message to package authors when the package has been pre-release too long asking for commitment (joke). I think adding more rules increases the complexity without solving the root problem. Especially when there are easy ways to skirt around it. |
👍 |
I think part of the reason @isaacs opened this issue is that we at npm have maneuvered ourselves into a bit of a tricky position with respect to our community and its behavior. We introduced the About a month and a half ago, we collectively noticed that the way Unfortunately, our community has not really followed our lead (in part because it's very difficult to reach all of them in a consistent way, especially because we are not all of one mind, as this issue shows), and we are now at the point where, if we release npm 2.0.0 with this behavior, we are going to break several plugin-based ecosystems because of how a wide network of distributed developers have decided to implement versioning in their plugins. In particular, this will make it impossible for grunt, broccoli, and gulp users (who are not necessarily Node developers) to install certain sets of plugins that were compatible before, because some of those plugins are (peer-)dependent on The fundamental problem is that
are all boil-the-ocean problems: they require extensive evangelization efforts, and presume that we even can reach (and convince) enough of our user community to make a significant impact. As this thread has shown, there are a number of uncompromising, hard-line opinions within the Node community about the significance and proper interpretation of semver with respect to npm (I sort of blame @domenic for getting us in this mess in the first place). I see some value in normative behavior for 0.x.y versions, but I also see strong evidence that, in our community at least, it hasn't achieved a strong enough consensus to warrant how punitive this change is turning out to be. The least painful thing we could do prior to npm 2.0.0's release would be to revert this change to how /cc @rvagg, who has been known to have strong opinions about how npm deals with semver in the past |
My 2 (relatively unexperienced and naive) cents are this: At this point, the Those who remain While almost everyone can agree on "no breaking changes in patch releases", some folks operate on the assumption they can do minor breaking changes in minor versions. This is partially because the old default in npm was On top of that, the semantics of semver are such that major breaking changes can not be distinguished from minor breaking changes at all. Some devs find this undesirable. On top of that, some devs want their users intentionally (vs. automatically) upgrading when they release new features. On top of that, some developers believe that requiring a major version bump on every breaking change reduces innovation because projects tend to "save up" their breaks and do them all at once, making the threat of 1.0.0 -> 2.0.0 artificially seem less panic inducing than a bump from 1.0.0 -> 10.0.0 would. I share several (but not all) of the "problematic" beliefs above, but I'm personally willing to forgo them. However, I whole heartedly agree on the nature of these problems: boiling the ocean. For every me who's willing to bend, there are 10 who aren't. Therefore, in light of this, it seems that the simplest change that could be made is to return the default behavior of That'll allow the grunt, gulp, and brocolli ecosystems to once again work, it'll allow authors the freedom they used to have to instrument what they consider major vs. minor, and it'll make devs consider the benefits of upgrading minor versions (which theoretically are only for new features, which perhaps devs shouldn't be blindly upgrading in the first place). The downside of this approach seems to be more manual updating of libraries. But to prove that, we need hard numbers, not theory: How often is a major release published compared to a minor compared to patch? |
npm will not be hiding 0.x versions. Interesting idea, but the costs dramatically outweigh any potential benefits. There are at the current moment, 418,088 releases of 0.x versions, and only 64,536 releases of 1.x versions, 15069 at 2.x, and 5017 at 3.x. (It falls of dramatically from there.) Most npm modules never are bumped up to 1.x. The reason is most often not a lack of support, but rather a lack of breaking changes. If a module is created, and given a 0.0.0 version, then each release that fixes a bug gets a 0.0.1, 0.0.2, etc., and each release that adds functionality gets 0.1.0, 0.2.0, etc. Are all of those releases "unstable"? Not fit for public consumption? Let's look at the data. The most downloaded module on npm is The spec says that 1.0 is the "first public release", but that's not actually how it people are using versions most often in JavaScript land. npm already is defaulting to 1.0.0 as the first version number in We can either change the spec to reflect what people are doing, or we can change people to reflect what we think the spec ought to be. So, is SemVer a political manifesto, or a reflection of expected practices and reasonable expectations? Are we paving cowpaths or exercising eminent domain to build highways through existing cities? As it stands, I have been coming to the conclusion that the |
👍 |
Sounds similar to what I interpreted the situation as. The core problem in the npm situation is very likely:
and means that the core aspects of semver were not communicated well enough, especially considering that they use it the same way for 0.x.y versions. So, I think the easiest band-aid fix is to make the Regarding "1.0.0 as the first public release", I think this is wrong. I'm not sure whether this is actually in the spec, but if it is it should be removed. 1.0.0 is for when you reached a point where people depend on your library to "not break", and if they do that while you're still on 0.5.4 without breaking it regularly (~once a month) you should consider bumping to 1.0.0 for that reason. You don't even have to change anything in the code, a simple version bump would be perfectly fine here. Which brings us to the other problem with people using semver: They don't want to reach the 1.0.0 threshold, but that has been talked about before alread. I think we should arrange an "international 1.0.0 day" where everyone gets to raise their projects' versions to 1.0.0 when he thinks he can. I recently did that, too. |
Also treat zero major version as if Magic Zero rule was dropped. See semver/semver#221. Upgrade of major version to 1 means incompatible changes. Also add version constraints for Terraform providers implemented in Terraform 0.10.0.
IMO, 0.x.y or 0.0.y should both be banned from the SemVer spec in version 3.0.0. The -prerelease tag effectively has the same default semantics. Virtually all packaging schemes seem to cover the prerelease tag semantics quite well. Dropping the 0.x.y loop-hole would simplify the world and add the ability for developers to tell their customers, here's what I think is just a new non-breaking feature, but I know this technology is immature and we're still receiving surprising feed-back from our customers so I have this prerelease tag on it because I am uncertain that I won't break a significant number of my customers. Forcing all prerelease versions to have a prerelease tag on them, frees up the entire SemVer triplet for the package producers to advertise their full intent while simultaneously tagging the release as risky. I see no problem with packaging tools refusing to handle this one feature of SemVer, provided they offer proper support for the prerelease tag and semantics. EDIT: To clarify, 0.0.0-X.Y.Z and x.y.z-anytag would all be valid prerelease forms, but specifically, the leading 0.x.y (no prerelease tag) form would be banned. I think the original 0.x.y bootstrap form was conceived before the full semantics of how prerelease tags might be used was fully understood. |
@isaacs, unless you intend to pursue this issue further, please close this issue at your earliest possible convenience. |
couldn't this all be solved if you add the exception that you can bump from 0.x.y to 1.0.0 without needing a breaking change? just allow people to bump when they feel the project is ready but the interface wont change anytime soon. if this is part of the standard then applications will simply ignore the pseudo major bump. the only downside is that you cannot do a major change while jumping to 1.0.0 but then you can still just do it right before. |
The standard already specifies that 1.0.0 is the first stable version. Literally every change up to and including the 1.0.0 release is potentially, but not required to be, a breaking change. In other words, risk averse consumers wait for 1.0.0. From that point forward, you should not bump the major version unless you have actually introduced breaking changes. |
maybe make this more clear in the manifest so nobody gets the idea that you cannot just bump to 1.0.0 if you think the time is right. |
People get all kinds of ideas in their heads. The spec can't possibly account for every irrational idea that might come into every developer's head. That said, I would personally prefer to see the 0.x.y release mode removed from the spec in vesion 3.x.x. The prerelease tag can be used effectively to cover all prerelease contingencies. The current spec essentially requires that all 0.x.y versions must be treated as prerelease anyway, so why have two forms? Well, it's probably historical, so it was captured in early versions of the spec, but we don't have to continue to perpetuate it. |
@jwdonahue, could you clarify your opinion? Does I make these right?
If these are correct, then it looks OK for new libraries but not for existing. How, having |
@grv87 , The spec explicitly spells out what you must and should do as a publisher, when you make certain kinds of changes, depending on whether they break back-compat (major bump), add back-compat (minor bump) features or just publish changes with no new features (patch). It does not prohibit version changes in the absence of underlying product changes. In fact, the only way to recover from publishing errors is to remove the erroneously versioned package from public feeds and issue a new package with a correct version number based on the rules (ie, two packages in the world with identical content and two different version numbers is okay, but probably SHOULD be avoided). The spec also implicitly defines expected risk levels to consumers of your published packages and therefore also guides their policy choices in automatically accepting updates. If you have been publishing a series of 0.y.z releases, your consumers are already treating them as though each release is very risky and also might be valuable to them. They are in a co-development phase with you and are eagerly awaiting completion of a relatively bug free and stable product. They may be taking every update from you, testing it and then deciding whether to publish their own bits that include your updates, or they may be stuck on a more-or-less useful version for their own purposes and waiting for you to complete the project before they devote much more effort into taking a new update. It's actually a continuum between those extremes for most of your consumers. An arbitrary change on your part from 0.y.z to 1.y.z-prerelease might trigger some of your customers to take a closer look at your new release, and that will likely consume some of their resources. In the absence of guidance from you, they might assume that you are entering a more stable phase than in the past. Most of their tooling however, should distinguish both 0.25.48 and 1.0.0-tag as being of the prerelease risk class, but I don't know that there aren't some tools out there, that break the prerelease category down to higher and lower prerelease subcategories. No-one has labeled my earlier suggestion as barking mad, yet, so I take that as a good sign, but you have to consider what you know about your customers and make the correct choices for you and them, to the best of your abilities. I can only make some general recommendations how you might convert to the prerelease tag form from the development form. First, taking your example above, your next release would be 0.26.0, whether or not you added new features or breaking changes, because you're about to make a big change in your versioning semantics. You include in the your release notes, a prominent notice of the intended change in versioning and the next package version number, which will be 1.0.0-a.dev (or whatever tag is appropriate for you) and except for a change in the release notes, that package contains the same bits as 0.26.0. Your customers can then fix any knock-on bugs in their own products caused by integrating 0.26.0, review and adjust their intake policies and then verify that the entire publish/consume chain of events works correctly, without having to worry about changes in your code. Personally, I would only go to all that trouble, if I was going to produce new products. In that case, I wouldn't want to be supporting different workflows for different products. If I had been using the 0.y.z scheme on an earlier product line, I would convert. After working with semantic versioning for several years and having developed tooling around it, I see an advantage to the 1.0.0-X.Y.Z.Tag form of prerelease series, where the X.Y.Z are given full SemVer semantics and it is obvious to everyone that the target release is 1.0.0. It conveys a richer set of information to my consumers and it allows me to more easily support overlapping version 1 and version 2 projects (ie, development on N and maintenance on N-1). I tend to fix bugs first, then do features, so my typical version history might look something like: 1.0.0-0.1.0.dev // Made available to QA and very early adopters (VEA's). The above version history is a plausible SemVer compliant sequence. Some CI tooling already supports it, some don't, in fact, some get in the way of implementing it like that. Obviously, not all of those versions are available to everyone. Unfortunately, SemVer does not provide the means for defining the semantics for the prerelease tag identifiers (fields), beyond their sort order. Pure numeric prerelease identifiers sort lower than alpha-numeric identifiers. I have been working on and off, over the past few months, on a scheme to provide the means for developers to publish the full semantics of every field in their version scheme. A human and machine readable VersionSchema is required to bring more order to semantic versioning. See https://VersionMeta.org/ and stay tuned. |
IMO, @ronen suggestion to just drop rules 4 and 5 is simpler. When we could expect semver 3.0.0 prerelease with changed magic zero rule? |
Version 0.18.0 has a vulnerability https://nvd.nist.gov/vuln/detail/CVE-2019-10742 And bumps to x on 0.x.y are considered a major bump semver/semver#221
Feature/uk version
The "anything may change at any time" nature of a leading zero major version is somewhat disruptive for authors who may feel intimidated at the perceived commitment involved in a
1.0.0
release.We may all have see The Light, and realized that the number
1
is in fact a perfectly fine place to start counting our releases, and casually increment the major version with every breaking change if that change provides some value. But many are timid, and talking them out of their timidity is very difficult.Yet, the language in section 4 makes it very difficult to rely on pre-1.0 code. I believe that this increases, rather than decreases, the trepidation at marking something 1.0. It would be better with a slight increase in commitment; a stepping stone from the wild world of
0.0.4
up to the public scrutiny of1.2.3
.This would also allow project authors to communicate non-breaking additive changes in the
0.x.y
version families. In practice, many seem to treat the transition from0.9.2
to0.9.3
as a non-breaking change, whereas they'd treat0.9.2
to0.10.0
as potentially introducing breaking changes. (Node, for example, operates this way, though that is a pretty egregious example of Sentimental Versioning.)In effect, the left-most non-zero version number is the "effective major version", and incrementing it indicates a breaking change. The next place is the "effective minor version", and the third is the "effective patch version". This allows authors to more gradually shift from "anything goes" to "grownup".
The
^
operator in https://github.com/isaacs/node-semver used to operate this way, until some users requested that it instead follow the SemVer specification. However, shifting to^0.x.y
meaning "exactly equal to 0.x.y" has proven very problematic in practice.I haven't wordsmithed this very much, but this is a first-pass at some language we could use to express this. If others on this repo feel it's worthwhile, I'd be happy to send a proper pull request.
cc @haacked @mojombo @othiym23 @domenic @ceejbot
The text was updated successfully, but these errors were encountered: