From 6132b7dce191855e49caa54b533926448a46a6b5 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 9 Feb 2026 22:15:24 +0000 Subject: [PATCH 1/6] Initial plan From fad6e8fd35bf1f632710154368194136b2c00c20 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 9 Feb 2026 22:28:19 +0000 Subject: [PATCH 2/6] fix: handle versioned selectors in globalOverrides for shrinkwrap comparison When globalOverrides uses versioned selectors (e.g. "webpack@5": "5.103.0"), the shrinkwrap comparison now correctly resolves the override by matching the package name and checking version range intersection with semver.intersects. Previously, only exact package name matches were checked (this.overrides.get(name)), which caused versioned selector keys like "webpack@5" to never match lookups for "webpack", making rush update never stabilize. Co-authored-by: bmiddha <5100938+bmiddha@users.noreply.github.com> --- .../src/logic/pnpm/PnpmShrinkwrapFile.ts | 50 +++++++++++++++++-- .../pnpm/test/PnpmShrinkwrapFile.test.ts | 45 +++++++++++++++++ .../versioned-overrides-not-modified.yaml | 32 ++++++++++++ .../versioned-overrides-not-modified.yaml | 32 ++++++++++++ .../versioned-overrides-not-modified.yaml | 41 +++++++++++++++ 5 files changed, 197 insertions(+), 3 deletions(-) create mode 100644 libraries/rush-lib/src/logic/pnpm/test/yamlFiles/pnpm-lock-v5/versioned-overrides-not-modified.yaml create mode 100644 libraries/rush-lib/src/logic/pnpm/test/yamlFiles/pnpm-lock-v6/versioned-overrides-not-modified.yaml create mode 100644 libraries/rush-lib/src/logic/pnpm/test/yamlFiles/pnpm-lock-v9/versioned-overrides-not-modified.yaml diff --git a/libraries/rush-lib/src/logic/pnpm/PnpmShrinkwrapFile.ts b/libraries/rush-lib/src/logic/pnpm/PnpmShrinkwrapFile.ts index 97068b557ec..af6a90fac77 100644 --- a/libraries/rush-lib/src/logic/pnpm/PnpmShrinkwrapFile.ts +++ b/libraries/rush-lib/src/logic/pnpm/PnpmShrinkwrapFile.ts @@ -1110,7 +1110,9 @@ export class PnpmShrinkwrapFile extends BaseShrinkwrapFile { if (!foundDependency) { return true; } - const resolvedVersion: string = this.overrides.get(importerPackageName) ?? foundDependency.version; + const resolvedVersion: string = + this._resolveOverrideVersion(importerPackageName, foundDependency.version) ?? + foundDependency.version; if (resolvedVersion !== importerVersionSpecifier) { return true; } @@ -1167,7 +1169,7 @@ export class PnpmShrinkwrapFile extends BaseShrinkwrapFile { if (this.shrinkwrapFileMajorVersion >= ShrinkwrapFileMajorVersion.V9) { // TODO: Emit an error message when someone tries to override a version of something in one of their // local repo packages. - let resolvedVersion: string = this.overrides.get(name) ?? version; + let resolvedVersion: string = this._resolveOverrideVersion(name, version) ?? version; // convert path in posix style, otherwise pnpm install will fail in subspace case resolvedVersion = Path.convertToSlashes(resolvedVersion); const specifier: string = importer.specifiers[name]; @@ -1183,7 +1185,7 @@ export class PnpmShrinkwrapFile extends BaseShrinkwrapFile { } else { // TODO: Emit an error message when someone tries to override a version of something in one of their // local repo packages. - let resolvedVersion: string = this.overrides.get(name) ?? version; + let resolvedVersion: string = this._resolveOverrideVersion(name, version) ?? version; // convert path in posix style, otherwise pnpm install will fail in subspace case resolvedVersion = Path.convertToSlashes(resolvedVersion); if ( @@ -1218,6 +1220,48 @@ export class PnpmShrinkwrapFile extends BaseShrinkwrapFile { return false; } + /** + * Look up the override value for a given package name and version. + * Handles versioned selectors like "webpack@5" in addition to simple "webpack" keys. + */ + private _resolveOverrideVersion(name: string, version: string): string | undefined { + // First, try exact match by package name + const exactMatch: string | undefined = this.overrides.get(name); + if (exactMatch !== undefined) { + return exactMatch; + } + + // Then try versioned selectors (e.g., "webpack@5" or "@scope/pkg@^2.0.0") + for (const [key, value] of this.overrides) { + // Skip nested dependency selectors (contain '>') + if (key.includes('>')) { + continue; + } + + // Parse the package name and version range from the override key. + // Handle scoped packages (@scope/pkg@range) by finding the '@' after the scope prefix. + const atIndex: number = key.startsWith('@') ? key.indexOf('@', 1) : key.indexOf('@'); + if (atIndex === -1) { + continue; // No version selector, already handled by exact match above + } + + const packageName: string = key.substring(0, atIndex); + const rangeStr: string = key.substring(atIndex + 1); + + if (packageName === name) { + try { + if (semver.intersects(version, rangeStr)) { + return value; + } + } catch { + // If semver parsing fails (e.g. for non-semver versions), skip this override + } + } + } + + return undefined; + } + private _getIntegrityForPackage(specifier: string, optional: boolean): Map { const integrities: Map> = this._integrities; diff --git a/libraries/rush-lib/src/logic/pnpm/test/PnpmShrinkwrapFile.test.ts b/libraries/rush-lib/src/logic/pnpm/test/PnpmShrinkwrapFile.test.ts index b0a090ed9fc..49cd88bdf98 100644 --- a/libraries/rush-lib/src/logic/pnpm/test/PnpmShrinkwrapFile.test.ts +++ b/libraries/rush-lib/src/logic/pnpm/test/PnpmShrinkwrapFile.test.ts @@ -362,6 +362,21 @@ snapshots: ) ).resolves.toBe(false); }); + + it('can detect versioned overrides', async () => { + const project = getMockRushProject(); + const pnpmShrinkwrapFile = getPnpmShrinkwrapFileFromFile( + `${__dirname}/yamlFiles/pnpm-lock-v5/versioned-overrides-not-modified.yaml`, + project.rushConfiguration.defaultSubspace + ); + await expect( + pnpmShrinkwrapFile.isWorkspaceProjectModifiedAsync( + project, + project.rushConfiguration.defaultSubspace, + undefined + ) + ).resolves.toBe(false); + }); }); describe('pnpm lockfile major version 6', () => { @@ -410,6 +425,21 @@ snapshots: ).resolves.toBe(false); }); + it('can detect versioned overrides', async () => { + const project = getMockRushProject(); + const pnpmShrinkwrapFile = getPnpmShrinkwrapFileFromFile( + `${__dirname}/yamlFiles/pnpm-lock-v6/versioned-overrides-not-modified.yaml`, + project.rushConfiguration.defaultSubspace + ); + await expect( + pnpmShrinkwrapFile.isWorkspaceProjectModifiedAsync( + project, + project.rushConfiguration.defaultSubspace, + undefined + ) + ).resolves.toBe(false); + }); + it('can handle the inconsistent version of a package declared in dependencies and devDependencies', async () => { const project = getMockRushProject2(); const pnpmShrinkwrapFile = getPnpmShrinkwrapFileFromFile( @@ -472,6 +502,21 @@ snapshots: ).resolves.toBe(false); }); + it('can detect versioned overrides', async () => { + const project = getMockRushProject(); + const pnpmShrinkwrapFile = getPnpmShrinkwrapFileFromFile( + `${__dirname}/yamlFiles/pnpm-lock-v9/versioned-overrides-not-modified.yaml`, + project.rushConfiguration.defaultSubspace + ); + await expect( + pnpmShrinkwrapFile.isWorkspaceProjectModifiedAsync( + project, + project.rushConfiguration.defaultSubspace, + undefined + ) + ).resolves.toBe(false); + }); + it('can handle the inconsistent version of a package declared in dependencies and devDependencies', async () => { const project = getMockRushProject2(); const pnpmShrinkwrapFile = getPnpmShrinkwrapFileFromFile( diff --git a/libraries/rush-lib/src/logic/pnpm/test/yamlFiles/pnpm-lock-v5/versioned-overrides-not-modified.yaml b/libraries/rush-lib/src/logic/pnpm/test/yamlFiles/pnpm-lock-v5/versioned-overrides-not-modified.yaml new file mode 100644 index 00000000000..e178078ab17 --- /dev/null +++ b/libraries/rush-lib/src/logic/pnpm/test/yamlFiles/pnpm-lock-v5/versioned-overrides-not-modified.yaml @@ -0,0 +1,32 @@ +lockfileVersion: 5.3 + +overrides: + typescript@~5: 5.0.4 + +importers: + .: + specifiers: {} + + ../../apps/foo: + specifiers: + tslib: ~2.3.1 + typescript: 5.0.4 + dependencies: + tslib: 2.3.1 + devDependencies: + typescript: 5.0.4 + +packages: + /typescript/5.0.4: + resolution: + { + integrity: sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw== + } + engines: { node: '>=12.20' } + hasBin: true + + /tslib/2.3.1: + resolution: + { + integrity: sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw== + } diff --git a/libraries/rush-lib/src/logic/pnpm/test/yamlFiles/pnpm-lock-v6/versioned-overrides-not-modified.yaml b/libraries/rush-lib/src/logic/pnpm/test/yamlFiles/pnpm-lock-v6/versioned-overrides-not-modified.yaml new file mode 100644 index 00000000000..98d524112d3 --- /dev/null +++ b/libraries/rush-lib/src/logic/pnpm/test/yamlFiles/pnpm-lock-v6/versioned-overrides-not-modified.yaml @@ -0,0 +1,32 @@ +lockfileVersion: '6.0' + +overrides: + typescript@~5: 5.0.4 + +importers: + .: {} + + ../../apps/foo: + dependencies: + tslib: + specifier: ~2.3.1 + version: 2.3.1 + devDependencies: + typescript: + specifier: 5.0.4 + version: 5.0.4 + +packages: + /typescript/5.0.4: + resolution: + { + integrity: sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw== + } + engines: { node: '>=12.20' } + hasBin: true + + /tslib/2.3.1: + resolution: + { + integrity: sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw== + } diff --git a/libraries/rush-lib/src/logic/pnpm/test/yamlFiles/pnpm-lock-v9/versioned-overrides-not-modified.yaml b/libraries/rush-lib/src/logic/pnpm/test/yamlFiles/pnpm-lock-v9/versioned-overrides-not-modified.yaml new file mode 100644 index 00000000000..4d19edffa07 --- /dev/null +++ b/libraries/rush-lib/src/logic/pnpm/test/yamlFiles/pnpm-lock-v9/versioned-overrides-not-modified.yaml @@ -0,0 +1,41 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +overrides: + typescript@~5: 5.0.4 + +importers: + .: {} + + ../../apps/foo: + dependencies: + tslib: + specifier: ~2.3.1 + version: 2.3.1 + devDependencies: + typescript: + specifier: 5.0.4 + version: 5.0.4 + +packages: + tslib@2.3.1: + resolution: + { + integrity: sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw== + } + + typescript@5.0.4: + resolution: + { + integrity: sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw== + } + engines: { node: '>=12.20' } + hasBin: true + +snapshots: + tslib@2.3.1: {} + + typescript@5.0.4: {} From 0ff1e63bb6b93319279a9bc4b74b918311ba7934 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 9 Feb 2026 22:41:39 +0000 Subject: [PATCH 3/6] fix: also handle nested dependency selectors (consumer>dependency) in override resolution The _resolveOverrideVersion method now extracts the dependency portion from nested selectors like "consumer>dependency" or "consumer@1>dependency@2" instead of skipping them entirely. This prevents the same "never stabilizes" bug from occurring with nested dependency override selectors. Co-authored-by: dmichon-msft <26827560+dmichon-msft@users.noreply.github.com> --- .../src/logic/pnpm/PnpmShrinkwrapFile.ts | 28 +++++++----- .../pnpm/test/PnpmShrinkwrapFile.test.ts | 45 +++++++++++++++++++ .../nested-overrides-not-modified.yaml | 32 +++++++++++++ .../nested-overrides-not-modified.yaml | 32 +++++++++++++ .../nested-overrides-not-modified.yaml | 41 +++++++++++++++++ 5 files changed, 168 insertions(+), 10 deletions(-) create mode 100644 libraries/rush-lib/src/logic/pnpm/test/yamlFiles/pnpm-lock-v5/nested-overrides-not-modified.yaml create mode 100644 libraries/rush-lib/src/logic/pnpm/test/yamlFiles/pnpm-lock-v6/nested-overrides-not-modified.yaml create mode 100644 libraries/rush-lib/src/logic/pnpm/test/yamlFiles/pnpm-lock-v9/nested-overrides-not-modified.yaml diff --git a/libraries/rush-lib/src/logic/pnpm/PnpmShrinkwrapFile.ts b/libraries/rush-lib/src/logic/pnpm/PnpmShrinkwrapFile.ts index af6a90fac77..ee689d53acb 100644 --- a/libraries/rush-lib/src/logic/pnpm/PnpmShrinkwrapFile.ts +++ b/libraries/rush-lib/src/logic/pnpm/PnpmShrinkwrapFile.ts @@ -1222,7 +1222,8 @@ export class PnpmShrinkwrapFile extends BaseShrinkwrapFile { /** * Look up the override value for a given package name and version. - * Handles versioned selectors like "webpack@5" in addition to simple "webpack" keys. + * Handles versioned selectors like "webpack@5" and nested dependency selectors like + * "consumer>webpack" or "consumer@1>webpack@5" in addition to simple "webpack" keys. */ private _resolveOverrideVersion(name: string, version: string): string | undefined { // First, try exact match by package name @@ -1232,21 +1233,28 @@ export class PnpmShrinkwrapFile extends BaseShrinkwrapFile { } // Then try versioned selectors (e.g., "webpack@5" or "@scope/pkg@^2.0.0") + // and nested dependency selectors (e.g., "consumer>webpack" or "consumer@1>webpack@5") for (const [key, value] of this.overrides) { - // Skip nested dependency selectors (contain '>') - if (key.includes('>')) { - continue; - } + // For nested dependency selectors (contain '>'), extract the dependency portion after '>'. + // For example: "bar@1>foo@2" -> dependency selector is "foo@2" + const depSelector: string = key.includes('>') ? key.substring(key.indexOf('>') + 1) : key; - // Parse the package name and version range from the override key. + // Parse the package name and version range from the selector. // Handle scoped packages (@scope/pkg@range) by finding the '@' after the scope prefix. - const atIndex: number = key.startsWith('@') ? key.indexOf('@', 1) : key.indexOf('@'); + const atIndex: number = depSelector.startsWith('@') + ? depSelector.indexOf('@', 1) + : depSelector.indexOf('@'); if (atIndex === -1) { - continue; // No version selector, already handled by exact match above + // No version selector; for non-nested keys this was already handled by exact match above. + // For nested keys (e.g. "consumer>webpack"), check if the dependency name matches. + if (key.includes('>') && depSelector === name) { + return value; + } + continue; } - const packageName: string = key.substring(0, atIndex); - const rangeStr: string = key.substring(atIndex + 1); + const packageName: string = depSelector.substring(0, atIndex); + const rangeStr: string = depSelector.substring(atIndex + 1); if (packageName === name) { try { diff --git a/libraries/rush-lib/src/logic/pnpm/test/PnpmShrinkwrapFile.test.ts b/libraries/rush-lib/src/logic/pnpm/test/PnpmShrinkwrapFile.test.ts index 49cd88bdf98..e00bfea64e9 100644 --- a/libraries/rush-lib/src/logic/pnpm/test/PnpmShrinkwrapFile.test.ts +++ b/libraries/rush-lib/src/logic/pnpm/test/PnpmShrinkwrapFile.test.ts @@ -377,6 +377,21 @@ snapshots: ) ).resolves.toBe(false); }); + + it('can detect nested dependency overrides', async () => { + const project = getMockRushProject(); + const pnpmShrinkwrapFile = getPnpmShrinkwrapFileFromFile( + `${__dirname}/yamlFiles/pnpm-lock-v5/nested-overrides-not-modified.yaml`, + project.rushConfiguration.defaultSubspace + ); + await expect( + pnpmShrinkwrapFile.isWorkspaceProjectModifiedAsync( + project, + project.rushConfiguration.defaultSubspace, + undefined + ) + ).resolves.toBe(false); + }); }); describe('pnpm lockfile major version 6', () => { @@ -440,6 +455,21 @@ snapshots: ).resolves.toBe(false); }); + it('can detect nested dependency overrides', async () => { + const project = getMockRushProject(); + const pnpmShrinkwrapFile = getPnpmShrinkwrapFileFromFile( + `${__dirname}/yamlFiles/pnpm-lock-v6/nested-overrides-not-modified.yaml`, + project.rushConfiguration.defaultSubspace + ); + await expect( + pnpmShrinkwrapFile.isWorkspaceProjectModifiedAsync( + project, + project.rushConfiguration.defaultSubspace, + undefined + ) + ).resolves.toBe(false); + }); + it('can handle the inconsistent version of a package declared in dependencies and devDependencies', async () => { const project = getMockRushProject2(); const pnpmShrinkwrapFile = getPnpmShrinkwrapFileFromFile( @@ -517,6 +547,21 @@ snapshots: ).resolves.toBe(false); }); + it('can detect nested dependency overrides', async () => { + const project = getMockRushProject(); + const pnpmShrinkwrapFile = getPnpmShrinkwrapFileFromFile( + `${__dirname}/yamlFiles/pnpm-lock-v9/nested-overrides-not-modified.yaml`, + project.rushConfiguration.defaultSubspace + ); + await expect( + pnpmShrinkwrapFile.isWorkspaceProjectModifiedAsync( + project, + project.rushConfiguration.defaultSubspace, + undefined + ) + ).resolves.toBe(false); + }); + it('can handle the inconsistent version of a package declared in dependencies and devDependencies', async () => { const project = getMockRushProject2(); const pnpmShrinkwrapFile = getPnpmShrinkwrapFileFromFile( diff --git a/libraries/rush-lib/src/logic/pnpm/test/yamlFiles/pnpm-lock-v5/nested-overrides-not-modified.yaml b/libraries/rush-lib/src/logic/pnpm/test/yamlFiles/pnpm-lock-v5/nested-overrides-not-modified.yaml new file mode 100644 index 00000000000..8d2160a9ffc --- /dev/null +++ b/libraries/rush-lib/src/logic/pnpm/test/yamlFiles/pnpm-lock-v5/nested-overrides-not-modified.yaml @@ -0,0 +1,32 @@ +lockfileVersion: 5.3 + +overrides: + foo>typescript: 5.0.4 + +importers: + .: + specifiers: {} + + ../../apps/foo: + specifiers: + tslib: ~2.3.1 + typescript: 5.0.4 + dependencies: + tslib: 2.3.1 + devDependencies: + typescript: 5.0.4 + +packages: + /typescript/5.0.4: + resolution: + { + integrity: sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw== + } + engines: { node: '>=12.20' } + hasBin: true + + /tslib/2.3.1: + resolution: + { + integrity: sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw== + } diff --git a/libraries/rush-lib/src/logic/pnpm/test/yamlFiles/pnpm-lock-v6/nested-overrides-not-modified.yaml b/libraries/rush-lib/src/logic/pnpm/test/yamlFiles/pnpm-lock-v6/nested-overrides-not-modified.yaml new file mode 100644 index 00000000000..e72742903ef --- /dev/null +++ b/libraries/rush-lib/src/logic/pnpm/test/yamlFiles/pnpm-lock-v6/nested-overrides-not-modified.yaml @@ -0,0 +1,32 @@ +lockfileVersion: '6.0' + +overrides: + foo>typescript: 5.0.4 + +importers: + .: {} + + ../../apps/foo: + dependencies: + tslib: + specifier: ~2.3.1 + version: 2.3.1 + devDependencies: + typescript: + specifier: 5.0.4 + version: 5.0.4 + +packages: + /typescript/5.0.4: + resolution: + { + integrity: sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw== + } + engines: { node: '>=12.20' } + hasBin: true + + /tslib/2.3.1: + resolution: + { + integrity: sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw== + } diff --git a/libraries/rush-lib/src/logic/pnpm/test/yamlFiles/pnpm-lock-v9/nested-overrides-not-modified.yaml b/libraries/rush-lib/src/logic/pnpm/test/yamlFiles/pnpm-lock-v9/nested-overrides-not-modified.yaml new file mode 100644 index 00000000000..f72f4940c95 --- /dev/null +++ b/libraries/rush-lib/src/logic/pnpm/test/yamlFiles/pnpm-lock-v9/nested-overrides-not-modified.yaml @@ -0,0 +1,41 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +overrides: + foo>typescript: 5.0.4 + +importers: + .: {} + + ../../apps/foo: + dependencies: + tslib: + specifier: ~2.3.1 + version: 2.3.1 + devDependencies: + typescript: + specifier: 5.0.4 + version: 5.0.4 + +packages: + tslib@2.3.1: + resolution: + { + integrity: sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw== + } + + typescript@5.0.4: + resolution: + { + integrity: sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw== + } + engines: { node: '>=12.20' } + hasBin: true + +snapshots: + tslib@2.3.1: {} + + typescript@5.0.4: {} From f1f640a64fbcabe1f047826ecfd7cac2a3b069e2 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 9 Feb 2026 22:43:48 +0000 Subject: [PATCH 4/6] refactor: extract isNested boolean to avoid redundant key.includes check Co-authored-by: dmichon-msft <26827560+dmichon-msft@users.noreply.github.com> --- libraries/rush-lib/src/logic/pnpm/PnpmShrinkwrapFile.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libraries/rush-lib/src/logic/pnpm/PnpmShrinkwrapFile.ts b/libraries/rush-lib/src/logic/pnpm/PnpmShrinkwrapFile.ts index ee689d53acb..e673e6b0857 100644 --- a/libraries/rush-lib/src/logic/pnpm/PnpmShrinkwrapFile.ts +++ b/libraries/rush-lib/src/logic/pnpm/PnpmShrinkwrapFile.ts @@ -1237,7 +1237,8 @@ export class PnpmShrinkwrapFile extends BaseShrinkwrapFile { for (const [key, value] of this.overrides) { // For nested dependency selectors (contain '>'), extract the dependency portion after '>'. // For example: "bar@1>foo@2" -> dependency selector is "foo@2" - const depSelector: string = key.includes('>') ? key.substring(key.indexOf('>') + 1) : key; + const isNested: boolean = key.includes('>'); + const depSelector: string = isNested ? key.substring(key.indexOf('>') + 1) : key; // Parse the package name and version range from the selector. // Handle scoped packages (@scope/pkg@range) by finding the '@' after the scope prefix. @@ -1247,7 +1248,7 @@ export class PnpmShrinkwrapFile extends BaseShrinkwrapFile { if (atIndex === -1) { // No version selector; for non-nested keys this was already handled by exact match above. // For nested keys (e.g. "consumer>webpack"), check if the dependency name matches. - if (key.includes('>') && depSelector === name) { + if (isNested && depSelector === name) { return value; } continue; From 898e99b0686c5cc3ad4e3b1bf772f1828e44a182 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 9 Feb 2026 23:11:29 +0000 Subject: [PATCH 5/6] chore: add change file for @microsoft/rush-lib patch bump Co-authored-by: bmiddha <5100938+bmiddha@users.noreply.github.com> --- .../fix-rush-update-stability_2026-02-09-23-11.json | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 common/changes/@microsoft/rush-lib/fix-rush-update-stability_2026-02-09-23-11.json diff --git a/common/changes/@microsoft/rush-lib/fix-rush-update-stability_2026-02-09-23-11.json b/common/changes/@microsoft/rush-lib/fix-rush-update-stability_2026-02-09-23-11.json new file mode 100644 index 00000000000..bba4013b2db --- /dev/null +++ b/common/changes/@microsoft/rush-lib/fix-rush-update-stability_2026-02-09-23-11.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@microsoft/rush-lib", + "comment": "Handle versioned selectors in `globalOverrides` during pnpm shrinkwrap comparison.", + "type": "patch" + } + ], + "packageName": "@microsoft/rush-lib" +} From f59570df4d603d9a676bd7307bb4531af7233ee7 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 10 Feb 2026 00:18:10 +0000 Subject: [PATCH 6/6] chore: move change file from @microsoft/rush-lib to @microsoft/rush Co-authored-by: bmiddha <5100938+bmiddha@users.noreply.github.com> --- .../fix-rush-update-stability_2026-02-09-23-11.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename common/changes/@microsoft/{rush-lib => rush}/fix-rush-update-stability_2026-02-09-23-11.json (65%) diff --git a/common/changes/@microsoft/rush-lib/fix-rush-update-stability_2026-02-09-23-11.json b/common/changes/@microsoft/rush/fix-rush-update-stability_2026-02-09-23-11.json similarity index 65% rename from common/changes/@microsoft/rush-lib/fix-rush-update-stability_2026-02-09-23-11.json rename to common/changes/@microsoft/rush/fix-rush-update-stability_2026-02-09-23-11.json index bba4013b2db..cb03b28a05a 100644 --- a/common/changes/@microsoft/rush-lib/fix-rush-update-stability_2026-02-09-23-11.json +++ b/common/changes/@microsoft/rush/fix-rush-update-stability_2026-02-09-23-11.json @@ -1,10 +1,10 @@ { "changes": [ { - "packageName": "@microsoft/rush-lib", + "packageName": "@microsoft/rush", "comment": "Handle versioned selectors in `globalOverrides` during pnpm shrinkwrap comparison.", "type": "patch" } ], - "packageName": "@microsoft/rush-lib" + "packageName": "@microsoft/rush" }