Skip to content
The AI Agent Factory

15.8 Checks that block

Approved by
Panaversity ·
14 min read

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 main until 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

RuleWhat it stops
Require a pull request before mergingAnyone pushing straight to main, including an agent
Require status checks to pass before mergingA merge while a required check has failed or not finished
Require conversation resolutionA merge while a review thread is still open
Require approvals, and review from code owners2A merge without the people 15.9 names
Dismiss stale approvals when new commits are pushedA merge of code nobody approved

What does a workflow do?

It runs the checks. A workflow is a file in .github/workflows/ that tells the host which checks to run, and when. An event, such as a new pull request, starts it. It is made of jobs, and each job is a list of steps that run in order. A job stops at its first failing step, so a later step in the same job never runs. Each job shows on the pull request as one check. Marking a check required in branch protection turns it from advisory into blocking. 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:

JobWhat it runs
checksBoth type checks, both test suites, the linter
tests-unchangedA 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-secretsA 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 test runner's settings were changed to skip tests. 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 token 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 }}"

On the left, one job with four steps in order: the type check passes, the tests fail on the cutoff test, and the test comparison and the secret check are skipped. On the right, three independent jobs for the same change, each failing on its own. The checks job fails on the cutoff test, tests-unchanged on four removed test lines, and no-secrets on key logging at line 14.

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.8: 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 it as running untrusted code. Give its 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 triggered by a fork, an outside copy of the repository. Never use a trigger that runs with your secrets, such as pull_request_target, to build or run a pull request's code.4 And when a check reads labels, such as tests-changed, make the workflow run on the labeled and unlabeled events too, or adding the label changes nothing until the next push.

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.

Advisory feedback, such as AI review findings, comments and summaries, helps people judge. Enforced requirements, set by the repository's rules, control the merge gate. They are required checks, which cover tests, types, the test comparison and the secret check, then required approvals and conversation resolution. A note says a comment is not a merge rule, and AI feedback blocks only when it is connected to an enforced requirement.

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?

  1. About rulesets, GitHub.↑
  2. About protected branches, GitHub.↑
  3. Using secrets in GitHub Actions, GitHub.↑
  4. Events that trigger workflows, GitHub.↑
  5. How the Claude Code team does code review, Anthropic.↑
Owner
Panaversity