Skip to content

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:

  1. pacto.yaml at the repository root
  2. pacto.lock next to it — the dependency lockfile
  3. The CI workflow that runs pacto validate and pacto 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

- name: Validate contract
  run: pacto 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

- name: Check for breaking changes
  run: pacto diff oci://ghcr.io/acme/my-service-pacto .

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.