Skip to content
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

RFC: No implicit tagging for non-latest release versions #776

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

kytta
Copy link

@kytta kytta commented May 24, 2024

First reported in npm/npm#13248 and npm/cli#7553, this RFC proposes changing the behavior of npm publish by disallowing publishing pre-release versions under the latest tag (implicitly). This RFC also tackles the not-yet-implemented behavior for the non-latest release versions (e.g. backports).

References

Related to #26 and RFC 7

Directly relates to npm/cli#7553

@kytta kytta requested a review from a team as a code owner May 24, 2024 05:33
@wesleytodd
Copy link

I am a big plus 1 on this change, but I dont think this repo is the best place to discuss anymore.

@wraithgar
Copy link
Member

Added a link to this in the v11 roadmap. This would be a breaking change. I also like that it suggests just erroring instead of trying to come up with some alternate default tag or guessing one for the user.

@ljharb
Copy link
Contributor

ljharb commented May 24, 2024

I will be very ecstatic if npm v11 obsoletes https://npmjs.com/safe-publish-latest :-D

@davidlj95
Copy link

davidlj95 commented May 26, 2024

Agree that it's a better default to avoid instability 👍

Expanding on use cases of marking prereleases as latest, what about when a package has no stable release yet?

Packages are recommended to start at 1.0.0 if using SemVer as 0.x rules are pretty different. For instance:

In that scenario, how can we first get some feedback from users before actually releasing 1.0.0? Seems pre-releases are a good fit. Therefore you start publishing alpha and beta releases until everyone's happy about a 1.0.0 release.

I think in that scenario it makes sense the default of npm publish is to add the latest tags to every new alpha (and later beta) release.

Otherwise, I guess one could also use alpha and beta channels to publish releases in there. But users would have to do npm install pkg@alpha and npm install pkg@beta. Which indeed is more explicit about the state of the package. But state of the package can also be properly stated in docs.

I think for first pre-releases, users could be instructed to do npm install pkg as usual.
latest would point to last pre-release. And at the point the first stable release, they'll get only stable releases. Kind of a way to: install a pre-release until first stable release is ready.

WDYT?

In rest of scenarios (a first stable release 1.0.0 exists) totally agree that latest shouldn't be the default for pre-releases

@kytta
Copy link
Author

kytta commented May 27, 2024

Expanding on use cases of marking prereleases as latest, what about when a package has no stable release yet?

I think there is a big difference between 'unstable' and 'pre-release', and I personally think that this RFC should only tackle the latter.

Packages are recommended to start at 1.0.0 if using SemVer as 0.x rules are pretty different. For instance:

Semantic Release doesn't support 0.x versions

In that scenario, how can we first get some feedback from users before actually releasing 1.0.0? Seems pre-releases are a good fit. Therefore you start publishing alpha and beta releases until everyone's happy about a 1.0.0 release.

This is unfortunate. This is something I didn't know and haven't considered. I must say that I myself do not use Semantic Release, and I have always been using 0.x versions for unstable APIs.

I think for first pre-releases, users could be instructed to do npm install pkg as usual. latest would point to last pre-release. And at the point the first stable release, they'll get only stable releases. Kind of a way to: install a pre-release until first stable release is ready.

WDYT?

I personally am rather against this. This adds just way too much complexity to what should be a bare-bones setup. The logic behind npm publish should be explainable in a simple sentence, without too many edge cases. Everything else should better be handled by more sophisticated tools, be that np or semantic-release.

I'm interested what the others think, though :)

@wraithgar
Copy link
Member

I personally am rather against this. This adds just way too much complexity to what should be a bare-bones setup.

100% agree here. This is currently solving one valid problem in a very straightforward way. Let's keep it on task.

@wesleytodd
Copy link

I agree keeping it focused on prerelease for stable lines is a good decision, but just to be clear this means we are agreeing on "no carve out for special behavior on pre-1.0.0" right? I just felt like the above comments might have been a bit unclear as to what specifically folks were agreeing to.

@ljharb
Copy link
Contributor

ljharb commented May 28, 2024

To be clear, pre-v1.0, a breaking change increments the first or second number when the first number is zero, and any of the three numbers when the first two are zero, so “special behavior” would be anything that deviates from that - ie, from the way carat works.

@wraithgar
Copy link
Member

no carve out for special behavior on pre-1.0.0" right

Yes. We are only looking for pre-release tags here. They are a VERY clear signal that this is not a release. It's what it says on the tin.

@ljharb
Copy link
Contributor

ljharb commented May 28, 2024

The OP includes:

This RFC also tackles the not-yet-implemented behavior for the non-latest release versions (e.g. backports).

I think both are valuable to solve together.

@kytta
Copy link
Author

kytta commented May 28, 2024

I'd summarize it like this:

This RFC tackles a big footgun of npm publish: publishing something you think others will not automatically get, but they do get it. This applies to both pre-releases and older versions (backports) being automatically tagged as latest without any hesitation.

Special behaviour for 0.x versions (vs. 1.x) is not a footgun, but a preference, so it should not be addressed by this RFC (or probably any npm RFC, for that matter)

@wraithgar
Copy link
Member

Great summary @kytta

@jimmy-zhening-luo
Copy link

jimmy-zhening-luo commented Oct 27, 2024

Firstly, agree with everyone that this RFC cleanly solves a well-scoped problem (it's in the excellent PR title!).

Why this RFC is good

Goodness

@wraithgar put it succinctly that pre-release semantic versions are clearly, "pre-release", as it says on the tin. This implies a clean separation of concerns from the rest of the package lifecycle:

  • Preserves alignment with semantic versioning, because dist-tags are syntactic sugar, not versions.
  • Safely breaks (no publish) existing CI flows, including npm itself, that attached incorrect business assumptions to syntactic sugar (never a good idea):
    • npm publish incorrectly attaches latest to unreleased (i.e. "pre-released", potato potato) versions. It is correct for this workflow to fail safe, and safe behavior is failing to publish.
    • npm install is less guilty here, because it more or less does what it says it will do. You want latest? I'll give you latest. You want semantic version match? I'll give you semantic version match.

Evil goodness

Another "virtue" of this RFC is that this RFC:

  • Unsafely breaks publishers and consumers who don't RTFM and likely have incorrectly anchored their workflows to the latest synctactic sugar, without realizing that latest is rarely what you want, when you really want foo semantic version match, because there's no guarantee of what an arbitrary syntactic sugar means means.
  • Will cause unexpected, silent, non-zero cost to any workflows that incorrectly assumes that latest should have any meaning at all. (I'm a product manager who has occasionally written code: that means I have done every disgusting arcane incantation that you actual devs can't imagine, in production software that you know and lovehate.)

In my opinion, it is good and righteous moral punishment for the software ecosystem for such workflows to break unsafely.

Why dist-tags are bad

However, I feel the shitposting urge to point out that there was a deeper truth to the v0 question, and to also question whether the latest tag should even exist. Some "semantic" vocabulary:

v0 semantic versions

To be clear, pre-v1.0, a breaking change increments the first or second number when the first number is zero, and any of the three numbers when the first two are zero, so “special behavior” would be anything that deviates from that - ie, from the way carat works.

Agreed. As @ljharb correctly asserts, npm in agreement with semantic versioning spec, does treat 0.y.z specially, effectively right-shifting semantics:

  • z increments are minor versions
  • y increments are major versions

@ljharb, @wraithgar, and @kytta all made great individual points, and common to all their points is that a pre-release version has a very clear (to-spec, to-publisher, and to-consumer) that conveys one clear intention ("this ain't released yet") orthogonally to one other clear intention ("once released, this will be a {major|minor|patch} release").

Zero to Hero

You might ask, "Well hold on a second there bucko, if incrementing y means a major release, what in tarnation does incrementing x mean?"

That is a great question! Maybe it comes from me being a PM, or maybe it comes from me working at Big-Box Microsoft for so long, but here's one thing PMs and Devs will always fight over. PMs like me believe:

v0 software is NOT, real, software.

In other words, and the semantic versioning spec could have explained (it did not) why v0 semantics are right-shifted, and why npm correctly aligns its caret to that right-shift:

  • When your software is v0, it is not software.
  • The way to indicate that your software has gone from being not software to being software, is by incrementing x from 0 to 1.
  • From x=1 onward, you are shipping real big-boy code and you can feel free to use that third number slot, buckaroo!

This shouldn't be controversial either. We always say at Microsoft:

  • Incompetent teams "ship" v0s (never reach market)
  • Business-savvy engineers ship v1s, collect their gigantic bonus/promotion, and then bounce to go ship their next v1 somewhere else, while leaving v2 (and all of v1's bugs!) to the poor sap who replaces you and ships the real product while getting 0 rewards

Now, say what you want about Microsoft cynicism, but there is a deep business truth underlying the decisions of my former employer:

When we declare it a V1, we are on the hook for eternity.

The case for un-existing dist-tag

I seethe with impotent standards-based rage at the thought of non-semantic tags:

  • Entropy always increases, so they will never be manually maintained
  • Automation can be used to get it right, but the inherent lack of semantic means that I can arbitrarily override what foo dist-tag means, and foo includes latest.
  • Therefore, you'd have to be an absolute casual to ever rely on latest syntactic sugar in any meaningful way in your workflow. And casual includes me and my shit-tier personal projects, but sadly it seems to also include plenty of nth-level dependencies that have snuck its way into production code bases the world over.

Put more succinctly: if dist-tags are manual, they're guaranteed to be bad, and if they're automated, they're not guaranteed to be good.

In conclusion, dist-tag is bad engineering, and I don't care enough to actually fight this fight (just enough to write a manifesto about it). But, consider this my on-the-record diss track about the npm team for failing to understand what semantic versioning is.

@ljharb
Copy link
Contributor

ljharb commented Oct 28, 2024

v0 is absolutely real software, ftr. For it not to be real software, it would have to not exist (or be published). Enterprises or their norms simply don’t dictate how open source works in any way whatsoever :-)

@wraithgar
Copy link
Member

However, I feel the shitposting urge

Please don't do this. Consider this your final code of conduct warning

@wraithgar
Copy link
Member

The pre-release portion of this RFC is implemented in npm/cli#7910
The "semver precedence" portion overlaps with rfc 7, and since there is no way to publish with no dist-tag, this is as close to implementing that as we can get. It is being implemented in npm/cli#7939

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants