Skip to content

Commit

Permalink
Build protobuf with buf
Browse files Browse the repository at this point in the history
It's annoying to get a recent protoc on LTS versions of Ubuntu, so I
thought I'd support my friends over at Buf and try out their tool. Turns
out that I had a lot of protobuf that didn't meet Peter's bar :)

This commit fixes all the lint errors, fixes the resulting build errors,
and moves the Makefile to use a locally-installed buf. This diff is
unmanageably enormous, but this is a personal project free of the
tyranny of code review.

Overall, buf is pretty nice. I can't find a way to skip gRPC and Twirp
codegen in the main module, so I'm just deleting the unwanted files. I
chimed in on bufbuild/buf#224 to see if
they're willing to add an allowlist.
  • Loading branch information
akshayjshah committed Feb 28, 2022
1 parent 513c262 commit 0ec8298
Show file tree
Hide file tree
Showing 40 changed files with 2,117 additions and 1,774 deletions.
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
*.bin filter=lfs diff=lfs merge=lfs -text
5 changes: 1 addition & 4 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
bin/
cover.out
internal/crosstest/crosspb/.faux
internal/pingpb/.faux
internal/statuspb/.faux
todo
.faux.pb
84 changes: 33 additions & 51 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,26 +6,37 @@ SHELL := bash
MAKEFLAGS += --warn-undefined-variables
MAKEFLAGS += --no-builtin-rules

HANDWRITTEN=$(shell find . -name '*.go' | grep -v -e '\.pb\.go$$' -e '_string.go')
MODULE=github.com/akshayjshah/rerpc
HANDWRITTEN=$(shell find . -type f -name '*.go' | grep -v -e '\.pb\.go$$' -e '_string.go')
PROTOBUFS=$(shell find . -type f -name '*.proto')

.PHONY: help
help: ## Describe useful make targets
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "%-30s %s\n", $$1, $$2}'

.PHONY: clean
clean: ## Delete build output and generated code
rm -f bin/{protoc-gen-go-grpc,protoc-gen-go-rerpc}
rm -rf internal/crosstest/crosspb/{v0,.faux}
rm -rf internal/pingpb/{v0,.faux}
rm -rf internal/statuspb/{v0,.faux}
find . -type f -name "*.proto" -exec touch {} +
clean: ## Delete build output
rm -f bin/{buf,protoc-gen-*}
rm -f .faux.pb
touch $(PROTOBUFS)

.PHONY: test
test: gen $(HANDWRITTEN) ## Run unit tests
@go test -race -cover ./...
@cd internal/crosstest && go test -race ./...

.PHONY: lint
lint: lintpb ## Lint Go and protobuf
test -z "$$(gofmt -s -l . | tee /dev/stderr)"

.PHONY: lintfix
lintfix: ## Automatically fix some lint errors
gofmt -s -w .

.PHONY: lintpb
lintpb: bin/buf $(PROTOBUFS)
@./bin/buf lint
@./bin/buf breaking --against image_v1.bin

.PHONY: cover
cover: cover.out ## Browse coverage for the main package
@go tool cover -html cover.out
Expand All @@ -34,56 +45,27 @@ cover.out: gen $(HANDWRITTEN)
@go test -cover -coverprofile=$(@) .

.PHONY: gen
gen: genpb ## Regenerate code

.PHONY: genpb
genpb: internal/statuspb/.faux internal/reflectionpb/.faux internal/healthpb/.faux internal/pingpb/.faux internal/crosstest/crosspb/.faux

internal/crosstest/crosspb/.faux: internal/crosstest/crosspb/cross.proto bin/protoc-gen-go-grpc bin/protoc-gen-go-rerpc bin/protoc-gen-twirp
PATH="./bin:$(PATH)" protoc internal/crosstest/crosspb/cross.proto \
--go_out=. \
--go_opt=module=$(MODULE) \
--go-grpc_out=. \
--go-grpc_opt=module=$(MODULE) \
--go-rerpc_out=. \
--go-rerpc_opt=module=$(MODULE) \
--twirp_out=. \
--twirp_opt=module=$(MODULE)
touch $(@)
gen: .faux.pb ## Regenerate code

internal/statuspb/.faux: internal/statuspb/status.proto
protoc internal/statuspb/status.proto \
--go_out=. \
--go_opt=module=$(MODULE)
.faux.pb: $(PROTOBUFS) bin/buf bin/protoc-gen-go-grpc bin/protoc-gen-twirp bin/protoc-gen-go-rerpc buf.gen.yaml
./bin/buf generate
rm internal/ping/v1test/ping{.twirp,_grpc.pb}.go
touch $(@)

internal/reflectionpb/.faux: internal/reflectionpb/reflection.proto
protoc internal/reflectionpb/reflection.proto \
--go_out=. \
--go_opt=module=$(MODULE)
touch $(@)

internal/healthpb/.faux: internal/healthpb/health.proto
protoc internal/healthpb/health.proto \
--go_out=. \
--go_opt=module=$(MODULE)
touch $(@)

internal/pingpb/.faux: internal/pingpb/ping.proto bin/protoc-gen-go-rerpc
PATH="./bin:$(PATH)" protoc internal/pingpb/ping.proto \
--go_out=. \
--go_opt=module=$(MODULE) \
--go-rerpc_out=. \
--go-rerpc_opt=module=$(MODULE)
touch $(@)
# Don't make this depend on $(PROTOBUFS), since we don't want to keep
# regenerating it.
image_v1.bin: bin/buf
./bin/buf build -o $(@)

bin/protoc-gen-go-grpc: internal/crosstest/go.mod
GOBIN=$(PWD)/bin cd internal/crosstest && go install google.golang.org/grpc/cmd/protoc-gen-go-grpc
touch $(@)
cd internal/crosstest && GOBIN=$(PWD)/bin go install google.golang.org/grpc/cmd/protoc-gen-go-grpc

bin/protoc-gen-go-rerpc: $(shell ls cmd/protoc-gen-go-rerpc/*.go) go.mod
go build -o $(@) ./cmd/protoc-gen-go-rerpc

bin/protoc-gen-twirp: internal/crosstest/go.mod
GOBIN=$(PWD)/bin cd internal/crosstest && go install github.com/twitchtv/twirp/protoc-gen-twirp
touch $(@)
cd internal/crosstest && GOBIN=$(PWD)/bin go install github.com/twitchtv/twirp/protoc-gen-twirp

bin/buf: internal/crosstest/go.mod
cd internal/crosstest && GOBIN=$(PWD)/bin go install github.com/bufbuild/buf/cmd/buf

17 changes: 17 additions & 0 deletions buf.gen.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
version: v1beta1
plugins:
- name: go
out: .
opt: paths=source_relative
- name: go-grpc
out: .
opt: paths=source_relative
path: ./bin/protoc-gen-go-grpc
- name: twirp
out: .
opt: paths=source_relative
path: ./bin/protoc-gen-twirp
- name: go-rerpc
out: .
opt: paths=source_relative
path: ./bin/protoc-gen-go-rerpc
7 changes: 7 additions & 0 deletions buf.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
version: v1beta1
lint:
use:
- DEFAULT
breaking:
use:
- WIRE_JSON
2 changes: 1 addition & 1 deletion client.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import (

"google.golang.org/protobuf/proto"

"github.com/akshayjshah/rerpc/internal/statuspb/v0"
statuspb "github.com/akshayjshah/rerpc/internal/status/v1"
)

// Doer is the transport-level interface reRPC expects HTTP clients to
Expand Down
4 changes: 2 additions & 2 deletions cmd/protoc-gen-go-rerpc/rerpc.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ func handshake(g *protogen.GeneratedFile) {

func service(file *protogen.File, g *protogen.GeneratedFile, service *protogen.Service) {
clientName := service.GoName + "ClientReRPC"
serverName := service.GoName + "ServerReRPC"
serverName := service.GoName + "ReRPC"

clientInterface(g, service, clientName)
clientImplementation(g, service, clientName)
Expand Down Expand Up @@ -268,7 +268,7 @@ func serverImplementation(g *protogen.GeneratedFile, service *protogen.Service,
g.P()
for _, method := range unaryMethods(service) {
g.P("func (Unimplemented", name, ") ", serverSignature(g, method), "{")
g.P("return nil, ", rerpcPackage.Ident("Errorf"), "(", rerpcPackage.Ident("CodeUnimplemented"), `, "method `, method.GoName, ` not implemented")`)
g.P("return nil, ", rerpcPackage.Ident("Errorf"), "(", rerpcPackage.Ident("CodeUnimplemented"), `, "`, method.Desc.FullName(), ` isn't implemented")`)
g.P("}")
g.P()
}
Expand Down
12 changes: 6 additions & 6 deletions example_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@ import (
"time"

"github.com/akshayjshah/rerpc"
pingpb "github.com/akshayjshah/rerpc/internal/pingpb/v0"
pingpb "github.com/akshayjshah/rerpc/internal/ping/v1test"
)

// ExamplePingServer implements some trivial business logic. The protobuf
// definition for this API is in internal/pingpb/ping.proto.
type ExamplePingServer struct {
pingpb.UnimplementedPingServerReRPC
pingpb.UnimplementedPingServiceReRPC
}

// Ping implements pingpb.PingServerReRPC.
Expand All @@ -29,10 +29,10 @@ func Example() {
checker := rerpc.NewChecker(reg) // basic health checks

mux := http.NewServeMux()
mux.Handle(pingpb.NewPingHandlerReRPC(ping, reg)) // business logic
mux.Handle(rerpc.NewReflectionHandler(reg)) // server reflection
mux.Handle(rerpc.NewHealthHandler(checker, reg)) // health checks
mux.Handle("/", rerpc.NewBadRouteHandler()) // Twirp-compatible 404s
mux.Handle(pingpb.NewPingServiceHandlerReRPC(ping, reg)) // business logic
mux.Handle(rerpc.NewReflectionHandler(reg)) // server reflection
mux.Handle(rerpc.NewHealthHandler(checker, reg)) // health checks
mux.Handle("/", rerpc.NewBadRouteHandler()) // Twirp-compatible 404s

srv := &http.Server{
Addr: ":http",
Expand Down
2 changes: 1 addition & 1 deletion handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import (

"google.golang.org/protobuf/proto"

"github.com/akshayjshah/rerpc/internal/statuspb/v0"
statuspb "github.com/akshayjshah/rerpc/internal/status/v1"
"github.com/akshayjshah/rerpc/internal/twirp"
)

Expand Down
2 changes: 1 addition & 1 deletion health.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (

"google.golang.org/protobuf/proto"

healthpb "github.com/akshayjshah/rerpc/internal/healthpb/v1"
healthpb "github.com/akshayjshah/rerpc/internal/health/v1"
)

// HealthStatus describes the health of a service.
Expand Down
3 changes: 3 additions & 0 deletions image_v1.bin
Git LFS file not shown
Loading

0 comments on commit 0ec8298

Please sign in to comment.