GitHub Action — review in CI
CommitBrief/commitbrief-action runs the CLI on every pull request — inline review comments, a severity gate, or a declarative policy gate.
CommitBrief/commitbrief-action is a composite GitHub Action that
runs an LLM code review on every pull request. Add it to a workflow
with uses: CommitBrief/commitbrief-action@v1, give it a provider and
an API key, and it installs the CommitBrief CLI on the runner and
reviews the PR diff in one of three modes: post inline review comments
with a verdict (comment), fail the job on finding severity (gate),
or evaluate a declarative policy file (guard).
It is a thin wrapper — every mode shells out to a CommitBrief command you can run locally, so a CI failure reproduces on your machine.
Quick start
Add .github/workflows/commitbrief.yml to the repo you want reviewed.
version defaults to the CLI release the Action tag was cut against, so
@v1 on its own is reproducible; set it explicitly when you want to
choose the upgrade moment yourself:
name: CommitBrief
on: pull_request
permissions:
contents: read
pull-requests: write # comment mode posts the review
jobs:
review:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: CommitBrief/commitbrief-action@v1
with:
provider: anthropic
api-key: ${{ secrets.ANTHROPIC_API_KEY }}
version: v1.18.1
That is the whole setup for comment mode (the default). The Action
downloads the prebuilt CLI binary for the runner from the matching GitHub
release, checks its SHA-256 against that release’s checksums.txt, puts
it on PATH, and reviews the pull request. There is no Go setup and no
compile step, so the install takes seconds instead of the half a minute
or more a go install build needs.
What the checksum proves. A download that does not match
checksums.txt fails the job; the Action never falls back to a source
build after a failed check. The check proves integrity — the archive is
exactly the one the release lists — not provenance: checksums.txt is
not signed and comes from the same release as the archive.
When it builds from source instead. Linux, macOS, and Windows
runners on x64 or ARM64 get the prebuilt binary. Any other runner, or a
version that is a branch name or commit SHA, sets up Go and runs
go install for that ref, with a warning in the job log. That path is
slower and is not checked against release checksums.
The checkout step is not optional. The Action does not check out
your repository for you, and none of the three modes work without a
git working tree: comment mode resolves the target repo from the git
remote, and gate / guard diff two commits that have to exist
locally.
Inputs
| Input | Default | Required | What it does |
|---|---|---|---|
provider | — | yes | anthropic, openai, gemini, deepseek, mistral, cohere, or ollama. Anything else fails the step. |
api-key | "" | no | Provider API key. Pass a repository secret. Not needed for ollama. |
model | "" | no | Model override. Empty uses the provider’s default. |
mode | comment | no | comment, gate, or guard. |
request-changes-on | "" | no | comment mode: severity at or above which the verdict becomes request-changes (critical, high, medium, low). Empty — the default — never requests changes. |
fail-on | high | no | gate mode: fail the job when a finding meets or exceeds this severity (critical, high, medium, low, info, any). |
policy | .commitbrief/policy.yml | no | guard mode: policy file path, relative to the repo root. |
version | current release | no | CLI version to install, e.g. v1.18.1. A release tag installs the checksum-verified prebuilt binary. latest resolves to the newest stable release on every run. A branch or commit SHA builds from source. |
request-changes-on, fail-on, and policy are each read by exactly
one mode and ignored by the other two.
Permissions
| Mode | Required permissions: |
|---|---|
comment | contents: read and pull-requests: write |
gate | contents: read |
guard | contents: read |
comment mode posts through the workflow’s own GITHUB_TOKEN, which
is why it needs pull-requests: write. Grant that only for the mode
that uses it — a gate-only workflow should stay read-only.
Mode: comment
Runs commitbrief remote pr <number>. Each
finding is posted as an inline review comment on the PR, then a
verdict is submitted.
- uses: CommitBrief/commitbrief-action@v1
with:
provider: anthropic
api-key: ${{ secrets.ANTHROPIC_API_KEY }}
version: v1.18.1
mode: comment # default
request-changes-on: high # opt in to a blocking verdict
Without request-changes-on the verdict is only ever approve or
comment — the review never blocks a merge. Setting it to high
turns any high or critical finding into a request-changes review.
The full verdict table, and the comment-volume caps that come with
each threshold, are in
Review a GitHub PR.
The step exits 0 whenever the review submits successfully, verdict
included. comment mode reports through GitHub, not through the exit
code; use gate or guard if you want a red check.
Mode: gate
Runs commitbrief diff <base>...<head> --fail-on=<severity>.
No comments, no PR write access — just a pass/fail check.
- uses: actions/checkout@v4
with:
fetch-depth: 0 # both PR endpoints must be local
- uses: CommitBrief/commitbrief-action@v1
with:
provider: openai
api-key: ${{ secrets.OPENAI_API_KEY }}
version: v1.18.1
mode: gate
fail-on: high
fetch-depth: 0 matters here. On a pull_request event the default
shallow checkout does not contain the base and head commits the Action
diffs, and commitbrief diff fails on the missing objects. What the
severities mean, and which exit code each produces, is in
Severity and CI gating.
Mode: guard
Runs commitbrief guard --diff <base>...<head> --policy <path>.
A per-severity budget rather than a single threshold — useful when a
repo takes a high volume of AI-authored pull requests.
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: CommitBrief/commitbrief-action@v1
with:
provider: anthropic
api-key: ${{ secrets.ANTHROPIC_API_KEY }}
version: v1.18.1
mode: guard
policy: .commitbrief/policy.yml # default
Requires CLI v1.10.0 or newer — the default version already is;
check it only if you pin an older release. The policy file has to be committed, and
CommitBrief adds .commitbrief/ to your .gitignore on its first
cache write, so un-ignore the one file explicitly:
.commitbrief/
!.commitbrief/policy.yml
A missing or malformed policy blocks rather than passes — see Policy gate.
Secrets
api-key is the only secret the Action takes. Pass it from a
repository (or organization) secret and let the Action map it to the
environment variable the CLI reads:
provider | Environment variable set for the CLI |
|---|---|
anthropic | ANTHROPIC_API_KEY |
openai | OPENAI_API_KEY |
gemini | GEMINI_API_KEY |
deepseek | DEEPSEEK_API_KEY |
mistral | MISTRAL_API_KEY |
cohere | COHERE_API_KEY |
ollama | none — leave api-key empty |
ollama needs no key but does need a reachable server, so it is
practical only on a self-hosted runner or with a service container;
point the CLI at it with OLLAMA_HOST in the workflow’s env:.
The three CLI-backed providers
— claude-cli, gemini-cli, codex-cli — are rejected outright by
the provider input. They drive a locally authenticated host CLI,
which a CI runner does not have.
Pinning versions
Two versions are in play, and they are pinned separately.
- The Action —
uses: CommitBrief/commitbrief-action@v1.v1is a moving tag: it is repointed as the Action changes, so a behavioral fix reaches you without a workflow edit. Pin a commit SHA instead if your organization requires immutable third-party actions. - The CLI — the
version:input. Its default is the CLI release the Action tag was cut against, and it moves only whenv1is repointed, so a new CLI release never changes your gate between two runs of the same workflow. Set a released tag yourself to hold the CLI still across Action updates.latestasks the GitHub releases API on every run and follows the newest release, so what your gate flags can change from one run to the next.
Each mode has a CLI floor:
| Mode | Needs CLI |
|---|---|
gate | Requires v0.9.0 or later (the diff subcommand) |
comment | Requires v1.1.0 or later (remote pr) |
guard | Requires v1.10.0 or later (commitbrief guard) |
Notes for CI
- Pull requests only. The Action reads the PR number, base SHA,
and head SHA from the
pull_requestevent payload and fails immediately without one. It is not apush-event tool. - Large diffs can abort on the cost preflight. CommitBrief aborts
rather than prompts when it is not on a TTY and the estimated spend
exceeds
cost.warn_threshold_usd(default$0.50). The Action exposes no--no-cost-checkinput; raise or disable the ceiling in a committed.commitbrief/config.yml— the cost key only, never anapi_key— un-ignored the same way as the policy file. See Safety, cost, and cache. - The cache never survives a run. The response cache lives at
.commitbrief/cacheinside the checkout, so every job starts cold and every review is a paid call. COMMITBRIEF.mdis honored. The Action reviews a real checkout, so your committed review rules apply in CI exactly as they do locally.
See also
- Review pull requests automatically — a
guided walkthrough of
commentmode. - Gate CI on review findings — a guided
walkthrough of
gateandguardmodes. - Review a GitHub PR — remote pr — the command
behind
commentmode, and how to run it from your own terminal. - Severity and CI gating — the severity scale and
--fail-on, behindgatemode. - Policy gate — guard — the policy file format,
behind
guardmode. - Providers — which provider to pick, and what a review costs.