Skip to content

Monthly Accessibility Scan #1

Monthly Accessibility Scan

Monthly Accessibility Scan #1

Workflow file for this run

name: Monthly Accessibility Scan
on:
schedule:
# Run at 14:00 UTC on the 1st of every month.
- cron: '0 14 1 * *'
workflow_dispatch:
permissions:
contents: write
pages: write
id-token: write
concurrency:
group: "pages"
cancel-in-progress: false
jobs:
scan-and-deploy:
runs-on: ubuntu-latest
# 112 sites at concurrency 5 runs ~10-12 min; this ceiling stops a
# pathological run (hung browser, bot-gated site) from burning CI
# minutes while still leaving headroom for the occasional slow tail.
timeout-minutes: 30
environment:
name: github-pages
url: ${{ steps.deploy.outputs.page_url }}
steps:
- name: Checkout
uses: actions/checkout@v4
with:
# Always check out main at runtime, not the trigger SHA. A
# `gh run rerun` against a previous scheduled or dispatched
# run would otherwise re-check-out the stale trigger commit
# and then fail to push its new "Monthly scan $MONTH" commit
# because main had already moved forward during the first
# attempt's successful commit step.
ref: main
# Full history so the commit step can rebase onto origin/main
# cleanly if main moves mid-run (the commit step also handles
# this with a rebase + retry loop as a belt-and-suspenders
# safeguard against concurrent pushes).
fetch-depth: 0
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '24'
cache: 'npm'
- name: Install npm dependencies
run: npm ci
- name: Cache Playwright browsers
uses: actions/cache@v4
with:
path: ~/.cache/ms-playwright
key: playwright-${{ hashFiles('package-lock.json') }}
- name: Install Chromium
run: npx playwright install --with-deps chromium
- name: Run accessibility scan
run: node scan/run.mjs
- name: Commit results
run: |
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git add data/
MONTH=$(date -u +"%Y-%m")
if git diff --quiet --cached; then
echo "No data changes to commit — skipping commit/push."
exit 0
fi
git commit -m "Monthly scan ${MONTH}"
# Rebase onto latest origin/main before pushing. Handles the case
# where a previous run already pushed a "Monthly scan $MONTH"
# commit (e.g. this is a rerun after a downstream deploy step
# failed). Scans only touch data/ files so conflicts are not
# expected, but if they ever happen the run should fail loudly
# rather than force-pushing. Retry the push up to 3 times in
# case the ref moved between fetch and push.
for attempt in 1 2 3; do
git fetch origin main
git rebase origin/main || {
echo "Rebase of monthly scan commit failed — aborting."
git rebase --abort || true
exit 1
}
if git push; then
echo "Push succeeded on attempt ${attempt}."
exit 0
fi
echo "Push rejected on attempt ${attempt}, retrying..."
sleep 2
done
echo "Push failed after 3 attempts."
exit 1
- name: Prepare Pages artifact
run: |
# site/data is a symlink to ../data in the repo (for local dev),
# but GitHub Pages would deploy the entire data/ tree including
# large per-run JSONs. Replace it with a clean directory containing
# only history.json, which is all the site actually fetches.
rm -rf site/data
mkdir -p site/data
cp data/history.json site/data/history.json
- name: Upload Pages artifact
uses: actions/upload-pages-artifact@v3
with:
path: ./site
- name: Deploy to GitHub Pages
id: deploy
uses: actions/deploy-pages@v4