Use the protoc lint and breaking plugins

Buf ships two binaries, protoc-gen-buf-check-breaking and protoc-gen-buf-check-lint, that perform the lint and breaking change detection functionality as protoc plugins. These are useful in situations where you already have a protoc plugin setup, such as Bazel.

All flags and config are passed as an option to the plugin as JSON. This must be done with the --buf-check-breaking_opt or --buf-check-lint_opt flags as opposed to a parameter to --*_out as the option will include the ":" character as part of JSON.

The option for protoc-gen-buf-check-lint has the following shape:

{
"input_config": @string_or_json_config,
"log_level": @string,
"log_format": @string,
"error_format": @string,
"timeout": @duration
}

The option for protoc-gen-buf-check-breaking has the following shape:

{
"against_input": @string,
"against_input_config": @string_or_json_config,
"input_config": @string_or_json_config,
"limit_to_input_files": @bool,
"exclude_imports": @bool,
"log_level": @string,
"log_format": @string,
"error_format": @string,
"timeout": @duration
}

Installation

This section of the tour assumes you have also installed the protoc-gen-buf-check-breaking and protoc-gen-buf-check-lint binaries on your $PATH, and have a working installation of protoc. See the installation docs for more details.

protoc-gen-buf-check-lint

Let's return to our lint example. The ENUM_NO_ALLOW_ALIAS and IMPORT_NO_PUBLIC checkers should still be commented out:

version: v1beta1
lint:
use:
- BASIC
- FILE_LOWER_SNAKE_CASE
except:
#- ENUM_NO_ALLOW_ALIAS
#- IMPORT_NO_PUBLIC
- PACKAGE_AFFINITY
- PACKAGE_DIRECTORY_MATCH
- PACKAGE_SAME_DIRECTORY
breaking:
use:
- WIRE_JSON

Run the following:

$ protoc -I . --buf-check-lint_out=. $(find . -name '*.proto')
google/maps/roads/v1op/roads.proto:20:1: warning: Import google/api/annotations.proto is unused.
...
--buf-check-lint_out: google/appengine/v1/app_yaml.proto:53:5:Enum option "allow_alias" on enum "ErrorCode" must be false.
google/appengine/v1/app_yaml.proto:264:3:Enum option "allow_alias" on enum "SecurityLevel" must be false.
google/cloud/policytroubleshooter/v1/checker.proto:20:1:Import "google/cloud/policytroubleshooter/v1/explanations.proto" must not be public.
google/cloud/recommendationengine/v1beta1/catalog.proto:132:5:Enum option "allow_alias" on enum "StockState" must be false.
google/cloud/securitycenter/v1/securitycenter_service.proto:19:1:Import "google/cloud/securitycenter/v1/run_asset_discovery_response.proto" must not be public.
google/cloud/securitycenter/v1p1beta1/securitycenter_service.proto:20:1:Import "google/cloud/securitycenter/v1p1beta1/run_asset_discovery_response.proto" must not be public.
google/cloud/websecurityscanner/v1beta/scan_config_error.proto:35:5:Enum option "allow_alias" on enum "Code" must be false.
google/storage/v1/storage.proto:1902:5:Enum option "allow_alias" on enum "Values" must be false.

We can instead use a custom configuration as well.

$ protoc -I . --buf-check-lint_out=. '--buf-check-lint_opt={"input_config":{"version":"v1beta1","lint":{"use":["ENUM_NO_ALLOW_ALIAS"]}}}' $(find . -name '*.proto')
google/maps/roads/v1op/roads.proto:20:1: warning: Import google/api/annotations.proto is unused.
...
--buf-check-lint_out: google/appengine/v1/app_yaml.proto:53:5:Enum option "allow_alias" on enum "ErrorCode" must be false.
google/appengine/v1/app_yaml.proto:264:3:Enum option "allow_alias" on enum "SecurityLevel" must be false.
google/cloud/recommendationengine/v1beta1/catalog.proto:132:5:Enum option "allow_alias" on enum "StockState" must be false.
google/cloud/websecurityscanner/v1beta/scan_config_error.proto:35:5:Enum option "allow_alias" on enum "Code" must be false.
google/storage/v1/storage.proto:1902:5:Enum option "allow_alias" on enum "Values" must be false.

protoc-gen-buf-check-breaking

Let's return to our breaking change detection example.

First, build an image of your current state to a file:

$ buf build -o image.bin

Then, change a field type again:

diff --git a/google/type/date.proto b/google/type/date.proto
index b958feeba..916f1da93 100644
--- a/google/type/date.proto
+++ b/google/type/date.proto
@@ -46,5 +46,5 @@ message Date {
// Day of month. Must be from 1 to 31 and valid for the year and month, or 0
// if specifying a year by itself or a year and month where the day is not
// significant.
- int32 day = 3;
+ string day = 3;
}

Run the following:

$ protoc -I . --buf-check-breaking_out=. '--buf-check-breaking_opt={"against_input":"image.bin","limit_to_input_files":true}' $(find . -name '*.proto')
google/maps/roads/v1op/roads.proto:20:1: warning: Import google/api/annotations.proto is unused.
...
--buf-check-breaking_out: google/type/date.proto:49:3:Field "3" on message "Date" changed type from "int32" to "string".

Note that protoc-gen-buf-check-breaking can only take images as the against input, i.e. it cannot take in directories, git repositories, tarballs, or zip archives.