Skip to content

fix(test) resolve cyclonedx binary once instead of using npx per call#18

Merged
indexzero merged 3 commits intomainfrom
fix/integration-test
Mar 16, 2026
Merged

fix(test) resolve cyclonedx binary once instead of using npx per call#18
indexzero merged 3 commits intomainfrom
fix/integration-test

Conversation

@indexzero
Copy link
Owner

What

runCycloneDX in test/support/parity.js no longer invokes npx @cyclonedx/cyclonedx-npm on every call. A new getCycloneDXBin() helper resolves the binary path once — first trying require.resolve from node_modules, then falling back to a one-time npm install into a temp prefix — and caches it for the process lifetime. All subsequent calls invoke the binary directly via node.

Why

getParityResults runs runCycloneDX twice in parallel (lockfile-only and full). Both npx invocations attempt to install or update @cyclonedx/cyclonedx-npm in the same shared ~/.npm/_npx/ cache directory simultaneously. npm's rename-based atomic install (rename(dir, .dir-XXXX)) collides, producing ENOTEMPTY: directory not empty, rename '…/cyclonedx-library' -> '…/.cyclonedx-library-LGlIfzMw'. This is a known npm concurrency bug with no upstream fix.

The previous behavior caused non-deterministic test failures — the debug@4.3.4 parity test would pass or fail depending on filesystem timing. By resolving the binary once and calling it with node directly, the npx cache is never touched during parallel execution.

Risk Assessment

Low risk. Only affects test infrastructure, not library code. The binary resolution has a two-tier fallback (require.resolve → temp npm install), so it works both with and without @cyclonedx/cyclonedx-npm as a devDependency. All 9 parser parity tests pass deterministically.

References

  • Failing test: test/verification/parser-parity.test.jsdebug@4.3.4
  • npm issue: ENOTEMPTY during concurrent npx cache writes

🤖 Generated with Claude Code

indexzero and others added 3 commits March 16, 2026 01:19
Concurrent npx invocations race on the shared npx cache, causing
ENOTEMPTY on directory renames. Instead, resolve the cyclonedx-npm
binary once (via require.resolve or a one-time npm install into a
temp prefix) and invoke it directly with node for all subsequent
calls.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
test:coverage was missing ./test/**/*.test.js, so verification and
parser-specific tests were excluded from coverage runs.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add pretest/pretest:coverage hooks to run fixture decoding so that
test/parsers/*.test.js can find decoded fixtures in CI. Align test
and test:coverage globs to include test/parsers/*.test.js. Add
test:all for running the full suite including verification and
monorepo tests locally.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@indexzero indexzero merged commit 6c84c32 into main Mar 16, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant