Skip to content

fix(release): keep generated release notes when the write-back fails - #1008

Open
shashank-100 wants to merge 1 commit into
modem-dev:mainfrom
shashank-100:fix/preserve-generated-changelog
Open

fix(release): keep generated release notes when the write-back fails#1008
shashank-100 wants to merge 1 commit into
modem-dev:mainfrom
shashank-100:fix/preserve-generated-changelog

Conversation

@shashank-100

Copy link
Copy Markdown

Problem

scripts/changeset-version.ts keeps Hunk's changelog canonical at the repository root by staging it beside packages/hunk, running Changesets, and copying the generated result back. The cleanup ran in a finally:

copyFileSync(packageChangelog, canonicalChangelog);   // write-back
} finally {
  rmSync(packageChangelog, { force: true });          // always deletes
}

If the write-back fails — disk full, permissions, an interrupted write — the staged file is deleted anyway. At that moment it holds the only copy of the new release notes: Changesets has already consumed the .changeset/*.md entries that produced them, and the root still contains pre-version content. The generated history is gone and recovery is manual, during a release.

Approach

Remove the staged copy only once it is reproducible again. A failure before Changesets produced output still cleans up and rethrows unchanged; a failure after leaves the generated file in place and reports where to find it:

Failed to return the generated changelog to <root>/CHANGELOG.md.
The generated history is preserved at <package>/CHANGELOG.md;
move it to the repository root before retrying.

Non-goals: the staging strategy, the canonical-root invariant, and the success path are unchanged. This only narrows when the cleanup is allowed to run. The original error is attached as cause.

Why core

Release tooling under scripts/, alongside the code it fixes. No runtime or extension surface is involved.

Tests

Added keeps the generated changelog when it cannot be returned to the root in scripts/changeset-version.test.ts. It makes the write-back fail after Changesets has produced output, then asserts the generated notes survive. Confirmed to fail on the unfixed code (raw EACCES, staged file already deleted) and pass with the fix.

The existing removes the staged package changelog when Changesets fails test still passes, so the pre-output failure path is unchanged.

Beyond the test, I verified the data loss directly against both versions of the function:

===== WITH FIX =====
threw: Failed to return the generated changelog to /var/folders/.../CHANGELOG.md
staged file still exists?  true
generated notes recoverable? YES

===== WITHOUT FIX (original code) =====
threw: EACCES: permission denied, copyfile '.../packages/hunk/CHANGELOG.md' -> '.../CHANGELOG.md'
staged file still exists?  false
generated notes recoverable? NO — DATA LOST

Commands run

bun run typecheck    # clean
bun run lint         # 0 warnings, 0 errors
bun test scripts/changeset-version.test.ts   # 4 pass, 0 fail
bun run test         # 3846 pass, 47 skip, 2 fail

The 2 full-suite failures are not from this change; the diff touches only scripts/changeset-version.*:

  • install VM contract > allows cleaning only real harness-owned paths... — pre-existing on main. Reproduced on a clean tree at upstream/main: bun test test/cli/install-vm/contract.test.ts10 pass, 1 fail. The harness compares a realpathSync-resolved root against an unresolved target, so macOS's /var/private/var symlink breaks the containment check.
  • filesystem watch observer and Jujutsu source reading failures appear only under full-suite parallel load and are timing-sensitive. Re-running bun test packages/hunk/src/core/watch/ with this change applied gives 68 pass, 0 fail.

Platforms

Verified on macOS (darwin 25.6.0). The new test skips on Windows and as root, where the permission denial it depends on does not hold; the fix itself is platform-neutral node:fs control flow.

Changeset

Empty, per CONTRIBUTING — this is release tooling with no user-visible behavior change.

Follow-up

Found while reviewing e76b0039; noted as a follow-up in #1007 and split out here so each change is reviewable on its own. Independent of #1007 — branched from main, no shared files, either can merge first.

🤖 Generated with Claude Code

https://claude.ai/code/session_019jAgP7j1gaT9fSk5syLHDH

`versionPackages` staged the root changelog beside the package, let
Changesets write the new release notes into it, copied the result back to
the root, and removed the staged file in a `finally`.

That cleanup ran unconditionally. If the write-back on line 53 failed —
disk full, permissions, an interrupted write — the staged file was deleted
anyway, and it was at that moment the only copy of the new release notes:
Changesets has already consumed the `.changeset/*.md` entries that produced
them, and the root still holds pre-version content. Recovery was manual.

Remove the staged copy only after the write-back succeeds. A failed
write-back now leaves the generated history in place and reports where to
find it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019jAgP7j1gaT9fSk5syLHDH
@greptile-apps

greptile-apps Bot commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

PR author is not in the allowed authors list.

@vercel

vercel Bot commented Sep 6, 2026

Copy link
Copy Markdown

@shashank-100 is attempting to deploy a commit to the Modem Team on Vercel.

A member of the Team first needs to authorize it.

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