Reusable GitHub Actions for PR-scoped linting and accessibility audits.
Linters run opt-in checks only on changed files. Accessibility Audits run axe-core and Lighthouse CI against deployed URLs and/or local HTML — tuned for fast, actionable feedback in pull requests.
✓ Opt-in linters ✓ Changed-files only ✓ axe-core + Lighthouse ✓ Consumer-friendly inputs ✓ MIT licensed
Quality Checks provides two reusable workflows for pull requests:
| Workflow | Reusable workflow | Purpose |
|---|---|---|
| Linters | quality-checks.yaml |
Language and config linters on the PR diff |
| Accessibility Audits | accessibility-checks.yaml |
axe-core and Lighthouse accessibility audits |
Each tool is opt-in (*_run defaults to false). Jobs no-op when nothing
relevant changed, keeping runs fast.
name: 'Quality Checks'
on: pull_request
jobs:
linters:
name: 'Linters'
uses: garretpatten/quality-checks/.github/workflows/quality-checks.yaml@master
with:
diff_base: ${{ github.event.pull_request.base.sha }}
actionlint_run: true
editorconfig_run: true
eslint_run: true
hadolint_run: true
jq_run: true
markdownlint_run: true
prettier_run: true
ruff_run: true
shellcheck_run: true
shfmt_run: true
taplo_run: true
typos_run: true
yamllint_run: true
secrets: inheritname: 'Accessibility Checks'
on: pull_request
jobs:
accessibility:
name: 'Accessibility Audits'
uses: garretpatten/quality-checks/.github/workflows/accessibility-checks.yaml@master
with:
axe_run: true
lighthouse_run: true
urls: |
https://your-preview.example.com/
local_html_paths: |
docs/index.html
lighthouse_min_accessibility: '0.9'
secrets: inheritPin a commit SHA instead of @master for supply-chain control:
uses: garretpatten/quality-checks/.github/workflows/quality-checks.yaml@<full-commit-sha>By default, workflows diff against origin/main, then origin/master, otherwise
HEAD~1. For pull requests, pin the merge base:
with:
diff_base: ${{ github.event.pull_request.base.sha }}| Parameter | Type | Default | Description |
|---|---|---|---|
diff_base |
string | (empty) | Git ref to diff against |
node_version |
string | 24 |
Node.js for ESLint, markdownlint, Prettier |
go_version |
string | stable |
Go toolchain for golangci-lint |
stylua_args |
string | --check . |
Arguments for StyLua |
stylua_version |
string | v2.4.1 |
StyLua release tag |
actionlint_run |
boolean | false |
GitHub Actions workflow linter |
editorconfig_run |
boolean | false |
EditorConfig consistency |
eslint_run |
boolean | false |
ESLint (JS/TS) |
golangci_lint_run |
boolean | false |
golangci-lint (--new-from-rev) |
hadolint_run |
boolean | false |
Dockerfile linter |
jq_run |
boolean | false |
JSON syntax validation |
markdownlint_run |
boolean | false |
Markdownlint-cli2 |
prettier_run |
boolean | false |
Prettier format check |
ruff_run |
boolean | false |
Ruff (Python) |
shellcheck_run |
boolean | false |
ShellCheck |
shfmt_run |
boolean | false |
shfmt shell formatting |
stylua_run |
boolean | false |
StyLua (Lua) |
taplo_run |
boolean | false |
Taplo (TOML) |
typos_run |
boolean | false |
typos spell checker |
typos_config |
string | (empty) | Path to typos.toml (auto-detected if empty) |
yamllint_run |
boolean | false |
Yamllint |
| Parameter | Type | Default | Description |
|---|---|---|---|
diff_base |
string | (empty) | Git ref for changed .html detection |
node_version |
string | 24 |
Node.js for axe-core CLI |
axe_run |
boolean | false |
Run axe-core audits |
lighthouse_run |
boolean | false |
Run Lighthouse CI (accessibility category) |
urls |
string | (empty) | URLs to audit (one per line; required for Lighthouse) |
local_html_paths |
string | (empty) | Extra repo HTML paths served locally for axe |
lighthouse_min_accessibility |
string | 0.9 |
Minimum Lighthouse accessibility score (0–1) |
static_server_port |
string | 8765 |
Port for local HTML serving |
If the consumer repo already has lighthouserc.json or lighthouserc.js, that
config is used instead of the generated accessibility-only defaults.
| Tool | Files | Notes |
|---|---|---|
| Actionlint | .github/workflows, .github/actions |
GitHub Actions-specific rules |
| EditorConfig | Changed text files | Uses ec; respects .editorconfig |
| ESLint | .js, .jsx, .ts, .tsx |
Installs npm ci when package.json exists |
| golangci-lint | Go packages | --new-from-rev on PR diff |
| Hadolint | Dockerfile, *.dockerfile |
Dockerfile best practices |
| jq | .json |
Syntax validation (jq -e) |
| Markdownlint | .md, .markdown |
markdownlint-cli2 |
| Prettier | JS/TS, JSON, CSS, MD | Format check; honors .prettierignore (not YAML) |
| Ruff | .py, .pyw |
Python lint |
| ShellCheck | .sh, .bash, .zsh |
Shell analysis (runner image binary) |
| shfmt | .sh, .bash, .zsh |
Shell formatting (-d) |
| StyLua | Lua (via stylua_args) |
Whole-tree or path-scoped |
| Taplo | .toml |
TOML lint |
| typos | .md, .txt, .rst, .html, … |
Prose spell check; uses your repo’s typos.toml |
| Yamllint | .yml, .yaml |
General YAML lint |
When typos_run: true, the job checks out your repository and runs typos from
its root. Your typos.toml (or _typos.toml / .typos.toml) is loaded automatically
so you can allow names, product terms, and other valid words:
[default.extend-words]
Patten = "Patten"
MyProduct = "MyProduct"Copy docs/typos.toml.example as a starting point. For a
config file outside the root, pass typos_config: path/to/typos.toml in the workflow
with: block.
- jq validates JSON syntax; Prettier enforces formatting — enable both for JSON-heavy repos.
- Markdownlint enforces Markdown style; Prettier formats Markdown — complementary.
- Yamllint owns YAML formatting and lint; Prettier does not format
.yml/.yamlin this workflow (they conflict on quote style and wrapping). - Actionlint targets GitHub Actions semantics; Yamllint covers all YAML — use both for workflows.
- ShellCheck finds shell bugs; shfmt enforces layout — complementary.
Tools that duplicate Ruff/ESLint/Prettier for the same languages (e.g. Flake8, Black,
Biome-as-full-replacement) or need heavy language SDKs (RuboCop, Clippy, terraform validate)
are out of scope so the workflow stays maintainable. Open an issue if you need a
narrow, high-signal addition.
| Job | Tool | When to use |
|---|---|---|
| axe-core | @axe-core/cli | WCAG checks; CI syncs ChromeDriver via browser-driver-manager |
| Lighthouse | Lighthouse CI | Accessibility category score gate on deployed URLs |
- Static site / docs: set
axe_run: trueand rely on changed.htmlplus optionallocal_html_paths. - Web app with preview: pass the preview URL in
urlsfor both axe and Lighthouse. - Production smoke:
urlsonly, on a schedule or after deploy (call the reusable workflow fromworkflow_dispatchordeployment_status).
- Security Guardrails — companion repo for SAST, secrets, and supply-chain checks.
See CONTRIBUTING.md. Security reports: SECURITY.md. Conduct: CODE_OF_CONDUCT.md.
MIT — Copyright (c) 2025 Garret Patten