-
Notifications
You must be signed in to change notification settings - Fork 414
142 lines (129 loc) · 5.91 KB
/
Copy pathdocs-a11y.yml
File metadata and controls
142 lines (129 loc) · 5.91 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
# Scans the built docs site for WCAG 2 AA accessibility violations with
# pa11y-ci, using the same "hugo server" flow contributors run locally
# (see docs/Dockerfile). Originally landed as the last step of the
# docs-a11y-audit remediation (PR 9); the docs-a11y-smart-gate plan later
# evolved it from a fixed URL list into a path-aware, two-tier scan:
#
# Tier 1 (always): a small static list of layout-archetype pages in
# docs/.pa11yci.json, each scanned in both themes — guards against
# systemic regressions (shared CSS/JS/templates/SVG) on every run.
#
# Tier 2 (pull_request only): the content pages the PR actually
# modifies, mapped from changed Markdown to rendered URLs by
# scripts/docs-a11y-urls.sh (deterministically capped, both themes) —
# guards against authored-content issues on exactly what changed. A
# generated config (static + changed) is used when there's anything to
# add; push-to-main and content-free PRs fall back to the static-only
# config, since there's no PR diff to compute Tier 2 from.
#
# Each URL is listed once with ?theme=light and once with ?theme=dark:
# the headless browser's default color-scheme is otherwise indeterminate
# (observed as "light" locally), so without the query param the gate
# would only ever exercise one theme. js/app.js's initTheme() honors
# ?theme= ahead of localStorage/prefers-color-scheme for exactly this
# reason.
#
# The changed-file diff is git-native (`git diff HEAD^1 HEAD` against the
# pull_request test-merge commit, fetch-depth: 2) rather than a
# changed-files action, keeping the SHA-pinned, minimal-supply-chain
# convention (see scripts/docs-a11y-urls.sh's header for the mapping
# rules and env vars, and docs/STYLE.md for how to reproduce a scan
# locally).
#
# pa11y only treats HTML_CodeSniffer "error"-level results as failures
# (warnings/notices are informational and excluded by default), so this
# gates on real violations rather than every possible nit.
name: docs-a11y
permissions:
contents: read
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ github.ref != 'refs/heads/main' }}
on:
push:
branches: [main]
paths:
- ".github/workflows/docs-a11y.yml"
- "docs/**"
- "scripts/docs-a11y-urls.sh"
pull_request:
paths:
- ".github/workflows/docs-a11y.yml"
- "docs/**"
- "scripts/docs-a11y-urls.sh"
env:
HUGO_VERSION: 0.163.0
jobs:
pa11y:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
with:
# Need the merge commit's parent too, so `git diff HEAD^1 HEAD`
# (below) can compute the PR's changed files without a
# changed-files action or extra token scope.
fetch-depth: 2
# pa11y-ci@3.1.0 bundles an old Puppeteer whose postinstall Chromium
# download doesn't happen under `npx --yes` ("Could not find expected
# browser (chrome) locally"). Installing a pinned Chrome and pointing
# Puppeteer at it via PUPPETEER_EXECUTABLE_PATH (below) sidesteps that
# download entirely, per pa11y-ci's own guidance for Ubuntu > 20.04.
- name: Install Chrome
id: setup-chrome
uses: browser-actions/setup-chrome@2e1d749697dd1612b833dba4a722266286fbefcd # v2.1.2
with:
chrome-version: stable
- name: Install Hugo
run: |
curl -fsSL "https://github.com/gohugoio/hugo/releases/download/v${HUGO_VERSION}/hugo_extended_${HUGO_VERSION}_linux-amd64.tar.gz" \
| sudo tar -xz -C /usr/local/bin hugo
hugo version
- name: Start Hugo server
working-directory: docs
run: nohup hugo server --bind 127.0.0.1 --port 1313 > hugo-server.log 2>&1 &
- name: Wait for server
run: npx --yes wait-on@7.2.0 http://127.0.0.1:1313/docker-agent/ --timeout 60000
# Tier 2: map this PR's changed content Markdown to rendered URLs.
# `actions/checkout` puts the pull_request test-merge commit at
# HEAD, whose first parent (HEAD^1) is the base branch tip, so this
# diff is exactly the PR's changed files — token-free and identical
# for fork PRs. Skipped on push (no PR diff to compute from).
- name: Compute changed-page URLs
id: changed-urls
if: github.event_name == 'pull_request'
env:
A11Y_BASE_URL: http://127.0.0.1:1313
run: |
git diff --name-only --diff-filter=d HEAD^1 HEAD \
| ./scripts/docs-a11y-urls.sh > /tmp/changed-urls.txt
count=$(wc -l < /tmp/changed-urls.txt | tr -d ' ')
echo "count=$count" >> "$GITHUB_OUTPUT"
echo "Tier 2: $count changed-page URL(s):"
cat /tmp/changed-urls.txt
# Merge Tier 2's URLs into the static (Tier 1) config from
# docs/.pa11yci.json. Only runs when there's something to add;
# otherwise the run step below falls back to the static-only config.
- name: Assemble pa11y config
if: github.event_name == 'pull_request' && steps.changed-urls.outputs.count != '0'
run: |
jq -Rn '[inputs]' /tmp/changed-urls.txt > /tmp/changed-urls.json
jq --slurpfile extra /tmp/changed-urls.json '.urls += $extra[0]' \
docs/.pa11yci.json > /tmp/pa11yci.generated.json
echo "Merged pa11y-ci config (static + changed pages):"
jq -r '.urls[]' /tmp/pa11yci.generated.json
- name: Run pa11y-ci
working-directory: docs
env:
PUPPETEER_EXECUTABLE_PATH: ${{ steps.setup-chrome.outputs.chrome-path }}
run: |
config=.pa11yci.json
if [ -f /tmp/pa11yci.generated.json ]; then
config=/tmp/pa11yci.generated.json
fi
echo "Using pa11y-ci config: $config"
npx --yes pa11y-ci@3.1.0 --config "$config"
- name: Show Hugo server log on failure
if: failure()
working-directory: docs
run: cat hugo-server.log || true