Skip to content

fix: Check for semver before patch-release.js requires it - #970

Draft
kriszyp wants to merge 5 commits into
mainfrom
fix/patch-release-deps-preflight
Draft

kriszyp wants to merge 5 commits into
mainfrom
fix/patch-release-deps-preflight

Conversation

@kriszyp

@kriszyp kriszyp commented Oct 5, 2026 •

Copy link
Copy Markdown
Member

Authored by Claude Sonnet 5 (dispatch harper-pro-patch-release-deps-preflight).

⊙ Problem

scripts/patch-release.js loads semver at module load with no guard. In a fresh release clone with no node_modules, the script dies with a raw MODULE_NOT_FOUND stack and never prints a RESULT: line, so neither a human nor a --json caller learns the fix. Seen during the 5.2.0 release cut.

❓ Your call: Fix as specified. The check runs before any git, version, or push step, so a missing dependency stops the run before it changes anything.

💡 Solution

  • When run as the CLI, the script calls require.resolve('semver') before the require and, on failure, exits 1 with semver is not installed. Run npm ci in <repo root> first. plus a RESULT: {"ok":false,...} line.
  • CONTRIBUTING.md adds npm ci before node scripts/patch-release.js in the release procedure.

❓ Your call: The failure writes its RESULT: line without --json. Other die() calls emit only under --json. This one follows the --yes missing-backport abort path, which already emits without --json (CONTRIBUTING.md). Changing it is a one-line edit.

❓ Your call: The one-line comment at scripts/patch-release.js:93 (why the check is skipped under require()) is kept. A review nit asked to drop it. The reason is not visible in the code.

⚖️ Alternatives

  • Docs only (npm ci in CONTRIBUTING.md). Rejected: a run without npm ci still crashes with the raw stack and no RESULT: line.
  • npm pre script wrapper. Rejected: a second entry point for one script.

🔧 Changes

❓ Your call: The dispatch's acceptance route named NODE_PATH at an empty dir or a fixture copy without node_modules. Neither isolates the child from ancestor or global node_modules on a given host, so the test runs the real script with a -r preload that makes require('semver') fail.

✅ Verification

  • mocha --require unitTests/unitTestSetup.cjs unitTests/scripts/patchRelease.test.mjs unitTests/scripts/patchReleasePresence.test.mjs on 93ef0250: 63 passing.
  • Fails on base: the new test, run against 36efd7e4:scripts/patch-release.js, fails. The base crashes with Cannot find module 'semver' and no RESULT: line.
  • Manual run on base, semver absent: raw MODULE_NOT_FOUND stack, no RESULT: line. On this branch: the npm ci message, RESULT: {"ok":false,...}, exit 1.
  • prettier --check and oxlint --deny-warnings clean on the changed files.
  • Not run: full npm run test:unit and integration tests. The change is a script and its test; no build output changes.
  • Pre-push review (codex + gemini + cursor-composer + harper-domain): 6 rounds, all exit 0. Converged on 93ef0250; receipt on the pushed head. Round 1 found one test-isolation minor and two nits, all fixed. Rounds 3–4 drove the switch to the -r preload and comment trims. One Gemini major (undefined tmpdir) was dropped as factually wrong: tmpdir is imported at unitTests/scripts/patchRelease.test.mjs:16.

No tracking issue: the bug was found during the 5.2.0 release cut.

🤖 Generated with Claude Code

Related PRs: none found

Review-Coverage: authored=claude; ran=cursor-composer,gemini,codex; adjudicated=domain; declined=cursor-grok,cursor-kimi,cursor-muse; rounds=6; full=2 @ 93ef025

Review-Attention: skim ~12m (decisions: result-line-without-json) @ 93ef025

kriszyp and others added 5 commits October 5, 2026 08:47
scripts/patch-release.js required semver at load time with no guard, so a clone without node_modules died with an unformatted MODULE_NOT_FOUND and no RESULT line. The CLI now resolves semver first and exits with a RESULT line naming `npm ci` in the repo root. CONTRIBUTING.md's release section lists the npm ci step.

Dispatch-Task: harper-pro-patch-release-deps-preflight
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JcQh5MH3dUbrLzfQ5swiXh
The spawned-CLI test asserted the npm ci message from a fixture under TMPDIR. Node still resolves ancestor node_modules and HOME's global folders, so a semver found there would pass the preflight and fail the test for an unrelated reason. The test now sets HOME to the fixture and fails first if semver still resolves from the fixture. The preflight comment drops the narrative and keeps the require() reason.

Dispatch-Task: harper-pro-patch-release-deps-preflight
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JcQh5MH3dUbrLzfQ5swiXh
The probe-based guard failed whenever a host resolved semver from an ancestor of TMPDIR or a global folder, which made the test depend on the machine's layout. A -r preload now makes require('semver') fail in the child, so the preflight branch runs everywhere. The script comment keeps only the reason for the require.main check.

Dispatch-Task: harper-pro-patch-release-deps-preflight
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JcQh5MH3dUbrLzfQ5swiXh
The test copied the script into a fixture tree, which still inherits ancestor and global module lookup. It now runs scriptPath directly with the preload, and asserts the message names the real repo root. The fixture only holds the preload and is removed only if it was created. The script comment keeps only the reason for the require.main check.

Dispatch-Task: harper-pro-patch-release-deps-preflight
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JcQh5MH3dUbrLzfQ5swiXh
Dispatch-Task: harper-pro-patch-release-deps-preflight
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JcQh5MH3dUbrLzfQ5swiXh

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a runtime dependency preflight check to scripts/patch-release.js to ensure that the semver package is installed before execution, providing a clear error message to run npm ci if it is missing. It also updates CONTRIBUTING.md with instructions to install dependencies first and adds a comprehensive unit test suite to verify this preflight behavior. There are no review comments, and I have no feedback to provide.

This branch has not been deployed

No deployments
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