Setup & usage¶
Brimyr gates a pull request on two things: patch coverage (always) and net-new
quality findings (opt-in). It runs your tests on the runner, so the test toolchain
and dependencies must be present before the gate runs. Install them in a setup step (reusable
workflow) or your own steps (composite action), or skip the run entirely by
feeding a pre-made coverage report via coverage_file.
1. Composite action¶
# .github/workflows/coverage.yml
name: Coverage
on:
pull_request:
push:
branches: [main]
permissions:
contents: read
pull-requests: write # only needed for the PR comment
jobs:
coverage:
runs-on: ubuntu-latest
steps:
# Check out FIRST: the deps install below needs a populated workspace, so
# the action's own checkout would be too late.
- uses: actions/checkout@v6
with: { fetch-depth: 0 }
- run: pip install -e '.[test]' # install your test deps first
- uses: magmamoose/brimyr@v1
with:
checkout: 'false' # already checked out above
threshold: '80'
pr_comment: 'true'
# sonar_url: https://sonar.example.com
# sonar_token: ${{ secrets.SONAR_TOKEN }}
On pull requests it runs your tests with coverage, gates on patch coverage, and ships
to SonarQube when sonar_url is set. On a push to the default branch it runs a
non-gating baseline that still feeds the trend.
If Brimyr is your only step, drop both the checkout and checkout: 'false': the action
checks out with fetch-depth: 0 by default, which is what patch coverage needs. Any
step that touches the workspace first needs the explicit checkout, because the action's
own would run too late.
Every input and output is in the Action reference.
Wire it on
pull_request, notpull_request_target. Brimyr runs the PR's own test code on the runner.pull_request_targetruns that code with the base repo's write token and secrets in scope, so a malicious fork could exfiltrate them, exactly the privilege a gate that runs the PR's tests doesn't need. Both events gate if Brimyr sees them, butpull_requestis the safe default; only reach forpull_request_targetif you fully control who can open PRs.
2. pre-push hook¶
# .pre-commit-config.yaml
repos:
- repo: https://github.com/MagmaMoose/brimyr
rev: v1.0.0
hooks:
- id: brimyr
pre-commit install --hook-type pre-push
git push # runs the tests + patch-coverage gate against the default branch
It runs at pre-push (not pre-commit): patch coverage means running the test suite, too heavy for every commit but fine before a push.
Ingesting a pre-made report (escape hatch)¶
If your CI already produces a coverage file, point Brimyr at it instead of letting it run the tests:
- uses: magmamoose/brimyr@v1
with:
coverage_file: coverage.xml # or coverage/lcov.info, comma-separated
checkout: 'false'
Format is inferred from the extension (.xml → Cobertura, .info/.lcov → lcov);
append :lcov / :cobertura to force it.
SonarQube¶
Optional and non-blocking:
- uses: magmamoose/brimyr@v1
with:
sonar_url: https://sonarqube.example.com
sonar_token: ${{ secrets.SONAR_TOKEN }}
sonar_project_key: my-service
The action installs a scanner for you and points it at the coverage files it just
produced. A Sonar failure never fails the gate: it becomes a ::warning:: and the
run continues. The token travels in SONAR_TOKEN, never on the command line.
.NET is the exception, and Brimyr handles it automatically: the CLI scanner can't
analyse C# at all, so dotnet sonarscanner wraps the build instead of following it.
Java needs sonar_args: '-Dsonar.java.binaries=...' or the analysis is skipped with a
warning. Both are covered in SonarQube.
Quality findings¶
Off by default. Turn it on and the action runs Chargate as a nested step and folds the net-new findings into the same summary and the same comment as coverage:
- uses: magmamoose/brimyr@v1
with:
quality: 'true'
# quality_fail_on: 'error' # leave unset to stay report-only
It needs Docker on the runner. quality_fail_on defaults to none, so the half
ships report-only: findings are counted and shown, nothing blocks. Measure a release
cycle before picking a level — the failure mode here is abandonment, not error.
The threshold speaks SARIF levels (note, warning, error, any), not Chargate's
severity bands. Full detail, and why, in Quality findings.
Local development¶
uv sync # install deps + dev tools
uv run pytest -q # run the test suite
uv run ruff check . # lint
uv run ruff format --check . # format check (CI gate)
(If uv is not on PATH, python -m uv ... works after pip install uv.)
Building these docs¶
uv run --group docs mkdocs serve # live preview at http://127.0.0.1:8000
uv run --group docs mkdocs build # render to ./site (gitignored)
The docs dependency group (mkdocs-material) is non-default, so uv sync and CI
are unaffected until you opt in with --group docs.
PR comment¶
Brimyr can post one consolidated comment on the pull request. It carries the coverage verdict — the percentage, the threshold, and the changed lines the tests never executed — and, when the quality half is on, the net-new findings beneath it, under a second heading in the same comment. It is updated in place on every push rather than stacked, so a long-running PR keeps exactly one comment.
permissions:
contents: read
pull-requests: write # ← required; the default `read` cannot comment
# ...
- uses: magmamoose/brimyr@v1
with:
pr_comment: 'true'
# github_token defaults to the job token (comments as github-actions[bot])
Add token_broker_url, plus id-token: write on the job, and the comment is
authored by Brimyr[bot] instead of the shared github-actions[bot]:
permissions:
contents: read
pull-requests: write
id-token: write # ← required to mint the Brimyr[bot] identity
# ...
with:
pr_comment: 'true'
token_broker_url: https://broker-brimyr.magmamoose.com
Commenting is non-blocking: a missing token, a 403, or a network failure is reported on stderr and never changes the gate verdict, the same contract the SonarQube step follows. The broker is non-blocking too, and silently so: any problem with it costs the byline and nothing else.
Both pr_comment and token_broker_url are inputs of the composite action;
the reusable workflow does not forward them today. See
PR comment for what both blocks look like, how the two
comment markers work, and the full list of broker failure messages.