Skip to content

The no-op merge guard only stops robots: make it block a human merge, via the aggregate required check - #219

Merged
ALLiDoizCode merged 1 commit into
mainfrom
ci/no-op-merge-required
Aug 16, 2026
Merged

The no-op merge guard only stops robots: make it block a human merge, via the aggregate required check#219
ALLiDoizCode merged 1 commit into
mainfrom
ci/no-op-merge-required

Conversation

@ALLiDoizCode

Copy link
Copy Markdown

The fleet no-op merge guard (toon-meta#405) catches a PR whose merge result is empty —
connector#1008 merged green, closed its ticket, and git show returned zero files. But as
shipped it only stopped robots: it ran in a workflow of its own, and a red non-required check
is a warning on the merge button, not a block. block#1008 was merged by a human.

This wires the guard into this repo's aggregate required check, so a red guard turns that
context red and branch protection refuses the merge. Ported from toon-meta#408 /
toon-meta#409.

What changed

  • ci.yml gains a no-op-merge job that calls
    toon-protocol/toon-meta/.github/workflows/empty-pr-guard.yml@main — the same reusable
    workflow the shim called, now inside the workflow that computes the aggregate.
  • The aggregate now asserts on needs.no-op-merge.result.
  • .github/workflows/empty-pr-guard-shim.yml is deleted. Running both would put two identical
    No-op merge guard check runs on every PR.

Net effect on branch protection: none. This repo still has exactly one required context,
unchanged in name. No protection or ruleset setting was modified through the API.

Why through the aggregate rather than a second required context

Mainly because it is the smaller change — the required-context set is untouched, so the guard
cannot introduce a new way for this repo to become unmergeable. That mattered acutely earlier
today: a changesets Version Packages PR could sit at action_required with zero check runs,
so its required context never reported and the PR was BLOCKED forever (swap#147). That cause is
now fixed (toon#208 / relay#135 / swap#149: actions/checkout was persisting GITHUB_TOKEN
into .git/config, so the changesets push triggered nothing; token: now falls back to the App
token, the org convention from toon-client#467) and swap#147 has recovered green — verified.
So this is no longer load-bearing, but it costs nothing and keeps the blast radius of a guard
change at one context per repo.

Why a bare needs: would not have been enough

When a needs: dependency fails, GitHub reports the dependent job with conclusion skipped, and
branch protection treats a skipped required check as a pass. So the aggregate keeps
if: always() and asserts on the result explicitly.

Why it is safe to require

The guard warns and passes wherever it cannot tell — a required check that fails on "I could not
tell" is how guards get disabled. Verified on a deliberately conflicted throwaway PR
(toon-meta#407): GitHub does not dispatch pull_request workflows at all for a conflicted
PR, so neither the guard nor CI even runs; the PR is blocked by its own conflict exactly as
before, and the guard cannot wedge it further. On push the guard passes with a plain "no merge
result to evaluate" — deliberately not a job-level if:, because a skipped gating job must never
read as a pass (toon-meta#279).

Part of toon-protocol/toon-meta#408

🤖 Generated with Claude Code

…-merge pass

The guard from toon-meta#405 catches a PR whose merge result is empty, but it
ran as a stand-alone shim - and a red NON-required check is a warning on the
merge button, not a block. connector#1008, the empty merge it exists for, was
merged by a human.

Move it inside the workflow that computes this repo's one aggregate required
check and make that aggregate assert on its result, so a red guard turns the
required context red. Delete the now-redundant shim; running both would put
two identical 'No-op merge guard' check runs on every PR.

Deliberately NOT a second required context: a required context that can never
appear wedges a repo permanently (swap#147 is in that state right now - a
changesets Release PR whose runs sit at action_required, so its rollup is
empty and the required context never reports). One required context per repo,
before and after; no protection or ruleset setting touched.

Part of toon-protocol/toon-meta#408

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@ALLiDoizCode
ALLiDoizCode enabled auto-merge (squash) August 16, 2026 22:57
@ALLiDoizCode
ALLiDoizCode merged commit 981d9e1 into main Aug 16, 2026
25 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant