Skip to main content

An OpenAPI breaking-change detector that knows which downstream consumers will actually break.

Project description

PactWatch

Your microservices have a contract. PactWatch enforces it before merge.

An OpenAPI breaking-change detector that knows which downstream consumers will actually break. Most API diff tools tell you what changed. PactWatch tells you who cares.

The Problem

Team A changes their API. Team B's mobile app breaks in production. The spec diff showed "field removed" — but nobody connected it to Team B.

PactWatch maintains a service-to-consumer graph (pactwatch.yaml). When a producer's spec changes, it classifies each change as BREAKING, RISKY, or SAFE, then filters the results per consumer. Same spec change, different verdict per team.

How It Works

1. Diff    — structurally compare two OpenAPI 3.x specs
2. Classify — label each change: BREAKING / RISKY / SAFE
3. Filter  — check the consumer graph: who uses the affected endpoints?

Installation

pip install pactwatch

Quick Start

Raw diff (Phase 1)

Compare two specs and get classified changes:

# Rich terminal output
pactwatch diff old-spec.yaml new-spec.yaml

# JSON for CI
pactwatch diff old-spec.yaml new-spec.yaml --format json

Per-consumer impact (Phase 2)

Define your service topology in pactwatch.yaml:

version: 1
producers:
  api:
    spec: ./services/api/openapi.yaml

consumers:
  mobile-app:
    consumes:
      - producer: api
        endpoints:
          - GET /users/{id}
          - POST /orders
  web-dashboard:
    consumes:
      - producer: api
        endpoints:
          - GET /users/{id}
          - GET /admin/*

Then check per-consumer impact:

# Check all consumers
pactwatch check -c pactwatch.yaml -p api --old old.yaml --new new.yaml

# Check a single consumer
pactwatch check -c pactwatch.yaml -p api --old old.yaml --new new.yaml --consumer mobile-app

# JSON for CI
pactwatch check -c pactwatch.yaml -p api --old old.yaml --new new.yaml -f json

GitHub Action (Phase 3)

Add to your workflow:

name: API Contract Check
on: pull_request

jobs:
  pactwatch:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - uses: pyjeebz/pactwatch@v1
        with:
          config: pactwatch.yaml
          producer: api
          old-spec: services/api/openapi.yaml  # from base branch
          new-spec: services/api/openapi.yaml  # from PR branch
          github-token: ${{ secrets.GITHUB_TOKEN }}

PactWatch will:

  • Post a PR comment showing per-consumer impact
  • Set a commit status check (pass/fail)
  • Exit with code 1 if breaking changes affect any consumer

Classification Rules

Breaking

Change Why
Endpoint removed Consumers calling it will get 404s
Required response field removed Consumers parsing it will crash
Response field type changed Consumers deserializing it will get wrong types
New required request field Existing client code won't send it
Status code removed Consumers handling it will get unexpected responses
Auth scheme changed Existing tokens/keys will stop working

Risky

Change Why
Optional field made required Consumers not sending it may start failing
Field made nullable Consumers not handling null may crash
Enum value removed Consumers matching on it will miss cases

Safe

Change Why
New endpoint Existing consumers unaffected
New optional request field Old clients just don't send it
New response field Old clients ignore extra fields
New enum value Old clients still see their known values
Documentation changes No runtime impact

CLI Reference

pactwatch diff

pactwatch diff OLD NEW [--format text|json]

Compare two OpenAPI specs. Exits with code 1 if BREAKING changes found.

pactwatch check

pactwatch check --config PATH --producer NAME --old PATH --new PATH
                [--consumer NAME] [--format text|json]

Check per-consumer impact using the consumer graph. Exits with code 1 if any consumer has BREAKING changes.

Exit Codes

Code Meaning
0 No breaking changes
1 Breaking changes detected
2 Input error (bad spec, bad config, unknown producer)

Demo

See the demo monorepo for a working example with 3 services.

# Run the demo
pactwatch check \
  -c examples/demo-monorepo/pactwatch.yaml \
  -p user-api \
  --old examples/demo-monorepo/services/producer-api/openapi.yaml \
  --new examples/demo-monorepo/services/producer-api/openapi-breaking.yaml

License

Apache 2.0

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pactwatch-0.1.0.tar.gz (30.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pactwatch-0.1.0-py3-none-any.whl (25.8 kB view details)

Uploaded Python 3

File details

Details for the file pactwatch-0.1.0.tar.gz.

File metadata

  • Download URL: pactwatch-0.1.0.tar.gz
  • Upload date:
  • Size: 30.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.7

File hashes

Hashes for pactwatch-0.1.0.tar.gz
Algorithm Hash digest
SHA256 5260cd4523d61cb21f04b9bc0fffca812adda3fac0506817babe794f6e802683
MD5 6ad45d66bfbf7f574471c7ae791036cd
BLAKE2b-256 640019ce16498c61c34ee63a7e2c899e37416b44b54f2ed34a21abb444a8b8ad

See more details on using hashes here.

File details

Details for the file pactwatch-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: pactwatch-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 25.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.7

File hashes

Hashes for pactwatch-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 6007cff22f2effbfa114d9e0f1c07542c28e77816f65fef8358a372df4abb3af
MD5 ae5e7d37d8ea84a75b7b38140258704a
BLAKE2b-256 06e960594e7191318fb75c375bbdf4b08f0189090e1f6c9be92c0e68fd958098

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page