Gate your pull requests on BeaverCheck scores with the GitHub Action
The beavercheck/audit-action GitHub Action lets your CI fail a pull request when your site's composite score drops, its Lighthouse performance score regresses, or new critical findings appear. It posts a PR comment with the current grade and a pass/fail breakdown of every threshold you configured.
What it is
A read-only wrapper around the public BeaverCheck v2 API. Every run does three things:
- Fetches the latest audit for a URL via
/api/v2/results?url=... - Compares the result against the thresholds you specify in your workflow
- Posts a PR comment, writes a step summary, and fails the step if any threshold is breached
The action is released separately at github.com/beavercheck/audit-action so you can pin a version with uses: beavercheck/audit-action@v1.
Why use it
- Catch regressions before merge. A PR that drops your score below a threshold fails the check, and the failure comment on the PR explains exactly which gate broke.
- Measure business impact in CI. Pair
max-monthly-costwith a staging URL and your team sees the estimated dollar cost of a regression on every PR, not just the score. - Zero setup. No API key, no service account. The action talks to the public API that doesn't require authentication.
How to use it
Minimal example
name: BeaverCheck
on:
pull_request:
branches: [main]
jobs:
audit:
runs-on: ubuntu-latest
steps:
- uses: beavercheck/audit-action@v1
with:
url: https://staging.example.com
min-composite-score: 80
This fails the step if the composite score drops below 80. The PR gets a comment with the full audit summary.
Full configuration
- uses: beavercheck/audit-action@v1
with:
url: https://staging.example.com
min-composite-score: 80
min-performance-score: 70
max-critical-findings: 0
max-monthly-cost: 100
comment-on-pr: true
update-pr-comment: true
fail-on-threshold: true
Every threshold has a disable sentinel — 0 for score/cost gates, -1 for count gates — so an unset input is a no-op. The action is safe to install and configure one gate at a time.
Consuming outputs
Every invocation exports structured outputs for downstream steps:
- uses: beavercheck/audit-action@v1
id: audit
with:
url: https://example.com
- name: Notify Slack on low score
if: steps.audit.outputs.composite-score < 70
run: |
curl -X POST "$SLACK_WEBHOOK" \
-d '{"text":"Audit score dropped to ${{ steps.audit.outputs.composite-score }}"}'
Available outputs: composite-score, composite-grade, performance-score, monthly-cost-usd, critical-findings-count, warning-findings-count, result-url, job-id, thresholds-passed.
Important constraints
The action doesn't submit new audits
The action looks up the latest audit that already exists for your URL. If you need a fresh audit on every build, pair this action with a separate job that triggers one:
jobs:
trigger-audit:
runs-on: ubuntu-latest
steps:
- name: Request a fresh audit
run: |
curl -X POST "https://beavercheck.com/submit" \
-d "url=https://staging.example.com"
audit:
needs: trigger-audit
runs-on: ubuntu-latest
steps:
- name: Wait for audit to complete
run: sleep 60
- uses: beavercheck/audit-action@v1
with:
url: https://staging.example.com
min-composite-score: 80
This is a deliberate design choice — see the DECISIONS doc for the full rationale.
Missing audits fail by default
If no audit exists for the URL, the action fails the step (with fail-on-threshold: true). This prevents a missing audit from silently passing a PR — a URL that has never been scanned is effectively ungraded. Set fail-on-threshold: false to treat it as a warning instead.
Monthly cost is estimated client-side
The action computes the monthly cost estimate client-side using the same $50/critical + $15/warning heuristic documented in our methodology. The public v2 API doesn't carry a monthly-cost field — keeping the formula in the action (rather than embedding it in the API) means we can refine the heuristic without breaking the public contract.
What happens on the PR
The PR receives a markdown comment with:
- A pass/fail headline with a check mark or X
- A summary table: composite grade, performance score, critical/warning counts, monthly cost, a live badge
- A threshold table showing each configured gate, its threshold, the actual value, and whether it passed
- A link to the full report on beavercheck.com
On subsequent runs, the existing comment updates in place (by default) rather than piling up duplicates. Turn this off with update-pr-comment: false if you prefer a running history in the thread.
Self-hosted BeaverCheck
The action accepts an api-base-url input for pointing at a self-hosted BeaverCheck instance:
- uses: beavercheck/audit-action@v1
with:
url: https://staging.example.com
api-base-url: https://beavercheck.internal.example.com
All other inputs and outputs work identically.