Skip to content

Read the release label from the merge, not from a lookup - #33

Merged
evandhoffman merged 1 commit into
mainfrom
fix/release-label-lookup
Aug 19, 2026
Merged

Read the release label from the merge, not from a lookup#33
evandhoffman merged 1 commit into
mainfrom
fix/release-label-lookup

Conversation

@evandhoffman

Copy link
Copy Markdown
Contributor

Summary

Four merges carried release:minor. #23 and #28 shipped minor versions; #30 and #32 shipped patches. The label was on all four, and querying the same endpoint by hand afterwards answers correctly for all four — so the bug is in when the answer is available, not in the data.

  • The label now comes from the merge commit's own subject. A squash merge writes (#32) into it, so the number is read from there and the labels come from that pull request directly, instead of asking GitHub which pull request a commit came from. That association is not reliably present at the moment this runs.
  • Failures are no longer swallowed. labels="$(… || true)" turned every refusal, timeout and empty answer into an empty label list — indistinguishable from an unlabelled merge, and therefore a patch bump. A number that is not a pull request now stops the release. A blocked release is a message; a release that quietly picks the wrong version is not.
  • permissions: gains pull-requests: read. The block sets every scope it does not name to none, so with contents: write alone the lookup could only ever be refused — which may well be the original cause, and is exactly what the old code could not report.
  • Every decision goes to stdout as well as the job summary: the pull request number, the labels found, the bump chosen. All four echo … >> $GITHUB_STEP_SUMMARY became | tee -a, because the summaries come back empty through the API and the logs held nothing.
  • AGENTS.md gains the constraint and a troubleshooting entry.

No version is renumbered. v1.3.1 and v1.3.2 were feature releases that shipped as patches and stay as they are.

Test plan

  • YAML parses
  • The subject parser dry-run: (#32) → 32, (#28) → 28, Version 1.3.2 [skip ci] → none, (#12) mid-sentence → none, a plain direct push → none
  • End-to-end dry-run against the real merges: 492a442 → PR Stack the slices of a whole, and dash the lines among them #32release:minorminor, 5ce3ad7 → PR Mirror the in/out charts, when you ask for it #30release:minorminor, 249e8db (a bump commit) → no number → patch. The first two are precisely the merges that got this wrong.
  • The real proof is the next labelled merge. This PR is release:skip and only touches .github/ and AGENTS.md, so it publishes nothing itself.

https://claude.ai/code/session_01UPbN2SqYq8t2vcx2YWQTcs

Four merges carried release:minor. Two shipped a minor version and two shipped
a patch, and nothing distinguished them: the label was on every one of them, and
querying the same endpoint by hand afterwards answered correctly for all four.

The lookup asked GitHub which pull request a commit came from. That association
is not reliably present at the moment this workflow runs, and the failure had
nowhere to go -- `|| true` turned every refusal, timeout and empty answer into
an empty label list, which is the same value as an unlabelled merge, which is a
patch bump. Two feature releases went out as patches and the log recorded
nothing about it, because every line in the step wrote to the job summary and
the summaries come back empty through the API.

So stop asking. A squash merge writes the pull request number into its own
subject, so the number is read from there and the labels come from that pull
request directly. A direct push to main has no number in its subject, which is
simply no labels and still takes the patch default.

The lookup no longer swallows failures. A number that is not a pull request now
stops the release, which is the intended trade: a blocked release is a message,
and a release that quietly picks the wrong version is not.

permissions gains pull-requests: read. The block sets every scope it does not
name to none, so with contents alone the lookup could only ever be refused --
which may well be what happened, and is exactly the kind of thing the old code
could not tell anybody.

Every decision the step makes now goes to stdout as well as the summary: the
pull request number, the labels found, the bump chosen.

No version is renumbered. v1.3.1 and v1.3.2 were feature releases that shipped
as patches, and they stay as they are.

Claude-Session: https://claude.ai/code/session_01UPbN2SqYq8t2vcx2YWQTcs
@evandhoffman evandhoffman added the release:skip Merging this publishes no release label Aug 19, 2026
@evandhoffman
evandhoffman merged commit adf2f57 into main Aug 19, 2026
0 of 2 checks passed
@evandhoffman
evandhoffman deleted the fix/release-label-lookup branch August 19, 2026 13:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

release:skip Merging this publishes no release

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant