How-to guidesCatch breaking changes in CI
Catch breaking changes in CI
A breaking change is one that makes a working client fail: a removed operation, a new required
parameter, a response field that went away. This guide makes apigenie diff stop such changes in
pull requests, shows how to remove things without breaking anyone, and builds a changelog from the
history of the file. It uses an OpenAPI file, openapi.yaml; Swagger 2.0, AsyncAPI, Protobuf and
GraphQL files are compared the same way, each by what its clients depend on.
You need the CLI installed; the Quickstart shows how.
Compare two versions
apigenie diff takes the version clients use today and the new one:
git show main:openapi.yaml > main.yaml
apigenie diff main.yaml openapi.yaml
Every change is rated breaking, non-breaking or non-functional (a description, an
example). The command exits with status 1 when any change is breaking, so a script or a CI job can
stop there. --report picks what it prints: changelog (the default), status (one word) or
detailed (every property that changed); --formatter writes it as JSON, Markdown, HTML or a
format editors understand.
Both files must be of the same standard. Here is the report for two versions of a Protobuf file:
shop.proto
19 1 breaking Modified message 'Customer'
19 1 non-breaking Removed field 'fax'
25 3 breaking Modified field 'full_name'
25 3 breaking Modified field name
Check every pull request
The GitHub Action compares each file with its version at the base of the pull request and shows the changes as annotations:
on: pull_request
jobs:
api:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: mykulyak/api-genie-action@v0
with:
command: diff
files: api/openapi.yaml
The step fails on breaking changes. Set base to compare with another branch or tag, such as the
last release, and fail-on: never to report without failing.
A failing step only blocks the merge once the check is required. In the repository’s settings,
under Branches, add a branch protection rule for the base branch (or a ruleset under Rules),
turn on Require status checks to pass before merging and pick the api job. From then on a pull
request with a breaking change waits until the change is withdrawn, or its severity is
reconsidered.
Decide what breaks your clients
The recommended rules fit most APIs. When yours differ, change them in apigenie.yaml: each
property of each kind of node takes a severity (breaking, non_breaking, non_functional or
none), or one each for add, remove and modify. List recommended in extends to change only
some of its rules:
version: '1.0'
commands:
diff:
extends: [recommended]
rules:
operation:
tags: none
The diff configuration lists the node types and their properties, and how to set different rules for requests and responses.
Retire an operation on a schedule
Removing an operation is breaking, unless clients were told in advance. Deprecate it with a sunset date first, and ship that: deprecating is not breaking.
paths:
/v1/orders:
get:
deprecated: true
x-sunset: 2027-01-31
Once the date has passed, the recommended rules treat the removal as non-breaking, and the same CI
job lets it through. --today sets the date of the comparison, to try it out before then.
For changes bigger than one operation, apigenie evolve plan does the planning. It takes the
document clients use and the one you want, and writes an expand wave (the new shape next to the old
one, deprecated, safe to ship now) and a contract wave (the target, to ship after the sunset):
apigenie evolve plan main.yaml openapi.yaml --out evolve-out/
evolve is experimental; see
evolve for its recipes.
Set the version and keep a changelog
--update-version writes the smallest info.version the changes allow, a new major version for
breaking changes, minor for non-breaking and patch for non-functional ones, and keeps the rest of the
file as it is:
apigenie diff main.yaml openapi.yaml --update-version
apigenie changelog compares the committed versions of a file and describes what changed for
clients, per commit or per release tag:
apigenie changelog openapi.yaml --revisions tags --tag-pattern 'v*' --unreleased
Next steps
- diff: every option, the rules of each standard and the JSON report.
- changelog: revisions, tags and output formats.
- Publish API documentation: the changelog of each API on its documentation site.