Evaluate a merge queue for Forgejo (gitea-mq vs shunt); no native support in v16 #25
Labels
No labels
dependencies
major
security-pin
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
trails-cool/trails#25
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
ci.ymlcarries the note "nomerge_grouptrigger (Forgejo has no merge queue)", andCLAUDE.mdstill instructsgh pr merge --merge --autoagainst a GitHub merge queue that no longer exists. This is the gap.Forgejo has no native merge queue, and none is scheduled
Not in v16.0 — its Actions work went into artifact REST endpoints, log downloads, and prioritized workflow runs. There is an open upstream feature request, forgejo/forgejo#5102 "feat: Add a Merge Queue/Merge Train", but nothing landed. So this is third-party or nothing.
What Forgejo does have is auto-merge ("Merge when checks succeed"). Both candidates build on it rather than replacing it — they insert themselves as a required status check and let Forgejo perform the actual merge.
The two candidates
Recommendation: gitea-mq. "Stable" with real deployments beats a 2-star v0.8 for something that gates every merge to
main, and its serial default matches how this repo actually works. Its weaker Forgejo story is the one real concern — it advertises "Forgejo (based on Gitea 1.24+)" while we run v16.0.1, and Forgejo stopped tracking Gitea version numbers long ago, so that claim needs verifying against our instance rather than trusting it. shunt is the more interesting design (bisection is the right answer to batch failures) and explicitly validated on v16, so it is the fallback if gitea-mq's API assumptions break.The thing to check before either one: signed commits
We enabled
require_signed_commitsonmain. Both tools work by pushing temporary branches (gitea-mq/<pr>,mq/<base>/staging-*) and then letting Forgejo's auto-merge land the result. That should be fine, because:mainis created by Forgejo itself, signed with the instance key we configured.But gitea-mq's documented limitation — "batched PRs merge as commits regardless of repository merge style preferences" — means a batched merge may not take the same path. Any adoption needs one throwaway PR to prove a queued merge actually satisfies
require_signed_commitsbefore we route real work through it. Getting this wrong would wedge merges entirely.Both also need a bot account with repo admin rights (a Forgejo/Gitea API limitation, not a design choice). On a single-maintainer instance that is a real expansion of the trust surface for modest benefit — worth naming rather than glossing.
Do we actually need this?
Honestly, not urgently. A merge queue exists to stop PRs that pass individually from breaking
maintogether — semantic conflicts that no per-PR check can catch. With branch protection already requiringCI / *to pass and typically 1–3 concurrent PRs by one maintainer, that window is narrow.The argument for doing it anyway is that our checks are slow (~10 min) and PRs here are frequently stacked, which is exactly the shape where a stale-base merge slips through: PR B is tested against a
mainthat PR A has since moved. We have not been bitten by it yet.Suggested sequencing:
CLAUDE.mdfirst — it documents a workflow (gh pr merge --merge --auto, "merge queue") that cannot work. That is actively misleading today and costs nothing to correct. Covered by the broader GitHub-reference cleanup.Note also
ci.ymlgates the security scan ongithub.actor != 'dependabot[bot]'andcd-staging.ymlondependabot/github_actions/head refs — both dead conditions post-Renovate, unrelated to the queue but in the same neighbourhood.Sources
uses:no longer resolves to GitHub #27