ci: adopt the fleet release-PR healer - #117
Merged
Merged
Conversation
Release PRs here arrive with their required contexts absent rather than red: release-please creates them with GITHUB_TOKEN and GitHub raises no workflow-triggering events for that token, so branch protection holds a PR with a missing context forever. The healer lives in forkwright/.github; this file only asks for it. The permissions block is load-bearing rather than boilerplate: for a called workflow the caller's permissions are a CAP, never a default it may exceed, so the customary `contents: read` alone would leave the healer unable to approve a single run -- and the only symptom would be a release that stayed stuck.
Uh oh!
There was an error while loading. Please reload this page.
forkwright added a commit
that referenced
this pull request
Aug 26, 2026
…se-please (#121) ## Finding Release Please has aborted every single run since PR #58 merged 2026-07-28T21:12:21Z — a full month, entirely unrelated to today's Actions outage/billing lockout (hamma is public). hamma has zero git tags and zero GitHub Releases while `.release-please-manifest.json` and `CHANGELOG.md` both already declare v0.2.0 shipped. ## Evidence `gh api repos/forkwright/hamma/tags` and `.../releases` both return `[]`. PR #58 ("chore: release main") still carries the `autorelease: pending` label today — it was never flipped to `autorelease: tagged`, which only happens when release-please successfully creates the release. The run immediately after the merge (id 30399683185, 2026-07-28T21:12:24Z, conclusion=success) and the most recent run before this PR (id 33002219225, 2026-08-26T18:53:53Z, run *after* PR #117's healer merged) both log the identical sequence: ``` ✔ Building releases ❯ Found pull request #58: 'chore: release main' ✔ Building release for path: . ⚠ PR component: undefined does not match configured component: hamma ... ❯ Building candidate release pull request for path: . ❯ Found pull request #58: 'chore: release main' ⚠ There are untagged, merged release PRs outstanding - aborting ``` Traced against `googleapis/release-please` v17.6.0 (the pinned action version) source: - `Manifest.createReleases()` → `buildReleases()` → per-strategy `buildRelease()` (`src/strategies/base.ts:640-656`) parses the merged PR's **branch name** via `BranchName.parse()`. hamma's branch is `release-please--branches--main` — matches `DefaultBranchName` (`src/util/branch-name.ts`), which **never sets `.component`** (only `AutoreleaseBranchName`/`ComponentBranchName` do, neither of which this repo's shape produces, since `separate-pull-requests: false` always yields the plain branch pattern). - That `undefined` is compared against `getBranchComponent()` (`src/strategies/base.ts:191`), which returns `this.component || getDefaultComponent()` — **ignoring `include-component-in-tag` entirely** — and falls back through `package-name` when `component` is unset. hamma's config set both to `"hamma"`, so this always resolves to `"hamma"`. - `"hamma" !== undefined` → `buildRelease()` returns early with no release built → `createReleases()` creates nothing, silently. - `Manifest.createPullRequests()` (`src/manifest.ts:920-933`) then finds the same still-`autorelease: pending` PR #58 via `findMergedReleasePullRequests()` and aborts opening a new PR too — the exact log line above. This is not a one-off: every future hamma release PR will produce the identical component-less branch name, so this wedges every release forever, not just this one. **Fleet comparison** (`gh api repos/forkwright/<repo>/contents/release-please-config.json`): akroasis, epistole, harmonia, gnomon, and thumos all carry **neither** `package-name` nor `component` in their package block, and all have real tags. hamma is the only one of the six checked that sets both — and the only one stuck. `include-component-in-tag: false` is already set, so removing both fields changes no *observable* tag/branch/PR-title format: PR #58's actual body (`<summary>0.2.0</summary>`, no `hamma:` prefix) and branch name were already component-less before this fix — `getComponent()` already returns `''` when `include-component-in-tag` is false. The bug is purely in `getBranchComponent()`'s separate, unguarded fallback. ## Why this matters A missing release is worse than a failing one to notice, but this is actively worse than "release-please is idle": it looks like nothing is wrong (CHANGELOG.md and the manifest both say 0.2.0 shipped), until someone tries to depend on hamma via a tagged version, or `cargo add --git ... --tag v0.2.0`, and there is nothing there. ## Desired correction Remove `package-name`/`component` from `release-please-config.json`'s `.` package block so `getBranchComponent()` resolves to the same empty value the branch name already carries. **Done when:** the next release-please run after this merges creates the `v0.2.0` tag + GitHub Release for PR #58 and flips its label from `autorelease: pending` to `autorelease: tagged`, without manual intervention. **This is unverified** — see below. ## Not verified, and why I could not run release-please locally (`npx`/network package execution is outside what this lane is authorized to do) or dispatch this fix on a feature branch to test it: the reusable workflow's `release-please` job does no repo checkout and reads `release-please-config.json` from the `main` branch via the GitHub Contents API regardless of which ref triggers the run (confirmed in both run logs above — `Fetching release-please-config.json from branch main`), so a feature-branch `workflow_dispatch` would not exercise this change at all. The diagnosis above is source-traced against the exact pinned release-please version, not guessed, but the merge itself is the first real test. I also verified, and did **not** perform, the alternative direct fix: create the `v0.2.0` tag at PR #58's merge commit (`6cc5781693ab276cc0f53369c86ac0062087cbf7`, confirmed on `main` via `git merge-base --is-ancestor`) and the matching GitHub Release from CHANGELOG.md's 0.2.0 section — both blocked by this session's own sandbox policy (direct tag-push and `gh release create` were both refused). If the config fix above does **not** self-heal on the next run, that manual recipe is the fallback and is fully worked out; it needs write authority this session doesn't have. **Watch the first release-please run after this merges** and confirm the tag/release/label actually land. Co-authored-by: forkwright <cody@forkwright.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for freeto join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Finding
Release PRs in this repo arrive with their required contexts absent rather than red.
release-pleasecreates its PR withGITHUB_TOKEN, and GitHub raises no workflow-triggeringevents for that token, so branch protection holds a PR with a missing context forever — nothing to
re-run, nothing to approve.
Evidence
Measured across the fleet 2026-08-26: four release PRs (akroasis#465, epistole#127, harmonia#733,
gnomon#68) sat 8 days at
mergeStateStatus: BLOCKEDwith an emptystatusCheckRollupwhile their workflow runs waited at
action_required.aletheia has carried the only healer for months. A file-existence check found
release-pr-checks.yml404 in all 17 other release-please repos, and nothing visible frominside any of them revealed the gap.
Why this matters
A missing check is worse than a failing one. A red check advertises itself; an absent one looks
exactly like a PR that has not finished. Releases stop, and the only symptom is a PR that appears
to be waiting on CI.
Desired correction
Adopt the reusable healer (
forkwright/.github#56). This file asks for it and declares nothingabout how it works, so it cannot drift from the other adopters.
Done when: a subsequent release PR here reaches a non-empty
statusCheckRollupwithout a humanapproving runs by hand.
The permissions block is load-bearing
Not the usual boilerplate. For
workflow_callthe caller'spermissionsis a cap — a calledworkflow can only downgrade the token, never upgrade it. A caller declaring the customary
contents: readalone would leave the healer unable to approve a single run, and the only symptomwould be a release that stayed stuck.
Proven, not assumed
The whole path was exercised on akroasis before this rollout:
Actions: writeconfirmed present in the reusable's job token, so the caller's grant does reachit (run 32982564877).
GITHUB_REPOSITORYresolves to the caller — the healer reported#465 at b75af1a6f,akroasis's own release PR, while running from
forkwright/.github.workflow_runtrigger fired automatically on release-please completion and superseded amanual dispatch via
cancel-in-progress, exactly as designed.GITHUB_TOKEN+actions: writeapproving a genuinely held run:201, and the run movedaction_required→in_progress(probed on zetesis run 31286567826). No PAT and no reposecret are required — an assertion to the contrary lived unexamined in aletheia's copy for
months and is false.