feat: walk up directory tree to find JS lockfile in monorepos#431
feat: walk up directory tree to find JS lockfile in monorepos#431ruromero merged 3 commits intoguacsec:mainfrom
Conversation
Add parent-traversal logic to Base_javascript.validateLockFile and _buildDependencyTree, matching the existing Cargo provider pattern. When a nested package.json has no lockfile in its directory, the provider now walks up looking for package-lock.json/yarn.lock/ pnpm-lock.yaml, stopping at a package.json with "workspaces" field (the workspace root boundary) or the filesystem root. This enables single-file stack analysis to work for modules in JS/TS monorepos where the lockfile lives at the workspace root. TRUSTIFY_DA_WORKSPACE_DIR still takes precedence as an explicit override (no walk-up when set). Assisted-by: Claude Code Ref: TC-3891
ⓘ You are approaching your monthly quota for Qodo. Upgrade your plan Review Summary by QodoAdd monorepo lockfile discovery via directory tree walk-up
WalkthroughsDescription• Add parent-traversal lockfile discovery to JavaScript provider for monorepos - Walks up directory tree to find lock file at workspace root - Stops at package.json with "workspaces" field (workspace root boundary) - TRUSTIFY_DA_WORKSPACE_DIR env var overrides walk-up behavior • Extract lockfile search logic into new _findLockFileDir() method • Add 4 new test cases with workspace member fixtures - Workspace member with lock file at root (walk-up succeeds) - Workspace member without lock file at root (walk-up fails) - Override with correct TRUSTIFY_DA_WORKSPACE_DIR (succeeds) - Override with wrong TRUSTIFY_DA_WORKSPACE_DIR (fails) Diagramflowchart LR
A["Nested package.json<br/>in monorepo"] -->|"_findLockFileDir()"| B["Walk up directory tree"]
B -->|"Lock file found"| C["Return lock file dir"]
B -->|"Workspace root found<br/>no lock file"| D["Return null"]
B -->|"Filesystem root reached"| D
E["TRUSTIFY_DA_WORKSPACE_DIR<br/>env var set"] -->|"Override"| F["Check only that dir"]
F -->|"Lock file exists"| C
F -->|"Lock file missing"| D
File Changes1. src/providers/base_javascript.js
|
Code Review by Qodo
1. Workspace SBOM root mismatch
|
Address Qodo review: #executeListCmd and #createLockFile now pass
{ cwd: manifestDir } to #invokeCommand so commands run from the
lockfile directory, not the manifest directory.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Ref: TC-3891
Verification Report for TC-3891
Acceptance Criteria Detail
Overall:
|
|
/review |
|
Persistent review updated to latest commit 5dc6216 |
5dc6216 to
fe3dd96
Compare
Address Qodo review: _findLockFileDir now also stops at directories containing pnpm-workspace.yaml, preventing the walk-up from escaping pnpm workspace roots that don't use package.json#workspaces. Ref: TC-3891 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Qodo Review ResponseAddressed all 5 findings: 1. Workspace SBOM root mismatch — Not a regression. This is the same behavior as the previous 2. Wrong command working dir — Fixed in the second commit: 3. pnpm workspace root missed — Fixed in 5c95677. Added 4. Ambiguous provider selection — This requires multiple different lockfiles at different ancestor levels (e.g. 5. Redundant Windows chdir — Valid observation, but the |
Summary
Base_javascript, matching the existing Cargo provider patternpackage.json, the provider now walks up the directory tree to find the lock file at the workspace rootpackage.jsonwith a"workspaces"field (workspace root boundary) — analogous to Cargo's[workspace]boundaryTRUSTIFY_DA_WORKSPACE_DIRoverrides the walk-up (checks only that directory)#executeListCmdand#createLockFileto pass{ cwd: manifestDir }to#invokeCommandCloses #430
Related Jira: TC-3891
Test plan
TRUSTIFY_DA_WORKSPACE_DIRoverride works correctlyTRUSTIFY_DA_WORKSPACE_DIRfails even when walk-up would succeed🤖 Generated with Claude Code