← notes

A required check is a name, not a job

Oct 11, 2026

Branch rules went on seven repositories with no bypass. Four days later a pull request with every check green could not merge.

Seven repositories had no branch protection at all. In one of them, none of the last 15 commits on main had come through a pull request. The rules that went on are plain: no deleting the branch, no force push, a pull request for every change with no approval needed, and no bypass, not even for the owner. The flight software also requires eight CI checks to pass.

The rules were meant to go on once, for the whole organization. That call returned a 404, because the token lacked the admin:org scope, so each repository got its own ruleset instead. The catch is that a new repository starts with nothing.

Four days later a pull request showed 24 passing checks and a merge state of BLOCKED. Asking the classic branch protection API why returned “Branch not protected”. That was true. The rules live in rulesets, and that API only knows the older kind.

The cause was a rename in the same pull request. Adding an x86 target to the static binary job had changed its name from “static ARM binary” to “static binary”, and a ruleset requires checks by exact name. The three ARM checks it was waiting for would never report, because no job had that name anymore. Every check that did run was green.

The job name is now an expression that keeps “static ARM binary” for the ARM targets. The ruleset did not change. The name came back.