[rush] Support per-subspace pnpmVersion override in subspace-level pnpm-config.json
Nessuno ha ancora preso questa issue.
Valutazione
- Difficoltà
- 5/5
- Tempo stimato
- Più di una settimana
- Idoneità per principianti
- 45/100
- Tipo di issue
- Funzionalità
- Chiarezza
- Abbastanza chiara
- Stato di attività
- Tranquilla
- Stack tecnologico
- typescript
- Ambito
- build-system, cli, tooling
Direzione di ricerca
Start with Subspace.ts, pnpm-config.schema.json, and PnpmOptionsConfiguration.ts to trace configuration and fallback behavior. Then follow the listed entry points in BaseInstallManager.ts, WorkspaceInstallManager.ts, InstallHelpers.ts, RushPnpmCommandLineParser.ts, and PublishAction.ts; done means each subspace can resolve its version while global-version behavior remains unchanged.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
Summary
I'm working on many large Rush monorepos that uses the subspaces feature. Different subspaces have different needs for pnpm versions due to:
- Legacy subspaces that need to stay on older pnpm versions for stability
- New subspaces that want to adopt newer pnpm features (e.g., pnpm 11.x catalogs, improved worktree dependency handling)
- Gradual migration strategies where we can't upgrade all subspaces at once
Currently, rush.json has a single pnpmVersion that applies globally to the entire repository. When the subspaces feature is enabled, each subspace already has its own pnpm-config.json (for things like useWorkspaces, strictPeerDependencies, etc.), but there is no way to specify a different pnpmVersion per subspace.
This forces us to either:
- Upgrade all subspaces simultaneously (risky for large repos)
- Stay on an older global pnpm version and miss new features
- Maintain separate Rush repositories (defeating the purpose of a unified monorepo)
I would like to propose that when subspaces are enabled, each subspace's pnpm-config.json should be able to optionally override the global pnpmVersion from rush.json. If not specified, it should fall back to the global version.
Details
Proposed Design
We have done an analysis of the impact and prepared a detailed implementation plan. The key points are:
1. Configuration Extension
Add an optional pnpmVersion field to pnpm-config.json (the subspace-level config file, not the global one):
// common/config/subspaces/legacy/pnpm-config.json
{
"pnpmVersion": "8.8.0",
"useWorkspaces": true
}
// common/config/subspaces/modern/pnpm-config.json
{
"pnpmVersion": "11.0.0",
"useWorkspaces": true
}
If omitted, it falls back to the global pnpmVersion from rush.json — preserving full backward compatibility.
2. Subspace-Level Resolution
Add a getPnpmVersion() method to the Subspace class that implements the priority:
public getPnpmVersion(): string {
// 1. Subspace pnpm-config.json (if pnpmVersion is specified)
// 2. Fallback to rush.json global pnpmVersion
}
3. pnpm-local Installation Path Isolation
Currently, InstallHelpers.ensureLocalPackageManagerAsync() installs pnpm to ~/.rush/pnpm-<version> and creates a junction at common/temp/pnpm-local.
Assume that the version of pnpm configured in rush.json is 8.8.0, whereas a subspace is configured with version 9.15.0.
We need to version-isolate the junction:
# Current:
common/temp/pnpm-local/ -> ~/.rush/pnpm-8.8.0
# Proposed:
common/temp/pnpm-local/8.8.0/ -> ~/.rush/pnpm-8.8.0
common/temp/pnpm-local/9.15.0/ -> ~/.rush/pnpm-9.15.0
common/temp/pnpm-local/ -> ~/.rush/pnpm-8.8.0
Same version across different subspaces shares the same junction.
4. Install Manager Adaptation
The following modules need to use subspace.getPnpmVersion() instead of rushConfiguration.packageManagerToolVersion:
- BaseInstallManager.pushConfigurationArgs — pnpm version condition logic
- WorkspaceInstallManager — use subspace pnpm version
packageManagerFilenamepath, replacerushConfigurationJson.pnpmVersionwithsubspace.getPnpmVersion() - RushPnpmCommandLineParser — version compatibility checks (
patch>=7.4.0,patch-remove>=8.5.0,approve-builds>=10.1.0, etc.) and the binary execution path when runrush-pnpm - InstallHelper.ensureLocalPackageManagerAsync() —
ensureLocalPackageManagerAsync()to accept an optional version parameter - PublishAction._npmPublishAsync() — use the subspace pnpm junction first, falling back to the global one
5. Backward Compatibility
- No subspaces enabled: Behavior is identical to today.
rushConfiguration.packageManagerToolVersionandpackageManagerToolFilenameremain unchanged. - Subspaces enabled but no
pnpmVersionin subspace config: Falls back to globalrush.jsonvalue. - External plugins: They can continue using
rushConfiguration.packageManagerToolVersionas the global default. - Autoinstallers: The can continue using
rushConfiguration.packageManagerToolVersionas the global default. rush add: Thepnpm viewcommand can continue usingrushConfiguration.packageManagerToolVersionas the global default.
6. Known Constraints (acceptable trade-offs)
- pnpm-sync cross-version inject dependencies: Not supported for the first iteration. We can add a validation that cross-subspace injected dependencies require the same pnpm version across involved subspaces.
rush-pnpmCLI: Already supports--subspace, so it naturally maps to the correct version once the above changes are made.
Full Impact Analysis with AI
Have identified 10 categories, 30+ files/modules affected.
A quick summary of the most impactful files:
| Category | Key Files | Nature of Change |
|---|---|---|
| Config | pnpm-config.schema.json, PnpmOptionsConfiguration.ts |
Add pnpmVersion field |
| Data Model | Subspace.ts, RushConfiguration.ts |
Add getPnpmVersion(), fallback logic |
| Install | InstallHelpers.ts |
Version-parameterized ensureLocalPackageManagerAsync() |
| Install Manager | BaseInstallManager.ts |
All version checks → subspace version |
| Install Manager | WorkspaceInstallManager.ts |
packageManagerFilename → subspace path |
| CLI | RushPnpmCommandLineParser.ts |
All version checks → _subspace.getPnpmVersion() |
| Utilities | PackageJsonUpdater.ts, SetupChecks.ts |
Batch by subspace or global fallback |
| Plugins | rush-resolver-cache-plugin |
Version check → subspace version |
Standard questions
| Question | Answer |
|---|---|
@microsoft/rush globally installed version? |
5.172.1 |
rushVersion from rush.json? |
5.172.1 |
pnpmVersion, npmVersion, or yarnVersion from rush.json? |
pnpm@11.6.0 |
(if pnpm) useWorkspaces from pnpm-config.json? |
true |
| Operating system? | Mac |
| Would you consider contributing a PR? | Yes |
Node.js version (node -v)? |
22.21.0 |
- Lingua principale
- TypeScript
- Stelle
- 6.5k
- Fork
- 708
- Merge medio
- 4g 13h
- PR unite (30g)
- 62
Guida per i contributori
Nessuna guida per i contributori indicizzata per questo repository
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di microsoft/rushstack
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 72/100
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 65/100
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 68/100
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 70/100
-
Difficoltà 4/5 3-5 giorni Idoneità per principianti 45/100
Tutte le issue di microsoft/rushstack
Issue simili
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 84/100
bcgov/bc-wallet-mobile#4761 · 1 commento ·
-
external-issue to-triage
Difficoltà 2/5 1-3 ore Idoneità per principianti 88/100
-
area-deployment area-integrations triage:bot-seen
Difficoltà 2/5 Mezza giornata Idoneità per principianti 86/100
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 82/100
-
refactor
Difficoltà 2/5 1-3 ore Idoneità per principianti 84/100