-
fix(core): use workspace root for package manager detection in script targets (#35550)
发布于
2026-05-04 20:57:17 +00:00 Current Behavior
readTargetsFromPackageJson(in
packages/nx/src/utils/package-json.ts) receives aworkspaceRoot
argument but never passes it to package manager detection:for (const script of includedScripts) { packageManagerCommand ??= getPackageManagerCommand(); // ← no workspaceRoot res[script] = buildTargetFromScript(script, scripts, packageManagerCommand); }Two consequences:
-
Wrong package manager —
detectPackageManager()defaultsdir = '', so the lockfile probe runs in the CWD, not the workspace. When that
finds nothing it falls back tonpm_config_user_agent, so the inferred
runCommand(npm run Xvspnpm run Xvsyarn X) on script targets
ends up depending on whoever invoked the nx process rather than on the
workspace's actual lockfile. -
Module-level cache —
let packageManagerCommand(cleared with
??=) memoizes the first detection result across all subsequent calls
in the process. So even if the first call had the rightworkspaceRoot,
every later call inherits that detection regardless of its
workspaceRoot. This is also why
packages/nx/src/plugins/package-json/create-nodes.spec.tshad four
pre-existing snapshot failures locally (pnpm run …instead of the
expectednpm run …) — the first test in any process locked detection
to the host's PM.
This is a follow-up to #35116, which moved package manager detection
into thecreateNodescallback for the inferred plugins but missed this
code path.Expected Behavior
- Drop the module-level cache.
- Thread
workspaceRootinto bothdetectPackageManagerand
getPackageManagerCommand, so the lockfile probe runs in the right
directory.
if (includedScripts.length > 0) { const packageManagerCommand = getPackageManagerCommand( detectPackageManager(workspaceRoot), workspaceRoot ); for (const script of includedScripts) { res[script] = buildTargetFromScript(script, scripts, packageManagerCommand); } }The
packages/nx/src/plugins/package-json/create-nodes.spec.tsfixture
now seedspackage-lock.jsoninto memfs in abeforeEach, matching the
pattern #35116 established for plugin specs. Without the lockfile the
detector still falls back to the env var; with it, every test
deterministically picksnpm, matching the existing snapshots.Verification
Before this PR: 4 failures in
packages/nx/src/plugins/package-json/create-nodes.spec.ts:✕ should build projects from package.json files ✕ should store js package metadata ✕ should add a script target if the sibling project.json file does not exist ✕ should add a script target if the sibling project.json exists but does not have a conflicting target Tests: 4 failed, 7 passed, 11 totalAfter this PR:
Tests: 11 passed, 11 totalRelated Issue(s)
Follow-up to #35116.
下载附件
-