Skip to content

Commit 2a01cc8

Browse files
authored
fix: do not pass --prefer-frozen-lockfile during --lockfile-only phase with pnpm v10
1 parent 86d53ab commit 2a01cc8

2 files changed

Lines changed: 47 additions & 2 deletions

File tree

libraries/rush-lib/src/logic/base/BaseInstallManager.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -883,8 +883,11 @@ ${gitLfsHookHandling}
883883
// On pnpm@8, disable the "dedupe-peer-dependents" feature when doing a filtered CI install so that filters take effect.
884884
args.push('--config.dedupe-peer-dependents=false');
885885
}
886-
} else if (experiments.usePnpmPreferFrozenLockfileForRushUpdate) {
887-
// In workspaces, we want to avoid unnecessary lockfile churn
886+
} else if (experiments.usePnpmPreferFrozenLockfileForRushUpdate && !onlyShrinkwrap) {
887+
// In workspaces, we want to avoid unnecessary lockfile churn.
888+
// Do NOT use --prefer-frozen-lockfile during the --lockfile-only phase: pnpm v10
889+
// omits the packages:/snapshots: sections when this combination is used, producing
890+
// a broken lockfile that fails the subsequent --frozen-lockfile install phase.
888891
args.push('--prefer-frozen-lockfile');
889892
} else {
890893
// Ensure that Rush's tarball dependencies get synchronized properly with the pnpm-lock.yaml file.

libraries/rush-lib/src/logic/test/BaseInstallManager.test.ts

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,4 +129,46 @@ describe('BaseInstallManager Test', () => {
129129
);
130130
}
131131
});
132+
133+
it('usePnpmPreferFrozenLockfileForRushUpdate should not add --prefer-frozen-lockfile when onlyShrinkwrap is true', () => {
134+
const rushJsonFile: string = path.resolve(__dirname, 'ignoreCompatibilityDb/rush3.json');
135+
const rushConfiguration: RushConfiguration = RushConfiguration.loadFromConfigurationFile(rushJsonFile);
136+
const purgeManager: typeof PurgeManager.prototype = new PurgeManager(rushConfiguration, rushGlobalFolder);
137+
138+
// Enable the usePnpmPreferFrozenLockfileForRushUpdate experiment
139+
Object.defineProperty(rushConfiguration.experimentsConfiguration, 'configuration', {
140+
value: { usePnpmPreferFrozenLockfileForRushUpdate: true },
141+
writable: false,
142+
configurable: true
143+
});
144+
145+
const fakeBaseInstallManager: FakeBaseInstallManager = new FakeBaseInstallManager(
146+
rushConfiguration,
147+
rushGlobalFolder,
148+
purgeManager,
149+
{ subspace: rushConfiguration.defaultSubspace } as IInstallManagerOptions
150+
);
151+
152+
// When onlyShrinkwrap is true (Phase 1 of two-phase install), --prefer-frozen-lockfile must NOT be added.
153+
// pnpm v10 omits packages:/snapshots: sections when --prefer-frozen-lockfile and --lockfile-only are
154+
// combined, producing a broken lockfile that fails the subsequent --frozen-lockfile install phase.
155+
const argsWithOnlyShrinkwrap: string[] = [];
156+
fakeBaseInstallManager.pushConfigurationArgs(
157+
argsWithOnlyShrinkwrap,
158+
{ onlyShrinkwrap: true, pnpmFilterArgumentValues: [] } as unknown as IInstallManagerOptions,
159+
rushConfiguration.defaultSubspace
160+
);
161+
expect(argsWithOnlyShrinkwrap).not.toContain('--prefer-frozen-lockfile');
162+
expect(argsWithOnlyShrinkwrap).toContain('--lockfile-only');
163+
164+
// When onlyShrinkwrap is false (single-phase or Phase 2), --prefer-frozen-lockfile should be added.
165+
const argsWithoutOnlyShrinkwrap: string[] = [];
166+
fakeBaseInstallManager.pushConfigurationArgs(
167+
argsWithoutOnlyShrinkwrap,
168+
{ onlyShrinkwrap: false, pnpmFilterArgumentValues: [] } as unknown as IInstallManagerOptions,
169+
rushConfiguration.defaultSubspace
170+
);
171+
expect(argsWithoutOnlyShrinkwrap).toContain('--prefer-frozen-lockfile');
172+
expect(argsWithoutOnlyShrinkwrap).not.toContain('--lockfile-only');
173+
});
132174
});

0 commit comments

Comments
 (0)