Skip to content

[Bug] Promoting integration to main deletes the integration branch #67

Closed

Description

@rocklambros

Observed live on 2026-09-10 while promoting the first change through the three-tier branch model.

What happened

PR #66 promoted integration into main. Merging it deleted the integration branch, and GitHub then fired automatic_base_change_succeeded on PR #64, silently retargeting it from integration to main. A pull request that touches .github/, tools/, and tests/ was moved onto the branch the base-branch guard forbids those paths from targeting.

Causal chain

  1. delete_branch_on_merge was true at the repository level.
  2. A promotion pull request uses integration as its head, so merging it triggers head-branch deletion. Every other pull request in this repository uses a disposable feature branch as head, which is the case that setting was designed for.
  3. protect-integration carries a deletion rule that should have blocked it. The merge used --admin, and the ruleset grants RepositoryRole 5 an always-bypass, so the deletion went through.
  4. With the base branch gone, GitHub retargeted the open pull request built on it.

The admin bypass exists so a single maintainer can merge without a second reviewer. That same bypass defeated the deletion protection it sits beside.

Fixed already

  • delete_branch_on_merge set to false. A permanent branch used as a pull request head is incompatible with auto-delete, and promotion is routine under this model rather than exceptional.
  • integration recreated from main, which already contained everything it held.
  • PR Install the contribution governance for the OWASP re-launch #64 retargeted back to integration.

Still open

Nothing enforces this. If someone re-enables auto-delete, the next promotion deletes integration again and the failure is silent until a contributor is confused by a retargeted pull request. Options worth weighing: a scheduled check asserting integration exists and that delete_branch_on_merge is false, or promoting by fast-forwarding main rather than by pull request so no head branch is consumed.

Blocked on the branch model landing in #64.

Activity

  1. added
    type:bugSomething isn't working
    scope:in-focusFeeds the ninety-day committed outcome. Maintainers only
    status:blockedWaiting on another decision or PR
    on Sep 10, 2026
  2. rocklambros commented on Sep 10, 2026

    @rocklambros
    CollaboratorAuthor

    Closed structurally rather than by a setting.

    A new ruleset, protect-branch-existence, now covers refs/heads/main and refs/heads/integration with deletion and non_fast_forward rules and zero bypass actors. GitHub evaluates every matching ruleset and the most restrictive wins, so the existing protect-main and protect-integration keep their admin always-bypass for pull request review and status checks, while deletion and force-push are refused for everyone including administrators.

    Verified live rather than assumed. git push --dry-run does not evaluate server-side rulesets, so it reported a successful delete and proved nothing. The real test used a throwaway protection-probe branch temporarily added to the same ruleset:

    remote: - Cannot delete this branch
     ! [remote rejected] protection-probe (push declined due to repository rule violations)
    

    The probe survived the delete attempt, then was removed from the ruleset and cleaned up.

    Also corrected while investigating: aibom-generator was suggested as the reference implementation of this pattern. Its integ branch has no branch protection at all, only the org-level repository_delete and repository_transfer rules that apply everywhere, and all eight of its recent pull requests target main rather than integ. The two settings worth copying from it, delete_branch_on_merge: false and allow_merge_commit: true, now match here.

    Remaining exposure is narrow: an administrator can still delete the ruleset itself. That is a deliberate act rather than a side effect of merging, which was the actual failure mode.

  3. moved this to Needs triage in ACS Project Trackeron Sep 10, 2026
  4. rocklambros commented on Oct 5, 2026

    @rocklambros
    CollaboratorAuthor

    The protect-branch-existence ruleset (id 22712052), which has no bypass actors, blocks deleting integration.

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:P1Maintainers onlyscope:in-focusFeeds the ninety-day committed outcome. Maintainers onlytype:bugSomething isn't working

    Type

    No type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions