From f85731c01ec7fc789ee4ff356fa8c2e98d5c089b Mon Sep 17 00:00:00 2001 From: "Yoshiaki Ueda (bootjp)" Date: Wed, 22 Apr 2026 22:53:11 +0900 Subject: [PATCH 1/3] build(proto): switch to buf and gate gen on breaking check Replace protoc-based proto/Makefile with buf (v1.55.1). `make -C proto gen` now runs `buf breaking` against main before `buf generate`, so wire- incompatible changes fail locally before regenerating. Add a Proto workflow that runs the same breaking check, regenerates, and fails if the committed *.pb.go drift from the generated output. Regenerate all *.pb.go under buf; the only functional diff is normalized internal symbol names in internal.pb.go (no exported API change). --- .github/workflows/proto.yml | 53 +++++++++++++++++ proto/Makefile | 58 ++++++++++--------- proto/buf.gen.yaml | 8 +++ proto/buf.yaml | 6 ++ proto/distribution.pb.go | 2 +- proto/distribution_grpc.pb.go | 2 +- proto/dynamodb_internal.pb.go | 2 +- proto/etcd_raft.pb.go | 2 +- proto/etcd_raft_grpc.pb.go | 2 +- proto/internal.pb.go | 106 +++++++++++++++++----------------- proto/internal_grpc.pb.go | 6 +- proto/redis_internal.pb.go | 2 +- proto/service.pb.go | 2 +- proto/service_grpc.pb.go | 2 +- 14 files changed, 161 insertions(+), 92 deletions(-) create mode 100644 .github/workflows/proto.yml create mode 100644 proto/buf.gen.yaml create mode 100644 proto/buf.yaml diff --git a/.github/workflows/proto.yml b/.github/workflows/proto.yml new file mode 100644 index 000000000..ad3a59baf --- /dev/null +++ b/.github/workflows/proto.yml @@ -0,0 +1,53 @@ +on: + push: + paths: + - 'proto/**' + - '.github/workflows/proto.yml' + pull_request: + paths: + - 'proto/**' + - '.github/workflows/proto.yml' + +name: Proto +permissions: + contents: read + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + proto: + runs-on: ubuntu-latest + env: + BUF_VERSION: 1.55.1 + PROTOC_GEN_GO_VERSION: v1.36.11 + PROTOC_GEN_GO_GRPC_VERSION: v1.6.1 + steps: + - uses: actions/checkout@v6 + with: + fetch-depth: 0 + - uses: actions/setup-go@v6 + with: + go-version-file: 'go.mod' + - name: Install buf + run: go install github.com/bufbuild/buf/cmd/buf@v${{ env.BUF_VERSION }} + - name: Install protoc-gen-go + run: go install google.golang.org/protobuf/cmd/protoc-gen-go@${{ env.PROTOC_GEN_GO_VERSION }} + - name: Install protoc-gen-go-grpc + run: go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@${{ env.PROTOC_GEN_GO_GRPC_VERSION }} + - name: buf breaking (against main) + if: github.ref != 'refs/heads/main' + working-directory: proto + run: buf breaking --against '../.git#subdir=proto,branch=main' + - name: buf generate + working-directory: proto + run: buf generate + - name: Fail on regenerated diff + run: | + if ! git diff --exit-code -- proto/; then + echo "::error::Generated proto files differ from committed output. Run 'make -C proto gen' and commit the result." + exit 1 + fi + - name: go build + run: go build ./... diff --git a/proto/Makefile b/proto/Makefile index c329a70b5..abacc13b2 100644 --- a/proto/Makefile +++ b/proto/Makefile @@ -1,39 +1,41 @@ -PROTOC_VERSION := libprotoc 29.3 -PROTOC_GEN_GO_VERSION := protoc-gen-go v1.36.11 -PROTOC_GEN_GO_GRPC_VERSION := protoc-gen-go-grpc 1.6.1 +BUF_VERSION := 1.55.1 +PROTOC_GEN_GO_VERSION := v1.36.11 +PROTOC_GEN_GO_GRPC_VERSION := 1.6.1 -.PHONY: all gen check-tools +BUF ?= buf +BREAKING_AGAINST ?= ../.git#subdir=proto,branch=main + +.PHONY: all gen check-tools breaking all: gen check-tools: - @if [ "$$(protoc --version)" != "$(PROTOC_VERSION)" ]; then \ - echo "expected $(PROTOC_VERSION), got $$(protoc --version)"; \ + @command -v $(BUF) >/dev/null 2>&1 || { \ + echo "buf not found; install with:"; \ + echo " go install github.com/bufbuild/buf/cmd/buf@v$(BUF_VERSION)"; \ exit 1; \ + } + @installed_buf=$$($(BUF) --version 2>/dev/null); \ + if [ "$$installed_buf" != "$(BUF_VERSION)" ]; then \ + echo "warning: buf version mismatch (expected $(BUF_VERSION), got $$installed_buf)"; \ fi - @if [ "$$(protoc-gen-go --version)" != "$(PROTOC_GEN_GO_VERSION)" ]; then \ - echo "expected $(PROTOC_GEN_GO_VERSION), got $$(protoc-gen-go --version)"; \ + @command -v protoc-gen-go >/dev/null 2>&1 || { \ + echo "protoc-gen-go not found; install with:"; \ + echo " go install google.golang.org/protobuf/cmd/protoc-gen-go@$(PROTOC_GEN_GO_VERSION)"; \ exit 1; \ - fi - @if [ "$$(protoc-gen-go-grpc --version)" != "$(PROTOC_GEN_GO_GRPC_VERSION)" ]; then \ - echo "expected $(PROTOC_GEN_GO_GRPC_VERSION), got $$(protoc-gen-go-grpc --version)"; \ + } + @command -v protoc-gen-go-grpc >/dev/null 2>&1 || { \ + echo "protoc-gen-go-grpc not found; install with:"; \ + echo " go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v$(PROTOC_GEN_GO_GRPC_VERSION)"; \ exit 1; \ + } + +breaking: check-tools + @if git -C .. rev-parse --verify main >/dev/null 2>&1; then \ + $(BUF) breaking --against '$(BREAKING_AGAINST)'; \ + else \ + echo "skip breaking check: main branch not found"; \ fi -gen: check-tools - protoc --go_out=. --go_opt=paths=source_relative \ - --go-grpc_out=. --go-grpc_opt=paths=source_relative \ - service.proto - protoc --go_out=. --go_opt=paths=source_relative \ - --go-grpc_out=. --go-grpc_opt=paths=source_relative \ - internal.proto - protoc --go_out=. --go_opt=paths=source_relative \ - --go-grpc_out=. --go-grpc_opt=paths=source_relative \ - distribution.proto - protoc --go_out=. --go_opt=paths=source_relative \ - dynamodb_internal.proto - protoc --go_out=. --go_opt=paths=source_relative \ - redis_internal.proto - protoc --go_out=. --go_opt=paths=source_relative \ - --go-grpc_out=. --go-grpc_opt=paths=source_relative \ - etcd_raft.proto +gen: check-tools breaking + $(BUF) generate diff --git a/proto/buf.gen.yaml b/proto/buf.gen.yaml new file mode 100644 index 000000000..c5ca49b88 --- /dev/null +++ b/proto/buf.gen.yaml @@ -0,0 +1,8 @@ +version: v2 +plugins: + - local: protoc-gen-go + out: . + opt: paths=source_relative + - local: protoc-gen-go-grpc + out: . + opt: paths=source_relative diff --git a/proto/buf.yaml b/proto/buf.yaml new file mode 100644 index 000000000..b3b2e2276 --- /dev/null +++ b/proto/buf.yaml @@ -0,0 +1,6 @@ +version: v2 +modules: + - path: . +breaking: + use: + - FILE diff --git a/proto/distribution.pb.go b/proto/distribution.pb.go index de927c182..11eed115d 100644 --- a/proto/distribution.pb.go +++ b/proto/distribution.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.36.11 -// protoc v5.29.3 +// protoc (unknown) // source: distribution.proto package proto diff --git a/proto/distribution_grpc.pb.go b/proto/distribution_grpc.pb.go index 6401c0727..f8d9b82e4 100644 --- a/proto/distribution_grpc.pb.go +++ b/proto/distribution_grpc.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: // - protoc-gen-go-grpc v1.6.1 -// - protoc v5.29.3 +// - protoc (unknown) // source: distribution.proto package proto diff --git a/proto/dynamodb_internal.pb.go b/proto/dynamodb_internal.pb.go index 13fb2468a..2ad37852b 100644 --- a/proto/dynamodb_internal.pb.go +++ b/proto/dynamodb_internal.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.36.11 -// protoc v5.29.3 +// protoc (unknown) // source: dynamodb_internal.proto package proto diff --git a/proto/etcd_raft.pb.go b/proto/etcd_raft.pb.go index bba5e7917..39db618f8 100644 --- a/proto/etcd_raft.pb.go +++ b/proto/etcd_raft.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.36.11 -// protoc v7.34.0 +// protoc (unknown) // source: etcd_raft.proto package proto diff --git a/proto/etcd_raft_grpc.pb.go b/proto/etcd_raft_grpc.pb.go index 8c0a5915d..11a8bcb81 100644 --- a/proto/etcd_raft_grpc.pb.go +++ b/proto/etcd_raft_grpc.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: // - protoc-gen-go-grpc v1.6.1 -// - protoc v7.34.0 +// - protoc (unknown) // source: etcd_raft.proto package proto diff --git a/proto/internal.pb.go b/proto/internal.pb.go index 391c44076..09d8d171e 100644 --- a/proto/internal.pb.go +++ b/proto/internal.pb.go @@ -1,8 +1,8 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.36.11 -// protoc v7.34.0 -// source: proto/internal.proto +// protoc (unknown) +// source: internal.proto package proto @@ -60,11 +60,11 @@ func (x Op) String() string { } func (Op) Descriptor() protoreflect.EnumDescriptor { - return file_proto_internal_proto_enumTypes[0].Descriptor() + return file_internal_proto_enumTypes[0].Descriptor() } func (Op) Type() protoreflect.EnumType { - return &file_proto_internal_proto_enumTypes[0] + return &file_internal_proto_enumTypes[0] } func (x Op) Number() protoreflect.EnumNumber { @@ -73,7 +73,7 @@ func (x Op) Number() protoreflect.EnumNumber { // Deprecated: Use Op.Descriptor instead. func (Op) EnumDescriptor() ([]byte, []int) { - return file_proto_internal_proto_rawDescGZIP(), []int{0} + return file_internal_proto_rawDescGZIP(), []int{0} } type Phase int32 @@ -112,11 +112,11 @@ func (x Phase) String() string { } func (Phase) Descriptor() protoreflect.EnumDescriptor { - return file_proto_internal_proto_enumTypes[1].Descriptor() + return file_internal_proto_enumTypes[1].Descriptor() } func (Phase) Type() protoreflect.EnumType { - return &file_proto_internal_proto_enumTypes[1] + return &file_internal_proto_enumTypes[1] } func (x Phase) Number() protoreflect.EnumNumber { @@ -125,7 +125,7 @@ func (x Phase) Number() protoreflect.EnumNumber { // Deprecated: Use Phase.Descriptor instead. func (Phase) EnumDescriptor() ([]byte, []int) { - return file_proto_internal_proto_rawDescGZIP(), []int{1} + return file_internal_proto_rawDescGZIP(), []int{1} } type Mutation struct { @@ -139,7 +139,7 @@ type Mutation struct { func (x *Mutation) Reset() { *x = Mutation{} - mi := &file_proto_internal_proto_msgTypes[0] + mi := &file_internal_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -151,7 +151,7 @@ func (x *Mutation) String() string { func (*Mutation) ProtoMessage() {} func (x *Mutation) ProtoReflect() protoreflect.Message { - mi := &file_proto_internal_proto_msgTypes[0] + mi := &file_internal_proto_msgTypes[0] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -164,7 +164,7 @@ func (x *Mutation) ProtoReflect() protoreflect.Message { // Deprecated: Use Mutation.ProtoReflect.Descriptor instead. func (*Mutation) Descriptor() ([]byte, []int) { - return file_proto_internal_proto_rawDescGZIP(), []int{0} + return file_internal_proto_rawDescGZIP(), []int{0} } func (x *Mutation) GetOp() Op { @@ -205,7 +205,7 @@ type Request struct { func (x *Request) Reset() { *x = Request{} - mi := &file_proto_internal_proto_msgTypes[1] + mi := &file_internal_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -217,7 +217,7 @@ func (x *Request) String() string { func (*Request) ProtoMessage() {} func (x *Request) ProtoReflect() protoreflect.Message { - mi := &file_proto_internal_proto_msgTypes[1] + mi := &file_internal_proto_msgTypes[1] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -230,7 +230,7 @@ func (x *Request) ProtoReflect() protoreflect.Message { // Deprecated: Use Request.ProtoReflect.Descriptor instead. func (*Request) Descriptor() ([]byte, []int) { - return file_proto_internal_proto_rawDescGZIP(), []int{1} + return file_internal_proto_rawDescGZIP(), []int{1} } func (x *Request) GetIsTxn() bool { @@ -277,7 +277,7 @@ type RaftCommand struct { func (x *RaftCommand) Reset() { *x = RaftCommand{} - mi := &file_proto_internal_proto_msgTypes[2] + mi := &file_internal_proto_msgTypes[2] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -289,7 +289,7 @@ func (x *RaftCommand) String() string { func (*RaftCommand) ProtoMessage() {} func (x *RaftCommand) ProtoReflect() protoreflect.Message { - mi := &file_proto_internal_proto_msgTypes[2] + mi := &file_internal_proto_msgTypes[2] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -302,7 +302,7 @@ func (x *RaftCommand) ProtoReflect() protoreflect.Message { // Deprecated: Use RaftCommand.ProtoReflect.Descriptor instead. func (*RaftCommand) Descriptor() ([]byte, []int) { - return file_proto_internal_proto_rawDescGZIP(), []int{2} + return file_internal_proto_rawDescGZIP(), []int{2} } func (x *RaftCommand) GetRequests() []*Request { @@ -322,7 +322,7 @@ type ForwardRequest struct { func (x *ForwardRequest) Reset() { *x = ForwardRequest{} - mi := &file_proto_internal_proto_msgTypes[3] + mi := &file_internal_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -334,7 +334,7 @@ func (x *ForwardRequest) String() string { func (*ForwardRequest) ProtoMessage() {} func (x *ForwardRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_internal_proto_msgTypes[3] + mi := &file_internal_proto_msgTypes[3] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -347,7 +347,7 @@ func (x *ForwardRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ForwardRequest.ProtoReflect.Descriptor instead. func (*ForwardRequest) Descriptor() ([]byte, []int) { - return file_proto_internal_proto_rawDescGZIP(), []int{3} + return file_internal_proto_rawDescGZIP(), []int{3} } func (x *ForwardRequest) GetIsTxn() bool { @@ -375,7 +375,7 @@ type ForwardResponse struct { func (x *ForwardResponse) Reset() { *x = ForwardResponse{} - mi := &file_proto_internal_proto_msgTypes[4] + mi := &file_internal_proto_msgTypes[4] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -387,7 +387,7 @@ func (x *ForwardResponse) String() string { func (*ForwardResponse) ProtoMessage() {} func (x *ForwardResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_internal_proto_msgTypes[4] + mi := &file_internal_proto_msgTypes[4] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -400,7 +400,7 @@ func (x *ForwardResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ForwardResponse.ProtoReflect.Descriptor instead. func (*ForwardResponse) Descriptor() ([]byte, []int) { - return file_proto_internal_proto_rawDescGZIP(), []int{4} + return file_internal_proto_rawDescGZIP(), []int{4} } func (x *ForwardResponse) GetSuccess() bool { @@ -427,7 +427,7 @@ type RelayPublishRequest struct { func (x *RelayPublishRequest) Reset() { *x = RelayPublishRequest{} - mi := &file_proto_internal_proto_msgTypes[5] + mi := &file_internal_proto_msgTypes[5] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -439,7 +439,7 @@ func (x *RelayPublishRequest) String() string { func (*RelayPublishRequest) ProtoMessage() {} func (x *RelayPublishRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_internal_proto_msgTypes[5] + mi := &file_internal_proto_msgTypes[5] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -452,7 +452,7 @@ func (x *RelayPublishRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use RelayPublishRequest.ProtoReflect.Descriptor instead. func (*RelayPublishRequest) Descriptor() ([]byte, []int) { - return file_proto_internal_proto_rawDescGZIP(), []int{5} + return file_internal_proto_rawDescGZIP(), []int{5} } func (x *RelayPublishRequest) GetChannel() []byte { @@ -478,7 +478,7 @@ type RelayPublishResponse struct { func (x *RelayPublishResponse) Reset() { *x = RelayPublishResponse{} - mi := &file_proto_internal_proto_msgTypes[6] + mi := &file_internal_proto_msgTypes[6] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -490,7 +490,7 @@ func (x *RelayPublishResponse) String() string { func (*RelayPublishResponse) ProtoMessage() {} func (x *RelayPublishResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_internal_proto_msgTypes[6] + mi := &file_internal_proto_msgTypes[6] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -503,7 +503,7 @@ func (x *RelayPublishResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use RelayPublishResponse.ProtoReflect.Descriptor instead. func (*RelayPublishResponse) Descriptor() ([]byte, []int) { - return file_proto_internal_proto_rawDescGZIP(), []int{6} + return file_internal_proto_rawDescGZIP(), []int{6} } func (x *RelayPublishResponse) GetSubscribers() int64 { @@ -513,11 +513,11 @@ func (x *RelayPublishResponse) GetSubscribers() int64 { return 0 } -var File_proto_internal_proto protoreflect.FileDescriptor +var File_internal_proto protoreflect.FileDescriptor -const file_proto_internal_proto_rawDesc = "" + +const file_internal_proto_rawDesc = "" + "\n" + - "\x14proto/internal.proto\"G\n" + + "\x0einternal.proto\"G\n" + "\bMutation\x12\x13\n" + "\x02op\x18\x01 \x01(\x0e2\x03.OpR\x02op\x12\x10\n" + "\x03key\x18\x02 \x01(\fR\x03key\x12\x14\n" + @@ -557,20 +557,20 @@ const file_proto_internal_proto_rawDesc = "" + "\fRelayPublish\x12\x14.RelayPublishRequest\x1a\x15.RelayPublishResponse\"\x00B#Z!github.com/bootjp/elastickv/protob\x06proto3" var ( - file_proto_internal_proto_rawDescOnce sync.Once - file_proto_internal_proto_rawDescData []byte + file_internal_proto_rawDescOnce sync.Once + file_internal_proto_rawDescData []byte ) -func file_proto_internal_proto_rawDescGZIP() []byte { - file_proto_internal_proto_rawDescOnce.Do(func() { - file_proto_internal_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_proto_internal_proto_rawDesc), len(file_proto_internal_proto_rawDesc))) +func file_internal_proto_rawDescGZIP() []byte { + file_internal_proto_rawDescOnce.Do(func() { + file_internal_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_internal_proto_rawDesc), len(file_internal_proto_rawDesc))) }) - return file_proto_internal_proto_rawDescData + return file_internal_proto_rawDescData } -var file_proto_internal_proto_enumTypes = make([]protoimpl.EnumInfo, 2) -var file_proto_internal_proto_msgTypes = make([]protoimpl.MessageInfo, 7) -var file_proto_internal_proto_goTypes = []any{ +var file_internal_proto_enumTypes = make([]protoimpl.EnumInfo, 2) +var file_internal_proto_msgTypes = make([]protoimpl.MessageInfo, 7) +var file_internal_proto_goTypes = []any{ (Op)(0), // 0: Op (Phase)(0), // 1: Phase (*Mutation)(nil), // 2: Mutation @@ -581,7 +581,7 @@ var file_proto_internal_proto_goTypes = []any{ (*RelayPublishRequest)(nil), // 7: RelayPublishRequest (*RelayPublishResponse)(nil), // 8: RelayPublishResponse } -var file_proto_internal_proto_depIdxs = []int32{ +var file_internal_proto_depIdxs = []int32{ 0, // 0: Mutation.op:type_name -> Op 1, // 1: Request.phase:type_name -> Phase 2, // 2: Request.mutations:type_name -> Mutation @@ -598,27 +598,27 @@ var file_proto_internal_proto_depIdxs = []int32{ 0, // [0:5] is the sub-list for field type_name } -func init() { file_proto_internal_proto_init() } -func file_proto_internal_proto_init() { - if File_proto_internal_proto != nil { +func init() { file_internal_proto_init() } +func file_internal_proto_init() { + if File_internal_proto != nil { return } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: unsafe.Slice(unsafe.StringData(file_proto_internal_proto_rawDesc), len(file_proto_internal_proto_rawDesc)), + RawDescriptor: unsafe.Slice(unsafe.StringData(file_internal_proto_rawDesc), len(file_internal_proto_rawDesc)), NumEnums: 2, NumMessages: 7, NumExtensions: 0, NumServices: 1, }, - GoTypes: file_proto_internal_proto_goTypes, - DependencyIndexes: file_proto_internal_proto_depIdxs, - EnumInfos: file_proto_internal_proto_enumTypes, - MessageInfos: file_proto_internal_proto_msgTypes, + GoTypes: file_internal_proto_goTypes, + DependencyIndexes: file_internal_proto_depIdxs, + EnumInfos: file_internal_proto_enumTypes, + MessageInfos: file_internal_proto_msgTypes, }.Build() - File_proto_internal_proto = out.File - file_proto_internal_proto_goTypes = nil - file_proto_internal_proto_depIdxs = nil + File_internal_proto = out.File + file_internal_proto_goTypes = nil + file_internal_proto_depIdxs = nil } diff --git a/proto/internal_grpc.pb.go b/proto/internal_grpc.pb.go index 841cde9f7..3828db02a 100644 --- a/proto/internal_grpc.pb.go +++ b/proto/internal_grpc.pb.go @@ -1,8 +1,8 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: // - protoc-gen-go-grpc v1.6.1 -// - protoc v7.34.0 -// source: proto/internal.proto +// - protoc (unknown) +// source: internal.proto package proto @@ -157,5 +157,5 @@ var Internal_ServiceDesc = grpc.ServiceDesc{ }, }, Streams: []grpc.StreamDesc{}, - Metadata: "proto/internal.proto", + Metadata: "internal.proto", } diff --git a/proto/redis_internal.pb.go b/proto/redis_internal.pb.go index da8cec39c..f017d77a3 100644 --- a/proto/redis_internal.pb.go +++ b/proto/redis_internal.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.36.11 -// protoc v7.34.0 +// protoc (unknown) // source: redis_internal.proto package proto diff --git a/proto/service.pb.go b/proto/service.pb.go index bdf25734b..8264bf21e 100644 --- a/proto/service.pb.go +++ b/proto/service.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.36.11 -// protoc v7.34.0 +// protoc (unknown) // source: service.proto package proto diff --git a/proto/service_grpc.pb.go b/proto/service_grpc.pb.go index 031392297..246d7339a 100644 --- a/proto/service_grpc.pb.go +++ b/proto/service_grpc.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: // - protoc-gen-go-grpc v1.6.1 -// - protoc v7.34.0 +// - protoc (unknown) // source: service.proto package proto From bee4bef309f2afb356275e99bf5ff0b0d05c0a23 Mon Sep 17 00:00:00 2001 From: "Yoshiaki Ueda (bootjp)" Date: Thu, 23 Apr 2026 03:35:48 +0900 Subject: [PATCH 2/3] build(proto): address review feedback - Swap breaking rule FILE -> WIRE so non-wire-breaking evolution (field renames, etc.) is no longer flagged as breaking. - Strictly enforce buf, protoc-gen-go, and protoc-gen-go-grpc versions in check-tools; mismatches now fail rather than warn. - Fix Proto CI: explicitly fetch refs/remotes/origin/main and compare against it (branch=main is not materialized in PR checkouts). --- .github/workflows/proto.yml | 5 ++++- proto/Makefile | 24 +++++++++++++++++++----- proto/buf.yaml | 2 +- 3 files changed, 24 insertions(+), 7 deletions(-) diff --git a/.github/workflows/proto.yml b/.github/workflows/proto.yml index ad3a59baf..e9f9d7abd 100644 --- a/.github/workflows/proto.yml +++ b/.github/workflows/proto.yml @@ -27,6 +27,9 @@ jobs: - uses: actions/checkout@v6 with: fetch-depth: 0 + - name: Fetch main for breaking baseline + if: github.ref != 'refs/heads/main' + run: git fetch --no-tags --prune origin +refs/heads/main:refs/remotes/origin/main - uses: actions/setup-go@v6 with: go-version-file: 'go.mod' @@ -39,7 +42,7 @@ jobs: - name: buf breaking (against main) if: github.ref != 'refs/heads/main' working-directory: proto - run: buf breaking --against '../.git#subdir=proto,branch=main' + run: buf breaking --against '../.git#subdir=proto,ref=refs/remotes/origin/main' - name: buf generate working-directory: proto run: buf generate diff --git a/proto/Makefile b/proto/Makefile index abacc13b2..0207ef620 100644 --- a/proto/Makefile +++ b/proto/Makefile @@ -1,5 +1,5 @@ BUF_VERSION := 1.55.1 -PROTOC_GEN_GO_VERSION := v1.36.11 +PROTOC_GEN_GO_VERSION := 1.36.11 PROTOC_GEN_GO_GRPC_VERSION := 1.6.1 BUF ?= buf @@ -15,20 +15,34 @@ check-tools: echo " go install github.com/bufbuild/buf/cmd/buf@v$(BUF_VERSION)"; \ exit 1; \ } - @installed_buf=$$($(BUF) --version 2>/dev/null); \ - if [ "$$installed_buf" != "$(BUF_VERSION)" ]; then \ - echo "warning: buf version mismatch (expected $(BUF_VERSION), got $$installed_buf)"; \ + @installed=$$($(BUF) --version 2>/dev/null); \ + if [ "$$installed" != "$(BUF_VERSION)" ]; then \ + echo "buf version mismatch: expected $(BUF_VERSION), got $$installed"; \ + echo "install with: go install github.com/bufbuild/buf/cmd/buf@v$(BUF_VERSION)"; \ + exit 1; \ fi @command -v protoc-gen-go >/dev/null 2>&1 || { \ echo "protoc-gen-go not found; install with:"; \ - echo " go install google.golang.org/protobuf/cmd/protoc-gen-go@$(PROTOC_GEN_GO_VERSION)"; \ + echo " go install google.golang.org/protobuf/cmd/protoc-gen-go@v$(PROTOC_GEN_GO_VERSION)"; \ exit 1; \ } + @installed=$$(protoc-gen-go --version 2>/dev/null); \ + if [ "$$installed" != "protoc-gen-go v$(PROTOC_GEN_GO_VERSION)" ]; then \ + echo "protoc-gen-go version mismatch: expected v$(PROTOC_GEN_GO_VERSION), got $$installed"; \ + echo "install with: go install google.golang.org/protobuf/cmd/protoc-gen-go@v$(PROTOC_GEN_GO_VERSION)"; \ + exit 1; \ + fi @command -v protoc-gen-go-grpc >/dev/null 2>&1 || { \ echo "protoc-gen-go-grpc not found; install with:"; \ echo " go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v$(PROTOC_GEN_GO_GRPC_VERSION)"; \ exit 1; \ } + @installed=$$(protoc-gen-go-grpc --version 2>/dev/null); \ + if [ "$$installed" != "protoc-gen-go-grpc $(PROTOC_GEN_GO_GRPC_VERSION)" ]; then \ + echo "protoc-gen-go-grpc version mismatch: expected $(PROTOC_GEN_GO_GRPC_VERSION), got $$installed"; \ + echo "install with: go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v$(PROTOC_GEN_GO_GRPC_VERSION)"; \ + exit 1; \ + fi breaking: check-tools @if git -C .. rev-parse --verify main >/dev/null 2>&1; then \ diff --git a/proto/buf.yaml b/proto/buf.yaml index b3b2e2276..e2420f96e 100644 --- a/proto/buf.yaml +++ b/proto/buf.yaml @@ -3,4 +3,4 @@ modules: - path: . breaking: use: - - FILE + - WIRE From 851919521ec636e5b2d34f7493359b2ebdeb255b Mon Sep 17 00:00:00 2001 From: "Yoshiaki Ueda (bootjp)" Date: Fri, 24 Apr 2026 01:54:50 +0900 Subject: [PATCH 3/3] build(proto): harden breaking baseline and drift detection - Makefile breaking target no longer silently skips when main is missing. It auto-detects main or origin/main, lets BREAKING_AGAINST override, and fails closed when no baseline is reachable. - CI drift check now runs `git add -N proto/` before `git diff --exit-code` so newly generated .pb.go files (e.g. after adding a .proto but forgetting to commit the generated output) surface as a diff instead of slipping past the gate. --- .github/workflows/proto.yml | 4 ++++ proto/Makefile | 18 +++++++++++++----- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/.github/workflows/proto.yml b/.github/workflows/proto.yml index e9f9d7abd..802897934 100644 --- a/.github/workflows/proto.yml +++ b/.github/workflows/proto.yml @@ -48,6 +48,10 @@ jobs: run: buf generate - name: Fail on regenerated diff run: | + # intent-to-add surfaces newly generated .pb.go that would + # otherwise be invisible to `git diff` (adding a .proto without + # committing its generated .pb.go must fail this gate). + git add -N proto/ if ! git diff --exit-code -- proto/; then echo "::error::Generated proto files differ from committed output. Run 'make -C proto gen' and commit the result." exit 1 diff --git a/proto/Makefile b/proto/Makefile index 0207ef620..c23d840c9 100644 --- a/proto/Makefile +++ b/proto/Makefile @@ -3,7 +3,8 @@ PROTOC_GEN_GO_VERSION := 1.36.11 PROTOC_GEN_GO_GRPC_VERSION := 1.6.1 BUF ?= buf -BREAKING_AGAINST ?= ../.git#subdir=proto,branch=main +# BREAKING_AGAINST lets callers override the auto-detected baseline. +BREAKING_AGAINST ?= .PHONY: all gen check-tools breaking @@ -45,11 +46,18 @@ check-tools: fi breaking: check-tools - @if git -C .. rev-parse --verify main >/dev/null 2>&1; then \ - $(BUF) breaking --against '$(BREAKING_AGAINST)'; \ + @baseline=''; \ + if git -C .. rev-parse --verify main >/dev/null 2>&1; then \ + baseline='../.git#subdir=proto,branch=main'; \ + elif git -C .. rev-parse --verify origin/main >/dev/null 2>&1; then \ + baseline='../.git#subdir=proto,ref=refs/remotes/origin/main'; \ else \ - echo "skip breaking check: main branch not found"; \ - fi + echo "no breaking baseline found: neither 'main' nor 'origin/main' is reachable"; \ + echo "fetch main first (git fetch origin main) or override with BREAKING_AGAINST=..."; \ + exit 1; \ + fi; \ + if [ -n "$(BREAKING_AGAINST)" ]; then baseline='$(BREAKING_AGAINST)'; fi; \ + $(BUF) breaking --against "$$baseline" gen: check-tools breaking $(BUF) generate