Este é o GO SDK para a estrutura do bufplugin. Atualmente, bufplugin-go
fornece os pacotes de check, checkutil e teste de checktest para simplificar o autor e o teste de fiapos personalizados e plugins de troca de quebra. Ele envolve a API bufplugin
com o pluginrpc-go em interfaces e conceitos fáceis de usar que organizam em torno da API ProtoReflect padrão que alimenta a maior parte do ecossistema Go Protobuf. bufplugin-go
também é a estrutura que a equipe de BUF usa para autorizar todo o fiapo e quebra de regras de mudança na CLI da BUF-garantimos que o bufplugin-go
seja poderoso o suficiente para representar o fiapo mais complexo e o intervalo de mudanças e as regras de mudança mantendo -o o mais simples possível para você usar. Se você deseja criar um plug-in de alteração de fiapo ou quebra hoje, use bufplugin-go
.
Um plug -in é apenas um binário no seu sistema que implementa a API de bufplugin. Depois de instalar um plug -in, basta adicionar uma referência a ele e suas regras no seu buf.yaml
. Por exemplo, se você instalou o plug-in Buf-Plugin-Timestamp-Suffix de exemplo no seu $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 a configuração funciona como você esperaria: você pode continuar configurando use
, except
, ignore
, ignore_only
e usar // buf:lint:ignore
comentários ignoram, exatamente como faria com as regras incorporadas.
Os plugins podem ser nomeados o que você deseja que eles sejam, no entanto, recomendamos seguir a convenção de prefixar seus nomes binários com buf-plugin-
para maior clareza.
Dado o seguinte arquivo:
# foo.proto
syntax = "proto3" ;
package foo ;
import "google/protobuf/timestamp.proto" ;
message Foo {
google.protobuf.Timestamp start = 1 ;
google.protobuf.Timestamp end_time = 2 ;
}
O seguinte erro será retornado do 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)
Nesse caso, os exemplos valem mais que mil palavras e recomendamos que você leia os exemplos em cheque/interno/exemplo/cmd para começar:
TIMESTAMP_SUFFIX
, que verifica se todos os campos google.protobuf.Timestamp
têm um sufixo consistente para o nome de seu campo. Este sufixo é configurável por meio de opções de plug -in.PLUGIN_FIELD_LOWER_SNAKE_CASE
, que verifica se todos os nomes de campo são lower_snake_case
.FIELD_OPTION_SAFE_FOR_ML_SET
e uma regra de mudança de ruptura FIELD_OPTION_SAFE_FOR_ML_STAYS_TRUE
, ambos pertencentes à categoria FIELD_OPTION_SAFE_FOR_ML
. Isso aplica propriedades em torno de um exemplo de opção personalizada acme.option.v1.safe_for_ml
, destinada a denotar se um campo é ou não seguro ou não nos modelos ML. Uma organização pode querer dizer que todos os campos devem ser explicitamente marcados como seguros ou inseguros em todos os seus esquemas, e nenhuma mudança de campo de segura para insegura. Este plugin aplicaria esse lado da organização. O exemplo mostra a implementação de várias regras, categorizando -as e levando em consideração os valores de opção personalizados.PLUGIN_SYNTAX_SPECIFIED
, que verifica se todos os arquivos têm uma declaração explícita syntax
. Isso demonstra o uso de metadados adicionais presentes na API bufplugin
além do que um FileDescriptorProto
fornece. Todos esses exemplos têm checktest
implementação de plug main_test.go
main.go
. O pacote checktest
usa o protocompilo para compilar os arquivos .proto
em tempo real, executá -los contra suas regras e comparar as anotações resultantes com uma expectativa.
Aqui está um pequeno exemplo de implementação de plug -in - isso é o suficiente:
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"
}
A bufplugin está atualmente na versão beta e pode mudar enquanto trabalhamos com os primeiros adotantes. Pretendemos enviar um V1.0 estável até o final de 2024. No entanto, acreditamos que a API está perto de sua forma final.
Oferecido sob a licença Apache 2.