Repository navigation
feat: auto-merge the mechanical release PR and show its timeline - #821
Conversation
HugoXK-bot
left a comment
There was a problem hiding this comment.
Verdict: PASS at 161a26f
Written-by: HugoXK-bot
Posted-by: HugoXK-bot
The step does what the release routine needs and nothing more: it opts the mechanical release PR into auto-merge and lets the required checks decide, and it cannot merge anything it did not open.
- Gating.
.github/workflows/daily-release.yml:411-417runs only wheninputs.dry_run != trueand the opener state isopenedorreused; arefusedopener exits earlier (:408), so a refused run cannot reach this step. - Head pinning.
PUSHEDcomes from the push step, which sets it to the remote head on both paths including a reused branch, so the emptiness guard at:421-424cannot fire on the reuse path with a stale value.:430passes--match-head-commit "$PUSHED", so a force-push between the push and the merge aborts instead of merging a different tree. - Repository capability. Read from the API this turn:
allow_auto_merge=true,allow_squash_merge=true,allow_merge_commit=false, so--auto --squashmatches what the repository will accept; the merge still waits forci-ok,review-gateandpr-lint, all of which are required onmain. - No bypass. There is no
--adminin the workflow, and the test asserts the exact command line and its absence.
Non-blocking, for a later tidy-up: when releaseStatus exists but compareRunning returns null the card renders an empty detail with stateBadge('unknown') (same shape as #809), and #780's dead duplicate branch is still there; neither belongs to this PR.
Ran at 161a26f:
npm run check— pass, 1989/1989 tests, typecheck and build includednode scripts/risk-gate.mjs --base cc305a6030ae11f6de4766ad19e36934112a7020 --head HEAD—risk-tier: T3; basis: .github/workflows/daily-release.ymlnode scripts/pr-lint.mjs --pr 821—pr-lint: ok (#821, T3, 10 files)node scripts/changelog.mjs check— 42 fragments oknode scripts/version.mjs check— 0.3.6 oknode scripts/secret-scan.mjs— no suspected value
Not run: a live release dispatch, GitHub's auto-merge queue itself (that needs a real release PR).
Conclusion: safe to enqueue. The step only enables auto-merge on the PR the routine just opened or refreshed, pins the head sha, and leaves every required check as the actual gate.
Merge live main. Both conflicts are paragraphs added at the same anchor, so both sides are kept in docs/architecture.md, and src/views/pages.ts keeps the pull request's additions. Written-by: Fledge Platform Dev-1
HugoXK-bot
left a comment
There was a problem hiding this comment.
Verdict: PASS at 9a44b29
Written-by: HugoXK-bot
Posted-by: HugoXK-bot
Read the tip 9a44b29426c7070ee1b416c3dbd10f5602de0a57 (7 files +82/−9, T3; .github/workflows/daily-release.yml blob 72bd5fe6 matches the contents API). This supersedes my PASS at 161a26f3 only because the forward merge moved the tip; the change I read there is the change I read here.
Findings, none blocking:
.github/workflows/daily-release.yml:418-438— auto-merge is gated onsteps.open.outputs.statebeingopenedorreused(:422), refuses whenPRorPUSHEDis empty (:429-432), and pins the tip with--match-head-commit "$PUSHED"(:437). No--admin, and the token is the sameRELEASE_OPEN_TOKENthat opened the PR..github/workflows/daily-release.yml:378-391withscripts/release-open.mjs:269,365—pris written by the opener for both thereusedandopenedresults, and the open step only runs whensteps.push.outputs.pushedis non-empty, so the two values the new step requires cannot both be absent on an allowed path..github/workflows/daily-release.yml:437withtest/dailyRelease.test.ts:164-175— the structural test keepsgh pr create/gh release/git tagforbidden, allows exactly onegit push(the release branch), and now asserts the auto-merge line and the absence of--admin.src/lib/releaseStatus.ts:33-36,94-99— the three timestamps are optional and read only when they are strings, so an older snapshot still parses;src/views/pages.ts:2488-2495,2509renders only the parts that exist and keeps them behind onedata-release-timelineline.- Enabling auto-merge does not bypass anything: GitHub still waits for
ci-ok,review-gateandpr-lintat the pinned head.
Ran (exact tip tree; blob hash above verified):
npm run check— lint 11 baseline warnings, typecheck clean, 2183/2183 tests, build oknode scripts/pr-lint.mjs --pr 821— ok (#821, T3, 7 files)node scripts/changelog.mjs check— 63 fragments oknode scripts/version.mjs check— 0.3.6 oknode scripts/secret-scan.mjs— no suspected value in the tracked files
Not run: a real nightly run against GitHub (the workflow cannot be exercised here), Docker, production.
CI at this tip: everything green except review-gate failure 12:21:37Z, which is the pre-verdict state this review replaces.
Written-by: HugoXK
Fixes #819
risk-tier: T3; basis: .github/workflows/daily-release.yml
Stacked on #809. This branch starts from #809's admin-card commit; until #809 merges, the PR diff also shows that commit. Merge #809 first, then this PR shows only the auto-merge/timeline commit.
What changed
.github/workflows/daily-release.ymlpr=) in its outputs;opened/reusedmechanical release PRs with the sameRELEASE_OPEN_TOKEN:gh pr merge "$PR" --auto --squash --match-head-commit "$PUSHED";--adminremains forbidden.src/lib/releaseStatus.tsandsrc/views/pages.ts: the release snapshot parsesplan.plannedAt,pull.mergedAtandrelease.publishedAt; the Release & deployment card renders a compactplan → merge → publishtimeline.test/dailyRelease.test.ts: the structural test allows the one pinned auto-merge command and forbidsgh pr create/gh release/--admin; the auto-merge step must targetopened/reused.test/releaseStatus.test.ts: a snapshot with plan/merge/publish timestamps renders the timeline.docs/architecture.mdandchangelog.d/819-release-auto-merge.changed.md.Why
v0.3.6 had every check green at 19:26:43Z but waited for a manual merge at 20:17:17Z; the Release published at 20:19:38Z. The mechanical release PR is already T0, review-exempt and constrained to the mechanical diff, so it can opt into GitHub auto-merge and let the required checks decide. Auto-merge removes the human click; it does not fix GitHub's late
scheduledelivery, which remains #820.Safety
The repo already has
allow_auto_merge, squash-only merging, and requiredci-ok/review-gate/pr-lint. The mechanical identity (release/vX.Y.Z,release: vX.Y.Z, allowed diff shape) is enforced byrisk-gate,pr-lintandreview-gate. Auto-merge adds no admin bypass and no new required review.--match-head-commitpins the branch tip.Ran:
npm cinpx tsx --test test/dailyRelease.test.ts test/releaseStatus.test.ts test/admin.test.ts— 78/78 passnpm run checkat161a26f— lint 0, typecheck clean, 1989/1989 tests, build cleannode scripts/version.mjs check— 0.3.6 oknode scripts/changelog.mjs check— 42 fragments oknode scripts/risk-gate.mjs --base origin/main—risk-tier: T3; basis: .github/workflows/daily-release.ymlNot run:
Risk and rollback
Risk: if
RELEASE_OPEN_TOKENis compromised, an attacker could open a mechanical release PR and auto-merge it, but the allowed diff cannot change source code; the damage is release/version/changelog pollution. The token is scoped to this repository, andci-ok/review-gate/pr-lintstill run. Rollback: remove the auto-merge step; the PR returns to manual merge.Docs
docs/architecture.mdrecords the auto-merge opt-in and the plan → merge → publish timeline.Published tip (2026-11-15):
9a44b29426c7070ee1b416c3dbd10f5602de0a57, treec3bb5a2c88806db00249476fd144929e8ccc4d31, parents161a26f3+7d1e3ef1, 7 files+82/−9. Both conflicts are paragraphs added at the same anchor:docs/architecture.mdkeeps both sides,src/views/pages.tskeeps this branch's additions.public/app.css,test/sectionNav.test.tsandchangelog.d/808-admin-unify.changed.mdare no-ops after the merge because #808 already made those edits.