Skip to content

Commit 602e751

Browse files
Merge pull request #330 from coding-for-reproducible-research/accessibility_ci
[WIP] Accessibility Assessment CI with Pa11y
2 parents a179a46 + db48176 commit 602e751

File tree

4 files changed

+170
-1
lines changed

4 files changed

+170
-1
lines changed

.github/workflows/accessibility.yml

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
name: pa11y-accessibility-check
2+
3+
on:
4+
pull_request:
5+
6+
jobs:
7+
accessibility_assessment_comment:
8+
runs-on: ubuntu-latest
9+
container:
10+
image: mcr.microsoft.com/playwright:v1.42.1-jammy # includes Chromium, Node, and tools
11+
steps:
12+
- uses: actions/checkout@v3
13+
14+
- name: Set up Python 3.11
15+
uses: actions/setup-python@v4
16+
with:
17+
python-version: '3.11.6'
18+
19+
- name: Install Poetry
20+
run: |
21+
curl -sSL https://install.python-poetry.org | python3 -
22+
echo "$HOME/.local/bin" >> $GITHUB_PATH
23+
24+
- name: Install dependencies
25+
run: |
26+
export PATH="$HOME/.local/bin:$PATH"
27+
poetry install
28+
29+
- name: Cache executed notebooks
30+
uses: actions/cache@v4
31+
with:
32+
path: _build/.jupyter_cache
33+
key: jupyter-book-cache-${{ hashFiles('pyproject.toml') }}
34+
35+
- name: Build the book
36+
run: poetry run jupyter-book build .
37+
38+
- name: Upload error logs
39+
uses: actions/upload-artifact@v4
40+
with:
41+
name: error-logs
42+
path: _build/html/reports/pathways/related_courses.err.log
43+
continue-on-error: true
44+
45+
- name: Install Node.js and dependencies
46+
run: |
47+
apt-get update
48+
apt-get install -y curl gnupg jq findutils
49+
curl -fsSL https://deb.nodesource.com/setup_20.x | bash -
50+
apt-get install -y nodejs
51+
npm install --save-dev pa11y-ci
52+
npx puppeteer browsers install chrome
53+
54+
- name: Identify changed files and map to HTML
55+
id: map_html_targets
56+
shell: bash
57+
run: |
58+
git config --global --add safe.directory "$GITHUB_WORKSPACE"
59+
60+
declare -A seen
61+
echo "[" > pa11y_targets.json
62+
first=true
63+
64+
git fetch origin ${{ github.base_ref }} --depth=1
65+
git diff --name-only FETCH_HEAD HEAD | grep -E "\.md$|\.ipynb$" > changed_files.txt || true
66+
echo "Changed source files:"
67+
cat changed_files.txt || echo "None"
68+
69+
while IFS= read -r file; do
70+
[ -z "$file" ] && continue
71+
basefile=$(basename "$file")
72+
name="${basefile%.*}"
73+
matches=$(find _build/html -type f -name "${name}.html")
74+
for match in $matches; do
75+
if [[ -z "${seen[$match]}" ]]; then
76+
seen[$match]=1
77+
if [ "$first" = true ]; then
78+
first=false
79+
else
80+
echo "," >> pa11y_targets.json
81+
fi
82+
echo "\"$match\"" >> pa11y_targets.json
83+
fi
84+
done
85+
done < changed_files.txt
86+
87+
echo "]" >> pa11y_targets.json
88+
echo "Generated pa11y_targets.json:"
89+
cat pa11y_targets.json
90+
91+
- name: Run Pa11y CI on changed pages only and save output
92+
id: run_pa11y
93+
shell: bash # <-- this fixes the mapfile error
94+
run: |
95+
num_files=$(jq length pa11y_targets.json)
96+
touch pa11y_output.md
97+
98+
if [ "$num_files" -eq 0 ]; then
99+
echo "No relevant HTML files to check. Skipping Pa11y." | tee pa11y_output.md
100+
else
101+
echo "### 🚦 Pa11y Accessibility Report" > pa11y_output.md
102+
echo "" >> pa11y_output.md
103+
104+
# Deduplicate HTML targets and read into array
105+
mapfile -t html_files < <(jq -r '.[]' pa11y_targets.json | sort -u)
106+
107+
for file in "${html_files[@]}"; do
108+
echo "#### 📄 $file" >> pa11y_output.md
109+
echo '```' >> pa11y_output.md
110+
result=$(npx pa11y-ci --reporter cli --config pa11yci.js "file://$(pwd)/$file" 2>&1 || true)
111+
echo "$result" >> pa11y_output.md
112+
echo '```' >> pa11y_output.md
113+
114+
# Attribution line for accessibility error source
115+
base=$(basename "$file" .html)
116+
echo "_⚠️ This issue likely originates from \`${base}.md\` or \`${base}.ipynb\`, which is used to generate this HTML file._" >> pa11y_output.md
117+
echo "" >> pa11y_output.md
118+
done
119+
fi
120+
121+
122+
123+
- name: Debug GitHub context
124+
run: |
125+
echo "Event name: ${{ github.event_name }}"
126+
echo "PR number: ${{ github.event.pull_request.number || 'None' }}"
127+
128+
- name: Find previous PR comment (if exists)
129+
id: find_comment
130+
uses: peter-evans/find-comment@v3
131+
with:
132+
issue-number: ${{ github.event.pull_request.number }}
133+
comment-author: 'github-actions[bot]'
134+
body-includes: '### 🚦 Pa11y Accessibility Report'
135+
136+
- name: Create or update PR comment with Pa11y results
137+
uses: peter-evans/create-or-update-comment@v4
138+
with:
139+
token: ${{ secrets.GITHUB_TOKEN }}
140+
issue-number: ${{ github.event.pull_request.number }}
141+
body-path: pa11y_output.md
142+
comment-id: ${{ steps.find_comment.outputs.comment-id }}
143+
edit-mode: replace
144+
145+
146+
147+

home_page.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
# Coding for Reproducible Research (CfRR) Training Programme Home Page
2+
23
## Mission Statement
34
Coding for Reproducible Research (CfRR) actively supports the delivery of the university’s Strategy 2030 commitment to research excellence through an open, ethical and supportive research culture while ensuring its community is well-equipped to capitalize on the opportunities presented by technology, big data and artificial intelligence.
45

@@ -12,4 +13,4 @@ You can contact the CfRR team at the following email: [codingforreproduciblerese
1213

1314
Please register your interest in a particular course by completing the relevant form on the Workshop Schedule and Signup page available [here](cfrr_program_details/courses_overview.ipynb).
1415

15-
For more details on the structure and use of this website, please go to ['How to use this website'](cfrr_program_details/how_to_use_CfRR.ipynb).
16+
For more details on the use of this website, please go to ['How to use this website'](cfrr_program_details/how_to_use_CfRR.ipynb).

pa11yci.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
const fs = require('fs');
2+
const path = require('path');
3+
4+
// Get current working directory to prefix file paths
5+
const base = process.env.PA11Y_BASE_DIR || process.cwd();
6+
7+
module.exports = {
8+
defaults: {
9+
chromeLaunchConfig: {
10+
args: ['--no-sandbox']
11+
}
12+
},
13+
urls: JSON.parse(fs.readFileSync('pa11y_targets.json', 'utf-8'))
14+
.map(rel => 'file://' + path.join(base, rel))
15+
};

package.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"devDependencies": {
3+
"axe-core": "^4.10.3",
4+
"puppeteer": "^24.15.0"
5+
}
6+
}

0 commit comments

Comments
 (0)