Skip to content

fix(pr-merge): do not queue a head a pr-unblock lane stopped #10777

Closed

Description

@kyle-sexton

Problem

About 20-26 merge-group runs a day fail on a designed hold, and ci-status checks that hold only after every lane leg has run, about 32 job-minutes each. pr-merge's enable-auto-merge already refuses labels, body and member holds, hold and cost paths, the verifier verdict and the kill switch before it arms. The one ci-status hold it does not check is a failing pr-unblock/* status on the head, so it queues a head a pr-unblock lane stopped, and the merge queue then ejects it.

Acceptance criteria

  • merge-holds.mjs exports the pr-unblock rule as ci-status states it (unblockStops, readStatuses).
  • enable-auto-merge reads the head's commit statuses and does not queue a head a pr-unblock lane stopped. It disarms one already armed and adds a run-summary line for each.
  • A head whose statuses do not read is not queued, and an armed one is disarmed (fails closed).
  • A later success status for the same context clears the stop, and a head with no stop still arms.
  • No hold loosens: ci-status's own steps are unchanged.

Not in scope

#10747 stays the follow-up: switching ci-status to the shared rule, and early merge_group hold checks in select-tests.

Activity

  1. added
    needs-triageNot yet classified. Floor until a type and one priority tier are set.
    on Oct 28, 2026
  2. github-actions commented on Oct 28, 2026

    @github-actions
    Contributor

    Proposed work class: work-class: scoped
    Basis: automated intake triage; the lanes App applied this class.

    Size: Small
    Complexity: Low
    Uncertainty: Known
    Flags: none
    Blocked by: none

    Understood: pr-merge's enable-auto-merge should read a head's commit statuses via a shared rule in merge-holds.mjs. It should not queue, and should disarm, a head whose pr-unblock/* lane status is failing. It should fail closed when the statuses can't be read. The acceptance criteria are exact and the follow-up (#10747) is out of scope. No duplicates found; #10747 and #10434 are related but not the same work.

    Automated triage, applied by the lanes App.

  3. added
    priority: mediumReal value, no hard deadline; normal backlog flow.
    and removed
    needs-triageNot yet classified. Floor until a type and one priority tier are set.
    on Oct 28, 2026
  4. added
    status: readyTriaged, unblocked, and fully specified; eligible to pick up.
    work-class: scopedA briefed fix or small feature; blast radius bounded by the brief, tests exist.
    status: confirmedA maintainer confirmed the item is real and in scope; ready to be worked.
    and removed
    status: readyTriaged, unblocked, and fully specified; eligible to pick up.
    on Oct 28, 2026
  5. melodic-automation-lanes commented on Oct 28, 2026

    @melodic-automation-lanes
    Contributor

    Not admitted to the issue lane: a criterion names .github/workflows/pr-require-checks.yml, which the issue lane cannot push (patch-protected-path); a builder session takes it. Admission takes the issue once each of those is met, when intake triages it again (.github/actions/resolve-config/admission-rules.json).

  6. melodic-automation-lanes commented on Oct 28, 2026

    @melodic-automation-lanes
    Contributor

    The latest triage verdict holds nothing: admission moved the issue to status: confirmed; its comment says why.

  7. melodic-automation-lanes commented on Oct 28, 2026

    @melodic-automation-lanes
    Contributor

    Refinement. A read-only run explored this repository, searched its issues and pull requests, and read the allowed docs to draft what follows. On an issue a listed human filed, it counts as the issue's spec once posted, while unedited; it is still model text, so check it.

    Intended outcome: pr-merge's enable-auto-merge reads a head's commit statuses through a shared rule exported from merge-holds.mjs, refuses to queue and disarms a head a pr-unblock lane stopped, and fails closed on unreadable statuses.

    Acceptance criteria

    • .github/scripts/pr-merge/merge-holds.mjs exports unblockStops and readStatuses, and neither exists there today.
    • unblockStops applies ci-status's rule: for each pr-unblock/* context, only the newest status from github-actions\[bot\] counts, and the context stops the head when that state is failure or error.
    • unblockStops ignores statuses from other creators and ignores contexts that do not start with pr-unblock/.
    • A later success status on the same context clears the stop, and a head with no stop still arms; a unit test covers each.
    • enable-auto-merge reads the head's commit statuses via readStatuses and does not arm auto-merge for a head with a stop; a test in enable-auto-merge.test.mjs asserts no arm call.
    • enable-auto-merge disarms a head that is already armed and has a stop; a test asserts the disarm call.
    • Each refusal or disarm adds one run-summary line that names the stopping context(s).
    • When the statuses cannot be read (API error after retries, or a head that is not a 40-hex SHA), the head is not queued and an armed one is disarmed; a test covers each.
    • ci-status's own step Fail a head a pr-unblock lane stopped in .github/workflows/pr-require-checks.yml is unchanged, and scripts/ci-hold-pr-unblock-status.test.sh still passes.
    • No existing hold in enable-auto-merge (labels, body, member, hold and cost paths, verifier verdict, kill switch) is loosened, and the existing pr-merge tests pass.

    Dependencies

    • #​10747 is the follow-up and does not block this: it switches ci-status to the shared rule and adds early merge_group hold checks in select-tests.

    Related work

    Sources read

    • .github/workflows/pr-require-checks.yml:5015-5073: ci-status step fails a head whose newest github-actions[bot] pr-unblock/* status is failure or error, takes the head live in merge_group, and fails closed on unparsable refs, non-SHA heads or unreadable statuses.
    • .github/scripts/pr-merge/merge-holds.mjs:87-96: existing shared hold rules (bodyHolds, LANE_HOLD) live here; a grep found no unblockStops or readStatuses anywhere in the checkout.
    • .github/scripts/pr-merge/enable-auto-merge.test.mjs: existing test file where the new cases belong.

    Automated refinement by the lanes App. Intake triages the issue again with it.

  8. removed
    needs-triageNot yet classified. Floor until a type and one priority tier are set.
    on Oct 28, 2026
  9. added
    status: readyTriaged, unblocked, and fully specified; eligible to pick up.
    status: confirmedA maintainer confirmed the item is real and in scope; ready to be worked.
    and removed
    status: readyTriaged, unblocked, and fully specified; eligible to pick up.
    on Oct 28, 2026
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

    priority: mediumReal value, no hard deadline; normal backlog flow.status: confirmedA maintainer confirmed the item is real and in scope; ready to be worked.work-class: scopedA briefed fix or small feature; blast radius bounded by the brief, tests exist.

    Type

    Fields

    No fields configured for Bug.

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions