AccessLedger

GitHub Action

Scan on every push

Run a WCAG 2.2 scan when code changes, comment the result on the pull request, and fail the build when serious issues appear. Eight lines of YAML and one repository secret.

TJGaushas/accessledger-scan-action@v1

Setup

Two steps

1. Store your token

Create a token at Account, then API tokens. In your repository go to Settings, then Secrets and variables, then Actions, and add a new repository secret named ACCESSLEDGER_API_TOKEN.

Add it as a secret, not as a variable, and never paste it into the workflow file. A token in a committed file is public the moment the repository is, and is in the git history even after you delete the line.

2. Add the workflow

Save this as .github/workflows/accessibility.yml:

name: Accessibility

on:
  push:
    branches: [main]
  pull_request:

permissions:
  contents: read
  pull-requests: write

jobs:
  accessibility:
    runs-on: ubuntu-latest
    steps:
      - uses: TJGaushas/accessledger-scan-action@v1
        with:
          api-token: ${{ secrets.ACCESSLEDGER_API_TOKEN }}
          url: https://example.com/pricing
          fail-on: serious

Change the URL to a page of your own. That is the whole setup. The next push runs a scan.

Scope

One page, or the whole site

url scans a single page and needs nothing set up first. It is the right choice for a pull request check, because it is fast and it tests the page you probably changed.

site-id scans every page configured for a site you have verified you control, which is the right choice for a nightly run. Find the id in the address bar of the site page in your account.

Send one or the other, never both. Both together is a configuration error and the Action says so rather than quietly picking one.

Inputs

Everything you can set

Action inputs, whether they are required, and their defaults.
Input Required Default What it does
api-token yes Your token, from a repository secret. Never hard code it.
url no A single page to scan. Provide this or site-id, not both.
site-id no A verified site. Scans every page configured for it.
fail-on no serious Lowest severity that fails the job: critical, serious, moderate, minor, or never.
max-wait-seconds no 300 How long to wait for the scan before giving up and reporting a timeout.
comment-on-pr no true Post a summary on the pull request, updated in place rather than added again on each push.
github-token no the workflow token Used only to write that comment. Needs pull-requests: write.
api-base no https://theaccessledger.com/api/v1 Advanced. Point the Action at a different environment.

Outputs

Using the result in later steps

What the Action returns to the rest of your workflow.
OutputWhat it is
criticalCount of critical violations. Empty if the scan did not complete.
seriousCount of serious violations.
moderateCount of moderate violations.
minorCount of minor violations.
report-urlLink to the full dated record in your account.
statuscomplete, service-error, quota-exceeded, timeout, or config-error.
- uses: TJGaushas/accessledger-scan-action@v1
  id: a11y
  with:
    api-token: ${{ secrets.ACCESSLEDGER_API_TOKEN }}
    url: https://example.com

- run: echo "Serious issues: ${{ steps.a11y.outputs.serious }}"

The important part

Our outage must never look like your bug

A build that fails is a message to whoever reads it, and the worst possible version of that message is one that blames the wrong thing. So the Action separates the two cases, and you should too.

A status of complete means the scan ran and the counts are real. Only then can the job fail for accessibility reasons, and only when something at or above your fail-on level was found.

service-error and timeout mean the scan could not be completed. That is our problem, not a finding about your site. Check the status page, which reports what is actually working at the moment you load it.

quota-exceeded means the monthly allowance is spent, and config-error means the inputs do not make sense, such as both url and site-id. Neither is an accessibility result.

If you would rather never fail a build on findings and only collect the record, set fail-on: never. The scan still runs, the comment still appears, and the dated history still builds.

Worth doing

Two settings that save you scans

Add a concurrency group so a second push cancels the first run rather than spending two scans from your quota on the same branch:

concurrency:
  group: accessibility-${{ github.ref }}
  cancel-in-progress: true

And add a nightly schedule alongside the push trigger. Most accessibility regressions arrive with content rather than with code, and a content change never touches your repository at all.

on:
  push:
    branches: [main]
  pull_request:
  schedule:
    - cron: '17 6 * * *'

Limits

What a passing build means

It means the automated checks found nothing at or above your threshold, on the pages they reached, on that date. Automated testing reliably detects roughly 30 to 40 percent of WCAG success criteria.

A green check is worth having and it is not a conformance statement. The value of running this on every push is the dated record it builds, which is the thing that cannot be produced afterwards when somebody asks what you have been doing about accessibility.

API reference