Code linting – Tutorial
Buf offers linting for Protobuf files via the buf lint
command in the Buf CLI. In this tutorial, we'll explore how to
use linting to maintain code quality and consistency in your projects. Read the overview to
learn about editor integration and see usage examples.
Prerequisites
We recommend completing the Buf CLI tour to get an overview of the Buf CLI first.
- Install the Buf CLI
- Clone the
buf-tour
repo:$ git clone git@github.com:bufbuild/buf-tour.git
1. Inspect the module
Modules represent a collection of files that are configured, built, and versioned as a logical unit when performing Buf CLI operations. The example code provides a module to work with, so start there. From the directory you cloned into, go to the tutorial code:
$ cd buf-tour/start/tutorial-lint
Your module has the directory structure shown below, and is defined by the buf.yaml
file in the proto
directory (the
root of your schemas). This module is your input for the buf lint
commands in the rest
of the tutorial.
.
└── proto
├── buf.yaml
└── acme
└── weather
└── v1
└── weather.proto
The example buf.yaml
file contains all of its required fields. The lint
field controls your lint settings. It's set
to our recommended default of DEFAULT
, which includes every rule we feel is important for modern Protobuf development.
version: v1
name: buf.build/tutorials/lint
breaking:
use:
- FILE
lint:
use:
- DEFAULT
For more information about specific fields, see the buf.yaml
reference.
2. Run lint
Run buf lint
on your module by specifying the filepath to the directory containing the buf.yaml
file. It uses the
current directory by default, but in the example code the input is the proto
subdirectory.
You can target it with this command, and should receive the following errors:
$ buf lint proto
Outputproto/acme/weather/v1/weather.proto:3:1:Files with package "weather" must be within a directory "weather" relative to root but were in directory "acme/weather/v1". proto/acme/weather/v1/weather.proto:3:1:Package name "weather" should be suffixed with a correctly formed version, such as "weather.v1". proto/acme/weather/v1/weather.proto:6:3:Enum value name "SUNNY" should be prefixed with "CONDITION_". proto/acme/weather/v1/weather.proto:6:3:Enum zero value name "SUNNY" should be suffixed with "_UNSPECIFIED". proto/acme/weather/v1/weather.proto:7:3:Enum value name "RAINY" should be prefixed with "CONDITION_". proto/acme/weather/v1/weather.proto:21:19:RPC request type "Location" should be named "GetWeatherRequest" or "WeatherServiceGetWeatherRequest".
3. Fix lint errors
Now that you know what needs to be fixed, you can go through your .proto
files and fix them. Let's start with the
package name—it should match the directory structure under which the schema lives (relative to the module root), so
change the package declaration:
syntax = "proto3";
- package weather;
+ package acme.weather.v1;
If you run buf lint proto
again, the first two errors about the package no longer appear. You can work through the
rest of the errors in a similar way—the messages provide specific suggestions to help you fix them.
The changes the linter recommends are breaking changes for this package, which illustrates why it's best (if possible)
to start linting when you first create your Protobuf files. However, it's not always possible, so we also
provide a way to temporarily ignore rules when you first bring your .proto
files into Buf—see step 5 below.
4. Customize lint configuration
We generally recommend that you use the DEFAULT
category for linting—it represents what we consider to be best
practice for Protobuf development. However, if your organization's style has other requirements, you can choose a
different category or add and remove individual rules from your configuration.
For example, if your org generally agrees with DEFAULT
rules but doesn't want to check for a suffix on service names,
you can selectively ignore that rule in the configuration like this:
version: v1
lint:
use:
- DEFAULT
except:
- SERVICE_SUFFIX
You can also add individual rules to the more minimal categories if they better match your style. For example, to add
only the SERVICE_SUFFIX
rule to the BASIC
category, you can use this configuration:
version: v1
lint:
use:
- BASIC
- SERVICE_SUFFIX
5. Temporarily ignore lint errors
There may be times when you want to ignore errors temporarily, such as adding buf lint
to an existing project (where
fixing lint errors would introduce breaking changes). We've provided a flag to make it simple to ignore them in this
case. Once you've fixed everything you want to fix, run this command to get a set of lint settings that you can copy
and paste into your buf.yaml
file to ignore the remaining errors:
$ buf lint proto --error-format=config-ignore-yaml
Outputversion: v1 lint: ignore_only: ENUM_VALUE_PREFIX: - acme/weather/v1/weather.proto ENUM_ZERO_VALUE_SUFFIX: - acme/weather/v1/weather.proto RPC_REQUEST_STANDARD_NAME: - acme/weather/v1/weather.proto
Remember to change your buf.yaml
file back to avoid committing the temporary settings.
Related docs
- Get detailed explanations of the linter rules and categories
- Browse the buf.yaml configuration file reference and
buf lint
command reference - See more about the types of inputs that the Buf CLI accepts