proto-compatibility-tool
is an utility that verifies .proto files and ensures backwards compatibility to prevent breaking changes on exposed APIs.
It runs as part of the CI process, and runs verifications against published versions of .proto files in NPM packages, S3, static URL or local files.
This tool does generate any kind of code, it only performs validations on .proto files.
npm i -g proto-compatibility-tool
# proto-compatibility-tool <local file> <remote file>
# compare two local files
proto-compatibility-tool \
./api-v0.proto \
./api-v1.proto
Types are evaluated nominally and then structurally. That means, this tool not only checks the structure and serialization of each message, it also checks that the name of the types matches to not break any generated code.
message MessageName {
int32 message_id = 1;
- required string message_payload = 2;
}
// 🚨 Throws
message MessageName {
int32 message_id = 1;
- string message_payload = 2;
+ reserved 2;
}
// ✅ Passes
message MessageName {
int32 message_id = 1;
- string message_payload = 2;
+ int32 message_payload = 2;
}
// 🚨 Throws
Fields are optional by default, field removal should be performed very few times during the development lifecycle. Once you remove a field there is no looking back, because this tool will verify against the previous published version, re-validating the field original type is not possible.
message MessageName {
int32 message_id = 1;
- reserved 2;
}
// 🚨 Throws
service Haberdasher {
- rpc MakeHat(Size) returns (Hat);
}
// 🚨 Throws
service Haberdasher {
- rpc MakeHat(Size) returns (Hat) [deprecated = true];
}
// ✅ Passes
service Haberdasher {
- rpc MakeHat(Size) returns (Hat);
+ rpc MakeTophat(Size) returns (Hat);
}
// 🚨 Throws
If a function receives different input or produces a different result, it is a different function, therefore it must have a different name.
service Haberdasher {
- rpc MakeHat(Size) returns (Hat);
+ rpc MakeHat(HatOptions) returns (Hat);
}
// 🚨 Throws
-package twirp.example.haberdasher;
+package twirp.example.hats;
service Haberdasher {
...
}
// 🚨 Throws
-service Haberdasher {
+service Hats {
rpc MakeHat(Size) returns (Hat);
}
// 🚨 Throws