PR gate
The GitHub Action that replays real incidents against a rules.yml change before it merges.
What it does
On a pull request that touches rules.yml, the action replays the last window-days (7 by default) of incidents from .brs/incidents against the PR's proposed rules and alertmanager config — the same deterministic replay engine the brs CLI uses — and posts one sticky comment with the verdict. It never pushes a commit and never changes your alerting stack; it only reports.
Workflow
on:
pull_request:
paths: ['rules.yml']
permissions:
contents: read
pull-requests: write
jobs:
pr-gate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: BurnRateSurgeon/burnratesurgeon/packages/pr-gate@v1
with:
rules-path: rules.yml
alertmanager-path: alertmanager.yml
window-days: '7'
fail-on-miss: 'true'Inputs
| Input | Default | Meaning |
|---|---|---|
rules-path | rules.yml | Prometheus recording and alerting rules to replay. |
alertmanager-path | alertmanager.yml | Routing and inhibit rules for the replay. |
history-path | .brs/incidents | Where the incident history to replay against lives in the repo. |
window-days | 7 | How many days of incident history to replay. |
fail-on-miss | true | Whether a missed incident fails the check, or only the comment reports it. |
comment | true | Whether to post/update the sticky PR comment at all. |
replay-api-url, replay-token, replay-timeout-seconds and replay-poll-seconds switch the replay from running inside the runner to queuing it against the BurnRateSurgeon API (Cloudflare Queues) and polling for the verdict — useful when a snapshot is too large for the runner's own resources.
The comment
One comment per PR, found and edited in place on every push rather than reposted — a hidden <!-- burnratesurgeon:pr-gate --> marker is how it is found again. It opens with the headline, then one row per rule:
## BurnRateSurgeon PR gate
rules.yml replayed against **42 incidents** from the last **7 days** (Aug 30 → Sep 6).
**2 of 42 incidents would have been missed.**
| Rule | Verdict |
| --- | --- |
| CheckoutErrorBudgetBurn | would have failed in 2 of the last 6 incidents |
| APILatencyBurn | caught all 12 incidents it was expected to catch |
### `CheckoutErrorBudgetBurn` — 2 misses
| Incident | Occurred at | Why it did not page |
| --- | --- | --- |
| inc_9f2a1c | 2026-09-02T03:14:00Z | never fired during the incident |
engine 1.4.0 · input checksum a1b2c3d4 · head 7e9f0ab
The gate only reports: it never pushes commits and never changes your alerting stack.A window with zero incidents still gets a comment saying nothing could be graded, rather than silence a reader could mistake for the check not having run.
Outputs
skipped, incidents, missed-incidents, failing-rules, checksum, run-id, cache-hit, comment-id — available to a later step in the same job, for example to gate a deploy on failing-rules == '0'.