fix: global installs respect build policy from global config.yaml when GVS is enabled#11363
Conversation
…dConfig re-application
The GVS default allowBuilds = {} was applied too early — before
workspace manifest settings were read and before .npmrc values
(dangerouslyAllowAllBuilds) were re-applied via globalDepsBuildConfig.
This caused hasDependencyBuildOptions() to return true (because {}} is
not null), blocking restoration of .npmrc values. Global installs
with GVS enabled would silently skip all build scripts even when
the config explicitly allowed them.
This fix moves the GVS default to after both workspace manifest
reading and globalDepsBuildConfig re-application, so that:
1. Workspace manifest allowBuilds takes precedence (if present)
2. .npmrc dangerously-allow-all-builds is properly restored
3. Empty {}} is only applied as a last resort
Closes pnpm#9249
|
💖 Thanks for opening this pull request! 💖 |
There was a problem hiding this comment.
Pull request overview
Fixes a config-merge ordering issue so global installs (pnpm add -g) correctly honor dependency build policy from .npmrc / global workspace manifest when Global Virtual Store (GVS) is enabled.
Changes:
- Moves the GVS defaulting of
allowBuilds = {}to run after workspace-manifest settings are loaded and.npmrc-derived build policy is re-applied. - Adds a changeset for a patch release of
@pnpm/config.readerandpnpm.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| config/reader/src/index.ts | Reorders when allowBuilds is defaulted under GVS to avoid blocking restoration of .npmrc build-policy settings. |
| .changeset/fix-global-allow-builds.md | Adds release notes for the fix (patch). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
From PR review discussion_r3141002317: - Replace hasDependencyBuildOptions() == null with hasDependencyBuildOptions() so the GVS default only applies when no build policy at all is configured (not even dangerouslyAllowAllBuilds). This is cleaner because the condition now matches the re-application guard on the line immediately before it. - Add regression test verifying that dangerouslyAllowAllBuilds with GVS preserves allowBuilds when no global workspace manifest exists.
c99f6f9 to
475ef6b
Compare
|
LOL, my agent reviewed my communication style on this comment
We had a conversation about owning self-made mistakes :) |
|
Update on related issues #9073 and #9478: After investigation, these are both the same root cause as this PR's fix — but in the v10 config reader, not v11:
This PR does NOT close #9073 or #9478 — it fixes only the v11 GVS ordering bug (PR #11363). The proper fix for #9073/#9478 is the v10 backport (adding |
|
GVS without an allow list kinda doesn't make sense at the moment unfortunately. We use the allow list to detect which packages should include the node.js version in the hash during installation. There's no other way to do it because the registry doesn't give us information about which dependencies should be built during resolution. So, if you allow all builds, gvs will have all package duplicated for all node.js runtimes. |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Fix unreachable GVS allowBuilds default: hasDependencyBuildOptions() always returns true after globalDepsBuildConfig re-applies defaults (dangerouslyAllowAllBuilds: false is != null). Replace with explicit allowBuilds == null && dangerouslyAllowAllBuilds !== true check. - Rename .npmrc references to global config.yaml in changeset, comments, and test names (zkochan: v11 reads from global rc file, not .npmrc). - Add try/finally env cleanup for XDG_CONFIG_HOME and PNPM_HOME in tests. - Add test for workspace manifest allowBuilds precedence over config.yaml.
Head branch was pushed to by a user without write access
- Use import.meta.dirname/global/v11 for globalPkgDir (matches env.PNPM_HOME) - Fix assertion: dangerouslyAllowAllBuilds coexists with allowBuilds - Clean up global/v11 directory in finally block to prevent test leakage
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…s; clean up parent global/ dir Fixes two PR pnpm#11363 review threads: 1. allowBuilds in workspace manifest must be Record<string, boolean>, not array — createAllowBuildFunction uses Object.entries() 2. Remove empty config/reader/test/global/ directory after test
- Update changeset: use camelCase dangerouslyAllowAllBuilds (YAML key, not .npmrc) - Add enableGlobalVirtualStore assertion to first GVS test - Add comment explaining dangerouslyAllowAllBuilds coexistence on config object
…T_VERSION, try/finally - Move XDG_CONFIG_HOME mutation and file setup inside try blocks so env is always restored even if setup throws - Replace hard-coded v11 with GLOBAL_LAYOUT_VERSION import - Fix corrupted try/finally in workspace manifest precedence test (missing finally block and mangled expect line from prior bad edit) - Reword comment: enableGlobalVirtualStore defaults to true for global installs, not \"when not in CI\"
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…ording, cleanup placement, test rename
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 10 out of 10 changed files in this pull request and generated 8 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Production-ready bar for this PR
Findings1. Correctness & functional completeness[NON-BLOCKING] Second test does not assert
|
|
@zkochan are you able to approve / restart the remaining hung(?) CI workflows? Thanks! |
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (3)
📜 Recent review details🧰 Additional context used📓 Path-based instructions (1)**/*.{ts,tsx,js,jsx}📄 CodeRabbit inference engine (AGENTS.md)
Files:
🧠 Learnings (1)📚 Learning: 2026-05-14T09:04:00.133ZApplied to files:
🔇 Additional comments (3)
📝 WalkthroughWalkthroughThis PR fixes the ordering of GVS ChangesGVS Build Policy Default Fix
Estimated code review effort🎯 2 (Simple) | ⏱️ ~12 minutes Suggested labels
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
|
Congrats on merging your first pull request! 🎉🎉🎉 |
…n GVS is enabled (pnpm#11363) * fix(config.reader): move GVS allowBuilds default after globalDepsBuildConfig re-application The GVS default allowBuilds = {} was applied too early — before workspace manifest settings were read and before .npmrc values (dangerouslyAllowAllBuilds) were re-applied via globalDepsBuildConfig. This caused hasDependencyBuildOptions() to return true (because {}} is not null), blocking restoration of .npmrc values. Global installs with GVS enabled would silently skip all build scripts even when the config explicitly allowed them. This fix moves the GVS default to after both workspace manifest reading and globalDepsBuildConfig re-application, so that: 1. Workspace manifest allowBuilds takes precedence (if present) 2. .npmrc dangerously-allow-all-builds is properly restored 3. Empty {}} is only applied as a last resort Closes pnpm#9249 * fix(config.reader): apply Copilot suggestion for GVS allowBuilds guard From PR review discussion_r3141002317: - Replace hasDependencyBuildOptions() == null with hasDependencyBuildOptions() so the GVS default only applies when no build policy at all is configured (not even dangerouslyAllowAllBuilds). This is cleaner because the condition now matches the re-application guard on the line immediately before it. - Add regression test verifying that dangerouslyAllowAllBuilds with GVS preserves allowBuilds when no global workspace manifest exists. * docs: update changeset * fix(config.reader): address PR review feedback - Fix unreachable GVS allowBuilds default: hasDependencyBuildOptions() always returns true after globalDepsBuildConfig re-applies defaults (dangerouslyAllowAllBuilds: false is != null). Replace with explicit allowBuilds == null && dangerouslyAllowAllBuilds !== true check. - Rename .npmrc references to global config.yaml in changeset, comments, and test names (zkochan: v11 reads from global rc file, not .npmrc). - Add try/finally env cleanup for XDG_CONFIG_HOME and PNPM_HOME in tests. - Add test for workspace manifest allowBuilds precedence over config.yaml. * fix(config.reader): fix GVS workspace manifest test - Use import.meta.dirname/global/v11 for globalPkgDir (matches env.PNPM_HOME) - Fix assertion: dangerouslyAllowAllBuilds coexists with allowBuilds - Clean up global/v11 directory in finally block to prevent test leakage * fix(config.reader): use object form for workspace manifest allowBuilds; clean up parent global/ dir Fixes two PR pnpm#11363 review threads: 1. allowBuilds in workspace manifest must be Record<string, boolean>, not array — createAllowBuildFunction uses Object.entries() 2. Remove empty config/reader/test/global/ directory after test * fix(config.reader): address production review nits - Update changeset: use camelCase dangerouslyAllowAllBuilds (YAML key, not .npmrc) - Add enableGlobalVirtualStore assertion to first GVS test - Add comment explaining dangerouslyAllowAllBuilds coexistence on config object * fix(config.reader): address Copilot review — env safety, GLOBAL_LAYOUT_VERSION, try/finally - Move XDG_CONFIG_HOME mutation and file setup inside try blocks so env is always restored even if setup throws - Replace hard-coded v11 with GLOBAL_LAYOUT_VERSION import - Fix corrupted try/finally in workspace manifest precedence test (missing finally block and mangled expect line from prior bad edit) - Reword comment: enableGlobalVirtualStore defaults to true for global installs, not \"when not in CI\" * fix(config.reader): address last 3 Copilot review threads — comment wording, cleanup placement, test rename * fix(config.reader): fix block-scoped globalDir leak in GVS test * fix: address Copilot review #4194783789 — restore auth test, fix naming, remove artifacts * Remove local dev tooling — not part of this PR * Remove PR.md — issue context is in the PR description --------- Co-authored-by: Zoltan Kochan <z@kochan.io> Co-authored-by: Tom Hale <tom@hale.net>
Summary
Fixes #9249
Global installs respect the global config build policy (e.g.,
dangerouslyAllowAllBuilds) when the global virtual store is enabled.Problem
The global virtual-store (GVS) default
allowBuilds = {}was applied before workspace manifest settings were read and before global config values (stripped byextractAndRemoveDependencyBuildOptions) were re-applied viaglobalDepsBuildConfig. This causedhasDependencyBuildOptionsto returntrue(because{}is not null), blocking restoration of global config values likedangerouslyAllowAllBuilds. As a result, global installs skipped all build scripts even when the config explicitly allowed them.Fix
Moves the GVS default to after workspace manifest reading and
globalDepsBuildConfigre-application, with an explicit null/true check instead ofhasDependencyBuildOptions():This ensures:
allowBuildstakes precedence (if present)dangerously-allow-all-buildsis properly restored (if set and no workspace policy exists){}is only applied as a last resort when no policy is configured anywhereSummary by CodeRabbit
dangerouslyAllowAllBuildsoption is properly respected when enabled globally.