Repository navigation
fix(scripts): make the Windows CI job green - #12
Merged
Merged
Conversation
Three red spots on the Windows job, two causes, all measured on the
runner (Node 24.20.0) before the fix:
1. package-manager-pin ran "<prefix>\bin\pnpm". npm installs global
launchers directly into the prefix on Windows: the prefix held
pnpm, pnpm.cmd, pnpm.ps1 and no bin directory ("exists prefix\bin:
false"); "<prefix>\pnpm" --version answered 11.14.0. The test now
accepts either layout, but exactly one launcher inside the prefix.
No shipped code assumes a bin path.
2. configuredRegistry() and 3. check:manifest started npm/pnpm with
execFileSync and no shell. Both are .cmd shims on Windows:
execFileSync('npm') -> ENOENT, execFileSync('npm.cmd') -> EINVAL
(CVE-2024-27980), shell:true -> DEP0190. The registry lookup
swallowed the error into "", and check:manifest printed only
stdout + stderr, which are empty when the process never started.
scripts/lib/run-command.mjs starts them through cross-spawn, pinned to
7.0.6 like the lenne.tech CLI (spawnCmdSync). Its errors always name
the command and the cause, e.g. "`npm pack --dry-run --ignore-scripts
--json` could not start (ENOENT)" where the old script printed nothing.
check-consumer-build.mjs had the same pattern and uses it too.
Also adopts killTreePlan verbatim from lt-monorepo origin/main: the
watchdog's pgrep walk does not exist on Windows and ended only the
shell. It lives in scripts/lib/process-tree.mjs because check.mjs runs
main() on import. Tests assert the plan and the call site; nothing
sends a signal or starts taskkill.
pnpm audit reports the same single moderate finding (devalue,
GHSA-9rgm-9g3h-6x36) on Windows and macOS.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
DKoenig9
marked this pull request as ready for review
September 23, 2026 09:40
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The Windows job has been red on
mainsince 15.09. There were three red spots with two different causes, all measured on the runner (Node 24.20.0) before any fix. With this branch, every step of the job is green exceptpnpm run check. That step stops only at the audit, which gives the same result on macOS (see below). Draft: no merge and no release without Daniel.Cause 1:
package-manager-pinassumed a path that doesn't exist on WindowsThe test ran
"<prefix>\bin\pnpm" --version. npm puts global launchers directly into the prefix on Windows. Probe output from the runner:The test now accepts either layout, but requires exactly one launcher inside the prefix, so it never runs a pnpm it finds on PATH. No shipped code assumes a
binpath: outsidetest/, only the#!/usr/bin/env nodeshebangs contain one.Cause 2: npm/pnpm started without a shell (
configuredRegistry()andcheck:manifest)On Windows,
npmandpnpmare.cmdshims. Probe output:configuredRegistry()swallowed the error and returned"".check:manifestprinted onlystdout + stderr. Both are empty when the process never starts, so the failure message was empty.scripts/lib/run-command.mjsnow starts these commands through cross-spawn 7.0.6, pinned exactly like the lenne.tech CLI (spawnCmdSync). Its errors always name the command and the cause. SamePATHwithout npm, before and after:check-consumer-build.mjs(run byrelease) had the same pattern and uses the helper too.Also:
killTreeon WindowsThe check wrapper's watchdog walked the process tree with
pgrep -P, which doesn't exist on Windows, so it ended only the shell and left the test workers running.killTreePlanis copied verbatim from lt-monorepoorigin/main(taskkill /PID <pid> /T /F). It lives inscripts/lib/process-tree.mjsbecause this repo'scheck.mjsrunsmain()on import, which makes any function inside it untestable. Nothing in the tests sends a signal or startstaskkill: they check the plan itself and, at source level, the call site.Tests and what they prove
test/run-command.test.ts,test/process-tree.test.ts, and the updated pin test./F, bypassing the call site, falling through topgrep.npm/pnpm, the pin layout) pass trivially on macOS/Linux. A regression toexecFileSyncor to thebinpath goes red only in the Windows job, so that job run is the proof for those cases.ok — 100 files, and format, lint, types and build all green.Not part of this PR
pnpm auditreports one moderate finding (devalue< 5.9.1, GHSA-9rgm-9g3h-6x36), identical on Windows and macOS. It's a package question, not a Windows one, so it stays out of this PR.🤖 Generated with Claude Code