Skip to content

The bump PR's summary heads the GitHub Release page - #172

Merged
JacobStephens2 merged 3 commits into
mainfrom
issue-161
Sep 30, 2026
Merged

JacobStephens2 merged 3 commits into
mainfrom
issue-161

Conversation

@JacobStephens2

Copy link
Copy Markdown
Owner

Summary

The published GitHub Release now opens with the bump PR's summary. release-notes.yml checks out the tag and runs a new script, scripts/release-notes.sh <tag> <install notes>, which builds the body:

release-notes.sh <tag> <install notes>
  commit = <tag>^{commit}
  pr     = gh api commits/<commit>/pulls, the PR whose merge_commit_sha == commit
  if pr's body has <!-- release-summary:start/end -->
    print summary, blank line
  print GitHub's generated notes          # as before
  print blank line, dist's install notes  # as before
  • A tag pushed by hand, a tag on a PR's head commit rather than its merge, or a PR with no summary section all get exactly the body they get today.
  • The script builds the body from the tag and the PR and never reads the Release's current body, so running it again gives the same body.
  • If the PR can't be read (say, the token is refused), the script warns and falls back to today's body. It does not fail the job and leave dist's body in place.
 release-notes.yml
+  actions/checkout@v7 (ref: the tag)
-  gh api generate-notes > notes.md; printf install >> notes.md
+  scripts/release-notes.sh "$TAG" "$INSTALL_NOTES" > notes.md
   gh release edit "$TAG" --notes-file notes.md

The fake gh now answers repos/<repo>/commits/<sha>/pulls, returning the PRs merged as <sha> and those whose head is <sha>, as GitHub does. Its generate-notes no longer needs target_commitish. release.yml, which dist generates, is untouched.

Evidence

  • Before: the new tests in tests/release.rs failed because scripts/release-notes.sh did not exist.
    After: cargo test passes, including these tests of the script as a black box:
release 0.2.0 via release.sh, then release-notes.sh v0.2.0 twice
  → "<agent summary>\n\n<generated notes>\n\n<install>\n", both times identical
v0.1.0 (merge of a PR without a summary), v0.1.2 (head of a PR with one), v0.1.3 (no PR)
  → "<generated notes>\n\n<install>\n"
commits/<sha>/pulls fails
  → warning on stderr, "<generated notes>\n\n<install>\n", exit 0

cargo clippy --all-targets and shellcheck scripts/*.sh are clean.

Merge Danger

Door: two-way

Revert the workflow and the script to go back to generated notes only.

Blast Radius: Release-page

Only the Release body changes, and only after the Release is published. The binaries, the installer, the smoke checks and the crates.io publish are unaffected. If the job fails outright, the Release keeps dist's body. It could fail only if the tag checkout or the generate-notes call fails, which is the same risk as before, plus the checkout.

Unaddressed findings

Standards

  • The generate-notes call now appears in both release.sh and release-notes.sh. Skipped: the two calls take different arguments (a target and previous tag, against the tag alone), so a shared helper would only hide that difference.
  • The fake gh's commit_prs repeats pr_view's head-OID lookup. Skipped: they fail differently on purpose. pr_view fails loudly on a missing branch, while the commit lookup has to skip PRs whose branch is gone, as GitHub does.
  • The workflow header, the README and the script header all describe the same body layout. Skipped: the repo documents behaviour at each of these layers, and the README is where the Releasing procedure lives.

Spec

  • The first real release should confirm that the job's token (contents: write only, set in the generated release.yml) can read PRs. Not fixable here, because release.yml must not be edited. The script now falls back with a warning, so a refusal costs only the summary.
  • When claude fails, release.sh's fallback summary is GitHub's generated notes, so the Release shows that list twice. Skipped: The bump PR's summary heads the GitHub Release page #161 doesn't cover this case, and release.sh already tells the maintainer to edit the PR body.

Closes #161

🤖 Generated with Claude Code

JacobStephens2 and others added 3 commits September 30, 2026 03:10
scripts/release-notes.sh builds the Release body: the summary section of
the PR merged as the tag's commit, then GitHub's generated notes, then
dist's install instructions. Without such a PR or summary, the body is as
before. release-notes.yml now checks out the tag and runs it. The fake gh
answers the commit-to-PRs endpoint so the script is tested as a black box.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The release-notes job's token has only contents: write, so a PR read may
be refused. Rather than failing and leaving dist's body, warn and build
the body without a summary. Also point each script's marker comments at
the other.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Keeps both sides: main's pre-flight refusals (#157) alongside this
branch's release body built from the bump PR's summary. In the README
the refusal paragraph sits before the release workflow paragraph, which
keeps this branch's description of the body; in tests/release.rs both
sets of tests are kept.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@JacobStephens2
JacobStephens2 merged commit ef5d8c6 into main Sep 30, 2026
13 checks passed
@JacobStephens2
JacobStephens2 deleted the issue-161 branch September 30, 2026 03:33
@JacobStephens2 JacobStephens2 mentioned this pull request Sep 30, 2026
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.

The bump PR's summary heads the GitHub Release page

1 participant