Commit Graph

4 Commits

Author SHA1 Message Date
Jordan Ritter e11625a35b fix(showcase/scripts): add post-heal drifted-baseline guard
The PR description advertised a drifted-baseline guard on CI for
restoreFromGitHead, but the implementation never actually ran a
post-heal `git diff --quiet HEAD -- <tracked>` check — the only
diff was the off-CI pre-checkout guard against clobbering developer
edits. A racing external mutator (or a parallel test suite we haven't
accounted for) could rewrite a tracked file between our `git checkout
HEAD --` and our subsequent snapshot, and we'd silently bake the drift
into the baseline and the afterEach restore loop would maintain it
forever.

This commit adds the missing post-heal check immediately after the
`git checkout HEAD --`. On CI it throws with `drifted-baseline guard:
post-heal diff failed` citing every offending path; off-CI it warns so
developers iterating on a dirty tree aren't blocked.

Also:

  - Rephrases the `isBenignPathspec` catch comment to describe the
    realistic case (belt-and-braces against a rm race, not the normal
    flow) now that partitionTrackedPaths pre-filters untracked paths.
    The branch is intentionally kept — cheap to tolerate, and it
    guards against a race that's hard to rule out in a shared worktree.

  - Red-green unit coverage: new tests use a counter-based git shim
    that fails the N-th `diff --quiet` invocation, so we can target
    the post-heal diff independently of the off-CI pre-checkout diff.
    - CI throws on drift with the advertised message
    - off-CI warns (does not throw) with the same message
    - no false-positive on a clean tracked path
    Verified red without the guard, green with it.
2026-04-18 03:43:25 -07:00
Jordan Ritter 599273e2d4 docs(showcase/scripts): tidy test-cleanup comments and JSDoc
- Rewrite restoreFromGitHead JSDoc to match actual behavior for tracked
  vs untracked paths (including the on-CI throw / off-CI warn for an
  entirely-untracked input list).
- Rephrase internal review-round markers ("CR4/CR5 HIGH/MEDIUM") in
  test-cleanup.ts and test-cleanup.test.ts to describe the behavior or
  invariant being guarded instead of the review history.
- Point the WINDOWS comment at the sibling test files that actually
  invoke npx (this module itself doesn't).
- Drop the "belt-and-braces" afterAll disclaimer from
  bundle-demo-content.test.ts and generate-registry.test.ts — the
  afterAll(restore) pattern is self-explanatory.
2026-04-18 03:23:17 -07:00
Jordan Ritter e002728828 fix(showcase/scripts): switch vitest to forks pool for Node 20 stability
unit (20.x) CI was failing with 'Timeout calling onTaskUpdate' during
the showcase-scripts test run — an unhandled vitest error that causes
ELIFECYCLE after otherwise-green tests. Reproducible on Node 20 only;
22.x and 24.x are green on the same code.

Root cause: vitest's default thread-based worker pool times out on the
parent-worker RPC channel when a test file spawns many subprocesses
(validate-pins.test.ts runs 134 tests each invoking a subprocess;
create-integration / generate-registry / bundle-demo-content each
spawn npx tsx via execFileSync). Under Node 20 the stdio / signal
traffic from these children contends with the worker-thread RPC
channel and surfaces as an unhandled timeout mid-suite.

Switch to pool: 'forks' — the fork pool uses node IPC for the RPC
rather than worker-thread messageports and is robust under the same
load. fileParallelism: false keeps files sequential so shared-env /
tmp-dir mutations don't race, but each file now gets its own fresh
fork so one file's subprocess churn can't stall the RPC for
subsequent files. Node 22/24 unaffected either way.

Also pipes stdio explicitly on every git subprocess in
test-cleanup.test.ts — inherited stdio on a fork vitest worker
interleaves with the worker's own stdout/stderr and is another input
to the RPC contention under Node 20.
2026-04-18 03:22:01 -07:00
Jordan Ritter 7ee5801160 test(showcase/scripts): add shared test-cleanup snapshot/restore helper
Introduces FileSnapshotRestorer + restoreFromGitHead helpers used by the
showcase test suites to snapshot tracked files in beforeAll and restore
them in afterEach / afterAll. Several of our test scripts invoke real
generators (create-integration, generate-registry, bundle-demo-content)
that write to tracked files outside any tmp dir: .github/workflows/ and
showcase/shell/src/data/*.json. Without explicit restoration these writes
leak into the working tree on every nx run-many -t test and, under Node
20 + vitest worker pools, the accumulated drift races the worker-RPC
channel surfacing as 'Timeout calling onTaskUpdate' -> ELIFECYCLE on CI.

Highlights:
  - FileSnapshotRestorer captures bytes at snapshot time, rewrites only
    drifted files via atomic temp+rename, and sweeps leftover
    .<basename>.<hex>.tmp stragglers scoped to the snapshotted basenames
    (no more whole-directory unlink).
  - restoreFromGitHead uses execFileSync with a frozen env (GIT_*
    scrubbed, PATH/HOME preserved) to heal a working tree left dirty by
    a crashed prior run before we snapshot.
  - On CI, a baseline that drifts after the pre-snapshot heal is a hard
    error (git binary missing, sandbox, etc.); off-CI it warns instead
    of blocking local iteration.
  - Narrow catch in the git path partitioner: only genuine 'not in
    index' pathspec errors are treated as untracked; ENOENT / EACCES /
    non-exit-1 failures re-raise so sandbox and missing-binary cases
    don't get silently swallowed and lock in a drifted baseline.
  - test-cleanup.test.ts itself strips GIT_* from child env when it
    creates tmp repos — pre-commit hooks (lefthook) run with GIT_DIR /
    GIT_INDEX_FILE set, which would cause tmp-repo 'git commit' calls
    to ignore cwd and write to the HOST working-tree HEAD. Without the
    scrub, running 'git commit' itself silently accumulates 'initial' /
    'init' commits on the real repo.

Also pulls scripts-dir / repo-root / data-dir constants into a shared
paths.ts so future layout changes flip in one place.
2026-04-18 03:14:28 -07:00