Configuration

Buf's linter is configured through a buf.yaml file that should be checked in to the root of your repository. Buf will automatically read this file if present. Configuration can also be provided via the command-line flag --config, which accepts a path to a .json or .yaml file, or direct JSON or YAML data.

The following is an example of all available configuration options. See the configuration reference for more details.

version: v1beta1
lint:
use:
- DEFAULT
except:
- PACKAGE_AFFINITY
ignore:
- bat
- ban/ban.proto
ignore_only:
ENUM_PASCAL_CASE:
- foo/foo.proto
- bar
SENSIBLE:
- foo
enum_zero_value_suffix: _UNSPECIFIED
rpc_allow_same_request_response: false
rpc_allow_google_protobuf_empty_requests: false
rpc_allow_google_protobuf_empty_responses: false
service_suffix: Service
allow_comment_ignores: true

If no lint section is specified, the following default configuration is used.

version: v1beta1
lint:
use:
- DEFAULT
enum_zero_value_suffix: _UNSPECIFIED
rpc_allow_same_request_response: false
rpc_allow_google_protobuf_empty_requests: false
rpc_allow_google_protobuf_empty_responses: false
service_suffix: Service

Lint checker selection

The primary purpose of configuration is to select the lint checkers you want to apply.

All lint checkers have an id, and belong to one or more categories. Configuration options accept both ids and categories, where specifying a category is equivalent to manually listing all ids in that categories.

You can print your currently-configured lint checkers at any time by running:

$ buf check ls-lint-checkers

Or run this to use a buf.yaml file that is not in your current directory:

$ buf check ls-lint-checkers --config foo/buf.yaml

To see all available lint checkers independent of configuration/defaults:

$ buf check ls-lint-checkers --all

Lint checker selection is done through the following options:

use

This selects the ids or categories to use for linting. For example, the following selects the BASIC lint category, as well as the FILE_LOWER_SNAKE_CASE id:

version: v1beta1
lint:
use:
- BASIC
- FILE_LOWER_SNAKE_CASE

The default value is the single item DEFAULT.

except

This removes ids or categories from the use list. For example, the following will result in all lint checkers in the DEFAULT lint category being used except for ENUM_NO_ALLOW_ALIAS and all lint checkers in the PACKAGE_AFFINITY category:

version: v1beta1
lint:
use:
- DEFAULT
except:
- ENUM_NO_ALLOW_ALIAS
- PACKAGE_AFFINITY

Note that since DEFAULT is the default value for use, this is equivalent to the above:

version: v1beta1
lint:
except:
- ENUM_NO_ALLOW_ALIAS
- PACKAGE_AFFINITY

ignore

This allows directories or files to be excluded from all lint checkers when running buf check lint. The specified directory or file paths should be relative to their root. For example, given a root proto, and a file proto/bar/baz.proto, the following will result in proto/bar/baz.proto being ignored:

version: v1beta1
build:
roots:
- proto
lint:
ignore:
- bar/baz.proto

This is so that buf check lint works regardless of what Input it is linting.

ignore_only

This allows directories or files to be excluded from specific lint checkers when running buf check lint by taking a map from lint checker id or category to path. As with ignore, the paths should be relative to their root.

For example, the following sets us specific ignores for the id ENUM_PASCAL_CASE and the category PACKAGE_AFFINITY:

version: v1beta1
lint:
ignore_only:
ENUM_PASCAL_CASE:
- foo/foo.proto
- bar
PACKAGE_AFFINITY:
- foo

allow_comment_ignores

This turns on comment-driven ignores.

version: v1beta1
lint:
allow_comment_ignores: true

If this option is set, leading comments can be added within Protobuf files to ignore lint errors for certain components. If any line in a leading comment starts with buf:lint:ignore ID, then Buf will ignore lint errors for this id. For example:

syntax = "proto3";
// buf:lint:ignore PACKAGE_LOWER_SNAKE_CASE
// buf:lint:ignore PACKAGE_VERSION_SUFFIX
package A;

We do not recommend using this. Buf's goal is to help everyone develop consistent Protobuf schemas regardless of organization, and for a large organization, it would not be helpful for individual engineers to decide what should and should not be ignored. This should instead be surfaced in a repository-wide configuration file such as buf.yaml. If you do have specific items that you want to ignore, we recommended adding the offending types to a special file, for example foo_lint_ignore.proto, and setting the corresponding ignore or ignore_only. For example, say we have a legacy enum that uses allow_alias.

enum Foo {
option allow_alias = true;
FOO_UNSPECIFIED = 0;
FOO_ONE = 1;
FOO_TWO = 1;
}

Place this enum in a file foo_lint_ignore.proto and then set up the following configuration:

version: v1beta1
lint:
ignore_only:
ENUM_NO_ALLOW_ALIAS:
- path/to/foo_lint_ignore.proto

We do recognize, however, that there are situations where comment-driven ignores are necessarily, and we want users to be able to make informed decisions. Therefore, allow_comment_ignores is added as an opt-in option. This also has the effect of making it possible to keep commen-driven ignores disabled, if you have commit checks for files via an authors/owners file - if you make sure buf.yaml is owned by a top-level repository owner, and you do not set allow_comment_ignores, Buf will ignore any buf:lint:ignore annotations.

Individual lint checker configuration

There are also options available for a few specific lint checkers. This option list will likely grow over time when we have additional lint checkers that should have configuration options.

enum_zero_value_suffix.

This controls the behavior of the ENUM_ZERO_VALUE_SUFFIX lint checker. By default, this checker verifies that the zero value of all enums ends in _UNSPECIFIED, as recommended by the Google Protobuf Style Guide. However, organizations may have a different preferred suffix, for example _NONE, and this allows this to be set.

version: v1beta1
lint:
enum_zero_value_suffix: _NONE

This will allow the following:

enum Foo {
FOO_NONE = 0;
}

rpc_allow_.*

The options rpc_allow_same_request_response, rpc_allow_google_protobuf_empty_requests, and rpc_allow_google_protobuf_empty_responses control the behavior of the RPC_REQUEST_STANDARD_NAME, RPC_RESPONSE_STANDARD_NAME, and RPC_REQUEST_RESPONSE_UNIQUE lint checkers.

One of the single most important rules to enforce in modern Protobuf development is to have a unique request and response message for every RPC. Separate RPCs should not have their request and response parameters controlled by the same Protobuf message, and if you share a Protobuf message between multiple RPCs, this results in multiple RPCs being affected when fields on this Protobuf message change. Even in simple cases, best practice is to always have a wrapper message for your RPC request and response types. Buf enforces this as part of the DEFAULT category by verifying the following:

  • All requests and responses are unique across your Protobuf schema.
  • All requests and response messages are named after the RPC, either by naming them MethodNameRequest/MethodNameResponse or ServiceNameMethodNameRequest/ServiceNameMethodNameResponse.

For example, the following service definition abides by these rules:

// request/response message definitions omitted for brevity
service FooService {
rpc Bar(BarRequest) returns (BarResponse) {}
rpc Baz(FooServiceBazRequest) returns (FooServiceBazResponse) {}
}

However, while not recommended, we allow for a few options to slightly loosen these restrictions:

  • rpc_allow_same_request_response allows the same message type to be used for a single RPC's request and response type.
  • rpc_allow_google_protobuf_empty_requests allows RPC requests to be google.protobuf.Empty messages. This can be set if you want to allow messages to be void forever, that is they will never take any parameters.
  • rpc_allow_google_protobuf_empty_responses allows RPC responses to be google.protobuf.Empty messages. This can be set if you want to allow messages to never return any parameters.

The file google/protobuf/empty.proto is part of the Well-Known Types, and can be directly included in any Protobuf schema. For example:

syntax = "proto3";
package foo.v1;
import "google/protobuf/empty.proto";
service BarService {
// NOT RECOMMENDED
rpc Baz(google.protobuf.Empty) returns (google.protobuf.Empty);
}

service_suffix

This controls the behavior of the SERVICE_SUFFIX lint checker. By default, this checker verifies that all service names are suffixed with Service. However, organizations may have a different preferred suffix, for example API, and this allows this to be set.

version: v1beta1
lint:
service_suffix: API

This will allow the following:

service FooAPI {}

Configuration overrides

As discussed in the configuration documentation, configuration can be specified using the --config flag.

Examples:

# Read the JSON file foo/bar.json.
buf check lint --config foo/bar.json
# Read the YAML file foo/bar.yaml.
buf check lint --config foo/bar.yaml
# Use the given JSON data.
# This results in the build assuming there is one root, the current directory, and only
# using the ENUM_NO_ALLOW_ALIAS lint checker for linting.
buf check lint --config '{"lint":{"use":["ENUM_NO_ALLOW_ALIAS"]}}'