Migrate to v2 configuration files#
v2 is the current shape for buf.yaml and buf.gen.yaml.
The Buf CLI continues to read v1 and v1beta1 configurations, so there’s no deadline; migrate when you want any of the v2-only features:
- Workspace-level
lintandbreakingdefaults, with per-module overrides. - Multi-module push: a single
buf pushcovers every module in the workspace, in the right dependency order, against a singlebuf.lock. - Inputs declared in
buf.gen.yaml, sobuf generateworks without a wrapping Makefile or shell script. - Simpler managed mode: top-level
disableandoverridekeys instead of options interwoven per file and per module.
v1beta1 configurations migrate the same way as v1; you don’t need to step through v1 first.
Run the migration tool#
buf config migrate discovers every buf.yaml, buf.gen.yaml, and buf.work.yaml under the current directory and rewrites them as a single v2 buf.yaml (and a v2 buf.gen.yaml if any v1 buf.gen.yaml was found) at the current directory.
Run it from the workspace root:
To preview the v2 files and directory layout before changing anything, print a diff:
The tool doesn’t auto-detect configuration files with non-standard names like buf.gen.go.yaml.
For those, or to migrate parts of a repository at a time, target specific paths:
$ buf config migrate --buf-gen-yaml </paths/to/files>
# Migrates buf.yaml and buf.lock files
$ buf config migrate --module </paths/to/modules>
# Migrates buf.work.yaml, buf.yaml, and buf.lock files
$ buf config migrate --workspace </paths/to/workspaces>
After migration, run buf build and buf lint from the repository root to confirm the v2 config behaves the same.
Handle the new PACKAGE_NO_IMPORT_CYCLE rule#
v2 adds the PACKAGE_NO_IMPORT_CYCLE rule to the STANDARD lint category.
The migration tool excludes the rule in the new buf.yaml so the migration itself doesn’t introduce new failures:
Remove the except block and run buf lint.
If the workspace passes, leave the rule on (delete the two lines).
If it fails, leave the rule excluded until the import cycles can be addressed.
buf.yaml: modules and workspaces#
In v2, the workspace is the unit of local Protobuf work, whether it contains one module or many.
A single buf.yaml at the workspace root replaces the buf.work.yaml plus per-module buf.yaml files of v1.
v1 layout#
v2 layout#
For a single-module repository where the buf.yaml sits next to the .proto files, the only required change is the version key.
With modules omitted, the Buf CLI treats the current directory as the single module:
version: v2
# Implicit if `modules` is omitted; including this block has no effect.
modules:
- path: .
Multi-module push#
In multi-module workspaces, buf push now publishes every module in the workspace in dependency order against a single shared buf.lock.
You no longer need to push modules one at a time after running buf dep update on each.
Modules within the workspace can also depend on one another without an explicit declaration.
Workspace-level lint and breaking defaults#
v2 allows workspace-level lint and breaking blocks, which set defaults for every module.
A module-level block on a specific module fully replaces the workspace-level rules for that module, rather than merging.
version: v2
breaking:
use:
- FILE
# By default, all modules in the workspace use the STANDARD lint rules.
lint:
use:
- STANDARD
modules:
- path: proto
- path: vendor
breaking:
use:
- WIRE_JSON
# The module under vendor/ uses the MINIMAL lint rules instead.
lint:
use:
- MINIMAL
For everything else, see Modules and workspaces and the v2 buf.yaml reference.
buf.gen.yaml: plugins, inputs, and managed mode#
Plugin type keys#
Plugins still live under a top-level plugins list, but the kind of plugin is now an explicit key: remote, local, or protoc_builtin.
The two configurations below are equivalent:
version: v1
plugins:
# Remote plugin on the BSR
- plugin: buf.build/protocolbuffers/java
out: gen/proto
# Local binary plugin in ${PATH}
- plugin: validate
out: gen/proto
# protoc built-in plugin for C++ (note lack of "protoc-gen-" prefix)
- plugin: cpp
out: gen/proto
version: v2
plugins:
# Remote plugin on the BSR
- remote: buf.build/protocolbuffers/java
out: gen/proto
# Local binary plugin in ${PATH}
- local: protoc-gen-validate
out: gen/proto
# protoc built-in plugin for C++ (note lack of "protoc-gen-" prefix)
- protoc_builtin: cpp
out: gen/proto
Inputs declared in config#
v2 buf.gen.yaml accepts an inputs list, so a single buf generate covers an entire workspace.
The configuration accepts modules, local directories, individual .proto files, Git repositories, tarballs and zip archives, and Buf images.
Anything passed on the command line still overrides what’s in the file.
For this layout:
workspace_root
├── buf.gen.yaml
├── buf.yaml
├── proto
│ ├── foo
│ │ └── foo.proto
│ └── bar
│ └── bar.proto
└── baz
└── baz.proto
v1 requires running buf generate once per input directory:
v2 declares both inputs in buf.gen.yaml and runs once:
Managed mode: disable and override#
Managed mode now uses two top-level keys, disable and override, instead of weaving overrides into per-file-option blocks.
Coverage now extends to field options as well as file options, and entries can scope down to individual fields.
A file option without a default behavior is left at the Protobuf default unless an override rule sets it.
The following two configurations are equivalent:
version: v1
managed:
enabled: true
optimize_for: CODE_SIZE
go_package_prefix:
default: github.com/acme/weather/private/gen/proto/go
except:
- buf.build/googleapis/googleapis
override:
buf.build/acme/weather: github.com/acme/weather/gen/proto/go
override:
JAVA_PACKAGE:
acme/weather/v1/weather.proto: "org"
version: v2
managed:
enabled: true
disable:
# Disables all go_package changes for this module only
- file_option: go_package
module: buf.build/googleapis/googleapis
override:
- file_option: optimize_for
value: CODE_SIZE
# Sets default go_package_prefix for all inputs
- file_option: go_package_prefix
value: github.com/acme/weather/private/gen/proto/go
# Overrides default go_package_prefix for this module only
- file_option: go_package_prefix
module: buf.build/acme/weather
value: github.com/acme/weather/gen/proto/go
# File options with prefix and suffix can now specify defaults directly
- file_option: java_package
path: acme/weather/v1/weather.proto
value: org
For everything else, see code generation overview, managed mode, and the v2 buf.gen.yaml reference.
buf mod command moves#
Because buf.yaml is now the configuration file for an entire workspace, the buf mod subcommands moved out of buf mod into namespaces that match what they actually act on:
| v1 command | v2 command |
|---|---|
buf mod init |
buf config init |
buf mod prune |
buf dep prune |
buf mod update |
buf dep update |
buf mod ls-breaking-rules |
buf config ls-breaking-rules |
buf mod ls-lint-rules |
buf config ls-lint-rules |
buf mod {clear-cache,cc} |
buf registry cc |
The buf mod subcommands still work and print a deprecation warning to stderr:
$ buf mod update
Command "update" is deprecated, use "buf dep update" instead. However, "buf mod update" will continue to work.
Further reading#
- v2
buf.yamlreference: every supported key. - v2
buf.gen.yamlreference: every plugin, input, and managed-mode key. - Managed mode: the full set of file and field options that managed mode can set.
- Modules and workspaces: the conceptual model that v2 configs make explicit.
- Buf CLI: The Next Generation: blog post on why v2 exists.