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

pnpm update --filter --latest leads to the lockfile changing for unrelated project and dependencies, when dedupe-peer-dependents is false #8877

Closed
fpapado opened this issue Dec 16, 2024 · 1 comment

Comments

@fpapado
Copy link
Contributor

fpapado commented Dec 16, 2024

Last pnpm version that worked

9.4.0

pnpm version

9.15.0

Code to reproduce the issue

More specifically, this stopped working as expected in 9.5.0. Version 10 rc0 also does not work as expected.

I have a full reproduction at https://github.com/fpapado/pnpm-filtered-updated-changes-other-packages, so please refer to that for the full details / a cloneable set of code.

In prose:
You will need a workspace with two packages: a and b. Each of them depends (pure dependencies) on react@18.3.0.

Run pnpm --filter a update --latest react, to update react only for package a, resolving react@19.0.0. Optionally run pnpm install (the observed behaviour seems the same regardless).

Observe the lockfile diff, see that react@19.0.0 is resolved also for b. The package.json of b is unaffected.

diff --git a/packages/a/package.json b/packages/a/package.json
index 64bd07f..1dfb9e1 100644
--- a/packages/a/package.json
+++ b/packages/a/package.json
@@ -10,6 +10,6 @@
   "author": "",
   "license": "ISC",
   "dependencies": {
-    "react": "18.3.0"
+    "react": "19.0.0"
   }
 }
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index b3fe1d8..0cbf890 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -11,36 +11,21 @@ importers:
   packages/a:
     dependencies:
       react:
-        specifier: 18.3.0
-        version: 18.3.0
+        specifier: 19.0.0
+        version: 19.0.0

   packages/b:
     dependencies:
       react:
         specifier: 18.3.0
-        version: 18.3.0
+        version: 19.0.0

 packages:

-  js-tokens@4.0.0:
-    resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
-
-  loose-envify@1.4.0:
-    resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==}
-    hasBin: true
-
-  react@18.3.0:
-    resolution: {integrity: sha512-RPutkJftSAldDibyrjuku7q11d3oy6wKOyPe5K1HA/HwwrXcEqBdHsLypkC2FFYjP7bPUa6gbzSBhw4sY2JcDg==}
+  react@19.0.0:
+    resolution: {integrity: sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ==}
     engines: {node: '>=0.10.0'}

 snapshots:

-  js-tokens@4.0.0: {}
-
-  loose-envify@1.4.0:
-    dependencies:
-      js-tokens: 4.0.0
-
-  react@18.3.0:
-    dependencies:
-      loose-envify: 1.4.0
+  react@19.0.0: {}

pnpm ls -r react shows similar output:

pnpm ls -r react
Legend: production dependency, optional only, dev only

a@1.0.0 /Users/fotis/pnpm-filtered-updated-changes-other-packages/packages/a

dependencies:
react 19.0.0

b@1.0.0 /Users/fotis/pnpm-filtered-updated-changes-other-packages/packages/b

dependencies:
react 19.0.0

Expected behavior

That a resolves react@19.0.0 and b resolves react@18.3.0

Actual behavior

Now a resolves react@19.0.0 and b also resolves react@19.0.0

Additional information

While debugging and after reading the changelog for 9.5.0, I decided to set dedupe-peer-dependents=false in .npmrc, kind of on a whim. This actually fixes the issue, but I am confused, because we are not dealing with packages that are peer dependents.

It also seems odd to me that react@19.0.0 would be able to deduplicate react@18.3.0, since the major versions differ.

Please let me know if there is any other information I can provide; I might have missed something 😌

Node.js version

v22.12.0

Operating System

macOS

@fpapado fpapado changed the title pnpm update --filter leads to the lockfile changing for unrelated workspace packages pnpm update --filter leads to the lockfile changing for unrelated workspace packages, in a seemingly incompatible way Dec 16, 2024
fpapado added a commit to fpapado/pnpm that referenced this issue Dec 17, 2024
@fpapado
Copy link
Contributor Author

fpapado commented Dec 23, 2024

After some investigation, this seems to be an issue with update --latest and dedupe-peer-dependents=true, rather than update more generally.

For example, using an @latest specifier works as intended:

pnpm --filter a update react@latest

It updates only packages/a/package.json, and the relevant importers for packages/a in the lockfile:

diff --git a/packages/a/package.json b/packages/a/package.json
index 1ed69e4..96bf809 100644
--- a/packages/a/package.json
+++ b/packages/a/package.json
@@ -2,7 +2,6 @@
   "name": "a",
   "version": "1.0.0",
   "description": "",
   "main": "index.js",
   "scripts": {
     "test": "echo \"Error: no test specified\" && exit 1"
@@ -11,6 +10,6 @@
   "author": "",
   "license": "ISC",
   "dependencies": {
-    "react": "^18.2.0"
+    "react": "^19.0.0"
   }
 }
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index b56350f..43e002d 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -11,8 +11,8 @@ importers:
   packages/a:
     dependencies:
       react:
-        specifier: ^18.2.0
-        version: 18.2.0
+        specifier: ^19.0.0
+        version: 19.0.0
 
   packages/b:
     dependencies:
@@ -47,6 +47,10 @@ packages:
     resolution: {integrity: sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==}
     engines: {node: '>=0.10.0'}
 
+  react@19.0.0:
+    resolution: {integrity: sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ==}
+    engines: {node: '>=0.10.0'}
+
 snapshots:
 
   js-tokens@4.0.0: {}
@@ -65,3 +69,5 @@ snapshots:
   react@18.2.0:
     dependencies:
       loose-envify: 1.4.0
+
+  react@19.0.0: {}

On the other hand --latest seems to act like a "global" flag in this scenario, that gets threaded to the general opts for install and eventually to resolution:

const {
dependenciesTree,
outdatedDependencies,
resolvedImporters,
resolvedPkgsById,
wantedToBeSkippedPackageIds,
appliedPatches,
time,
allPeerDepNames,
} = await resolveDependencyTree(projectsToResolve, opts)
.

The interaction with dedupe-peer-dependents seems incidental, and does not have to do with the deduping per se. Early on, opts.dedupePeerDependents prompts a codepath that will do an install for all projects, and thus --latest will end up doing a latest-version resolution for every package for the workspace 😱

This means that other packages, aside from the specified one, will be updated. I updated the reproduction to show this issue, showing that a third workspace package with is-negative also gets updated: https://github.com/fpapado/pnpm-filtered-updated-changes-other-packages

@zkochan, this seems like a bit of a footgun, or at least inconsistent since update --filter --latest works with dedupe-peer-dependents=false. I have written some tests for this (need to clean up my branch), but fixing this might require some internal refactoring with how --latest gets treated. Another option would be to disallow --latest in this scenario. Have you run into similar cases before? How would you approach this?

fpapado added a commit to fpapado/pnpm that referenced this issue Dec 24, 2024
fpapado added a commit to fpapado/pnpm that referenced this issue Dec 24, 2024
Fixes pnpm#8877, whereby
`update --filter --latest` with `dedupe-peer-dependents` would end up
updating all available dependencies for all projects.
@fpapado fpapado changed the title pnpm update --filter leads to the lockfile changing for unrelated workspace packages, in a seemingly incompatible way pnpm update --filter --latest leads to the lockfile changing for unrelated project and dependencies, when dedupe-peer-dependents is false Dec 24, 2024
zkochan pushed a commit that referenced this issue Dec 29, 2024
…ages and projects, with `dedupe-peer-dependents=true` (#8905)

* test(update): add failing tests for update with dedupe-peer-dependents=true

Relates to #8877

* fix: update --filter --latest should work with dedupe-peer-dependents

Fixes #8877, whereby
`update --filter --latest` with `dedupe-peer-dependents` would end up
updating all available dependencies for all projects.

* test(pnpm): more accurate dedupePeers filtered install case

* docs: add changeset for updateToLatest moving to projects/importers

* docs: add changesets for pnpm and plugin-commands-installation

* chore: fix tsc issue by removing unknown bound resolver property

This unknown property was accepted by tsc prior to adding updateToLatest
in toResovleImporter options, but now it was erroring out. This is
likely a tsc quirk about the shape of the object; regardless that
property is not defined, and should not be present.

* test: keep only pnpm/test/monorepo/dedupePeers.test.ts

There was duplicate coverage of the pnpm update --filter --latest
command between two tests, so this keeps only the one dedicated
to testing the dedupe-peer-dependents feature.

* chore: fix unused import error
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

No branches or pull requests

1 participant