cli icon indicating copy to clipboard operation
cli copied to clipboard

[BUG] npm install does not include pre-release when determining version to install

Open johnwc opened this issue 1 year ago • 18 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

When installing via npm install our-library@">4.2.0-beta", npm does not find any version to install. It ignores any pre-release version unless you specify the exact pre-release version. Same with npm outdated, it does show that there is a new pre-release version available in the Latest column, but Wanted column is always current installed pre-release version. I have tried using >4.2.0-beta, ^4.2.0-beta, and ~4.2.0-beta. None will cause the outdated to show the new pre-release as wanted.

Expected Behavior

With the use of >4.2.0-beta, outdated and install should consider pre-release versions. Or add a command line switch to enable looking for pre-release versions.

Steps To Reproduce

Installing

  1. Build library that has pre-release version 1.0.1-beta-123 and publish it to npm repo.
  2. Try to install using >1.0.0-beta

Updating

  1. Build library that has pre-release version 1.0.1-beta-123 and publish it to npm repo.
  2. Install using @^1.0.1-beta-123
  3. Build new pre-release version 1.0.2-beta-456 and publish it to npm repo.
  4. Run npm outdated. Wanted shows 1.0.1-beta-123, Latest shows 1.0.2-beta-456

Environment

  • npm: 10.9.0
  • Node.js: v21.7.3
  • OS Name: Windows 11
  • npm config:

johnwc avatar Oct 17 '24 19:10 johnwc

This is by design, in all versions of npm. If you want prereleases included, the range has to explicitly include them, at each level.

ljharb avatar Oct 17 '24 19:10 ljharb

@ljharb this bug report is pointing out that the range does not work at all for pre-release.

johnwc avatar Oct 17 '24 19:10 johnwc

beta-123 and beta-456 are incompatible prerelease categories. Perhaps you want beta.123 and beta.456?

ljharb avatar Oct 17 '24 19:10 ljharb

I have tried all different types of formats. I just changed it to using a dash instead of period to test if it would work. And why are stating it is incompatible, it adheres to semver formatting.

image

johnwc avatar Oct 17 '24 19:10 johnwc

Also this, doesn't seem to accept the range.

> npm install our-library@">4.2.32-beta.ge8343d1e"

npm error code ETARGET
npm error notarget No matching version found for our-library@>4.2.32-beta.ge8343d1e.
npm error notarget In most cases you or one of your dependencies are requesting
npm error notarget a package version that doesn't exist.

johnwc avatar Oct 17 '24 19:10 johnwc

It's certainly valid - i just meant that they're two completely different buckets. In that latter example, use ^ instead of >, and i'd expect it to work.

ljharb avatar Oct 17 '24 19:10 ljharb

It installs with ^ but it does not find any later pre-releases upon running the outdated command. The pre-release is stuck as Wanted, and the newer pre-release is in Latest. There is no way to update your pre-release installed version using npm update. You have to manually run install again with the new pre-release version.

johnwc avatar Oct 17 '24 19:10 johnwc

hm, i wonder if that's because the part after the dot isn't numeric?

ljharb avatar Oct 17 '24 19:10 ljharb

Should the value after the dot even come into play yet, as the patch number is already higher in the newer pre-release

Example

>npm install our-library@^4.2.29-beta.g8c00b605
npm warn deprecated @npmcli/[email protected]: This functionality has been moved to @npmcli/fs
npm warn deprecated @npmcli/[email protected]: This functionality has been moved to @npmcli/fs

added 5 packages, and audited 1427 packages in 9s

162 packages are looking for funding
  run `npm fund` for details

25 vulnerabilities (2 low, 8 moderate, 11 high, 4 critical)

To address all issues, run:
  npm audit fix

Run `npm audit` for details.

>npm outdated our-library
Package                    Current                 Wanted                Latest  Location                       Depended by
our-library  4.2.29-beta.g8c00b605  4.2.29-beta.g8c00b605  4.2.37-beta-439e0756  node_modules/our-library       project

>npm update our-library
npm warn deprecated @npmcli/[email protected]: This functionality has been moved to @npmcli/fs
npm warn deprecated @npmcli/[email protected]: This functionality has been moved to @npmcli/fs

up to date, audited 1427 packages in 6s

162 packages are looking for funding
  run `npm fund` for details

27 vulnerabilities (2 low, 9 moderate, 12 high, 4 critical)

To address all issues, run:
  npm audit fix

Run `npm audit` for details.

johnwc avatar Oct 17 '24 19:10 johnwc

oh! i missed that. prereleases are for a specific version triple. your range there can only ever match prereleases for v4.2.32. Prereleases for a higher version need their own explicit range.

ljharb avatar Oct 17 '24 19:10 ljharb

In other words, typically people only make prereleases for a new major version, because that way ^X.0.0-0 can cover all of them for a given X.

ljharb avatar Oct 17 '24 20:10 ljharb

That may be true and valid for public pre-releases, but for internal teams working off of shared libraries in repos, our patch versions increase with each build. The part after the period is just the commit hash of git.

How can we get a feature added then to have a command line switch or a setting in packages.json to allow upgrading pre-releases like normal releases?

johnwc avatar Oct 17 '24 20:10 johnwc

The commit hash seems like something that would go in the build signifier (+), which npm doesn't support and actively strips.

Is there a reason you can't just use normal patch versions?

ljharb avatar Oct 17 '24 20:10 ljharb

We are using patch version, as you can see that the patch version increments on each build 4.2.29-beta -> 4.2.37-beta

johnwc avatar Oct 17 '24 20:10 johnwc

Sorry, i meant, non-prerelease patch versions. Like, just 4.2.29 and 4.2.37. Then you'd get all the semver ranges you want.

Prereleases are meant for one-off testing, not for parallel release lines.

ljharb avatar Oct 17 '24 20:10 ljharb

That is a difference of opinion. Pre-release build is just that, a release that is not stable, not one-off tests. They are versions of the code that can be used while development is going on. Especially for large projects that have different libraries.

johnwc avatar Oct 17 '24 20:10 johnwc

I mean, given the way npm has implemented semver and ranges forever, it's a bit more concrete than opinion. It's not going to work for what you want, unfortunately.

ljharb avatar Oct 17 '24 20:10 ljharb

Ok, it is a npm opinion, but that should not force it upon everyone. npm is merely a package manager, it should not dictate a team's way of versioning when the team is perfectly aligned with the versioning scheme the package manager is supposed to conform to. Plus, if you go to npm documentation, they literally point you to an example search interface that explains how to select based on pre-release ranges... Why would it not work the way most folks would expect it to work, and most all other package managers work? Not asking to rewrite it, I am asking for an opt-in way of enabling it to work.

Also, just because something is always done a certain way doesn't mean change can't be made for improvement. Otherwise, we would still be writing in assembly...

johnwc avatar Oct 18 '24 01:10 johnwc

The special prerelease behaviour is surprising the first time you hit it when expecting a different behaviour.

There is extensive coverage in the semver README which explains the behaviour and the rationale: https://github.com/npm/node-semver#prerelease-tags

(@ljharb touched on the key issues above, but the README lays it out nicely.)

You might get most of what you want by not updating the patch version with every build? Conventionally 4.2.32-beta.ge8343d1e is a pre-release build of 4.2.32. What "release" are you heading towards? You can include a build number in the prerelease information like: 4.2.32-beta.1.ge8343d1e, or treating the hash as meta information: 4.2.32-beta.1+ge8343d1e

The underlying semver package supports a includePrerelease flag which is what you asked for, but as far as I can see that is not exposed by the npm CLI configuration.

shadowspawn avatar Oct 22 '24 19:10 shadowspawn