Este es el SDK Go para el marco Bufplugin. bufplugin-go
actualmente proporciona los paquetes de cheques, checkutil y de prueba para que sea simple del autor y probar complementos de cambio de pelusa y ruptura de cambio. Envuelve la API bufplugin
con PluginRPC-go en interfaces y conceptos fáciles de usar que se organizan en torno a la API de protoreflect estándar que alimenta la mayoría del ecosistema GO ProtoBuf. bufplugin-go
es también el marco que el equipo de BUF usa para autor todas las reglas de cambio de pelusa y cambio de ruptura de BUF: nos hemos asegurado de que bufplugin-go
sea lo suficientemente poderoso como para representar las reglas de pelusa y cambio de cambio más complejas mientras lo mantiene lo más simple posible para que lo use. Si desea autorizar un complemento de Cambio de pelusa o Breaking hoy, debe usar bufplugin-go
.
Un complemento es solo un binario en su sistema que implementa la API Bufplugin. Una vez que haya instalado un complemento, simplemente agregue una referencia y sus reglas dentro de su buf.yaml
. Por ejemplo, si ha instalado el complemento de ejemplo Buf-Plugin-Timestamp-Suffix en su $PATH
:
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
Toda la configuración funciona como era de esperar: puede continuar configurando use
, except
, ignore
, ignore_only
y usar // buf:lint:ignore
el comentario ignora, tal como lo haría para las reglas Builtin.
Los complementos se pueden nombrar lo que desee, sin embargo, recomendamos seguir la convención de prefijo sus nombres binarios con buf-plugin-
para mayor claridad.
Dado el siguiente archivo:
# foo.proto
syntax = "proto3" ;
package foo ;
import "google/protobuf/timestamp.proto" ;
message Foo {
google.protobuf.Timestamp start = 1 ;
google.protobuf.Timestamp end_time = 2 ;
}
El siguiente error se devolverá desde 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)
En este caso, los ejemplos valen mil palabras, y le recomendamos que lea los ejemplos en cheque/interno/ejemplo/cmd para comenzar:
TIMESTAMP_SUFFIX
, que verifica que todos los campos google.protobuf.Timestamp
tienen un sufijo consistente para su nombre de campo. Este sufijo es configurable a través de opciones de complemento.PLUGIN_FIELD_LOWER_SNAKE_CASE
, que verifica que todos los nombres de campo son lower_snake_case
.FIELD_OPTION_SAFE_FOR_ML_SET
y una regla de cambio de ruptura FIELD_OPTION_SAFE_FOR_ML_STAYS_TRUE
, ambos pertenecientes a la categoría FIELD_OPTION_SAFE_FOR_ML
. Esto impone propiedades en torno a una opción personalizada de ejemplo acme.option.v1.safe_for_ml
, destinada a denotar si un campo es seguro de usar en modelos ML. Una organización puede querer decir que todos los campos deben estar explícitamente marcados como seguros o inseguros en todos sus esquemas, y ningún cambio de campo de seguro a inseguro. Este complemento aplicaría este lado de la organización. El ejemplo muestra implementar múltiples reglas, clasificarlas y tener en cuenta los valores de opciones personalizados.PLUGIN_SYNTAX_SPECIFIED
, que verifica que todos los archivos tienen una declaración syntax
explícita. Esto demuestra el uso de metadatos adicionales presentes en la API bufplugin
más allá de lo que proporciona un FileDescriptorProto
. Todos estos ejemplos tienen una implementación de complementos main.go
y un archivo de prueba main_test.go
que utiliza el paquete de checktest
para probar el comportamiento del complemento. El paquete checktest
utiliza Protocompile para compilar los archivos de prueba .proto
Proto sobre la marcha, ejecutarlos con sus reglas y comparar las anotaciones resultantes con una expectativa.
Aquí hay un breve ejemplo de implementación de complementos: esto es todo lo que se necesita:
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 se encuentra actualmente en Beta, y puede cambiar a medida que trabajamos con los primeros usuarios. Tenemos la intención de enviar un establo V1.0 a fines de 2024. Sin embargo, creemos que la API está cerca de su forma final.
Ofrecido bajo la licencia Apache 2.