ci(actions): make mergeraptor auto-merge actually fire on main - #400
Merged
Conversation
The mergeraptor review-bypass allowance was already live on main's branch protection, but nothing could use it: this repo had no workflow_run caller for reusable-renovate-automerge.yml, so qualifying Renovate PRs sat green and unmerged waiting on a human approval. Add the caller and harden the reusable workflow: - Add .github/workflows/renovate-automerge.yml, triggered by every CI workflow in the repo, passing base_branch: main, require_auto_merge: true and the MergeRaptor app credentials. - Mint a MergeRaptor installation token via app_id/private_key secrets. The bypass allowance only applies to that app identity, so github-actions[bot] could never have merged. Credential presence is mirrored into job-level env because the secrets context is unavailable in step-level if:. - Fix the author matcher. GraphQL reports an app author as the bare slug "mergeraptor" while REST reports "app/mergeraptor"; the previous gh pr list filter matched neither reliably. Normalise all spellings. - Gate merges on a complete check rollup. SKIPPED/NEUTRAL are non-blocking per GitHub's own merge semantics; PENDING is waited out (bounded by the new check_timeout_seconds input) rather than skipped, so a consumer that triggers from a single CI workflow cannot stall; anything else blocks. - Skip drafts and conflicting PRs, and let a failed merge surface as a job failure instead of a swallowed warning. Existing consumers (bluefin, bluefin-lts, dakota) pass only head_sha; both new inputs default to the previous behaviour, so this is additive for them. Assisted-by: Claude Opus 5 via GitHub Copilot Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Dependency Review✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.Scanned FilesNone |
The consumer validation protocol says to open a *draft* PR in projectbluefin/bluefin, but its PR Validation workflow never starts while the PR is a draft, so there is no run ID to cite as evidence. Pushing more commits does not help. Record the `gh pr ready` workaround. Assisted-by: Claude Opus 5 via GitHub Copilot Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
`gh pr merge --squash` fails with "merge strategy for main is set by the merge queue" on a queued base branch — the queue owns the strategy. The hardcoded --squash would therefore have failed every merge on main. Add a merge_method input (squash by default, or "queue" to always omit the flag) and retry without the strategy flag automatically when that error is detected, so the workflow works on queued and unqueued branches alike. A genuine merge failure still fails the job. Assisted-by: Claude Opus 5 via GitHub Copilot Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
`gh pr merge --squash` on a merge-queue branch prints "! The merge strategy for main is set by the merge queue" and still enqueues the PR — with exit code 0. Exit status therefore says nothing about what happened; only the stderr text does. A retry can also hit "! Pull request <repo>#<n> is already queued to merge", which shares no substring with the first message and must be treated as success rather than a failed merge. Capture and echo stderr on every path, report enqueued vs merged accurately, and keep the no-flag retry for gh versions that hard-fail instead of warning. A genuinely unmergeable PR still fails the job. Verified against all eight real-world outcomes, using the verbatim strings observed while merging PRs #393, #396, #397 and #383. Assisted-by: Claude Opus 5 via GitHub Copilot Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Three defects found by auditing the gate against real merge behaviour observed on PRs #393, #394, #396, #397 and #383. 1. An absent check is not a passing check. `gh pr checks` reports only check-runs that already exist, so a queued workflow is missing from the rollup rather than PENDING — and a re-run removes its check-runs while they re-queue. Observed live on #394: three of seven checks were absent and the gate would have merged with them never having run. Because this workflow is triggered by one CI workflow completing while siblings may still be queued, that race is the normal case. Cross-check in-flight runs for the same commit via `gh run list --commit`. 2. An empty rollup or an unreadable run list now keeps waiting until the timeout instead of breaking immediately, so a transient API error is no longer terminal for a PR nothing else will re-evaluate. 3. Never infer the merge outcome from stderr or exit code. A plain `gh pr merge` enqueues while printing nothing and exiting 0, so the merge_method: queue path — the one used on a queued branch — reported every enqueue as "Merged". gh also writes its success line, including the PR title, to stderr, so a PR titled "...merge queue..." could be misread. Query the real PR state instead. All six gate scenarios re-verified, including the observed #394 and #397 cases; every ambiguous state now fails closed. Assisted-by: Claude Opus 5 via GitHub Copilot Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This was referenced Aug 7, 2026
castrojo
added a commit
that referenced
this pull request
Aug 7, 2026
renovate-automerge.yml was added in #400 with a workspace-relative `uses: ./.github/workflows/reusable-renovate-automerge.yml`, which the repository's own scripts/check-self-repository-references.py rejects. That left both the `Lint GitHub Actions` and `pytest` required checks red on `main`, blocking every subsequent PR. Switch to the documented `$/` self-repository prefix used by the five other in-repo reusable workflow calls. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.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 free
to 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.
What does this change?
The mergeraptor review-bypass allowance is already live on
main's branch protection, but nothing could ever use it. This repo had noworkflow_runcaller forreusable-renovate-automerge.yml, so qualifying Renovate/MergeRaptor PRs sat green and unmerged, waiting for a human approval. Tasks 2–4 ofdocs/superpowers/plans/2026-08-04-renovate-automerge-review-exception.mdwere never implemented.Add the caller (
.github/workflows/renovate-automerge.yml), triggered by every CI workflow in this repo, passingbase_branch: main,require_auto_merge: true, and the MergeRaptor app credentials.Harden the reusable workflow:
github-actions[bot]could never have merged. Credential presence is mirrored into job-levelenvbecause thesecretscontext is unavailable in step-levelif:.mergeraptor; REST/gh pr listreportsapp/mergeraptor; a legacy bot user reportsrenovate[bot]. The previous filter matched none of these reliably. Now normalised.gh pr checksreports only check-runs that already exist, so a queued workflow is missing from the rollup rather thanPENDING, and a re-run removes its check-runs while they re-queue. Observed live on chore(deps): update taiki-e/install-action digest to 05a4690 #394, where 3 of 7 checks were absent and a naive gate would have merged with them never having run. Since this workflow is triggered by one CI workflow completing while siblings may still be queued, that race is the normal case. Now cross-checks in-flight runs viagh run list --commit. An empty rollup or unreadable run list also keeps waiting rather than failing terminally.SKIPPED/NEUTRALare non-blocking per GitHub's own merge semantics.PENDINGis waited out (bounded by the newcheck_timeout_secondsinput) rather than skipped — a consumer triggering from a single CI workflow would otherwise stall permanently when sibling checks finish later. Anything else blocks.mainis governed by a merge queue, which rejects any explicit strategy flag (gh pr merge --squash→ "merge strategy for main is set by the merge queue"). The original hardcoded--squashwould therefore have failed every merge onmain. Added amerge_methodinput (defaultsquash, orqueue) plus automatic retry without the flag when that error is detected. Found while a review subagent was merging the open dependency PRs.gh pr mergeenqueues while printing nothing and exiting 0 — so themerge_method: queuepath, the one actually used on a queued branch, reported every enqueue as "Merged". gh also writes its success line (including the PR title) to stderr, so a PR titled "…merge queue…" could be misread. Now queries the real PR state.gh pr mergesurface as a job failure instead of a swallowed warning.renovate.jsonstays the single source of truth for what may merge unattended:require_auto_merge: truemeans only PRs Renovate marked auto-mergeable qualify. Major bumps still need a human.Consumer validation
Consumer PR: projectbluefin/bluefin#976
Consumer CI run: https://github.com/projectbluefin/bluefin/actions/runs/31131080663
Out-of-org consumer impact: N/A —
ublue-os/auroraandublue-os/bazzitedo not callreusable-renovate-automerge.yml. In-org consumers (bluefin, bluefin-lts, dakota) all pass onlyhead_sha; both new inputs (require_auto_merge,check_timeout_seconds) default to the previous behaviour, so the change is additive. No input was removed or renamed.ublue-os/aurora,ublue-os/bazzite) and documented the impact aboveVerification
actionlintclean on both workflows (exit 0).main— correctly selects only the MergeRaptor PRs withautoMergeRequestset.merge_method: queue, genuine merge failure, invalid input) — only the genuine failure exits non-zero.gh pr checksoutput for real PRs on this repo.Skill update
docs/skills/factory-operations.md§4 rewritten: it documented apackageRulesblock that does not exist inrenovate.json. Now describes the actual policy, the three merge gates, the bypass verification command, a troubleshooting table, and the three gotchas found here (REST-vs-GraphQL bot login,--autonot honouringbypass_pull_request_allowances,secretsunavailable in step-levelif:).Checklist
feat:,fix:,chore:, etc.)