Skip to content

Commit

Permalink
GitHub Action: runs Axe accessibility tests on changed files (#132)
Browse files Browse the repository at this point in the history
* Installs pa11y-ci NPM package as dev dependency

* Installs wait-on NPM package as dev dependency

* Bash script generates URLs for pa11y-ci from git diff

* Writes pa11y-ci configuration file

* Adds GitHub Action workflow file

* Adds CI/CD section to README

* Don't run pipeline on push to gh-pages branch
  • Loading branch information
jcarstairs-scottlogic authored Dec 11, 2023
1 parent bb059d2 commit 74adad6
Show file tree
Hide file tree
Showing 8 changed files with 2,055 additions and 1,434 deletions.
65 changes: 65 additions & 0 deletions .github/workflows/check-a11y-of-changed-content.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
name: Check accessibility of changed content

on:
workflow_dispatch:
pull_request:

permissions:
contents: read
pull-requests: read

concurrency:
group: '${{ github.workflow }} @ ${{ github.event.pull_request.head.label || github.head_ref || github.ref }}'
cancel-in-progress: true

jobs:
check-a11y-of-changed-content:
name: Check accessibility of changed content
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Fetch gh-pages branch
run: >-
git fetch origin gh-pages
&& git branch gh-pages origin/gh-pages;
- name: Calculate URLs and output to JavaScript module
run: >-
chmod +x ./generate_pa11y_ci_urls_from_git_diff.sh
&& ./generate_pa11y_ci_urls_from_git_diff.sh gh-pages
>> ./pa11y-ci-urls.js;
- name: Log contents of resulting JavaScript module
run: cat ./pa11y-ci-urls.js;

- name: Setup Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: 2.3

- name: Install gems
run: bundle config path vendor/bundle && bundle install

- name: Run the blog
run: bundle exec jekyll serve &

- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: 20.10.x
cache: npm

- name: Install NPM dependencies
run: npm ci

- name: Setup Chrome
uses: browser-actions/setup-chrome@v1
id: setup-chrome

- name: Wait for blog to be running
run: npx wait-on http://localhost:4000 --timeout 60000

- name: Run pa11y-ci
run: CHROMIUM_BIN=$(which chrome) npx pa11y-ci
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,7 @@ Gemfile.lock

/container_gem_cache/
/dist/
/scripts/generate-related/data/
/scripts/generate-related/data/

# Automatically generated by generate_pa11y_ci_urls_from_git_diff.sh
/pa11y-ci-urls.js
25 changes: 25 additions & 0 deletions .pa11yci.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/// This is a configuration file automatically picked up by pa11y-ci.

const relativeUrls = require('./pa11y-ci-urls');

const chromiumBin = process.env.CHROMIUM_BIN;
if (!chromiumBin) {
throw new Error('CHROMIUM_BIN environment variable is not set');
}

const baseUrl = 'http://localhost:4000';

// Colour contrast is a known issue. If we ever fix the brand colours, this should be removed.
const colourContrastRuleId = 'WCAG2AA.Principle1.Guideline1_4.1_4_3.G18.Fail';

module.exports = {
defaults: {
chromeLaunchConfig: {
executablePath: chromiumBin,
},
ignore: [
colourContrastRuleId,
],
},
urls: relativeUrls.map((url) => `${baseUrl}${url}`),
};
37 changes: 37 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,42 @@ BLOG_USERNAME=abirch ./shell/docker-dev-watch.sh

Visit the blog on [localhost][localhost].

## CI/CD

We use GitHub Actions for CI/CD. The workflow definitions are in YAML files
in `.github/workflows`.

### Compress Images Once a Month

Uses the [calibreapp/image-actions][calibreapp-image-actions] Action to
automatically compress images. The compression algorithm is near-lossless. It
compresses all images in the repo once per month, and creates a Pull Request to
merge in the resulting changes.

### Check accessibility of changed content

Runs [pa11y-ci][pa11y-ci] with the aXe test runner to detect some common
accessibility problems. It serves the blog locally and runs the tests on the
rendered webpages. It only checks pages and blog posts which have changed, but
doesn’t take any interest in changes to layouts or includes, so changes to
those should be tested across the whole site separately. This workflow runs on
Pull Requests, pushes to `gh-pages` and on manual dispatches.

### Generate Read More related

Generates Read More links on blog pages across the blog, using the OpenAI API
to determine which blog posts are on similar themes. This workflow runs only on
manual dispatches on the `gh-pages` branch and creates a Pull Request to merge
in the resulting changes.

### Remove Unused Images

For each image in the repo, searches all the blog posts, pages, YAML data files
and JavaScript scripts for any occurrences of its filename. If the filename
occurs nowhere, deletes the image. Then makes a Pull Request to merge in its
changes. This workflow runs only on a manual dispatch on the `gh-pages` branch.

[calibreapp-image-actions]: https://github.com/calibreapp/image-actions
[confluence-getting-started]: https://scottlogic.atlassian.net/wiki/spaces/INT/pages/3577479175/Getting+started+with+the+Scott+Logic+blog
[sparse-checkout-guide]: https://github.blog/2020-01-17-bring-your-monorepo-down-to-size-with-sparse-checkout/#sparse-checkout-and-partial-clones
[github-ssh]: https://docs.github.com/en/authentication/connecting-to-github-with-ssh
Expand All @@ -165,6 +201,7 @@ Visit the blog on [localhost][localhost].
[ruby-nokogiri]: https://nokogiri.org/
[ruby-liquid]: https://shopify.github.io/liquid/
[ruby-downloads]: https://www.ruby-lang.org/en/downloads/
[pa11y-ci]: https://github.com/pa11y/pa11y-ci
[project-gemfile]: Gemfile
[install-docker]: #docker

48 changes: 48 additions & 0 deletions generate_pa11y_ci_urls_from_git_diff.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#!/usr/bin/env bash
# Take in a base ref. Gets the files that have changed from the base to the HEAD.
# Export the list as a CommonJS module for the pa11y-ci configuration to use.
# Typical usage: generate_pa11y_ci_urls_from_git_diff.sh gh-pages > .pa11yci.js
# Assumes git is installed and on the path.

function generate_pa11y_ci_urls_from_git_diff {
base_ref=$1
if [ -z "$base_ref" ]; then
echo "No Git base ref provided. Usage: $0 <base_ref>"
exit 1
fi

changed_files=$(git diff --name-only $base_ref)

echo -n "module.exports=[";
for file in $changed_files; do
if [[ $file == _posts/* ]]; then
echo -n "'/$(url_of_post $file)',";
# _includes and _layouts don’t correspond to pages on the blog. If someone
# changes these files, they should run a test on the whole blog.
elif [[ \
$file == *.html \
&& ! ( $file == _includes/* || $file == _layouts/* ) \
]]; then
echo -n "'/$(url_of_page $file)',";
fi
done
echo -n "];";
}

function url_of_page {
# Remove trailing /index.html, index.html or .html
echo $1 | sed "s/\(\/\?index\)\?\.html$//";
}

function url_of_post {
year="\([0-9][0-9][0-9][0-9]\)"
month="\([0-9][0-9]\)"
day="\([0-9][0-9]\)"
slug="\(.*\)"
file_ext="\(html\|markdown\|md\)"

echo $1 | sed "s/^_posts\/$year-$month-$day-$slug\.$file_ext$/\1\/\2\/\3\/\4.html/";
}

generate_pa11y_ci_urls_from_git_diff $1

Loading

0 comments on commit 74adad6

Please sign in to comment.