Before this:Continuous integrationCode review
Required checks & branch protection
Key takeaways CI jobs only report; branch protection is what makes them gate: the platform refuses to merge until the required checks pass and a review approves. The catch every team learns the hard way: only checks explicitly marked required block anything — a PR can wear a green “mergeable” state while a non-required job is red, and that red ships. Audit the required set against what you actually build, and when reading a PR, read the checks, not the checkmark.
This unit built four guards — linting, formatting, review, CI. This closing lesson is about the bolt that fastens them to the door: the configuration that decides which guards can actually stop a merge, and the quiet failure mode when that configuration drifts out of sync with reality.
From reporting to gating
By default, CI results are informational: red jobs decorate the pull request,
and a human can merge anyway — deadline pressure guarantees someone will.
Branch protection (GitHub’s term; every platform has an equivalent — the
Git module covers the settings screen) flips
selected rules from advice to enforcement on a branch, typically main:
- Required status checks — named CI jobs that must pass before merging is possible.
- Required reviews — at least N approvals from reviewers.
- No direct pushes / no force pushes — all changes travel through a PR, and history can’t be rewritten out from under everyone.
With this in place, “keep main green” stops being etiquette and becomes physics: the merge button is disabled until the gates open. This is the enforcement layer the whole unit has been implying — an optional check protects nothing, because the day it’s inconvenient is exactly the day it matters.
The trap: green checkmark, red build
Now the sharp edge. Required checks are an explicit allowlist of job names. Jobs not on the list still run, still report — and block nothing. The platform’s summary optimizes for the merge question, so a PR whose required jobs pass shows mergeable-green even while a non-required job sits red below the fold.
This is not hypothetical; it’s a bug class with a known signature, and GopherTrunk hit it for real. The project’s web console is TypeScript, and its CI tests transpiled the code without typechecking it — so type errors sailed through the test jobs. The only job that ran a full production build (and thus the typechecker) was a packaging job nobody had marked required. A change landed with three type errors; every required job passed; the PR “passed CI” and merged — red job and all. The next person to run a real build found the project wouldn’t compile. Two lessons were extracted, and both generalize:
- The required set must cover what “working” means. If releases need
npm run buildto succeed, some required job must runnpm run build— not a proxy for it, the thing itself. - Read a PR’s checks, not its checkmark. The one-glance summary answers “may this merge?”; only the full list answers “is this healthy?” A red anything deserves an explanation before merge, required or not.
Rule of thumb: a check that can’t block a merge is documentation, not protection. Decide deliberately which is which — don’t let the default decide.
Auditing the gate
The required set drifts: jobs get renamed (silently detaching from the required list, which matches by name), new suites get added as non-required “for now,” and forever is made of for-nows. A periodic audit is cheap. Questions worth asking of any repo you work on:
| Question | Failure it prevents |
|---|---|
| Does some required job run the real production build for every artifact we ship? | The typecheck story above |
| Do required names still match the workflow’s actual job names? | A renamed job that gates nothing while everyone assumes it does |
| Is anything red-on-every-PR sitting in non-required limbo? | Normalized failure — the team has learned to un-see a red |
| Are quarantined flakes tracked, or just parked outside the gate? | Quarantine becoming silent deletion |
The deeper principle closing this unit: a safety system is only as strong as its enforcement path. Tests you don’t run, linters that only warn, reviews you can skip, checks that can’t block — each is a guard that works right up until the day it’s needed. The configuration is part of the system; audit it like code.
Quick check: a PR shows a green mergeable state, yet one CI job in its list is red. How is that possible?
Recap
- Branch protection turns checks and reviews from advice into a gate: no merge until required checks pass and approvals land.
- Only checks explicitly marked required block anything — non-required jobs report red and merge anyway.
- Hence the trap: green checkmark over a red build, exactly how a typecheck-shaped hole once let a broken build onto GopherTrunk’s main.
- Defenses: required set covers the real build, names stay synced, and reviewers read the checks, not the checkmark.
- The unit’s closing law: a safety system is only as strong as its enforcement path — audit the configuration like code.
Next up: Reproducing a bug