CI/CD pipeline integrations
August 8, 2026 · View on GitHub
Ready-to-paste templates wrapping the CLI (npx @surea11y/cli scan ...) in GitHub Actions and Bitbucket Pipelines. If you're calling the library directly from your own Node script instead of the CLI, see INTEGRATION.md instead — this page is specifically about the CLI as a pipeline step.
All of these rely on the CLI's own exit codes (0 clean, 1 at least one — or one new, with --baseline — fail outcome, 2 a usage/scan error) to gate the pipeline; no extra scripting is required for basic pass/fail gating.
GitHub Actions
Basic: gate on exit code
name: Accessibility scan
on: [pull_request]
jobs:
a11y-scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
- run: npm ci && npm run build # produce whatever static HTML you're scanning
- run: npx @surea11y/cli scan ./dist/index.html
This fails the job the moment any fail outcome is found. For an existing site with pre-existing violations, see the baseline variant below instead of disabling the step.
With a baseline (existing site, gate only on new violations)
# Once, locally: record every current fail occurrence, commit the file.
npx @surea11y/cli scan ./dist/index.html --write-baseline a11y-baseline.json
git add a11y-baseline.json
- run: npm ci && npm run build
- run: npx @surea11y/cli scan ./dist/index.html --baseline a11y-baseline.json
See BASELINE.md for what counts as "known" vs. "new", and how to regenerate the file as violations get fixed.
Uploading SARIF to GitHub Code Scanning
upload-sarif needs security-events: write permission and does not fail the job itself — pair it with a separate gating step (or continue-on-error + your own check) if you also want the build to fail on new violations.
name: Accessibility scan
on: [pull_request]
permissions:
contents: read
security-events: write
jobs:
a11y-scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
- run: npm ci && npm run build
- name: Scan (report, don't fail the job here)
run: npx @surea11y/cli scan ./dist/index.html --baseline a11y-baseline.json --sarif results.sarif
continue-on-error: true
id: scan
- name: Upload SARIF to Code Scanning
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: results.sarif
- name: Fail the job on new violations
if: steps.scan.outcome == 'failure'
run: exit 1
See SARIF.md for the output format and a known limitation: a scan of a local file in your checkout gets inline annotations in the Code Scanning UI; a scan of a live URL doesn't (SARIF/Code Scanning can only associate a finding with a real file in the repository).
Bitbucket Pipelines
Bitbucket Pipelines has no built-in SARIF-consuming dashboard equivalent to GitHub Code Scanning, so the CLI's exit code (plus, optionally, --html as a downloadable pipeline artifact) is the practical integration point rather than --sarif.
pipelines:
pull-requests:
'**':
- step:
name: Accessibility scan
image: node:20
script:
- npm ci
- npm run build
- npx @surea11y/cli scan ./dist/index.html --baseline a11y-baseline.json --html a11y-report.html
artifacts:
- a11y-report.html
The step fails the pipeline on the CLI's exit code exactly like any other script entry; a11y-report.html (see REPORT.md) is attached as a downloadable build artifact so a reviewer can open it without re-running the scan locally.
Free-tier/private-repo minute limits
If your pipeline provider's free tier is minute-limited (Bitbucket Pipelines' free tier is 50 build-minutes/month on private workspaces, for example), a jsdom-based scan of static/server-rendered HTML (what the CLI does) is far cheaper than driving a real browser — see the CLI docs for what that trades away (no client-rendered content, no real CSS layout).