# Gate CI on review findings

> Fail a CI check when a change carries a severe-enough finding — a single --fail-on threshold, or a richer per-severity budget via the guard policy gate.

CommitBrief docs · v1.x · Guides

Canonical URL: https://commitbrief.com/docs/1.x/ci-gate/

---

Commenting on a pull request (see [PR review](/docs/1.x/pr-review)) is
one way to surface findings; making the CI check itself fail on them
is another, and the two aren't mutually exclusive. CommitBrief gives
you two gates for this, from simplest to richest.

## The simple gate: `--fail-on`

Run a review with a severity threshold; a non-zero exit fails the job:

```yaml
# any CI system, plain step
- run: commitbrief diff origin/main...HEAD --fail-on=critical
```

Exit code `1` means at least one finding at or above that severity
survived; `0` means it didn't (or there was nothing to review). The
full value table (`critical`, `high`, `medium`, `low`, `info`, `any`,
`none`) and how it interacts with the secret scanner and cost
preflight are in [Severity and CI gating](/docs/1.x/severity#the---fail-on-flag);
the exact exit codes for every command are in
[Exit codes](/docs/1.x/exit-codes).

On the official Action, this is `mode: gate`:

```yaml
- uses: CommitBrief/commitbrief-action@v1
  with:
    mode: gate
    provider: anthropic
    api-key: ${{ secrets.ANTHROPIC_API_KEY }}
    fail-on: critical
```

`gate` mode runs `commitbrief diff <base>...<head> --fail-on=<severity>`
under the hood and needs `actions/checkout@v4` with `fetch-depth: 0` so
both ends of that range are present. See
[the Action's gate mode](/docs/1.x/github-action#mode-gate) for the
full input list and required permissions.

## The richer gate: `commitbrief guard`

`--fail-on` is a single cutoff. If you want a *budget* per severity
instead — "up to 5 medium findings is fine, but zero critical or
high" — that's what [`commitbrief guard`](/docs/1.x/policy-gate) is
for. It reads an opt-in `.commitbrief/policy.yml`:

```yaml
# .commitbrief/policy.yml
version: 1
thresholds:
  critical: 0
  high: 0
  medium: 5
  low: ~
```

```sh
commitbrief guard --diff origin/main...HEAD
```

On the Action, this is `mode: guard` (requires CLI `v1.10.0` or
later):

```yaml
- uses: CommitBrief/commitbrief-action@v1
  with:
    mode: guard
    provider: anthropic
    api-key: ${{ secrets.ANTHROPIC_API_KEY }}
    policy: .commitbrief/policy.yml
```

`guard` also has a **consume-mode** that skips the provider call
entirely and evaluates a review you already have — useful if a prior
step in the same pipeline already produced a `commitbrief --json`
report, or you're gating a
[credential scan](/docs/1.x/leaks) instead of a code review:

```sh
commitbrief diff origin/main...HEAD --json > review.json
commitbrief guard --from-json review.json
```

Either way, a **missing or unparseable policy file also blocks** — the
gate fails closed, not open, when it can't prove the change is within
policy. Full flag list, the `--json` verdict shape, and how `guard`
compares to `--fail-on` are in [Policy gate](/docs/1.x/policy-gate).

## Which one?

Both read the finding set after inline suppression is applied — a CI
runner has no local baseline file, so baselining doesn't reach either
gate here (see [Brownfield adoption](/docs/1.x/brownfield-adoption) for
what does keep old, known findings from tripping a CI gate) — and both
are plain exit codes any CI system understands.
A single threshold on a pre-commit hook and the richer `guard` policy
on the CI merge gate is a common split — nothing stops you from
running both in the same pipeline.

## See also

- [Severity and CI gating](/docs/1.x/severity) — the full `--fail-on`
  reference, including ready-to-paste recipes for GitHub Actions and
  GitLab CI.
- [Policy gate](/docs/1.x/policy-gate) — the full `guard` reference.
- [Exit codes](/docs/1.x/exit-codes) — what every command returns and
  why.
- [GitHub Action](/docs/1.x/github-action) — inputs and permissions
  for `gate` and `guard` modes.