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
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5260cd4523d61cb21f04b9bc0fffca812adda3fac0506817babe794f6e802683
|
|
| MD5 |
6ad45d66bfbf7f574471c7ae791036cd
|
|
| BLAKE2b-256 |
640019ce16498c61c34ee63a7e2c899e37416b44b54f2ed34a21abb444a8b8ad
|
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6007cff22f2effbfa114d9e0f1c07542c28e77816f65fef8358a372df4abb3af
|
|
| MD5 |
ae5e7d37d8ea84a75b7b38140258704a
|
|
| BLAKE2b-256 |
06e960594e7191318fb75c375bbdf4b08f0189090e1f6c9be92c0e68fd958098
|