15.8 Checks that block
- Approved by
- Panaversity ·
In everyday life. A smoke detector beeps. A circuit breaker cuts the power. Both notice a problem, but only one stops anything. Each is right for its job. The mistake is to believe the beeper is a breaker.
What you will learn. The difference between a check that stops a merge and one that only reports, and how to make the right ones stop it.
Why it matters. A gate is a check that can really stop a merge. A team that mistakes a report for a gate has no gate.
Which checks stop a merge?
Only the ones the repository requires. Every check on a pull request is one of two kinds.
- An advisory check is one that only reports. It may post findings, but the merge button still works.
- A blocking check is one that stops the merge. The pull request cannot join
mainuntil it passes.
A check blocks only when the repository says so. Branch protection, or a ruleset, its newer and more flexible form, is a set of rules on a branch such as main. The rules that matter here:1
| Rule | What it stops |
|---|---|
| Require a pull request before merging | Anyone pushing straight to main, including an agent |
| Require status checks to pass before merging | A merge while a required check has failed or not finished |
| Require conversation resolution | A merge while a review thread is still open |
| Require approvals, and review from code owners2 | A merge without the people 15.9 names |
| Dismiss stale approvals when new commits are pushed | A merge of code nobody approved |
What does a workflow do?
It runs the checks.
| Word | What it is |
|---|---|
| Workflow | A file in .github/workflows/ that tells the host which checks to run, and when |
| Event | What starts a workflow, such as a new pull request |
| Job | A list of steps that run in order. Each job shows on the pull request as one check |
| Step | One command in a job. A job stops at its first failing step, so later steps in that job never run |
A check on its own is the smoke detector. Marking it required in branch protection wires it to the breaker: the same check now stops the merge instead of only reporting. Running checks like this on every change is called continuous integration, or CI.
What are Brightline's required checks?
One workflow runs everything a machine can check every time, in three jobs, so a failing test cannot hide a weakened test or a printed key:
| Job | What it runs |
|---|---|
checks | Both type checks, the tests in both languages, the linter |
tests-unchanged | A script that fails if a change removes or edits a line in an existing test, or adds a line that switches a test off, such as .skip(, .only( or a bare return. The label tests-changed, a tag someone adds to the pull request, lets a removed or edited line through, and the team's rules pair that label with a written reason and approval from a named owner |
no-secrets | A script that fails if a logging or print call names a key, token, secret or password on the same line |
Each script fails closed: if it cannot do its job, because it cannot find the base branch, the one the pull request merges into, or a folder it should search, it fails instead of passing. A check that passes when it cannot see is worse than none, because it looks like protection.
What do these checks miss?
A lot, on purpose. Each script catches one common mistake, cheaply, on every change. Neither proves more than that. The test check cannot tell whether a new test checks anything useful, or whether the settings that run the tests were changed to skip some. The secret check misses a logging call split over two lines, or a key in a variable whose name looks harmless. Review covers what they miss. A check is only as strong as the files that run it. So the check scripts, the workflow, package.json and the type checkers' settings all have a named owner (15.9). Here is part of the workflow:
permissions:
contents: read # the workflow can read the code, nothing else
jobs:
checks: # the type checks and tests
steps:
- run: npm run typecheck
- run: npm test
tests-unchanged: # a separate job, so a failing test cannot hide it
steps:
- run: bash scripts/check-tests-unchanged.sh "origin/${{ github.base_ref }}"The host fills in ${{ github.base_ref }} with the branch the pull request merges into.

Figure 15.13. One job stops at the first failure. One job per check lets every problem report.
Can an AI review block a merge?
Only through the repository. An AI review is advisory by default. It never approves or blocks on its own (15.7). If you want open findings to stop a merge, choose one way to make the repository enforce it. Require conversation resolution, so an unresolved finding's thread blocks the merge. Or add a required job that reads the review's result and fails on an Important finding. Or run a security review inside your own workflow, with your own step that fails when it reports findings. A review in a workflow is the same agent outside the app that you met in 12.7: one task, run headless, with read-only access and nobody watching. The rule is the same in every case: the repository's settings do the blocking, not the reviewer.
What does the pull request template do?
A file, .github/pull_request_template.md, fills every new description with the questions a reviewer needs answered. They ask what and why, how it was tested, with the commands and their output, the level of risk, and how to undo it. It costs the author a minute and saves the reviewer from guessing.
How do I keep a workflow safe?
A workflow runs code from the pull request, so treat that code as untrusted. Three rules:
- Give the workflow's token, the key it uses to act on the repository, read-only permissions.
- Keep keys in repository secrets, which the host stores and gives to workflows.3 Never commit them to a file. The host gives no secrets to workflows started from a fork, an outside copy of the repository.
- Never run a pull request's code with your secrets.
pull_request_targetis a way of starting a workflow that gives it those secrets, so never use it to build or run that code.4
In the case study. No pull request merges while a finding from the bug review or the security review is open. Lint, type checks, tests and builds are required. The template asks how a change was tested and how to undo it.5
At work. Ana makes all three jobs required on main, with conversation resolution on. The agent-speedup pull request shows three red marks, one per job. The tests fail on the cutoff case. The test comparison fails on the edited expected value. The secret check fails on the debug line that prints the key. The merge button is gray. Nobody had to read the diff to stop it, though someone still will, to learn why an agent did this.
The operating rule: make every check a machine can run a required check, and never mistake an advisory report for a gate.

Figure 15.14. Advisory feedback and merge requirements. Only enforced requirements control the merge gate, and the repository's settings decide what they are.
Practice it. Practice: checks that block, in your own tool, fifteen minutes.
Check yourself
Question 1 / 8
0 answered
An AI reviewer posts five Important findings. The merge button still works. Why?
Sources
- Owner
- Panaversity