Builds a unified deployment-readiness gate that aggregates verdicts from any combination of Pact `can-i-deploy`, oasdiff (OpenAPI), graphql-inspector (GraphQL), and `buf breaking` (Protobuf), applies severity-aware pass/fail thresholds, and emits a single go / no-go decision with per-finding rationale. Use when authoring a CI step that gates a deployment on cross-protocol contract compatibility.
75
94%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Low
Low-risk findings worth noting
Modern services rarely speak just one protocol. A single deployment might depend on Pact verifications (consumer/provider HTTP), OpenAPI compatibility for an external REST surface, GraphQL schema regressions for a public graph, and Protobuf breaking-change checks for internal gRPC. Each tool has its own exit code, its own severity levels, and its own concept of "breaking":
| Tool | Verdict surface |
|---|---|
Pact can-i-deploy | Exit 0 = yes / 1 = no (can-i-deploy) |
oasdiff breaking | Exit driven by --fail-on ERR/WARN/INFO (oasdiff-breaking) |
graphql-inspector diff | Non-zero on BREAKING; zero on DANGEROUS / NON_BREAKING (gqi-diff) |
buf breaking | Non-zero on any rule violation in active categories (buf-breaking) |
This skill defines a unified gate: collect each tool's structured output, normalize to one record shape, apply a single severity rule, emit one verdict.
$GITHUB_STEP_SUMMARY (or equivalent)
rather than four separate "❌ pact" / "❌ oasdiff" CI badges.If the project uses one protocol only, defer this gate - use the matching per-tool SKILL.md's "CI integration" section directly.
blocker / warn / info (see Severity normalization).blocker makes the verdict
no-go; warnings report but do not block by default (see The gate decision
rule).no-go exits non-zero so CI halts. The full gate script, CI wiring, and
artifact format live in
references/gate-implementation-and-ci.md.For each protocol the deployment consumes, pick the tool from the
matching plugin skill and ensure its output is captured as a CI
artifact (always with if: always() on the upload):
| Tool | Skill | Artifact |
|---|---|---|
| Pact | pact-contract-testing | can-i-deploy exit code + matrix |
| oasdiff | openapi-contract-diff | --format json array |
| GraphQL | graphql-schema-regression | grep-parsed text or JSON action |
| Protobuf | protobuf-compat-checking | --error-format json array |
Flatten every tool's per-finding output into one shape:
{
"tool": "oasdiff",
"protocol": "openapi",
"finding": "response-success-status-removed",
"severity": "blocker",
"subject": "GET /pets",
"message": "the success response status '200' was removed",
"ratchet": false,
"owner": "@api-platform"
}| Field | Source |
|---|---|
tool | pact / oasdiff / graphql-inspector / buf. |
protocol | pact / openapi / graphql / protobuf. |
finding | tool-specific rule ID (oasdiff id, graphql-inspector change type, buf rule like FIELD_NO_DELETE). |
severity | normalized - blocker / warn / info. |
subject | endpoint / type / message + field that's affected. |
message | human-readable rationale (tool's own message). |
ratchet | optional - true if grandfathered; false blocks if severity is blocker. |
owner | optional - team/handle responsible for the surface. |
| Tool | Tool severity | Normalized |
|---|---|---|
| Pact | can-i-deploy exit 1 | blocker |
| oasdiff | ERR | blocker |
| oasdiff | WARN | warn |
| oasdiff | INFO | info |
| graphql-inspector | Breaking | blocker |
| graphql-inspector | Dangerous | warn |
| graphql-inspector | Non-breaking | info |
| buf breaking | any rule under active category | blocker |
buf breaking doesn't classify by severity - every violation is
treated as a blocker. To downgrade, exclude rules in buf.yaml rather
than at the gate level (see
protobuf-compat-checking).
Pseudocode:
def gate_decision(records, *, allow_warn=True):
blockers = [
r for r in records
if r["severity"] == "blocker" and not r.get("ratchet", False)
]
warnings = [r for r in records if r["severity"] == "warn"]
return {
"verdict": "no-go" if blockers else "go",
"blocker_count": len(blockers),
"warning_count": len(warnings),
"blockers": blockers,
"warnings": warnings,
}Default behavior is strict-but-warn-tolerant: any non-ratcheted
blocker fails the gate; warnings show up in the report but don't
block. For stricter projects, set allow_warn=False.
Run the gate on one provider PR end to end. The pets-api provider opens a
release PR that (a) removes the 200 response from GET /pets in its OpenAPI
spec and (b) deletes Order.amount from orders/v1.proto. The web-app
consumer already has a Pact contract verified against production.
|| true, so a
failing tool still emits its file):
pact-broker can-i-deploy for web-app -> production exits 0 - the
consumer never read the deleted field.oasdiff breaking --format json records response-success-status-removed
on GET /pets at level ERR.buf breaking --error-format json records FIELD_NO_DELETE on
orders/v1.Order.amount.graphql-inspector diff records a Dangerous change on Pet.legacyTag.[
{"tool": "pact", "protocol": "pact", "finding": "can-i-deploy-yes", "severity": "info", "subject": "web-app -> production"},
{"tool": "oasdiff", "protocol": "openapi", "finding": "response-success-status-removed", "severity": "blocker", "subject": "GET /pets"},
{"tool": "buf", "protocol": "protobuf", "finding": "FIELD_NO_DELETE", "severity": "blocker", "subject": "orders/v1.Order.amount"},
{"tool": "graphql-inspector", "protocol": "graphql", "finding": "Dangerous", "severity": "warn", "subject": "Pet.legacyTag"}
]gate_decision finds two non-ratcheted blockers, so the verdict is
no-go (blocker_count: 2, warning_count: 1).$GITHUB_STEP_SUMMARY and exits non-zero:# Contract Compatibility Gate - verdict: NO-GO
Blockers: 2
- oasdiff :: GET /pets :: response-success-status-removed
- buf :: orders/v1.Order.amount :: FIELD_NO_DELETE
Warnings: 1
- graphql-inspector :: Pet.legacyTag :: DangerousThe deployment halts on one verdict even though can-i-deploy alone would have
passed. To ship, the provider restores the removed response and field, or marks
each finding ratchet: true with a documented migration plan. The full gate
script, CI wiring, and artifact format are in
references/gate-implementation-and-ci.md.
pact-contract-testingopenapi-contract-diffgraphql-schema-regressionprotobuf-compat-checkingdata-quality-gate and visual-baseline-gate - sibling gate skills with the same artifact shape.