Skip to content

Commit 08a31b1

Browse files
Merge main into v2 for release (#170)
Per the [docs](https://github.com/github/accessibility/blob/main/docs/accessibility-scanner-maintainers-guide.md#publishing-new-versions), we need to make sure v2 is up-to-date so it can have the latest features. > If tests pass, open a PR that merges main into v2 (to ensure v2 always includes the latest 2.x code). Once approved with passing checks, merge. (base: v2 -> compare: main) both tests have passed: - [scorecard](https://github.com/github/accessibility-scorecard/actions/runs/23203836900) - [sandbox](https://github.com/github/accessibility-sandbox/actions/runs/23202066711)
2 parents fa76cfe + 28ba71e commit 08a31b1

31 files changed

+794
-255
lines changed

.github/actions/auth/package-lock.json

Lines changed: 7 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.github/actions/auth/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
"playwright": "^1.58.2"
1818
},
1919
"devDependencies": {
20-
"@types/node": "^25.3.3",
20+
"@types/node": "^25.4.0",
2121
"typescript": "^5.9.3"
2222
}
2323
}

.github/actions/file/action.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@ inputs:
1717
screenshot_repository:
1818
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."
1919
required: false
20+
open_grouped_issues:
21+
description: "In the 'file' step, also open grouped issues which link to all issues with the same root cause"
22+
required: false
23+
default: "false"
2024

2125
outputs:
2226
filings:

.github/actions/file/package-lock.json

Lines changed: 7 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.github/actions/file/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
"@octokit/plugin-throttling": "^11.0.3"
1919
},
2020
"devDependencies": {
21-
"@types/node": "^25.3.3",
21+
"@types/node": "^25.4.0",
2222
"typescript": "^5.9.3"
2323
}
2424
}

.github/actions/file/src/index.ts

Lines changed: 49 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type {Finding, ResolvedFiling, RepeatedFiling} from './types.d.js'
1+
import type {Finding, ResolvedFiling, RepeatedFiling, FindingGroupIssue, Filing, IssueResponse} from './types.d.js'
22
import process from 'node:process'
33
import * as core from '@actions/core'
44
import {Octokit} from '@octokit/core'
@@ -11,6 +11,7 @@ import {isResolvedFiling} from './isResolvedFiling.js'
1111
import {openIssue} from './openIssue.js'
1212
import {reopenIssue} from './reopenIssue.js'
1313
import {updateFilingsWithNewFindings} from './updateFilingsWithNewFindings.js'
14+
import {OctokitResponse} from '@octokit/types'
1415
const OctokitWithThrottling = Octokit.plugin(throttling)
1516

1617
export default async function () {
@@ -22,10 +23,12 @@ export default async function () {
2223
const cachedFilings: (ResolvedFiling | RepeatedFiling)[] = JSON.parse(
2324
core.getInput('cached_filings', {required: false}) || '[]',
2425
)
26+
const shouldOpenGroupedIssues = core.getBooleanInput('open_grouped_issues')
2527
core.debug(`Input: 'findings: ${JSON.stringify(findings)}'`)
2628
core.debug(`Input: 'repository: ${repoWithOwner}'`)
2729
core.debug(`Input: 'screenshot_repository: ${screenshotRepo}'`)
2830
core.debug(`Input: 'cached_filings: ${JSON.stringify(cachedFilings)}'`)
31+
core.debug(`Input: 'open_grouped_issues: ${shouldOpenGroupedIssues}'`)
2932

3033
const octokit = new OctokitWithThrottling({
3134
auth: token,
@@ -48,8 +51,12 @@ export default async function () {
4851
})
4952
const filings = updateFilingsWithNewFindings(cachedFilings, findings)
5053

54+
// Track new issues for grouping
55+
const newIssuesByProblemShort: Record<string, FindingGroupIssue[]> = {}
56+
const trackingIssueUrls: Record<string, string> = {}
57+
5158
for (const filing of filings) {
52-
let response
59+
let response: OctokitResponse<IssueResponse> | undefined
5360
try {
5461
if (isResolvedFiling(filing)) {
5562
// Close the filing’s issue (if necessary)
@@ -58,8 +65,19 @@ export default async function () {
5865
} else if (isNewFiling(filing)) {
5966
// Open a new issue for the filing
6067
response = await openIssue(octokit, repoWithOwner, filing.findings[0], screenshotRepo)
61-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
62-
;(filing as any).issue = {state: 'open'} as Issue
68+
;(filing as Filing).issue = {state: 'open'} as Issue
69+
70+
// Track for grouping
71+
if (shouldOpenGroupedIssues) {
72+
const problemShort: string = filing.findings[0].problemShort
73+
if (!newIssuesByProblemShort[problemShort]) {
74+
newIssuesByProblemShort[problemShort] = []
75+
}
76+
newIssuesByProblemShort[problemShort].push({
77+
url: response.data.html_url,
78+
id: response.data.number,
79+
})
80+
}
6381
} else if (isRepeatedFiling(filing)) {
6482
// Reopen the filing's issue (if necessary) and update the body with the latest finding
6583
response = await reopenIssue(
@@ -82,11 +100,37 @@ export default async function () {
82100
)
83101
}
84102
} catch (error) {
85-
core.setFailed(`Failed on filing: ${filing}\n${error}`)
103+
core.setFailed(`Failed on filing: ${JSON.stringify(filing, null, 2)}\n${error}`)
86104
process.exit(1)
87105
}
88106
}
89107

108+
// Open tracking issues for groups with >1 new issue and link back from each
109+
// new issue
110+
if (shouldOpenGroupedIssues) {
111+
for (const [problemShort, issues] of Object.entries(newIssuesByProblemShort)) {
112+
if (issues.length > 1) {
113+
const capitalizedProblemShort = problemShort[0].toUpperCase() + problemShort.slice(1)
114+
const title: string = `${capitalizedProblemShort} issues`
115+
const body: string =
116+
`# ${capitalizedProblemShort} issues\n\n` + issues.map(issue => `- [ ] ${issue.url}`).join('\n')
117+
try {
118+
const trackingResponse = await octokit.request(`POST /repos/${repoWithOwner}/issues`, {
119+
owner: repoWithOwner.split('/')[0],
120+
repo: repoWithOwner.split('/')[1],
121+
title,
122+
body,
123+
})
124+
const trackingUrl: string = trackingResponse.data.html_url
125+
trackingIssueUrls[problemShort] = trackingUrl
126+
core.info(`Opened tracking issue for '${capitalizedProblemShort}' with ${issues.length} issues.`)
127+
} catch (error) {
128+
core.warning(`Failed to open tracking issue for '${capitalizedProblemShort}': ${error}`)
129+
}
130+
}
131+
}
132+
}
133+
90134
core.setOutput('filings', JSON.stringify(filings))
91135
core.debug(`Output: 'filings: ${JSON.stringify(filings)}'`)
92136
core.info("Finished 'file' action")

.github/actions/file/src/types.d.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,14 @@ export type Issue = {
1818
state?: 'open' | 'reopened' | 'closed'
1919
}
2020

21+
export type IssueResponse = {
22+
id: number
23+
node_id: string
24+
number: number
25+
html_url: string
26+
title: string
27+
}
28+
2129
export type ResolvedFiling = {
2230
findings: never[]
2331
issue: Issue
@@ -34,3 +42,8 @@ export type RepeatedFiling = {
3442
}
3543

3644
export type Filing = ResolvedFiling | NewFiling | RepeatedFiling
45+
46+
export type FindingGroupIssue = {
47+
url: string
48+
id: number
49+
}

.github/actions/find/README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,14 @@ configuration option.
3131
[`colorScheme`](https://playwright.dev/docs/api/class-browser#browser-new-context-option-color-scheme)
3232
configuration option.
3333

34+
#### `include_screenshots`
35+
36+
**Optional** Bool - whether to capture screenshots of scanned pages and include links to them in the issue
37+
38+
#### `scans`
39+
40+
**Optional** Stringified JSON array of scans (string) to perform. If not provided, only Axe will be performed.
41+
3442
### Outputs
3543

3644
#### `findings`

.github/actions/find/action.yml

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,36 @@
1-
name: "Find"
2-
description: "Finds potential accessibility gaps."
1+
name: 'Find'
2+
description: 'Finds potential accessibility gaps.'
33

44
inputs:
55
urls:
6-
description: "Newline-delimited list of URLs to check for accessibility issues"
6+
description: 'Newline-delimited list of URLs to check for accessibility issues'
77
required: true
88
multiline: true
99
auth_context:
1010
description: "Stringified JSON object containing 'username', 'password', 'cookies', and/or 'localStorage' from an authenticated session"
1111
required: false
1212
include_screenshots:
13-
description: "Whether to capture screenshots of scanned pages and include links to them in the issue"
13+
description: 'Whether to capture screenshots of scanned pages and include links to them in the issue'
14+
required: false
15+
default: 'false'
16+
scans:
17+
description: 'Stringified JSON array of scans to perform. If not provided, only Axe will be performed'
1418
required: false
15-
default: "false"
1619
reduced_motion:
17-
description: "Playwright reducedMotion setting: https://playwright.dev/docs/api/class-browser#browser-new-page-option-reduced-motion"
20+
description: 'Playwright reducedMotion setting: https://playwright.dev/docs/api/class-browser#browser-new-page-option-reduced-motion'
1821
required: false
1922
color_scheme:
20-
description: "Playwright colorScheme setting: https://playwright.dev/docs/api/class-browser#browser-new-context-option-color-scheme"
23+
description: 'Playwright colorScheme setting: https://playwright.dev/docs/api/class-browser#browser-new-context-option-color-scheme'
2124
required: false
2225

2326
outputs:
2427
findings:
25-
description: "List of potential accessibility gaps, as stringified JSON"
28+
description: 'List of potential accessibility gaps, as stringified JSON'
2629

2730
runs:
28-
using: "node24"
29-
main: "bootstrap.js"
31+
using: 'node24'
32+
main: 'bootstrap.js'
3033

3134
branding:
32-
icon: "compass"
33-
color: "blue"
35+
icon: 'compass'
36+
color: 'blue'

.github/actions/find/package-lock.json

Lines changed: 7 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)