CI integration¶
Add two steps to your CI so a pull request that breaks your contract fails its checks: validate the contract, then compare it with the version you published. pacto diff exits non-zero when the change is breaking. Your branch protection rules turn that failed check into a blocked merge.
What to commit¶
Put three things in your repository:
pacto.yamlat the repository rootpacto.locknext to it — the dependency lockfile- The CI workflow that runs
pacto validateandpacto diff
pacto lock . writes the lockfile: it looks up every dependency and records its exact digest (a content hash). Commit it so every build uses the same dependency versions. Commit the interface files (interfaces/openapi.yaml, configuration schemas) too.
The two steps¶
Step 1: Validate¶
This catches missing or malformed fields, fields that contradict each other and policy failures. Add --readiness to gate on readiness scores; without it, validation ignores the readiness: block.
Step 2: Diff against the published version¶
pacto diff exits 1 when the classification is BREAKING. The first argument is the baseline, the second is the updated contract. For a local diff with no registry, compare two directories: pacto diff ./main ./feature-branch.
Exit codes and what blocks a merge¶
pacto diff exits 1 on a breaking change, so the CI step fails and the pull request shows a failing check. Pacto stops there. Your repository's branch protection rules decide whether a failing check blocks the merge.
A BREAKING classification means the new version is incompatible with consumers pinned to the old major. Release it as a new major (1.4.2 → 2.0.0) so consumers can choose when to move.
Handling exceptions¶
Sometimes a breaking change is unavoidable. Branch protection lets you merge a failing check with override permission. Document the reason (in the PR description, a comment or an ADR), then merge. Do not change pactoVersion or remove fields to dodge the gate.
Publishing the contract¶
After the PR merges, publish to your OCI registry:
- name: Push contract
run: pacto push oci://ghcr.io/acme/my-service-pacto -p .
env:
PACTO_REGISTRY_TOKEN: ${{ secrets.GITHUB_TOKEN }}
pacto push tags the bundle with service.version. If that tag exists, the command skips the push unless you pass --force.
GitHub Actions¶
The GitHub Actions integration wraps these steps in a reusable action. Use command: validate and command: diff instead of writing run: steps, and the action handles installation, caching and PR comments for you.
For other CI systems (GitLab CI, Jenkins, CircleCI), install the CLI with the installer script and call the commands directly as shown above.