Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
72 commits
Select commit Hold shift + click to select a range
fd9ac0a
chore(deps): Bump ruby/setup-ruby
dependabot[bot] May 19, 2026
1159927
chore(deps-dev): Bump the npm-minor-and-patch group across 5 director…
dependabot[bot] May 19, 2026
270eadb
chore(deps): Bump ruby/setup-ruby from 1.307.0 to 1.308.0 in the gith…
abdulahmad307 May 20, 2026
3cdb005
chore(deps-dev): Bump the npm-minor-and-patch group across 5 director…
abdulahmad307 May 20, 2026
87c3dad
chore(deps): Bump ruby/setup-ruby
dependabot[bot] May 26, 2026
798e09e
chore(deps): Bump ruby/setup-ruby from 1.308.0 to 1.310.0 in the gith…
JoyceZhu May 26, 2026
93a5067
chore(deps): Bump puma
dependabot[bot] Jun 3, 2026
a9afa92
chore(deps): Bump puma from 8.0.1 to 8.0.2 in /sites/site-with-errors…
lindseywild Jun 3, 2026
8009326
chore(deps): Bump ruby/setup-ruby
dependabot[bot] Jun 8, 2026
4516fce
chore(deps): Bump ruby/setup-ruby from 1.310.0 to 1.311.0 in the gith…
smockle Jun 12, 2026
b96847d
chore(deps): Bump ruby/setup-ruby
dependabot[bot] Jun 15, 2026
cace382
chore(deps-dev): Bump vite from 8.0.12 to 8.0.16
dependabot[bot] Jun 15, 2026
b526fe6
Add dry_run input to file action
taarikashenafi Jun 16, 2026
045b92b
Gate side effects on dry_run in composite action
taarikashenafi Jun 16, 2026
3991556
Make file action log intended actions in dry run
taarikashenafi Jun 16, 2026
16383c2
Add dryRun tests
taarikashenafi Jun 16, 2026
f58dfc0
Document dry_run option
taarikashenafi Jun 16, 2026
0b08a20
chore(deps): Bump ruby/setup-ruby from 1.311.0 to 1.313.0 in the gith…
abdulahmad307 Jun 17, 2026
cc9c746
chore(deps-dev): Bump vite from 8.0.12 to 8.0.16 (#228)
abdulahmad307 Jun 17, 2026
2099da3
Use console.table for dry-run summary, tighten OPEN assertion
taarikashenafi Jun 17, 2026
ec1334f
Update reflow-scan text to improve clarity and reference WCAG 2.2
taarikashenafi Jun 17, 2026
546190e
Merge branch 'main' into dry-run-option
taarikashenafi Jun 18, 2026
0459d86
Update FAQ.md
taarikashenafi Jun 18, 2026
c5538c2
Refactor dry-run to else block; update in-memory issue state for accu…
taarikashenafi Jun 18, 2026
571b42c
Apply suggestions from code review
taarikashenafi Jun 18, 2026
0aa982f
Fix solutionShort hyphen in test to match plugin
taarikashenafi Jun 18, 2026
dba0765
Update reflow-scan text to improve clarity and reference WCAG 2.2 (#231)
taarikashenafi Jun 18, 2026
ce2f468
Add `dry_run` option to the accessibility scanner (#232)
taarikashenafi Jun 19, 2026
cc8e4e2
Classify Axe findings by conformance tier
kzhou314 Jun 19, 2026
a753177
Surface finding category in issue body and label
kzhou314 Jun 19, 2026
7973e5f
Add switches to skip filing best-practice and experimental issues
kzhou314 Jun 19, 2026
eedc772
Set finding category in integration test expectations
kzhou314 Jun 19, 2026
a95cc31
Address Copilot feedback on input validation and acceptance criteria
kzhou314 Jun 19, 2026
3b62b40
Trimming verbose comments
kzhou314 Jun 19, 2026
06e558d
Skip reopening issues labeled wontfix
kzhou314 Jun 20, 2026
fb48e69
Document wontfix label in README
kzhou314 Jun 20, 2026
52d65a7
Trim verbose comments
kzhou314 Jun 20, 2026
2feeb9d
Proceed with reopen when wontfix label check fails
kzhou314 Jun 20, 2026
9d668aa
Document best-practice and experimental issue inputs in README
kzhou314 Jun 20, 2026
9b4a9bd
chore(deps): Bump the github-actions group across 4 directories with …
dependabot[bot] Jun 22, 2026
a71d89a
chore(deps-dev): Bump @types/node from 25.9.0 to 26.0.0
dependabot[bot] Jun 22, 2026
f9c1c34
chore(deps-dev): Bump @types/node from 25.9.0 to 26.0.0 (#236)
JoyceZhu Jun 22, 2026
4280890
chore(deps-dev): Bump undici from 6.24.1 to 6.27.0
dependabot[bot] Jun 22, 2026
35ebacb
Add group_by option to consolidate scanner issues
taarikashenafi Jun 22, 2026
8bd371d
chore(deps-dev): Bump undici from 6.24.1 to 6.27.0 (#237)
JoyceZhu Jun 22, 2026
4b07b83
Merge branch 'main' into dependabot/github_actions/github-actions-3e2…
JoyceZhu Jun 22, 2026
c1cf4d0
Remove comments
taarikashenafi Jun 22, 2026
b464ee5
chore(deps): Bump the github-actions group across 4 directories with …
JoyceZhu Jun 22, 2026
84f022f
chore(deps): Bump concurrent-ruby in /sites/site-with-errors
dependabot[bot] Jun 22, 2026
34581d4
Merge branch 'main' into group-by-option
taarikashenafi Jun 22, 2026
edc9c3f
Match axe findings by rule and report all failing elements
kzhou314 Jun 22, 2026
d5afdd2
Trim verbose comments
kzhou314 Jun 23, 2026
e3c2f59
chore(deps): Bump concurrent-ruby from 1.3.5 to 1.3.7 in /sites/site-…
JoyceZhu Jun 23, 2026
b61d801
Apply suggestions from code review
taarikashenafi Jun 23, 2026
8997171
Address review feedback: scannerType-safe keys, GroupBy source of tru…
taarikashenafi Jun 23, 2026
37b9db9
Batch wontfix lookups into a single set check
kzhou314 Jun 24, 2026
63eef9a
Update README.md
taarikashenafi Jun 24, 2026
33d72ad
Update README.md
kzhou314 Jun 24, 2026
26c8030
Disable reopen wontfix (#234)
kzhou314 Jun 24, 2026
f898bda
Wording changes
kzhou314 Jun 24, 2026
1024857
Use GFM note alert, WCAG 2.2, and core.getBooleanInput
kzhou314 Jun 24, 2026
b41d9f0
Merge remote-tracking branch 'origin/main' into distinguish-wcag-vs-b…
kzhou314 Jun 24, 2026
ff6f4bc
Merge remote-tracking branch 'origin/main' into robust-finding-finger…
kzhou314 Jun 24, 2026
165e8cb
Merge branch 'main' of https://github.com/github/accessibility-scanne…
taarikashenafi Jun 25, 2026
8d2bbf0
Distinguish wcag vs best practice (#233)
kzhou314 Jun 25, 2026
50bc06b
Merge branch 'main' of https://github.com/github/accessibility-scanne…
taarikashenafi Jun 25, 2026
f9a77a4
Fix openIssue array signature and category tests after merge
taarikashenafi Jun 25, 2026
668bd25
Merge remote-tracking branch 'origin/main' into robust-finding-finger…
kzhou314 Jun 26, 2026
f7a85f5
Add `group_by` option to the accessibility scanner (#239)
taarikashenafi Jun 27, 2026
03e4818
Rename describeWhat to describeFinding
kzhou314 Jun 27, 2026
276cac3
Merge remote-tracking branch 'origin/main' into robust-finding-finger…
kzhou314 Jun 27, 2026
55f52f1
Match axe findings by rule and report all failing elements (#240)
kzhou314 Jun 29, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions .github/actions/auth/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion .github/actions/auth/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"playwright": "^1.60.0"
},
"devDependencies": {
"@types/node": "^25.7.0",
"@types/node": "^25.9.0",
"typescript": "^6.0.3"
}
}
27 changes: 25 additions & 2 deletions .github/actions/file/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ Files GitHub issues to track potential accessibility gaps.
**Required** Path to a JSON file containing the list of potential accessibility gaps. The path can be absolute or relative to the working directory (which defaults to `GITHUB_WORKSPACE`). For example: `findings.json`.

The file should contain a JSON array of finding objects. For example:

```json
[]
```
Expand All @@ -28,27 +29,49 @@ The file should contain a JSON array of finding objects. For example:
**Optional** Path to a JSON file containing cached filings from previous runs. The path can be absolute or relative to the working directory (which defaults to `GITHUB_WORKSPACE`). Without this, duplicate issues may be filed. For example: `cached-filings.json`.

The file should contain a JSON array of filing objects. For example:

```json
[
{
"findings": [],
"issue": {"id":1,"nodeId":"SXNzdWU6MQ==","url":"https://github.com/github/docs/issues/123","title":"Accessibility issue: 1"}
"issue": {
"id": 1,
"nodeId": "SXNzdWU6MQ==",
"url": "https://github.com/github/docs/issues/123",
"title": "Accessibility issue: 1"
}
}
]
```

#### `group_by`

**Optional** How to consolidate findings into issues. One of:

- `finding` (default): one issue per individual violation — current behavior, unchanged.
- `rule`: one issue per rule (`ruleId`/`scannerType`), aggregating every occurrence across all scanned URLs.
- `rule+url`: one issue per rule per scanned URL.

When grouping, each additional occurrence is appended to the single "umbrella" issue body as a checklist item under an **Occurrences** section rather than spawning a new issue. This is the preferred mechanism for consolidating issues over `open_grouped_issues`.

### Outputs

#### `filings_file`

Absolute path to a JSON file containing the list of issues filed (and their associated finding(s)). The action writes this file to a temporary directory and returns the absolute path. For example: `$RUNNER_TEMP/filings-<uuid>.json`.

The file will contain a JSON array of filing objects. For example:

```json
[
{
"findings": [],
"issue": {"id":1,"nodeId":"SXNzdWU6MQ==","url":"https://github.com/github/docs/issues/123","title":"Accessibility issue: 1"}
"issue": {
"id": 1,
"nodeId": "SXNzdWU6MQ==",
"url": "https://github.com/github/docs/issues/123",
"title": "Accessibility issue: 1"
}
}
]
```
40 changes: 28 additions & 12 deletions .github/actions/file/action.yml
Original file line number Diff line number Diff line change
@@ -1,38 +1,54 @@
name: "File"
description: "Files GitHub issues to track potential accessibility gaps."
name: 'File'
description: 'Files GitHub issues to track potential accessibility gaps.'

inputs:
findings_file:
description: "Path to a JSON file containing the list of potential accessibility gaps"
description: 'Path to a JSON file containing the list of potential accessibility gaps'
required: true
repository:
description: "Repository (with owner) to file issues in"
description: 'Repository (with owner) to file issues in'
required: true
token:
description: "Token with fine-grained permission 'issues: write'"
required: true
base_url:
description: "Optional base URL to pass into Octokit for the GitHub API (for example, `https://YOUR_HOSTNAME/api/v3` for GitHub Enterprise Server)"
description: 'Optional base URL to pass into Octokit for the GitHub API (for example, `https://YOUR_HOSTNAME/api/v3` for GitHub Enterprise Server)'
required: false
cached_filings_file:
description: "Path to a JSON file containing cached filings from previous runs. Without this, duplicate issues may be filed."
description: 'Path to a JSON file containing cached filings from previous runs. Without this, duplicate issues may be filed.'
required: false
screenshot_repository:
description: "Repository (with owner) where screenshots are stored on the gh-cache branch. Defaults to the 'repository' input if not set. Required if issues are open in a different repo to construct proper screenshot URLs."
required: false
open_grouped_issues:
description: "In the 'file' step, also open grouped issues which link to all issues with the same root cause"
required: false
default: "false"
default: 'false'
group_by:
description: "How to group findings into issues: 'finding' (one issue per violation, default), 'rule' (one issue per rule), or 'rule+url' (one issue per rule per scanned URL)."
required: false
default: 'finding'
dry_run:
description: 'When true, log the issues that would be filed without opening, closing, or reopening any issues.'
required: false
default: 'false'
file_best_practice_issues:
description: 'File issues for best-practice findings (accessibility recommendations that are not hard WCAG failures). Disabling only suppresses new issues; existing ones are left untouched.'
required: false
default: 'true'
file_experimental_issues:
description: 'File issues for experimental findings (checks that are not yet stable). Disabling only suppresses new issues; existing ones are left untouched.'
required: false
default: 'true'

outputs:
filings_file:
description: "Path to a JSON file containing the list of issues filed (and their associated finding(s))"
description: 'Path to a JSON file containing the list of issues filed (and their associated finding(s))'

runs:
using: "node24"
main: "bootstrap.js"
using: 'node24'
main: 'bootstrap.js'

branding:
icon: "compass"
color: "blue"
icon: 'compass'
color: 'blue'
16 changes: 8 additions & 8 deletions .github/actions/file/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion .github/actions/file/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
"@octokit/plugin-throttling": "^11.0.3"
},
"devDependencies": {
"@types/node": "^25.7.0",
"@types/node": "^25.9.0",
"typescript": "^6.0.3"
}
}
56 changes: 51 additions & 5 deletions .github/actions/file/src/generateIssueBody.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import type {Finding} from './types.d.js'

export function generateIssueBody(finding: Finding, screenshotRepo: string): string {
export function generateIssueBody(occurrences: Finding | Finding[], screenshotRepo: string): string {
const findings = Array.isArray(occurrences) ? occurrences : [occurrences]
const finding = findings[0]

const solutionLong = finding.solutionLong
?.split('\n')
.map((line: string) =>
Expand All @@ -18,21 +21,64 @@ export function generateIssueBody(finding: Finding, screenshotRepo: string): str
`
}

let occurrencesSection = ''
if (findings.length > 1) {
const items = findings.map(f => `- [ ] ${f.html ? `\`${f.html}\` on ${f.url}` : f.url}`).join('\n')
occurrencesSection = `
## ${findings.length} Other Occurrences:

${items}
`
}
Comment on lines +24 to +32

const categoryNotice =
finding.category && finding.category !== 'wcag'
? `> [!NOTE]\n> This is ${
finding.category === 'experimental' ? 'an experimental check' : 'a best-practice recommendation'
}, not a definite WCAG failure.\n\n`
: ''

const standardsLine =
finding.category && finding.category !== 'wcag'
? '- [ ] The fix MUST meet the accessibility standards specified by the repository or organization (WCAG 2.2 if applicable).'
: '- [ ] The fix MUST meet WCAG 2.2 guidelines OR the accessibility standards specified by the repository or organization.'

const acceptanceCriteria = `## Acceptance Criteria
- [ ] The specific violation reported in this issue is no longer reproducible.
- [ ] The fix MUST meet WCAG 2.1 guidelines OR the accessibility standards specified by the repository or organization.
${standardsLine}
- [ ] A test SHOULD be added to ensure this specific violation does not regress.
- [ ] This PR MUST NOT introduce any new accessibility issues or regressions.`

const body = `## What
An accessibility scan ${finding.html ? `flagged the element \`${finding.html}\`` : `found an issue on ${finding.url}`} because ${finding.problemShort}. Learn more about why this was flagged by visiting ${finding.problemUrl}.
const body = `${categoryNotice}## What
${describeFinding(finding)}

${screenshotSection ?? ''}
To fix this, ${finding.solutionShort}.
${solutionLong ? `\nSpecifically:\n\n${solutionLong}` : ''}

${occurrencesSection}
${acceptanceCriteria}
`

return body
}

function describeFinding(finding: Finding): string {
const reason = `because ${finding.problemShort}. Learn more about why this was flagged by visiting ${finding.problemUrl}.`

// Axe carries every failing element; list them all, not just the first.
if (finding.nodes && finding.nodes.length > 0) {
const count = finding.nodes.length
const subject = count === 1 ? 'an element' : `${count} elements`
const elementList = finding.nodes
.map(node => `- \`${node.html}\`${node.target ? ` (selector: \`${node.target}\`)` : ''}`)
.join('\n')
const heading = count === 1 ? 'The following element needs' : 'The following elements need'
return `An accessibility scan flagged ${subject} on ${finding.url} ${reason}\n\n${heading} attention:\n\n${elementList}`
}

if (finding.html) {
return `An accessibility scan flagged the element \`${finding.html}\` ${reason}`
}

return `An accessibility scan found an issue on ${finding.url} ${reason}`
}
7 changes: 7 additions & 0 deletions .github/actions/file/src/groupBy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export const GROUP_BY_VALUES = ['finding', 'rule', 'rule+url'] as const

export type GroupBy = (typeof GROUP_BY_VALUES)[number]

export function isGroupBy(value: string): value is GroupBy {
return (GROUP_BY_VALUES as readonly string[]).includes(value)
}
Loading