You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[rush] Copy the temp lockfile when pnpm changes it during rush update - #6119
With pnpm 12, rush update can leave common/config/rush/pnpm-lock.yaml out of date. pnpm writes a new peer version to common/temp/pnpm-lock.yaml, but Rush does not copy that file back. A new clone then runs rush install and links packages that the committed lockfile does not record.
Details
The problem
rush update gives pnpm --no-prefer-frozen-lockfile, so pnpm resolves the dependencies again. pnpm 11 keeps the peer versions that the lockfile records. pnpm 12 recomputes them, so it can pick a different peer version when no package.json file changed.
Rush copies the temp lockfile back only when its own check finds a package.json change. Here that check finds none, so Rush drops the new lockfile:
After pnpm runs, rush update compares the temp lockfile with the committed lockfile. If they differ, Rush copies the temp lockfile back.
The new method BaseInstallManager.shouldCopyTempShrinkwrapAsync holds this decision.
It applies to pnpm 12 and later. npm, yarn, and pnpm 11 keep today's behavior.
rush install does not change.
Before pnpm runs, Rush copies the committed lockfile into common/temp. So the two files differ only when pnpm changed the temp lockfile, and an unchanged lockfile causes no copy.
How to test this with a repro case
# In the rushstack repo, on this branch, with Node 22:
node common/scripts/install-run-rush.js install
node common/scripts/install-run-rush.js build --to @microsoft/rush
# In https://github.com/brunojppb/rush-pnpm-12-lockfile-issue, with Node 24:
REPRO_RUSH_START=/path/to/rushstack/apps/rush/lib-commonjs/start-dev.js ./repro.sh
pnpm versions: pnpm 11.24.0 and 11.28.5 keep the old peer version. pnpm 12.4.0 to 12.10.1 change it.
The reason will be displayed to describe this comment to others. Learn more.
I reproduced this locally. With pnpm 12.10.1 and a lockfile that still records an old peer version, the default rush install exited 0. But node_modules linked graphql@16.13.1, and the committed lockfile recorded graphql@17.0.0-alpha.7.
In e902154, rush install with pnpm 12 or later now compares the temp lockfile with the committed lockfile after pnpm runs. If they differ, the install fails and tells the user to run rush update. With the same lockfile, rush install now exits 1.
I did not make --frozen-lockfile the default. That changes rush install for every pnpm 12 user. In this case it also keeps the old peer version, which does not satisfy the peer range ^17.0.0. usePnpmFrozenLockfileForRushInstall stays optional, and the docs now describe it that way. The check does not run when that setting is on, because pnpm then installs what the lockfile records.
Filtered installs (--to, --only) do not change a correct lockfile on pnpm 12, so they pass the check. The new tests are in BaseInstallManager.test.ts, under validateTempShrinkwrapAfterInstallAsync.
With pnpm 12, "rush install" gives pnpm "--no-prefer-frozen-lockfile".
pnpm can then recompute peer versions and link versions that the committed
lockfile does not record. "rush install" finished without an error.
Now "rush install" compares the temp lockfile with the committed lockfile
after pnpm runs. If they differ, it fails and tells the user to run
"rush update". The check does not run when usePnpmFrozenLockfileForRushInstall
is on, because pnpm then installs what the lockfile records.
… rush update
"rush update" ran validateShrinkwrapAfterUpdate on the committed lockfile,
then copied the temp lockfile over it. So the disallowInsecureSha1 policy
checked the old lockfile, and the new lockfile went in without a check.
If no committed lockfile existed, the check did not run at all.
Now "rush update" checks the temp lockfile, which is the file that it copies.
…ger tests
Two tests expect an error message. The manager wrote it to the console, so
it went to stderr. Rush reports stderr output as a warning, and CI fails
"rush retest" on a warning. The tests now use a StringBufferTerminalProvider
and check the error text there.
This new validation call changes rush install for pnpm 12+: it can now fail after pnpm rewrites the temp lockfile, while the PR description still states that “rush install does not change.” Since the new failure is intentional and is also documented in the change file, please update that PR-description bullet so reviewers and release consumers see the actual scope.
* By default, 'rush install' passes --no-prefer-frozen-lockfile to 'pnpm install'.
* Set this option to true to pass '--frozen-lockfile' instead for faster installs.
* With pnpm 12 and later, 'rush install' fails if pnpm changes the lockfile. Set this option to true to install the versions that the lockfile records instead.
The reason will be displayed to describe this comment to others. Learn more.
wondering if this should be enabled by default as a separate experiment flag. seems like the correct behavior to enable.
copying the common/temp/pnpm-lock.yaml file over is also what --recheck does. Does this make --recheck redundant?
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes #6117
With pnpm 12,
rush updatecan leavecommon/config/rush/pnpm-lock.yamlout of date. pnpm writes a new peer version tocommon/temp/pnpm-lock.yaml, but Rush does not copy that file back. A new clone then runsrush installand links packages that the committed lockfile does not record.Details
The problem
rush updategives pnpm--no-prefer-frozen-lockfile, so pnpm resolves the dependencies again. pnpm 11 keeps the peer versions that the lockfile records. pnpm 12 recomputes them, so it can pick a different peer version when nopackage.jsonfile changed.Rush copies the temp lockfile back only when its own check finds a
package.jsonchange. Here that check finds none, so Rush drops the new lockfile:The fix
After pnpm runs,
rush updatecompares the temp lockfile with the committed lockfile. If they differ, Rush copies the temp lockfile back.BaseInstallManager.shouldCopyTempShrinkwrapAsyncholds this decision.rush installdoes not change.Before pnpm runs, Rush copies the committed lockfile into
common/temp. So the two files differ only when pnpm changed the temp lockfile, and an unchanged lockfile causes no copy.How to test this with a repro case
Impacted documentation
The
usePnpmFrozenLockfileForRushInstalldocs (https://rushjs.io/pages/configs/experiments_json/) now recommend it for pnpm 12.