Managing Protobuf with Buf

Introduction⌗
Buf is an open-source ecosystem management tool for Protobuf, not just for managing Protobuf files and dependencies, but also for protobuf-compiler-plugin configuration options.
It allows developers to spend less effort on the Protobuf Compiler while also supporting Plugin Registry, which better manages private protobuf-compiler-plugins. Buf has played a crucial role in building the Protobuf ecosystem, and it’s not an exaggeration to say it’s revolutionary!
Installation⌗
Installation on macOS is as follows:
brew install bufbuild/buf/buf
For other platforms, refer to the official documentation.
Usage⌗
To use Buf, you need to configure the Buf CLI workspace with a buf.yaml
file, which defines a list of Protobuf file directories to be considered as a logical unit or module. Create this file using the following command:
buf config init
After running the command, there will be a buf.yaml in the workspace directory with the following content:
# For details on buf.yaml configuration, visit https://buf.build/docs/configuration/v2/buf-yaml
version: v2
lint:
use:
- STANDARD
breaking:
use:
- FILE
Setting Up the Workspace⌗
The generated buf.yaml
file behaves like a workspace containing one module with its path set to the current directory. To explicitly define modules in the workspace, provide paths to directories containing .proto
files. Add proto directories to the buf.yaml file using the modules key:
# For details on buf.yaml configuration, visit https://buf.build/docs/configuration/v2/buf-yaml
version: v2
lint:
use:
- STANDARD
modules:
- path: internal/proto
breaking:
use:
- FILE
My project’s .proto
files are located in the internal/proto
directory, so I set modules.path to internal/proto
here.
Setting Project Dependencies⌗
You can add dependencies by adding a deps
list to the buf.yaml
file and defining the required dependencies:
# For details on buf.yaml configuration, visit https://buf.build/docs/configuration/v2/buf-yaml
version: v2
lint:
use:
- STANDARD
deps:
- buf.build/googleapis/googleapis
modules:
- path: internal/proto
breaking:
use:
- FILE
In this case, I set up the buf.build/googleapis/googleapis
dependency because I’m using Google Protobuf-related RESTful definitions. Before Buf, we had to manually download the googleapis repository and specify the dependency path during compilation.
Generating Code⌗
The Buf CLI provides a user-friendly experience for generating code locally that’s compatible with protoc usage. Before starting, we need to create a buf.gen.yaml
configuration file to configure local code generation. It controls how the buf generate
command executes protocol plugins on a given module. You can use it to configure the path where each protobuf-compiler-plugin
writes its results and specify configuration options for each plugin.
touch buf.gen.yaml
version: v2
managed:
enabled: true
disable:
- file_option: go_package
module: buf.build/googleapis/googleapis
override:
- file_option: go_package_prefix
value: github.com/betterde/focusly/internal/gen
plugins:
- remote: buf.build/protocolbuffers/go
out: internal/gen
opt: paths=source_relative
- remote: buf.build/grpc/go
out: internal/gen
opt: paths=source_relative
- remote: buf.build/grpc-ecosystem/gateway
out: internal/gen
opt: paths=source_relative
- remote: buf.build/connectrpc/go:v1.12.0
out: internal/gen
opt: paths=source_relative
- local: protoc-gen-es
out: spa/src/gen
opt: target=ts
- local: protoc-gen-connect-es
out: spa/src/gen
opt: target=ts
- local: protoc-gen-connect-query
out: spa/src/gen
opt: target=ts
- remote: buf.build/community/google-gnostic-openapi:v0.7.0
out: docs/api
opt: paths=source_relative
The above configuration is used to generate the following files:
- *.pb.go
- *.pb.gw.go
- *_grpc.pb.go
- connect/.connect.go
- TypeScript files needed for the frontend project
- OpenAPI specification
If your project needs to use gRPC with other languages, you just need to find the corresponding protobuf-compiler-plugin
and install it, then you can use buf generate
to generate the corresponding code.
Code Linting⌗
You can use the following command to lint the .proto files in your project:
buf lint
Compatibility Check⌗
For Protobuf, file change compatibility is very important. To avoid compatibility issues, you can use the following command for compatibility detection:
buf breaking --against ".git#subdir=internal/proto"
You can set the comparison reference through --against
, with supported settings as follows:
- .git#branch=master
- .git#tag=v1.0.0
- .git#subdir=internal/proto
Besides the local .git
, you can also use a remote git as a comparison reference, such as https://github.com/betterde/focusly.git
. Additionally, you can use the --error-format=json
parameter to set the output format to JSON.
Formatting⌗
You can use the following command to format .proto
files:
# View the changes after formatting
buf format -d
# Write the formatted changes to files
buf format -w
Conclusion⌗
Buf’s power doesn’t stop there. It has improved the ecosystem of Protobuf and gRPC. Later, I will write more about practical experiences with Buf in projects…
I hope this is helpful, Happy hacking…