diff options
| author | Yuriy Andamasov <yuriy@vyos.io> | 2026-05-15 00:25:44 +0300 |
|---|---|---|
| committer | Yuriy Andamasov <yuriy@vyos.io> | 2026-05-15 00:25:44 +0300 |
| commit | 9b6a166382bdce525c1dcfb077c7a152267ee69e (patch) | |
| tree | e1512c4c3b41dbf64c178b74347a79ff6bb1833d | |
| parent | ab25a1a9412c3e0199f5d62f72badceb40ce70fc (diff) | |
| download | mergify-9b6a166382bdce525c1dcfb077c7a152267ee69e.tar.gz mergify-9b6a166382bdce525c1dcfb077c7a152267ee69e.zip | |
T8782: Block merge while backport-conflict label is present via merge_protections
Add a merge_protections rule requiring `label != backport-conflict` for
merge. The backport action above auto-applies the label on cherry-pick
conflicts, so this closes the loop: the conflicted PR exists (workspace
preserved), is labeled and assigned, AND cannot be merged until the
operator pushes a resolution and removes the label manually.
Per Mergify docs, merge_protections from `extends:` merges across parent
and child with same-name override semantics; consumer repos can opt out
by defining a same-named rule locally with weaker conditions.
`dequeue` is not exposed as a YAML action under pull_request_rules — only
as a user-facing slash command and a key under commands_restrictions.
merge_protections is the declarative equivalent. Manual `@Mergifyio
dequeue` remains available to Maintainers via commands_restrictions.
Active ejection of an already-queued PR when the label arrives vs.
holding the PR indefinitely in queue is not explicitly documented by
Mergify; the comment marks this as TBD on first real backport conflict.
| -rw-r--r-- | .mergify.yml | 57 |
1 files changed, 49 insertions, 8 deletions
diff --git a/.mergify.yml b/.mergify.yml index 01b818e..74e9439 100644 --- a/.mergify.yml +++ b/.mergify.yml @@ -39,14 +39,22 @@ defaults: # accountability loop — they wrote the change, they know what the # backport should look like. # - # Operational caveat — the label DOES NOT block merge by itself. The - # 2026-05-12 incident below shipped because branch protection did not - # require a check that catches conflict markers. Repos consuming - # `extends: mergify` need either (a) a required CI status that fails - # on `<<<<<<<` in tracked files, or (b) a branch-protection ruleset - # that forbids merging while `backport-conflict` is present. Both - # belong to fleet-wide governance, tracked under T8850 (Cat 1 branch - # governance rulesets) rather than this central-config repo. + # Merge is blocked while the label is present — see the + # `merge_protections` block at the bottom of this file. Mergify + # documents that merge_protections are "safe to edit live; + # re-evaluations happen automatically", so a PR that gains the + # label after queueing will fail the merge check at the next + # evaluation. Active ejection of a queued PR vs. holding it + # indefinitely is not explicitly documented; manual fallback is + # `@Mergifyio dequeue` (allowed to Maintainers per + # commands_restrictions below). + # + # This does NOT replace branch protection. A determined operator can + # still bypass via the GitHub "Merge" button if branch protection + # doesn't require Mergify checks. The defense-in-depth piece (required + # CI status that fails on `<<<<<<<` in tracked files, or branch- + # protection ruleset on the label) is tracked under T8850 (Cat 1 + # branch governance rulesets). # # Incident history (2026-05-12): # vyos/vyos-documentation#1994 was backported via `@Mergifyio backport @@ -158,3 +166,36 @@ commands_restrictions: requeue: *allowed squash: *allowed update: *allowed + +merge_protections: + # Block merge while the backport-conflict label is set on a PR. The + # `backport` action above adds this label whenever a backport cherry-pick + # produces conflict markers; this rule ensures the conflicted PR cannot + # proceed to merge until a human removes the label (which they should + # only do after pushing a resolution commit that overwrites the markers). + # + # Why merge_protections and not a pull_request_rules `dequeue` action: + # Mergify exposes `dequeue` as a user-facing slash command and as a key + # under `commands_restrictions`, but NOT as a YAML action in + # pull_request_rules. `merge_protections` is the declarative equivalent — + # a PR with the label fails the success_conditions and is held back from + # merge; manual `@Mergifyio dequeue` remains available as the escape + # hatch (allowed to Maintainers per commands_restrictions above). + # + # Inheritance: per Mergify docs, merge_protections from `extends:` + # merges across parent and child, with same-named rules in the child + # overriding the parent. Consumer repos can disable this rule by + # defining a same-named rule locally with weaker conditions. + # + # Caveat: merge_protections only governs Mergify-driven merges. A + # determined operator can still click GitHub's merge button if branch + # protection doesn't require Mergify checks. Defense-in-depth (required + # CI status, branch-protection ruleset on the label) is tracked under + # T8850 Cat 1 branch governance. + - name: backport-conflict label must be absent to merge + description: > + Block merge while the backport-conflict label is present. The label + is auto-applied by the backport action on cherry-pick conflicts and + must be manually removed after the conflict is resolved in the PR. + success_conditions: + - label != backport-conflict |
