CI integration
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 scanon: [pull_request]jobs:a11y-scan:runs-on: ubuntu-lateststeps:- uses: actions/checkout@v4- uses: actions/setup-node@v4with: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.$ surea11y 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 / allowlist 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 scanon: [pull_request]permissions:contents: readsecurity-events: writejobs:a11y-scan:runs-on: ubuntu-lateststeps:- uses: actions/checkout@v4- uses: actions/setup-node@v4with: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.sarifcontinue-on-error: trueid: scan- name: Upload SARIF to Code Scanninguses: github/codeql-action/upload-sarif@v3with:sarif_file: results.sarif- name: Fail the job on new violationsif: steps.scan.outcome == 'failure'run: exit 1
See the SARIF report 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 scanimage: node:20script:- npm ci- npm run build- npx @surea11y/cli scan ./dist/index.html --baseline a11y-baseline.json --html a11y-report.htmlartifacts:- a11y-report.html
The step fails the pipeline on the CLI's exit code exactly like any other script entry; a11y-report.html (see the HTML report) 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).