Skip to content

Merge gate reports green while checks are still runningΒ #943

Closed

Description

@thekevinbot

What

Mergify Merge Protections reports 🟒 "ready to merge" about 25 seconds after a PR opens, while most of the suite is still running. Measured on two independent commits of #942:

8f8ac63 4898724
Mergify β†’ success 16:07:22 16:20:25
last check finished 16:09:43 16:22:46
gap 2m21s 2m21s

Both runs ended green (91/91), so nothing broke β€” but the badge said "ready to merge" long before that was known, and that badge is the signal a human reads immediately before clicking merge.

The repo currently has no working merge gate. That is the framing that matters: this is not a nice-to-have hardening, it is a gate that does not gate.

Requirement

  1. Checks run dynamically depending on path filters.
  2. All checks green β†’ mergeable.
  3. Not green β†’ not mergeable, but auto-merge can be set and fires when everything goes green.

Nothing beyond that.

Cause

The whole gate is one condition:

success_conditions:
  - "#check-failure = 0"

"No check has failed" is not "all checks passed." The two differ exactly in the pending window. #check-pending = 0 was deliberately omitted, on the belief β€” recorded in .mergify.yml's comment and in AGENTS.md β€” that Mergify counts its own in-progress check, so the count could never reach zero and the gate would deadlock (#832).

Option A (try first): add the missing condition

success_conditions:
  - "#check-failure = 0"
  - "#check-pending = 0"

Yields yellow while any check runs, green once everything finishes with none failed, red on any failure β€” and names no checks, so path-filtered workflows stay maintenance-free. pull_request_rules already carries both conditions, so auto-merge already behaves correctly.

Why the deadlock belief is probably wrong: Mergify's own guidance is to combine #check-success >= N with #check-pending = 0 and #check-failure = 0 (discussion #2184). If merge protections self-counted, that advice would be broken for every user. There is also a first-class feature for exactly this β€” Merge Protections reports pending events (2024-11-07): protections containing pending conditions report as pending rather than resolving. Meanwhile #832 had a second documented way to deadlock that fits the symptom equally well β€” named anchors on path-filtered workflows that never run, which #828 predicted exactly. Likely the anchors deadlocked and #check-pending was blamed.

Not conclusive. The community guidance may predate merge_protections and describe pull_request_rules, where Mergify produces no check of its own. Mergify reads config from the default branch, so this can only be tested by landing it on main.

Try it first because the failure mode is loud. If it deadlocks, the next PR hangs visibly and one line reverts it. The current bug, by contrast, was silent until two timestamps were compared by accident.

Option B (fallback, known-good): restore pr-monitor

If Option A deadlocks, restore .github/workflows/pr-monitor.yml β€” deleted in #830, recoverable via git show f714f37^:.github/workflows/pr-monitor.yml β€” and anchor on it:

success_conditions:
  - "check-success = CI Gate"

This is a working gate and it satisfies the requirement; it ran this repo before #830. Its properties: no paths: filter so it always runs (an anchor on it can never orphan), job-name: 'CI Gate' excludes itself, and it polls workflow runs so path-filtered workflows need no enumeration.

Known costs, all of which Option A avoids: it occupies a runner for the CI duration, its fixed 20-minute timeout fires regularly, timeouts are ambiguous between flake and hang, and it has a start-race β€” a workflow that has not started when it polls is not counted, which is itself a narrow false-green window.

Option B does not require dropping Mergify. pull_request_rules (auto-merge) and CI Insights are independent of which check the gate anchors on.

Scope: deliberately excluded

A check that should have existed but doesn't is not this gate's problem. If a workflow mis-specifies its trigger or its YAML startup-fails, that is a defect in the workflow, not the gate. Consequences:

  • No #check-success >= 1 floor. A PR that legitimately matches no path filter (a CI-config-only change) has zero checks and is correctly mergeable; a floor would block it.
  • startup_failure detection is out of scope. It is the one thing pr-monitor's workflow-run polling sees and Mergify's check-run vocabulary cannot β€” and it is not wanted.
  • Whether the right checks exist for a diff belongs to CI paths: dirsql-checks ci-paths β€” assert workflow filters and Mergify anchors agreeΒ #862 (ci-paths), which validates workflow configuration.

Also rejected: building a gate that predicts the expected check set by parsing the repo's own paths: filters. Far more machinery, and fragile β€” reusable-workflow check names carry matrix expansion and drift with upstream @v0.

Acceptance

  • Gate is pending, not green, while any check is running
  • Gate goes green once all checks complete with none failed
  • Gate goes red if any check fails
  • A PR matching no path filter still merges (zero checks is a pass)
  • No deadlock: the gate resolves on a normal PR
  • AGENTS.md's "PR Monitoring" section updated β€” it still describes the anchors removed in ci: reduce the Mergify gate to a single failure countΒ #881 (tracked in Docs: post-#834 passΒ #932)

Activity

  1. changed the title [-]Mergify merge protection reports green before CI finishes[/-] [+]Restore pr-monitor: the merge gate reports green before CI finishes[/+] on Aug 14, 2026
  2. changed the title [-]Restore pr-monitor: the merge gate reports green before CI finishes[/-] [+]Merge gate reports green while checks are still running[/+] on Aug 14, 2026
  3. added a commit that references this issue on Aug 14, 2026
    f9ab355
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions