Enforce Protobuf Field Compatibility in CI
Catch wire-incompatible schema changes by comparing the new descriptor against the released one and failing the build on removed or renumbered fields.
Task
Add an automated compatibility check for protobuf changes before release.
When to use this
A developer reuses a deleted field number, and old clients decode the new value as a different field, silently corrupting data.
Prerequisites
- A base revision of the .proto files to compare against
- A descriptor-comparison tool in CI
Steps
1. Store the released descriptor set as the comparison baseline.
Expected output: CI has a reference to diff against.
2. Run a breaking-change check between the baseline and the working tree.
Expected output: Incompatible changes fail the pipeline.
3. Block removal, renumbering, and type changes of existing fields; allow additions.
buf breaking --against prev.bin .Expected output: Compatible evolution is permitted, unsafe changes are not.
4. Publish an updated baseline only after a reviewed, coordinated migration.
Expected output: The baseline never advances silently.
Troubleshooting
Problem
False positives on intentional breaks
Solution
Use a reviewed allowlist entry with an expiration so legitimate breaks are explicit and temporary.
Problem
Baseline drifts from production
Solution
Generate the baseline from the artifact actually shipped, not from an arbitrary branch.
Limitations
- The check covers wire compatibility only, not semantic compatibility of field meaning.
- It cannot detect a rename that keeps the number but changes intent, which still needs human review.
Context
Add an automated compatibility check for protobuf changes before release. A developer reuses a deleted field number, and old clients decode the new value as a different field, silently corrupting data.
Steps
- Store the released descriptor set as the comparison baseline. Expected: CI has a reference to diff against.
- Run a breaking-change check between the baseline and the working tree. Expected: Incompatible changes fail the pipeline.
- Block removal, renumbering, and type changes of existing fields; allow additions. Expected: Compatible evolution is permitted, unsafe changes are not.
- Publish an updated baseline only after a reviewed, coordinated migration. Expected: The baseline never advances silently.
buf breaking --against "https://github.com/acme/api#branch=main" .
# or against a stored image
buf breaking --against prev.bin .
Verify
- CI has a reference to diff against.
- Incompatible changes fail the pipeline.
- Compatible evolution is permitted, unsafe changes are not.
- The baseline never advances silently.
Limits
- The check covers wire compatibility only, not semantic compatibility of field meaning.
- It cannot detect a rename that keeps the number but changes intent, which still needs human review.