Skip to content

GitHub Actions Integration

Automate contract validation, breaking-change detection and publishing in your CI/CD pipeline using the official Pacto CLI GitHub Action.


Quick start

The action is command-driven: command: setup installs the pacto binary for later run: steps, while command: validate, diff, push or doc run those operations natively.

name: Contract CI

on:
  pull_request:
    paths:
      - 'pacto.yaml'
      - 'interfaces/**'
      - 'configuration/**'
      - 'policy/**'

jobs:
  validate:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Install Pacto CLI
        uses: TrianaLab/pacto-actions@v1
        with:
          command: setup

      - name: Validate contract
        run: pacto validate .

Common workflows

The quick start already runs pacto validate . on every pull request to catch schema and cross-field errors before merge. The workflows below add breaking-change detection and publishing.

Detect breaking changes

Compare the PR contract against the published version and block breaking changes. pacto diff takes the old contract first and the new one second, and exits non-zero on a BREAKING result (see change classification rules):

      - name: Check for breaking changes
        uses: TrianaLab/pacto-actions@v1
        with:
          command: diff
          old: oci://ghcr.io/acme/my-service-pacto
          new: .
          comment-on-pr: 'true'

fail-on-breaking defaults to true, so the step blocks the merge on a breaking change and comment-on-pr posts the diff. To gate in a plain run: step instead, pacto diff oci://ghcr.io/acme/my-service-pacto . exits non-zero on the same result.

comment-on-pr posts as the workflow's GITHUB_TOKEN, which is read-only by default, so the job has to be granted the permission or the comment fails with a 403 while the diff itself passes:

jobs:
  validate:
    permissions:
      contents: read
      pull-requests: write

Publish on release

Push the contract bundle to an OCI registry when a release is created:

name: Publish Contract

on:
  release:
    types: [published]

jobs:
  push:
    runs-on: ubuntu-latest
    permissions:
      packages: write
    steps:
      - uses: actions/checkout@v4

      - name: Install Pacto CLI
        uses: TrianaLab/pacto-actions@v1
        with:
          command: setup

      - name: Push contract
        uses: TrianaLab/pacto-actions@v1
        with:
          command: push
          ref: oci://ghcr.io/${{ github.repository }}-pacto
          path: .
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

Environment-specific validation

Validate the contract with environment-specific overrides:

      - name: Validate production config
        run: pacto validate . --values values/production.yaml

Action reference

The tables below cover TrianaLab/pacto-actions@v1 (currently v1.8.2).

Inputs

Input Applies to Default What it does
command every command (required) setup, validate, diff, push or doc
version setup latest Pacto version to install (e.g. v3.2.1)
github-token every command ${{ github.token }} Passed to the command as GH_TOKEN
cache every command true Reuse the OCI bundle cache (~/.cache/pacto/oci/) across runs
path validate, push, doc . Contract directory or oci:// reference
old diff Baseline contract: directory path or oci:// reference
new diff Updated contract: directory path or oci:// reference
output-format diff text text, json or markdown
fail-on-breaking diff true Fail the step when pacto diff exits non-zero
ref push Target OCI reference (e.g. oci://ghcr.io/org/name:tag)
registry push Registry hostname to authenticate against (e.g. ghcr.io)
username push Registry username
password push Registry password or token
values validate, diff, doc, push Values file(s) merged into the contract — newline-separated, last wins
set validate, diff, doc, push Inline contract values, newline-separated (e.g. service.version=2.0.0)
old-values diff Values file(s) merged into the old contract only
old-set diff Inline values set on the old contract only
new-values diff Values file(s) merged into the new contract only
new-set diff Inline values set on the new contract only
output-path doc File path to save the generated markdown
comment-on-pr diff, doc false Post the output as a pull-request comment
add-to-summary doc true Add the documentation to the GitHub step summary

Outputs

Give the step an id to read its outputs.

Output Set by Value
version setup The exact Pacto version installed
has-breaking-changes diff "true" or "false"
diff-output diff The full diff output, in output-format
doc-output doc The generated markdown documentation

has-breaking-changes is set from the CLI exit code. pacto diff exits non-zero on a BREAKING classification, so a POTENTIAL_BREAKING result reads "false". A diff that fails to run — an unresolvable reference, an unparseable contract — also exits non-zero and so also reads "true"; check the step log before treating it as a contract verdict. The output is written whether or not fail-on-breaking stops the step, so you can gate on it yourself:

      - name: Check for breaking changes
        id: contract-diff
        uses: TrianaLab/pacto-actions@v1
        with:
          command: diff
          old: oci://ghcr.io/acme/my-service-pacto
          new: .
          fail-on-breaking: 'false'

      - name: Require an approved exception
        if: steps.contract-diff.outputs.has-breaking-changes == 'true'
        run: exit 1

Further reading

For advanced configuration options, see the pacto-actions repository.