Skip to content

Fix the release pre-flight's worktree cleanup on Linux and macOS - #56

Merged
iLevyTate merged 2 commits into
mainfrom
claude/gallant-babbage-mlfl4c
Oct 31, 2026
Merged

iLevyTate merged 2 commits into
mainfrom
claude/gallant-babbage-mlfl4c

Conversation

@iLevyTate

Copy link
Copy Markdown
Owner

Summary

  • scripts/stability/compare-baseline.js (run by npm run test:critical-path:twice and npm run preflight:release[:quick]) links the main repo's node_modules into each stability worktree with fs.symlinkSync(target, dest, 'junction') and detaches it before removing the worktree with fs.rmdirSync. The 'junction' type only applies on Windows; elsewhere the link is a plain symlink, which rmdirSync rejects with ENOTDIR. Preparing 5.1.0 on Linux, preflight:release:quick crashed in that cleanup after both smoke runs, skipped check-release-thresholds.js, and left both worktrees behind.
  • removeNodeModulesLink now uses rmdirSync for the Windows junction and unlinkSync elsewhere. Both remove only the link, never the main repo's node_modules (the hazard the function's comment documents).
  • main() now runs only when the script is executed directly, so the function can be exported and unit-tested.

Scope

  • Area(s): release tooling (scripts/stability)
  • Risk Level: low (dev/release script only; nothing that ships)
  • Breaking Changes: none

Type of Change

  • Bug fix
  • Enhancement
  • New feature
  • Refactor
  • Documentation update
  • Breaking change

Test Plan

Automated

  • npm run format:check
  • npm run lint
  • npm test (new suite; CI runs the full set)
  • Additional tests added/updated when behavior changed: test/compareBaseline.removeNodeModulesLink.test.js checks that a linked node_modules is removed with its target intact (fails on the old code with the same ENOTDIR), a real node_modules is left alone, and a missing one is a no-op.

End to end on Linux: npm run test:critical-path:twice now completes. All three required journeys pass on v5.0.0 and HEAD, OK: Release thresholds satisfied., both worktrees are removed, and the main repo's node_modules is intact.

Manual QA

  • Manual checklist completed (see docs/TESTING.md)
  • Not applicable (explain below)

Manual QA notes:

  • Script-only change; the Windows junction path is unchanged.

Checklist

  • I scoped this PR to one logical change
  • I self-reviewed code and naming for clarity
  • I updated docs/config references where needed
  • I called out follow-up work or known limitations

Generated by Claude Code

…cOS too

compare-baseline links the main repo's node_modules into each stability
worktree with fs.symlinkSync(target, dest, 'junction') and detaches it
before removing the worktree with fs.rmdirSync. The 'junction' type only
applies on Windows; elsewhere the link is a plain symlink, which
rmdirSync rejects with ENOTDIR. On Linux, `npm run preflight:release:quick`
therefore crashed in cleanup after both smoke runs, skipped the release
threshold check, and left both worktrees behind.

removeNodeModulesLink now uses rmdirSync for the Windows junction and
unlinkSync elsewhere; both remove only the link, never the main repo's
node_modules. main() runs only when the script is executed directly, so
the function can be exported and tested.

New test: a linked node_modules is removed with its target intact (fails
on the old code with the same ENOTDIR), a real node_modules is left
alone, and a missing one is a no-op. `npm run test:critical-path:twice`
now completes on Linux: 3/3 journeys pass on v5.0.0 and HEAD, thresholds
satisfied, both worktrees removed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q5Uo5hC58DRSh1qB489Sos
The global test setup swaps fs for memfs, which has no Windows junctions,
so on the Windows runner the rmdir that removes a real junction failed with
ENOTDIR inside memfs. Opt the test out of the fs and os mocks, as the other
real-filesystem tests do, so each platform exercises the link it actually
creates.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q5Uo5hC58DRSh1qB489Sos
@iLevyTate
iLevyTate merged commit adf889c into main Oct 31, 2026
10 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.

2 participants