Skip to main content
Two minutes, three steps: run ctrlrun verify on every push, publish the badge JSON it writes, and point a Shields endpoint badge at the file. The badge then says what your own configuration proved, and updates itself.
1

Verify on every push

The action installs ctrlrun, runs it against your policy in a scratch store with no network, renders the job summary and the badge JSON from that one report, and fails the job if a guarantee failed. Pin the action to a release tag once you rely on it.
2

Publish the badge JSON

The action writes the badge and never publishes it: publishing needs contents: write, and asking for write access to your repository as the price of a badge is a bad trade for a tool whose subject is least privilege. So this job is yours, and the cost is visible.
Three things about that job are load-bearing: contents: write is on the job and not the workflow; it runs on a push to your default branch and never on a pull request, so a fork cannot write your badge; and it publishes the badge the verify job already produced rather than running verify a second time, so the badge and the report cannot disagree.
3

Point Shields at it

Link it to what the badge means, as above. A badge nobody can click through to is a claim without a definition.

What the badge means

The badge means the declared guarantees pass: every guarantee in the catalogue that your configuration can exercise was exercised, and none of them failed. It reads verified N/M, where M is what your configuration can exercise, not the size of the catalogue. It does not mean secure, safe, compliant, certified or audited. It says nothing about your executors, your reconcile hooks, where you put the decorator, your deployment, or whether your policy is the right policy.

What N/A means

A guarantee your configuration cannot exercise is reported not applicable, with the reason, and excluded from both sides of the fraction. A policy with no approve rule cannot exercise approval binding; one with no effect: templates cannot exercise the effect guarantees; one with no authority: section cannot exercise the authority guarantees. So a badge reading verified 6/6 on a policy with five N/As is honest, and 11/11 for the same policy would not be. Not applicable is not a pass, there is no flag that folds one into the count, and a run where nothing is applicable exits 2 and writes no badge at all. A partial run with --only writes no badge either.

If the badge does not appear

  • The badges branch has no verify-badge.json yet: the badge job runs only on a push to your default branch, so merge once.
  • Shields caches for a few minutes.
  • The badge URL and the branch the job pushes to must be the same; a mismatch is a 404 on your front page.

Next