145 lines
4.4 KiB
Markdown
145 lines
4.4 KiB
Markdown
# AI based Accessibility Review Action
|
|
|
|
A Gitea/GitHub Action that reviews modified files against a markdown rules document using OpenAI, and outputs the review as markdown for posting as a PR comment.
|
|
|
|
The action extracts files changed in a pull request, filters them by a glob pattern, sends them along with an accessibility rules file to OpenAI for analysis, and returns the review result as an output.
|
|
|
|
## Usage
|
|
|
|
```yaml
|
|
name: Accessibility review
|
|
on:
|
|
pull_request:
|
|
paths:
|
|
- 'src/**/*.tsx'
|
|
jobs:
|
|
review:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
with:
|
|
fetch-depth: 0
|
|
- id: ai-review
|
|
uses: https://gitea.dsv.su.se/stne3960/ai-review-action@v1
|
|
with:
|
|
openai-api-key: ${{ secrets.OPENAI_API_KEY }}
|
|
rules-file: AI_REVIEW.md
|
|
file-pattern: 'src/**/*.tsx'
|
|
- name: Post review comment
|
|
uses: actions/github-script@v7
|
|
if: steps.ai-review.outputs.review != ''
|
|
env:
|
|
REVIEW: ${{ steps.ai-review.outputs.review }}
|
|
with:
|
|
script: |
|
|
const review = process.env.REVIEW;
|
|
await github.rest.issues.createComment({
|
|
issue_number: context.issue.number,
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
body: `## Accessibility Review\n\n${review}`
|
|
})
|
|
```
|
|
|
|
## Inputs
|
|
|
|
| Input | Required | Default | Description |
|
|
|-------|----------|---------|-------------|
|
|
| `openai-api-key` | Yes | - | OpenAI API key |
|
|
| `rules-file` | Yes | - | Path to the accessibility rules markdown file |
|
|
| `file-pattern` | No | `**/*.tsx` | Glob pattern for filtering changed files |
|
|
| `model` | No | `gpt-4o` | OpenAI model to use |
|
|
|
|
## Outputs
|
|
|
|
| Output | Description |
|
|
|--------|-------------|
|
|
| `review` | The accessibility review result in markdown. Empty string if no matching files were changed. |
|
|
|
|
## Rules File
|
|
|
|
The action expects a markdown file with structured requirements. Each requirement needs an ID, WCAG reference, severity, and a check description.
|
|
|
|
### Format
|
|
|
|
```markdown
|
|
# Accessibility Review Rules
|
|
|
|
## Output Format
|
|
|
|
For each requirement violation found, report using this exact structure:
|
|
|
|
VIOLATION: <REQ-ID>
|
|
FILE: <file path>
|
|
LINE: <line number or range>
|
|
SEVERITY: Critical | Major | Minor
|
|
WCAG: <SC number>
|
|
DESCRIPTION: <specific description of the violation>
|
|
FIX: <concrete suggested fix>
|
|
|
|
## Requirements
|
|
|
|
REQ-IMG-001: All `<img>` elements must have an `alt` attribute.
|
|
|
|
- WCAG: 1.1.1
|
|
- Severity: Critical
|
|
- Check: Every `<img>` has `alt`. No missing `alt` attributes.
|
|
|
|
REQ-KBD-001: All interactive elements must be operable with keyboard alone.
|
|
|
|
- WCAG: 2.1.1
|
|
- Severity: Critical
|
|
- Check: Interactive elements use `<button>`, `<a>`, `<input>`, `<select>`,
|
|
or have `tabIndex={0}` with `onKeyDown`/`onKeyUp` handlers.
|
|
|
|
REQ-FORM-002: Error messages must be programmatically associated with their input.
|
|
|
|
- WCAG: 3.3.1
|
|
- Severity: Major
|
|
- Check: Error text elements have an `id`, and the input has
|
|
`aria-describedby` pointing to that `id`.
|
|
|
|
REQ-ARIA-006: Elements with no visible label must have an accessible name.
|
|
|
|
- WCAG: 4.1.2
|
|
- Severity: Critical
|
|
- Check: Focusable elements without visible text have `aria-label`
|
|
or `aria-labelledby`.
|
|
```
|
|
|
|
### Structure
|
|
|
|
Each requirement follows this pattern:
|
|
|
|
- **ID** - Unique identifier like `REQ-IMG-001`, `REQ-KBD-001`, `REQ-FORM-002`
|
|
- **WCAG** - The success criterion number (e.g. `1.1.1`, `2.1.1`)
|
|
- **Severity** - `Critical`, `Major`, or `Minor`
|
|
- **Check** - Concrete instructions for what the AI should look for in code
|
|
|
|
The output format section tells the AI how to structure its response. The AI will use the requirement IDs and check descriptions to analyze the code.
|
|
|
|
## Secrets
|
|
|
|
Add these as repository secrets:
|
|
|
|
- **OPENAI_API_KEY** - Your OpenAI API key
|
|
|
|
## How It Works
|
|
|
|
1. Gets the list of files changed in the PR (added, changed, modified, renamed)
|
|
2. Filters files by the `file-pattern` glob
|
|
3. Reads the rules file and all matching changed files
|
|
4. Sends everything to OpenAI with instructions to check each REQ-* rule
|
|
5. Returns the review as the `review` output
|
|
|
|
The action itself does not post comments or set commit statuses. This is left to the workflow so you can customize how results are presented.
|
|
|
|
## Development
|
|
|
|
```bash
|
|
npm install
|
|
npm run build # bundles src/index.js into dist/index.js with ncc
|
|
```
|
|
|
|
The `dist/index.js` file must be committed - it is what the action runner executes.
|