Skip to content

main branch protection deadlocks workflow-only PRs (app-pinned build-and-test required by ruleset + classic protection, no bypass) #375

Description

@don-petry

Summary

Workflow-only PRs to main (e.g. #370, the dev-lead statuses:read shim fix) cannot be merged through the API — not even by an org admin with --admin. Surfaced while merging the dev-lead #402 series.

Root cause — a self-deadlocking required check, enforced twice

The required status check build-and-test is:

  1. Required by the code-quality ruleset (id 14872174) — which has an empty bypass_actors list, so nobody (not even admins) can bypass it; and
  2. also required by classic branch protection on main, with strict: true and enforce_admins: true (admins are explicitly subject to it).

build-and-test is pinned to a specific GitHub App, and its workflow doesn't run on workflow-file-only changes (path filters), so it never posts a status → the required check sits in expected forever → the PR is permanently unmergeable. A manually-posted commit status is rejected ("not set by the expected GitHub app"). --admin is rejected because enforce_admins: true + the ruleset has no bypass actor.

This is a redundant + over-strict protection config: the same check is required by both a ruleset and legacy classic protection, and neither path allows an override.

Workaround used to merge #370 (fully reverted)

Temporarily, in a guarded sequence with a trap ensuring restoration:

  1. set code-quality ruleset enforcement → disabled
  2. disabled classic enforce_admins
  3. gh pr merge --admin --squash
  4. restored both (verified: enforcement=active, enforce_admins=true, bypass_actors=[])

Recommended fixes (for investigation)

  • Remove the redundant classic branch protection on main — rulesets supersede it; maintaining both is the core trap.
  • Make build-and-test not required for workflow-only PRs (path-aware), or post a neutral/success status for paths it skips, so it can't deadlock.
  • Add an admin bypass actor to the code-quality ruleset (mirroring protect-branches, which already has one), so future emergencies don't need protection to be toggled.
  • Audit the other org repos for the same classic-protection + ruleset redundancy and app-pinned-check deadlock (bmad-bgreat-suite#273 hit a similar CodeQL stall, resolvable via a posted status — gas was stricter).

Filed unlabeled deliberately (no dev-lead label) so the agent doesn't try to auto-implement it.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions