Perimetry Cloud in your CI (GitHub Action)
Run an audit after each deployment and fail the job when the score drops or a critical finding appears: GitHub Action, GitLab CI and any other CI.
From the Solo plan, Perimetry Cloud can stop a deployment that makes your domain less safe. After each deployment, your CI runs an audit of the domain (or reads the latest one), waits for the result, and fails the job when the score falls below a minimum, when it drops since the previous audit, or when a new critical finding appears. A readable summary goes to the job page, and the result as JSON to a file.
It works with the GitHub Action, or with the perimetry-ci command in any other CI (GitLab, Bitbucket, Jenkins, CircleCI…).
The GitHub Action is available as Enigmacker/perimetry-cloud-action. For the strongest guarantee, pin it to a full commit SHA instead of @v1. The perimetry-ci command for other CI tools is not on npm yet: until then, the API alone can gate a deployment, see Any other CI.
Set it up on GitHub
- In Perimetry Cloud, open Settings, create an API key named “GitHub Actions” and tick Can start audits (leave it unticked if the job only reads the latest audit).
- In your GitHub repository, open Settings › Secrets and variables › Actions and add the key as a secret named
PERIMETRY_API_KEY. - Add a step after your deployment step, as in the example below, with your proved domain.
- name: Perimetry Cloud
uses: Enigmacker/perimetry-cloud-action@v1
with:
api-key: ${{ secrets.PERIMETRY_API_KEY }}
domain: example.com
min-score: 80
The key comes from the secret and is never printed: GitHub hides it in the logs, and the action passes it to the command through the environment only.
Options
| Input | Default | What it does |
|---|---|---|
domain |
The proved domain, or its id. | |
mode |
run |
run starts an audit and waits for it; latest reads the latest audit (a read-only key is enough). |
timeout-minutes |
15 |
How long to wait for the audit. |
min-score |
none | Fail when the score is below this value (0 to 100). |
fail-on-drop |
true |
Fail when the score is lower than at the previous audit. |
max-drop |
0 |
Points the score may lose before fail-on-drop fails. |
fail-on-new |
critical |
Fail when a new finding at or above this severity appears (critical, high, medium, low, info or none). |
fail-on-open |
none |
Fail when any open finding is at or above this severity, new or not. |
on-too-soon |
latest |
When the plan does not allow another audit on demand yet: read the latest audit, or fail. |
lang |
en |
Language of the finding titles in the summary (en or fr). |
The outputs are passed, score, grade, previous-score, score-delta, new-findings, report-url and result-file (the JSON result), for the steps that follow.
What you see
The job summary shows the score and grade, the change since the previous audit, the open findings by severity, the new findings and the most serious open ones with their fix, why the gate failed if it did, and a link to the report. Finding titles quote what your sites publish: they are shown as plain text, never as markup.
The command ends with code 0 when the gate passes, 1 when it fails, 2 for a configuration or API error (wrong key, unknown domain), and 3 when the audit did not finish in time (it goes on, and its result will be on the domain page).
GitLab CI
Add the key as a masked CI/CD variable named PERIMETRY_API_KEY, and run the API example of the next section in a job of the .post stage (image alpine with curl and jq, for example).
Any other CI
The local server and the CI command will be published on npm soon; until then, use the remote MCP endpoint or the API with curl. The API alone is enough to read the latest audit and decide (here with curl and jq, failing below 80):
score=$(curl -fsS -H "Authorization: Bearer $PERIMETRY_API_KEY" \
https://app.perimetry.cloud/api/v1/domains/example.com | jq '.domain.score')
[ "$score" -ge 80 ] || { echo "Perimetry Cloud score $score is below 80"; exit 1; }
Good to know
- Audits on demand follow the limits of your plan: one an hour per domain on Solo, and one every 15 minutes per domain through the API. With several deployments in an hour, the next jobs read the latest audit instead (or fail, with
on-too-soon: fail). - An audit takes a few minutes. Starting it after the deployment lets it see the new version of your site.
- Each call counts against the hourly limit of your plan; a job uses about ten.