这是Bufplugin框架的GO SDK。 bufplugin-go
当前提供检查,Checkutil和CheckTest软件包,以使其对作者进行简单,并测试自定义棉绒和破坏更改插件。它将bufplugin
API与插件一起包装在易于使用的接口和概念中,这些接口和概念围绕标准的ProtoReflect API组织,从而为大多数GO ProtoBuf生态系统提供动力。 bufplugin-go
也是BUF团队在BUF CLI内使用所有内置的棉绒和破坏变更规则的框架 - 我们确保bufplugin-go
足够强大,足以代表最复杂的绒毛和打破变化规则同时使其尽可能简单地使用。如果您今天想撰写棉绒或打破更改插件,则应使用bufplugin-go
。
插件只是系统上实现Bufplugin API的二进制文件。安装插件后,只需在buf.yaml
中对其及其规则添加参考。例如,如果您已经在$PATH
上安装了Buf-Plugin-timestamp-Suffix-Suffix示例插件:
version : v2
lint :
use :
- TIMESTAMP_SUFFIX
plugins :
- plugin : buf-plugin-timestamp-suffix
options :
timestamp_suffix : _time # set to the suffix you'd like to enforce
所有配置都按照您的期望工作:您可以继续配置use
, except
, ignore
, ignore_only
,使用// buf:lint:ignore
评论忽略,就像您对内置规则一样。
可以将插件命名为您想要的任何东西,但是,我们建议按照将您的二进制名称与buf-plugin-
为了清楚起见。
给定以下文件:
# foo.proto
syntax = "proto3" ;
package foo ;
import "google/protobuf/timestamp.proto" ;
message Foo {
google.protobuf.Timestamp start = 1 ;
google.protobuf.Timestamp end_time = 2 ;
}
以下错误将从buf lint
返回:
foo.proto:8:3:Fields of type google.protobuf.Timestamp must end in "_time" but field name was "start". (buf-plugin-timestamp-suffix)
在这种情况下,示例值得一千个单词,我们建议您阅读check/internal/example/cmd中的示例以开始:
TIMESTAMP_SUFFIX
,该插件检查所有google.protobuf.Timestamp
字段是否具有一致的字段名称后缀。该后缀可通过插件选项配置。PLUGIN_FIELD_LOWER_SNAKE_CASE
,检查所有字段名称均为lower_snake_case
。FIELD_OPTION_SAFE_FOR_ML_SET
的插件和破坏更改规则FIELD_OPTION_SAFE_FOR_ML_STAYS_TRUE
,均属于FIELD_OPTION_SAFE_FOR_ML
类别。这将围绕一个示例定制选项acme.option.v1.safe_for_ml
强制实施属性,旨在表示字段是否安全地用于ML模型。一个组织可能想说的是,必须在其所有模式中明确标记所有领域是安全的或不安全的,并且没有从安全到不安全的领域变化。该插件将执行此组织侧。该示例展示了实施多个规则,对它们进行分类并考虑自定义选项值。PLUGIN_SYNTAX_SPECIFIED
,该插件检查所有文件是否均具有显式syntax
声明。这证明了使用bufplugin
API中存在的其他元数据超出了FileDescriptorProto
所提供的内容。所有这些示例都有一个main.go
插件实现,以及使用checktest
软件包测试插件行为的main_test.go
测试文件。 checktest
软件包使用protoCompile来编译测试.proto
启用文件,违反您的规则,并将结果注释与期望进行比较。
这是插件实现的一个简短示例 - 这就是全部所需的:
package main
import (
"context"
"buf.build/go/bufplugin/check"
"buf.build/go/bufplugin/check/checkutil"
"google.golang.org/protobuf/reflect/protoreflect"
)
func main () {
check . Main (
& check. Spec {
Rules : [] * check. RuleSpec {
{
ID : "PLUGIN_FIELD_LOWER_SNAKE_CASE" ,
Default : true ,
Purpose : "Checks that all field names are lower_snake_case." ,
Type : check . RuleTypeLint ,
Handler : checkutil . NewFieldRuleHandler ( checkFieldLowerSnakeCase , checkutil . WithoutImports ()),
},
},
},
)
}
func checkFieldLowerSnakeCase (
_ context. Context ,
responseWriter check. ResponseWriter ,
_ check. Request ,
fieldDescriptor protoreflect. FieldDescriptor ,
) error {
fieldName := string ( fieldDescriptor . Name ())
fieldNameToLowerSnakeCase := toLowerSnakeCase ( fieldName )
if fieldName != fieldNameToLowerSnakeCase {
responseWriter . AddAnnotation (
check . WithMessagef (
"Field name %q should be lower_snake_case, such as %q." ,
fieldName ,
fieldNameToLowerSnakeCase ,
),
check . WithDescriptor ( fieldDescriptor ),
)
}
return nil
}
func toLowerSnakeCase ( fieldName string ) string {
// The actual logic for toLowerSnakeCase would go here.
return "TODO"
}
Bufplugin目前正在Beta中,并且随着我们与早期采用者合作时可能会发生变化。我们打算在2024年底之前运送稳定的V1.0。但是,我们认为API接近其最终形状。
根据Apache 2许可提供。