Running the audit in CI for a year had produced a report; making it fail the merge produced a decision.
- run: composer audit --locked --format=json > audit.json
- run: |
high=$(jq '[.advisories[][] |
select(.severity=="high" or .severity=="critical")] | length' audit.json)
[ "$high" -eq 0 ] || {
echo "::error::$high high or critical advisories"
exit 1
}
Failing only on high and critical is what makes this survivable — a gate that fails on every advisory is a gate that gets disabled during the first release week. The three times it has fired, two were a patch bump and one was a package with no fix, which needed an ignore entry with a review date rather than a lowered threshold.