Gate a pull request with b8e ci
If you want a pull request to fail when it introduces accessibility violations, run b8e ci as a
build step. It scans, reports, and exits non-zero on gating findings, so your CI provider marks the
check red.
Fail the build on new violations only
Section titled “Fail the build on new violations only”If you want to gate only the files a pull request changed — not the whole backlog — diff against the
base branch with --base:
b8e ci --base origin/mainb8e scans the files changed since that git ref and gates on those alone. Point --base at
whatever ref your CI exposes as the merge target.
If the project already has a backlog of findings, changed-file scoping alone will not get you to green — a pull request that touches an old file inherits its old findings. Record the existing ones as a baseline first: see Adopt a baseline on an existing codebase.
Choose which findings fail the build
Section titled “Choose which findings fail the build”By default b8e ci fails on block-level findings and lets warn-level ones through. If you want
warnings to fail the build too, raise the enforcement level with --enforce:
b8e ci --base origin/main --enforce warnTo narrow the gate by severity instead — fail only on findings at or above a given impact — use
--fail-on:
b8e ci --base origin/main --fail-on seriousDeclare what blocks, or nothing gates
Section titled “Declare what blocks, or nothing gates”block is not a severity — a finding is block-level only when one of its WCAG success criteria is
listed in enforcement.block in binclusive.json. b8e init writes that list empty on purpose,
so your first run reports the backlog you already had without failing the build.
Until you declare a criterion, the gate has nothing to match. b8e ci says so:
NOT GATING — binclusive.json declares nothing in "enforcement.block", so every finding isadvisory, so this run could not have failed however bad the findings areThe run still exits 0 — a first run is meant to be green. To start gating, add the criteria you
want enforced to enforcement.block, or record today’s findings with
b8e baseline . first and tighten from there.
Asking for a gate that cannot fire is refused rather than passed: --fail-on against an empty
enforcement.block exits 4 and names what to configure, instead of reporting a pass over a
critical finding.
Read the exit code
Section titled “Read the exit code”b8e ci follows the grep/eslint convention:
0— nothing gated; the check passes.1— gating findings; the check fails.4— the invocation asked for a gate that cannot fire (a--fail-onover an emptyenforcement.block).7— no credential. The step never scanned; see Wire it into a workflow.2or higher — the tool failed to run (a bad--base, a broken baseline, a crash).
A crash exits 2, distinct from 1, so a findings failure is never confused with the tool falling
over. See the exit-codes reference for the full contract.
Wire it into a workflow
Section titled “Wire it into a workflow”In a GitHub Actions job, let the exit code drive the check — do not swallow it:
- run: b8e ci --base origin/${{ github.base_ref }} env: BINCLUSIVE_API_KEY: ${{ secrets.BINCLUSIVE_API_KEY }}b8e ci needs a credential to run, the same as every other b8e command. On a runner there is
nobody to b8e auth login, so on that lane the credential is BINCLUSIVE_API_KEY — without it the
step exits 7 and never scans.
b8e init --ci scaffolds this workflow for you, that secret included.
If you want a rollup digest in the job summary and a sticky PR comment, add --summary.
Send the findings to your dashboard
Section titled “Send the findings to your dashboard”The same key that authenticates the run is also what asks for an upload. Add the project to file into, and the findings land in your dashboard:
- run: b8e ci --base origin/${{ github.base_ref }} env: BINCLUSIVE_API_KEY: ${{ secrets.BINCLUSIVE_API_KEY }} BINCLUSIVE_PROJECT_ID: prj_your_project_idMint the token in the dashboard under Settings → CI access — it must be a project CI token; a personal API key will not authenticate ingestion.
Setting BINCLUSIVE_API_KEY is treated as “I want these uploaded”, so from then on any failure to
send fails the step loudly rather than passing green with nothing filed.
On a workflow that is not pull_request — an on: push or a schedule — also set
BINCLUSIVE_ENVIRONMENT to production or staging. Without it the run is stamped unknown and
its findings are attributed to no deployment — listed in the dashboard, but absent whenever anyone
narrows to Production. See the
environment reference.
Gate without sending anything
Section titled “Gate without sending anything”Needing a credential is not the same as transmitting one byte of your findings. Two ways to keep a gating run local:
b8e ci --base origin/main --no-upload--no-upload runs the gate exactly as normal and transmits nothing, whether or not a key is set.
The other way is to run under a b8e auth login session with no BINCLUSIVE_API_KEY in the
environment. The session is what satisfies the credential requirement; with no key there is nothing
asking for an upload, so the scan runs, the exit code is right, and the findings stay on the
machine. That is the local path on a laptop, or on a self-hosted runner someone has signed in on.
For every flag b8e ci accepts, see the ci reference.