cli icon indicating copy to clipboard operation
cli copied to clipboard

[BUG] "npm publish" tags pre-versions as "latest"

Open kytta opened this issue 1 year ago • 3 comments

Is there an existing issue for this?

  • [X] I have searched the existing issues

This issue exists in the latest npm version

  • [X] I am using the latest npm

Current Behavior

NOTE: This is rather a footgun than a bug

This was reported in https://github.com/npm/npm/issues/13248 and has been ignored and never re-opened since, even though the problem clearly still exists. Following is the (adapted) description from the issues' original author. I have verified that this behaviour is still present.


Running npm version premajor && npm publish will tag the premajor version as latest by default. I confirmed this happens when running all pre-release options: premajor | preminor | prepatch | prerelease.

As pointed out in https://github.com/npm/npm/issues/10189, there are valid reasons that authors would want to tag pre-release versions as latest. However, I think that this is not good default behaviour (though it is documented: "Publishing a package sets the latest tag to the published version unless the --tag option is used. For example, npm publish --tag=beta.")

Semver documentation states:

A pre-release version indicates that the version is unstable and might not satisfy the intended compatibility requirements as denoted by its associated normal version. Examples: 1.0.0-alpha, 1.0.0-alpha.1, 1.0.0-0.3.7, 1.0.0-x.7.z.92.

Source: http://semver.org/#spec-item-9

Expected Behavior

I propose that the latest tag only be set if the version to be published is not a pre-release version. Or, at the very least, there should be a warning about this.

Steps To Reproduce

  1. While in any package directory...
  2. Run npm version prepatch or ... preminor or ... premajor or ... prerelease or set a pre-release version manually
  3. Run npm publish
  4. See that the package gets published to the latest tag without any fuss

Environment

  • npm: 10.5.2
  • Node.js: 20.13.0
  • OS Name: macOS Ventura 13.6.6
  • System Model Name: MacBook Pro 14-inch 2023 M2 Pro 32GB RAM
  • npm config:
; "project" config from /Users/nikitakaramov/Code/@kytta/npmtest/.npmrc

@kytta:registry = (redacted) 
//(redacted)/:_authToken = (protected) 

; "env" config from environment

userconfig = "/Users/nikitakaramov/.config/npm/npmrc" 

; node bin location = /Users/nikitakaramov/.local/share/mise/installs/node/20.13.0/bin/node
; node version = v20.13.0
; npm local prefix = /Users/nikitakaramov/Code/@kytta/npmtest
; npm version = 10.5.2
; cwd = /Users/nikitakaramov/Code/@kytta/npmtest
; HOME = /Users/nikitakaramov
; Run `npm config ls -l` to show all defaults.

kytta avatar May 22 '24 12:05 kytta

Some tag must always be set - what tag would you expect as an alternative?

ljharb avatar May 22 '24 14:05 ljharb

Some tag must always be set - what tag would you expect as an alternative?

If not failing for pre-release builds (which would force the user to set the tag), I'd choose either:

  • next for any semver-compliant pre-release version, or
  • the tag that matches the prerelease suffix, if there is any. For example, 2.0.0-alpha.1 would get the tag alpha, 2.0.0-rc.3 would get the tag rc

kytta avatar May 22 '24 15:05 kytta

failing and forcing a tag seems nice. even better is if it implemented https://npmjs.com/safe-publish-latest, and failed to implicitly publish a latest whenever the version being published isn't a non-prerelease that is "later" than all existing versions.

ljharb avatar May 22 '24 15:05 ljharb

So, this behaviour, then?

npm version 1.0.0
npm publish # no problem

npm version 1.0.1-alpha.1
npm publish
# npm ERR no tag set

npm publish --tag alpha # no problem

npm version 1.0.1-alpha.2
npm publish --tag latest # no problem; set implicitly

npm version 0.1.0 # assuming it's possible
npm publish
# npm ERR a newer 'latest' version is already published

Another question. What should we do about this behaviour:

  1. developer willingly publishes a pre-release to latest (https://github.com/npm/npm/issues/10189#issuecomment-156324153)
    • say, 1.0.0-rc.1 => latest
  2. developer makes a new pre-release version with the same version number (major.minor.patch), and a different pre-release identifier combo
    • say, 1.0.0-rc.2
  3. developer runs npm publish

Should we allow this, because the developer "opted-in" to publishing pre-releases for 1.0.0 to latest (in other words, because the current latest is also a pre-release), or should we always require an explicit tag for pre-releases?

kytta avatar May 23 '24 07:05 kytta

If they explicitly want something to be "latest" then it would be wildly improper for npm to prevent that, but it seems reasonable to me that implicit "latest" must always be a "later" non-prerelease.

(to be clear, this is something that'd have to be accepted by the npm team, and probably should be discussed in the RFC repo instead of here)

ljharb avatar May 23 '24 16:05 ljharb

If they explicitly want something to be "latest" then it would be wildly improper for npm to prevent that, but it seems reasonable to me that implicit "latest" must always be a "later" non-prerelease.

Sounds good. It also matches the behaviour proposed in RFC 7

(to be clear, this is something that'd have to be accepted by the npm team, and probably should be discussed in the RFC repo instead of here)

Thanks for the heads-up! I've drafted one here: https://github.com/npm/rfcs/pull/776

kytta avatar May 24 '24 05:05 kytta

➕ 1 on failing when not passing an explicit --tag for prerelease versions. This has bitten me so many times over the years and has contributed to my beliefs automated publish workflows are superior (despite the tradeoffs). This would remove one of the rough edges around manual publish workflows and seems pretty clearly to be a good thing.

wesleytodd avatar May 24 '24 15:05 wesleytodd

Because this is not a bug I am going to close this issue. The rfc issue is probably the best place to add more input. Personally I'm a huge fan of this idea.

wraithgar avatar May 24 '24 16:05 wraithgar