Skip to content

Add CI workflow with Pa11y accessibility checks on PRs#100

Open
alexwolson wants to merge 7 commits intomainfrom
feature/accessibility-review
Open

Add CI workflow with Pa11y accessibility checks on PRs#100
alexwolson wants to merge 7 commits intomainfrom
feature/accessibility-review

Conversation

@alexwolson
Copy link
Collaborator

Summary

Adds a ci.yml GitHub Actions workflow that builds the Jekyll site on every PR and runs Pa11y WCAG2AA accessibility checks against a representative set of rendered pages.

Closes #99

Design decisions

  • Two-job structure: build job produces _site/ artifact; accessibility job downloads it and runs Pa11y. Avoids duplicating the expensive Jekyll build. Additional check jobs (broken links, etc.) can be added later using the same artifact.
  • Tool: Pa11y v9 (pinned) with WCAG2AA standard (HTML_CodeSniffer runner). Accepts local file paths directly — no local server required.
  • Scope: One representative page per layout type — homepage, event, project, person, organization, venue, resource, tag, category. Sufficient to catch template-level issues without scanning hundreds of generated pages.
  • Advisory: The check fails naturally (red X) when violations are found, but is not listed in branch protection required status checks, so it never blocks merge. This is the correct GitHub-native way to implement advisory checks.

Changes

  • .github/workflows/ci.yml — new workflow
  • docs/plans/2026-03-03-pa11y-accessibility-ci.md — implementation plan

GitHub's ubuntu-latest now runs 24.04, which restricts unprivileged
user namespaces via AppArmor. Pa11y/Puppeteer's Chromium fails to
launch without --no-sandbox on this version.
--chromium-flags is not a valid pa11y CLI option. The correct fix,
per pa11y's own TROUBLESHOOTING.md, is to disable Ubuntu 24.04's
AppArmor user namespace restriction at the runner level before
launching pa11y. This is the approach recommended for CI environments.
- Switch pa11y runs to --reporter json, saving per-page output to /tmp/
- Add Node.js step to aggregate JSON into a markdown report and write to GITHUB_STEP_SUMMARY
- Add actions/github-script@v8 step to post or update a PR comment (identified by <!-- pa11y-report --> marker)
- Move exit logic to a dedicated final step using GITHUB_OUTPUT
- Add 2>/dev/null to sort pipe to suppress broken-pipe noise
- Add pull-requests: write permission to accessibility job
@github-actions
Copy link
Contributor

github-actions bot commented Mar 3, 2026

Pa11y Accessibility Report

2 error(s), 0 warning(s) found (WCAG2AA)


Homepage

Homepage

2 error(s)

  • [WCAG2AA.Principle1.Guideline1_1.1_1_1.H37] Img element missing an alt attribute. Use the alt attribute to specify a short text alternative.

    • Context: <img class="ogimage" src="https://civicdashboard.ca/toronto.jpg" loading="lazy">
    • Selector: #main-content > section:nth-child(3) > div:nth-child(2) > article:nth-child(1) > div:nth-child(1) > img
  • [WCAG2AA.Principle1.Guideline1_1.1_1_1.H37] Img element missing an alt attribute. Use the alt attribute to specify a short text alternative.

    • Context: <img class="ogimage" src="https://bikespace.ca/opengraph-image.jpg" loading="lazy">
    • Selector: #main-content > section:nth-child(3) > div:nth-child(2) > article:nth-child(2) > div:nth-child(1) > img

Event

✅ No issues found.


Project

✅ No issues found.


Person

✅ No issues found.


Organization

✅ No issues found.


Venue

✅ No issues found.


Resource

✅ No issues found.


Tag

✅ No issues found.


Category

✅ No issues found.

The --reporter json CLI output is a JSON array of issue objects, not
{pageUrl, issues:[]}. The report aggregator was doing data.issues which
always returned undefined, so issues was always [], making every page
appear clean.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add automated accessibility checks (Pa11y) to PR workflow

1 participant