Conversation
scripts/validation/lint-md-staged.cjs called spawnSync("npx", [...])
with no shell: true, which fails with ENOENT on Windows -- npx is a
.cmd shim, and Node's spawnSync doesn't resolve .cmd/.bat PATH shims
without a shell. This blocked every commit touching a markdown file
on Windows unless bypassed with --no-verify.
Reads markdownlint-cli2's own package.json "bin" field via fs (not
require.resolve, since the package's "exports" field rejects that
subpath even though the file exists) to locate its actual script,
then invokes that directly via process.execPath. Deterministic (exact
locally-installed version, no npm registry resolution) and needs no
shell layer on any platform.
Fixes #3455
|
Warning Review limit reachedNext included review available in 50 seconds. View limit detailsLimit details: You’ve used the included review currently available. You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Review configuration: ⚙️ Run configurationConfiguration used: Repository: lightspeedwp/.github/.coderabbit.yml Review profile: CHILL Plan: Advanced Run ID: 📒 Files selected for processing (2)
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 |
📋 Changelog Quality ValidationSummary
Status✅ Validation PASSED - No new failures introduced by this PR. No action required. |
PR Template RoutingBranch Type: This PR was automatically routed based on the branch naming strategy. |
Bugfix Pull Request
Linked issues
Fixes #3455
Context
--no-verify(which skips the lint gate entirely, not just this bug).scripts/validation/lint-md-staged.cjs, invoked by the.lintstagedrc.cjspre-commit hook.Reproduction
.mdfile. 2)git commit.Failed to run markdownlint-cli2 --fix: spawnSync npx ENOENTon every attempt, regardless of the file's actual content.Root Cause
scripts/validation/lint-md-staged.cjscalledspawnSync("npx", [...])with noshell: true. On Windows,npxis a.cmdshim, and Node'schild_process.spawnSyncdoes not resolve.cmd/.batPATH shims without eithershell: trueor an explicit.cmdextension — a well-documented Node-on-Windows behaviour, not a PATH configuration issue. Confirmed by runningnpx markdownlint-cli2 --fix <file>directly in a shell — it resolves and runs fine; only thespawnSynccall inside the script failed.Fix Summary
Resolves the locally-installed
markdownlint-cli2binary directly instead of going throughnpx: reads the package's ownpackage.jsonbinfield (viafs, sincerequire.resolve("markdownlint-cli2/package.json")is rejected by the package'sexportsfield even though the file exists on disk) to locate its actual script, then invokes that directly withprocess.execPath. This avoids the shell-shim problem at the source — deterministic (the exact locally-installed version, no npm registry resolution) and needs no shell layer on any platform, rather than patching around it withshell: true(which would reintroduce shell-quoting risk for file paths with spaces on Windows).Verification
npxinvocation directly (it's invoked as a git hook, not imported as a module); verified via direct invocation and via a realgit commitexercising the actual pre-commit hook path (see below).node scripts/validation/lint-md-staged.cjs <file>directly — no moreENOENT, linter runs and reports correctly. Also verified end-to-end: staged a realCHANGELOG.mdchange and rangit commit— the pre-commit hook completed successfully for the first time on this Windows machine, without--no-verify.markdownlint-cli2's own CLI output (violation counts, summary) is unchanged from thenpx-based invocation — only the process-spawning mechanism changed, not the tool's behaviour.Risk & Rollback
shell: true), so no new injection surface.Changelog
Fixed
Checklist (Global DoD / PR)
/security-reviewrun with no findings.🤖 Generated with Claude Code