feat: create GitHub releases from the changelog during npm publish - #261
Conversation
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit df2e76c. Configure here.
|
Tick the box to add this pull request to the merge queue (same as
|
df2e76c to
04f20ca
Compare
Revision history
|
04f20ca to
21094d1
Compare
There was a problem hiding this comment.
Stale comment
Reviewed the PR-only range (
210a9ee...21094d1). This is not a dependency-only update.
pnpm publish:cinow files notes from CHANGELOG, publishes npm, writes the annotatedv*tag, pushes that tag, then runsgh release create --verify-tag. The Bugbot finding (tag never pushed before--verify-tag) is fixed on this sync. Changelog/publish AVA tests: 33 passed.I am not requesting changes. The remaining items are medium: dry-run can look green when a real run would stop; GitHub "missing release" matching is looser than the npm 404 classifier; the first write of
origin's tag still happens after npm; one test pins live CHANGELOG bullets; and the new one-step npm + GitHub rule has no Proof Decision (the lockstep-version Constraint does not cover it).Architecture COMMENT · quality COMMENT · Proof journal COMMENT · correctness COMMENT (one HIGH downgraded: post-npm tag push is the safer order and can retry; preflight the remote tag before npm rather than blocking the merge).
Sent by Cursor Automation: Flatbread PR Review
There was a problem hiding this comment.
Stale comment
Independent review of
21094d1(PR-only slice vs210a9ee). Not a dependency-only update. Architecture and Proof journal: no merge gap. The Bugbot high-severity hole is closed:pushReleaseTagrunsgit push origin refs/tags/<tag>beforegh release create --verify-tag.Lockstep still holds.
assertLockstepVersionsyields one version;githubReleaseTagbuilds onev*tag; bump andchangelog:shiftmay writeCHANGELOG.md;publish:cionly accepts a committed## <version>section. GitHub release after every public package is on npm matches the “together” step. Retry stays coherent: already-published packages skip; an existing GitHub release skips.Two medium notes before the first real
publish:ciunder this flow (inlines). Residual, not blocking:classifyGhReleaseViewtreatsNot Found/HTTP 404as create — afterassertCommitOnGithubthat is almost always a missing release, which is whatgh release viewprints. Quality cleanups (fold npm error flattening intocollectErrorDetails, oneapplyChangelogShifthelper, compute formatted notes once) can wait.Proof journal is absent. That is acceptable here:
CONTRIBUTING.mdand the scripts already carry the unique signal. If someone journals later, an accepted Decision deriving fromcon-public-npm-releases-use-one-lockstep-versionwithrejectSiblings: falseis enough.Checks:
pnpm exec ava scripts/publish.test.ts scripts/changelog.test.ts scripts/utils/changelog.test.ts— 33 passed.Sent by Cursor Automation: Flatbread PR Review
3999dfb to
6602314
Compare
There was a problem hiding this comment.
Stale comment
Reviewed the PR-only range (
210a9ee...6602314). This is not a dependency-only update.Every standing item from
21094d1is fixed.publish:drynow throws on the same clean-tree, changelog,gh, pushed-commit, remote-tag, and npm gates aspublish:ci.classifyGhReleaseViewtreats onlyrelease not foundor an HTTP 404 as create.git ls-remotechecks the release tag before any npm publish. The liveCHANGELOG.mdAVA fixture is gone. Accepted Decisiondec-create-changelog-backed-github-releases-in-publi--fh6bsn7jr296q93drecords the one-step npm + GitHub rule, derives from the lockstep-version Constraint, and was accepted without closing other proposed Decisions in that Effort.The release order still holds: hard gates, then the npm loop, then an annotated
v*tag push only when the remote tag is absent, thengh release create --verify-tag. A retry skips already-published packages and skips a GitHub release only when its body matches the filed notes.Architecture APPROVE. Proof journal APPROVE. Quality leftover LOW (duplicate error flattening; two changelog prepare passes). Correctness leftover LOW:
pnpm bumpcan still write an empty## <version>when Unreleased has no list items; publish then rejects that section before npm (fail-closed). Changelog and publish AVA: 41 passed.I am not requesting changes.
Sent by Cursor Automation: Flatbread PR Review
6602314 to
95b85ca
Compare
The 1.0.1 packages reached npm without a GitHub release or release notes. `pnpm publish:ci` now owns both halves of the release so that step cannot be missed. Before npm publication, the script checks the clean tree, a non-empty committed changelog section, GitHub access, the pushed commit, and the remote tag. After every public package is on npm, it creates and pushes the annotated `v<version>` tag and creates the GitHub release from that version's `CHANGELOG.md` section. Retries skip an existing GitHub release only when its body matches those filed notes. `pnpm publish:dry` runs the same readiness gates without writing. Bump and changelog commands distinguish moved notes from an empty version placeholder. The release policy and its reversal criteria are recorded in Proof. ## Test plan - [x] Focused AVA tests for bump, changelog, and publish behavior - [x] `pnpm typecheck` - [x] `pnpm verify` Change-Id: I88ddb9fb57904be037d03501f77f3d161d20c5f3 Co-authored-by: Cursor <cursoragent@cursor.com>
There was a problem hiding this comment.
Reviewed the PR-only range (210a9ee...95b85ca). This is not a dependency-only update.
The leftover LOW from 6602314 is fixed. PreparedChangelog.didMoveItems now splits “heading created” from “list items moved.” pnpm bump and pnpm changelog:shift warn on an empty ## <version> placeholder. prepareReadyReleaseChangelog still rejects that empty section before npm.
Architecture and Proof journal: no merge gap. The accepted Decision dec-create-changelog-backed-github-releases-in-publi--fh6bsn7jr296q93d still matches HEAD: one publish:ci step, filed CHANGELOG notes, npm then tag/GitHub, dry-run hard gates, idempotent retry, rejectSiblings: false.
One new LOW honesty gap remains (inline). When ## <version> already exists and is empty, changelog:shift prints a green ready line and the synthetic Release X.Y.Z. body. Publish still fail-closes, so this cannot ship empty GitHub notes.
Focused AVA: 41/41 on scripts/publish.test.ts, scripts/changelog.test.ts, and scripts/utils/changelog.test.ts.
Sent by Cursor Automation: Flatbread PR Review
| if (!prepared.didShift) { | ||
| console.log( | ||
| colors | ||
| .bold() | ||
| .green( | ||
| `CHANGELOG.md already has ## ${version}; Unreleased has no items to move` | ||
| ) | ||
| ); | ||
| printNotes(prepared.notes, version); |
There was a problem hiding this comment.
LOW, not blocking: when ## <version> already exists with an empty body, prepareReleaseChangelog returns didShift: false and notes: fallbackReleaseNotes(version) (Release ${version}.). This branch then prints a green “already has” line and those synthetic notes.
publish:ci still rejects the empty section, so empty GitHub notes cannot ship. An operator who only runs changelog:shift / --dry-run can still treat that printed body as ready.
Use the same yellow empty-section warning as the new-heading path (didShift && !didMoveItems just below), and skip printing fallback notes until the section has real list items.



The 1.0.1 packages reached npm without a GitHub release or release notes.
pnpm publish:cinow owns both halves of the release so that step cannot bemissed.
Before npm publication, the script checks the clean tree, a non-empty committed
changelog section, GitHub access, the pushed commit, and the remote tag. After
every public package is on npm, it creates and pushes the annotated
v<version>tag and creates the GitHub release from that version'sCHANGELOG.mdsection. Retries skip an existing GitHub release only when itsbody matches those filed notes.
pnpm publish:dryruns the same readiness gates without writing. Bump andchangelog commands distinguish moved notes from an empty version placeholder.
The release policy and its reversal criteria are recorded in Proof.
Test plan
pnpm typecheckpnpm verifyCo-authored-by: Cursor cursoragent@cursor.com