Skip to content

fix(fleet): the Friday merge needs --admin, or it can merge almost nothing - #645

Closed
rubenvdlinde wants to merge 1 commit into
mainfrom
fix/friday-merge-needs-admin
Closed

fix(fleet): the Friday merge needs --admin, or it can merge almost nothing#645
rubenvdlinde wants to merge 1 commit into
mainfrom
fix/friday-merge-needs-admin

Conversation

@rubenvdlinde

Copy link
Copy Markdown
Contributor

What was wrong

The org ruleset Development Branch Protection carries a pull_request rule with required_approving_review_count: 1, and its only bypass actor is OrganizationAdmin. gh pr merge --squash without --admin is refused:

Pull request #N is not mergeable: the base branch policy prohibits the merge.

Measured on run 33163749650 (schedule, 2026-08-28): of 49 candidates —

Outcome Count
skipped — checks pending / not green 24
merge refused by GitHub 20
merged 3
skipped — checks unreadable 2

18 of the 20 refusals were chore(release): *-unstable.* version bumps, which were then superseded and closed unmerged — so that work was not merely delayed, it was discarded and redone the next cycle.

The run reported success and summarised "3 merged/would-merge, 46 skipped". That reads as a fleet with little ready to merge, rather than a merge step that could not act at all. This is the failure mode the file's own header warns about: a routine that is documented, green, and doing nothing.

Reproduced directly on buildiq#553 — refused without --admin, merged with it.

Why this is not a weakening

That same ruleset requires zero status checks on development. GitHub would merge a red PR here without complaint. The rule this workflow enforces — every check reported, none failed, and at least one present — is strictly stronger than the policy being bypassed, and it is the only thing actually checking CI.

One thing I checked and did not change

DRY_RUN: ${{ inputs.dry-run == false && 'false' || 'true' }} looks like it would make every scheduled run a dry run, since inputs.dry-run is null on a schedule. It does not: GitHub casts both null and false to 0 when comparing across types, so the comparison is true and the scheduled run acts. The 08-28 log confirms it — real merges and real refusals, which the dry-run branch cannot produce. Left as-is, but it is subtle enough to be worth knowing.

Verification

  • YAML parses; bash -n on the run block extracted from the parsed YAML.
  • The refusal and the fix were both reproduced against a live PR rather than inferred from the ruleset alone.

…thing

The org ruleset "Development Branch Protection" carries a pull_request rule
with required_approving_review_count: 1, and its only bypass actor is
OrganizationAdmin. `gh pr merge --squash` without --admin is refused:

  Pull request #N is not mergeable: the base branch policy prohibits the
  merge.

Measured on run 33163749650 (schedule, 2026-08-28): of 49 candidates, 3
merged and 20 were refused by exactly this. Eighteen of the twenty were
`chore(release): *-unstable.*` version bumps, which were then superseded
and closed unmerged, so the work was not merely delayed - it was lost and
redone.

The run reported success and summarised "3 merged/would-merge, 46
skipped", which reads as a fleet with little ready to merge rather than a
merge step that could not act. Reproduced directly on buildiq#553: refused
without --admin, merged with it.

This does NOT weaken the gate. The same ruleset requires ZERO status
checks on development, so GitHub would merge a red pull request here. The
green rule this workflow enforces - every check reported, none failed,
and at least one present - is strictly stronger than the policy being
bypassed, and it is the only thing actually checking CI.

Verified: YAML parses, and bash -n on the run block extracted from the
parsed YAML.
@rubenvdlinde

Copy link
Copy Markdown
Contributor Author

Closing in favour of #643, which reached the same --admin diagnosis and goes further in two ways that matter.

It captures the refusal text. Mine kept 2>/dev/null, so a future refusal would again read as "refused by GitHub" with no reason — which is precisely why this took weeks to diagnose. #643 keeps the error and prints it.

It fixes a second defect that makes mine unsafe on its own. The header has always claimed this workflow refuses "PRs whose author is not trusted for unattended merge", and nothing enforced it — author was read and only ever printed. The sole reason no functional PR was ever merged unattended is that GitHub refused everything for the unrelated --admin reason. Landing my change alone would have removed that accidental protection and turned this into a workflow that merges human work without review.

Two bugs cancelling out is not a safety property. #643 fixes both; this adds nothing beyond it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant