improve contrast check workflow #2150
Workflow file for this run
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: A11y contrast check | |
on: | |
pull_request: | |
branches-ignore: | |
- 'changeset-release/**' | |
workflow_dispatch: | |
jobs: | |
changes: | |
uses: ./.github/workflows/hasChanged.yml | |
build: | |
needs: changes | |
if: needs.changes.outputs.tokens == 'true' || github.event_name == 'workflow_dispatch' | |
name: Check design token color contrast | |
runs-on: ubuntu-latest | |
continue-on-error: true | |
outputs: | |
faildChecks: ${{ steps.check-results.outputs.faildChecks }} | |
steps: | |
- name: Checkout repository | |
uses: actions/checkout@v4 | |
- name: Set up Node.js | |
uses: actions/setup-node@v4 | |
with: | |
node-version: 20 | |
cache: 'npm' | |
- name: Install dependencies | |
run: npm ci --no-audit --no-fund --ignore-scripts | |
- name: Build tokens | |
run: npm run build:tokens | |
- name: Run required checks | |
run: | | |
npm run contrast:check | |
- name: Prepare check results | |
id: check-results | |
continue-on-error: true | |
uses: actions/github-script@v7 | |
with: | |
script: | | |
const results = require('./color-contrast-check.json'); | |
const prepareResults = require('${{ github.workspace }}/.github/workflows/scripts/a11y-contrast/prepare-check-results.cjs'); | |
prepareResults(results); | |
- name: Report check results as summary | |
uses: actions/github-script@v7 | |
with: | |
script: | | |
const resultsMarkdown = `${{ steps.check-results.outputs.summaryMarkdown }}` | |
// output results to summary | |
core.summary.addRaw(resultsMarkdown, true) | |
core.summary.write({overwrite: true}) | |
- name: Report check results as comment | |
if: github.event_name == 'pull_request' | |
uses: actions/github-script@v7 | |
env: | |
GITHUB_REPOSITORY: ${{ github.repository }} | |
GITHUB_RUN_ID: ${{ github.run_id }} | |
with: | |
script: | | |
const results = ${{ steps.check-results.outputs.failedResults }} | |
const WORKFLOW_SUMMARY_URL = `https://github.com/${{env.GITHUB_REPOSITORY}}/actions/runs/${{env.GITHUB_RUN_ID}}` | |
// get comments | |
const {data: comments} = await github.rest.issues.listComments({ | |
issue_number: context.issue.number, | |
owner: context.repo.owner, | |
repo: context.repo.repo | |
}); | |
const possibleTitles = [ | |
'❌ `light`:', | |
'❌ `light_high_contrast`:', | |
'❌ `light_colorblind`:', | |
'❌ `light_tritanopia`:', | |
'❌ `dark`:', | |
'❌ `dark_dimmed`:', | |
'❌ `dark_high_contrast`:', | |
'❌ `dark_colorblind`:', | |
'❌ `dark_tritanopia`:' | |
] | |
// get comments of token issues | |
let currentComments = comments.filter(comment => possibleTitles.some(titleStart => comment.body.includes(titleStart))); | |
for (const {title, body} of results) { | |
// get token issue | |
const titleStart = title.substring(0, title.indexOf(':') + 1); | |
// remove from currentComments | |
currentComments = currentComments.filter(comment => !comment.body.includes(titleStart)); | |
// | |
const tokenCheckComment = comments.filter(comment => comment.body.includes(titleStart)); | |
const outputBody = `${title}\n\n${body}\n\n<a href="${WORKFLOW_SUMMARY_URL}">→ Details</a>` | |
// if token issue exists, update it | |
if(tokenCheckComment.length > 0) { | |
await github.rest.issues.updateComment({ | |
comment_id: tokenCheckComment[0].id, | |
owner: context.repo.owner, | |
repo: context.repo.repo, | |
body: outputBody | |
}) | |
} | |
// if token issue does not exist, create it | |
else { | |
await github.rest.issues.createComment({ | |
issue_number: context.issue.number, | |
owner: context.repo.owner, | |
repo: context.repo.repo, | |
body: outputBody | |
}) | |
} | |
} | |
// if token issue exists, update it | |
if(currentComments.length > 0) { | |
await currentComments.map(comment => { | |
console.log('deleting comment', comment.id, comment) | |
github.rest.issues.deleteComment({ | |
comment_id: comment.id, | |
owner: context.repo.owner, | |
repo: context.repo.repo, | |
}) | |
}) | |
} | |
Fail_action_on_contrast_failing: | |
needs: build | |
name: Fail action on contrast failing | |
if: needs.build.outputs.faildChecks > 0 | |
runs-on: ubuntu-latest | |
steps: | |
- name: Contrast checks failed | |
run: | | |
echo "::error::${{ needs.build.outputs.faildChecks }} contrast checks failed. Please fix the failing checks and try again." | |
exit 1 | |
remove_comment: | |
needs: changes | |
if: needs.changes.outputs.tokens == 'false' | |
runs-on: ubuntu-latest | |
steps: | |
- name: Remove comment and summary | |
if: github.event_name == 'pull_request' | |
uses: actions/github-script@v7 | |
with: | |
script: | | |
// get comments | |
const {data: comments} = await github.rest.issues.listComments({ | |
issue_number: context.issue.number, | |
owner: context.repo.owner, | |
repo: context.repo.repo | |
}); | |
const possibleTitles = [ | |
'❌ `light`:', | |
'❌ `light_high_contrast`:', | |
'❌ `light_colorblind`:', | |
'❌ `light_tritanopia`:', | |
'❌ `dark`:', | |
'❌ `dark_dimmed`:', | |
'❌ `dark_high_contrast`:', | |
'❌ `dark_colorblind`:', | |
'❌ `dark_tritanopia`:' | |
] | |
// get token issue | |
const tokenCheckComment = comments.filter(comment => possibleTitles.some(titleStart => comment.body.includes(titleStart))); | |
// if token issue exists, update it | |
if(tokenCheckComment.length > 0) { | |
await github.rest.issues.deleteComment({ | |
comment_id: tokenCheckComment[0].id, | |
owner: context.repo.owner, | |
repo: context.repo.repo, | |
}) | |
} | |
// remove summary | |
core.summary.clear() | |
core.summary.write({overwrite: true}) |