diff --git a/cmd/protoc-gen-multi/README.md b/cmd/protoc-gen-multi/README.md index 6200107..93e9680 100644 --- a/cmd/protoc-gen-multi/README.md +++ b/cmd/protoc-gen-multi/README.md @@ -23,6 +23,7 @@ In this example, we’ll demonstrate how to package the following plugins into t - `protoc-gen-go-grpc` - `protoc-gen-go` - `protoc-gen-go-vtproto` +- `protoc-gen-grpc-gateway` ### Step 1 - Create an organization to push custom plugin(s) @@ -36,18 +37,22 @@ Create a docker image with all the protoc plugins desired, plus `protoc-gen-mult ```dockerfile # syntax=docker/dockerfile:1.6 FROM --platform=$BUILDPLATFORM golang:1.21-alpine AS build -# Install plugins. ARG TARGETOS TARGETARCH + +# Add custom plugins here RUN CGO_ENABLED=0 GOOS=$TARGETOS GOARCH=$TARGETARCH \ - go install -ldflags "-s -w" google.golang.org/protobuf/cmd/protoc-gen-go@v1.32 -RUN CGO_ENABLED=0 GOOS=$TARGETOS GOARCH=$TARGETARCH \ - go install -ldflags "-s -w" google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.3 -RUN CGO_ENABLED=0 GOOS=$TARGETOS GOARCH=$TARGETARCH \ - go install -ldflags "-s -w" github.com/planetscale/vtprotobuf/cmd/protoc-gen-go-vtproto@v0.5.0 + go install -ldflags "-s -w" google.golang.org/protobuf/cmd/protoc-gen-go@v1.32 \ + && go install -ldflags "-s -w" google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.3 \ + && go install -ldflags "-s -w" github.com/planetscale/vtprotobuf/cmd/protoc-gen-go-vtproto@v0.5.0 \ + && go install -ldflags "-s -w" github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway@v2.19 + +# Install protoc-gen-multi, must be installed. RUN CGO_ENABLED=0 GOOS=$TARGETOS GOARCH=$TARGETARCH \ go install -ldflags "-s -w" github.com/bufbuild/tools/cmd/protoc-gen-multi@latest + # Move binaries prefixed with GOOS_GOARCH to /go/bin. RUN mv /go/bin/$TARGETOS_$TARGETARCH/* /go/bin || true + # Build final image. FROM scratch COPY --from=build --link /etc/passwd /etc/passwd @@ -66,19 +71,23 @@ docker buildx build --platform linux/amd64 -t buf.example.com/custom-plugins/mul At the very minimum you’ll need the following fields set: -```bash +```yaml version: v1 name: buf.example.com/custom-plugins/multi plugin_version: v0.1.0 output_languages: - go registry: + # Add the runtime deps required by your plugins for the generated SDK. go: deps: - module: google.golang.org/protobuf version: v1.32.0 - module: google.golang.org/grpc version: v1.3.0 + - module: github.com/grpc-ecosystem/grpc-gateway/v2 + version: v2.19 + # Add the options to invoke each plugin for the generated SDK. opts: - --go_out=. - --go_opt=paths=source_relative @@ -86,6 +95,8 @@ registry: - --go-grpc_opt=paths=source_relative - --go-vtproto_out=. - --go-vtproto_opt=paths=source_relative,features=marshal+unmarshal+size + - --grpc-gateway_out=. + - --grpc-gateway_opt=paths=source_relative,generate_unbound_methods=true ``` Note that typically a `buf.plugin.yaml` file defines a single plugin. However, in this case, we have three different plugins with different versions. So the version specified here should be whatever makes sense for your setup. @@ -98,7 +109,7 @@ There are additional fields that can be set. Please refer to the `buf.plugin.yam ```bash buf beta registry plugin push \ --visibility public \ - --image buf.example.com/custom-plugins/multi:v1.0.0 \ + --image buf.example.com/custom-plugins/multi:v0.1.0 \ --override-remote=buf.example.com ``` diff --git a/cmd/protoc-gen-multi/example/.gitignore b/cmd/protoc-gen-multi/example/.gitignore new file mode 100644 index 0000000..4f62b84 --- /dev/null +++ b/cmd/protoc-gen-multi/example/.gitignore @@ -0,0 +1 @@ +gen diff --git a/cmd/protoc-gen-multi/example/Dockerfile b/cmd/protoc-gen-multi/example/Dockerfile new file mode 100644 index 0000000..e8bc70f --- /dev/null +++ b/cmd/protoc-gen-multi/example/Dockerfile @@ -0,0 +1,24 @@ +# syntax=docker/dockerfile:1.6 +FROM --platform=$BUILDPLATFORM golang:1.21-alpine AS build +ARG TARGETOS TARGETARCH + +# Add custom plugins here +RUN CGO_ENABLED=0 GOOS=$TARGETOS GOARCH=$TARGETARCH \ + go install -ldflags "-s -w" google.golang.org/protobuf/cmd/protoc-gen-go@v1.32 \ + && go install -ldflags "-s -w" google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.3 \ + && go install -ldflags "-s -w" github.com/planetscale/vtprotobuf/cmd/protoc-gen-go-vtproto@v0.5.0 \ + && go install -ldflags "-s -w" github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway@v2.19 + +# Install protoc-gen-multi, must be installed. +RUN CGO_ENABLED=0 GOOS=$TARGETOS GOARCH=$TARGETARCH \ + go install -ldflags "-s -w" github.com/bufbuild/tools/cmd/protoc-gen-multi@latest + +# Move binaries prefixed with GOOS_GOARCH to /go/bin. +RUN mv /go/bin/$TARGETOS_$TARGETARCH/* /go/bin || true + +# Build final image. +FROM scratch +COPY --from=build --link /etc/passwd /etc/passwd +COPY --from=build /go/bin/ /bin +USER nobody +ENTRYPOINT [ "protoc-gen-multi" ] diff --git a/cmd/protoc-gen-multi/example/buf.gen.yaml b/cmd/protoc-gen-multi/example/buf.gen.yaml new file mode 100644 index 0000000..b06545c --- /dev/null +++ b/cmd/protoc-gen-multi/example/buf.gen.yaml @@ -0,0 +1,19 @@ +version: v1 +managed: + enabled: true + go_package_prefix: + default: "example.com" +plugins: + # Use the plugin as a remote plugin. + # NB: ensure BSR registry and version matches. + - plugin: bufbuild.internal/local/multi:v1.0.3 + out: gen + # Set the below options to invoke different commands. + opt: --go_out=. + --go_opt=paths=source_relative + --go-grpc_out=. + --go-grpc_opt=paths=source_relative + --go-vtproto_out=. + --go-vtproto_opt=paths=source_relative,features=marshal+unmarshal+size + --grpc-gateway_out=. + --grpc-gateway_opt=paths=source_relative,generate_unbound_methods=true diff --git a/cmd/protoc-gen-multi/example/buf.plugin.yaml b/cmd/protoc-gen-multi/example/buf.plugin.yaml new file mode 100644 index 0000000..33c6c4e --- /dev/null +++ b/cmd/protoc-gen-multi/example/buf.plugin.yaml @@ -0,0 +1,25 @@ +version: v1 +name: bufbuild.internal/local/multi # Change me to your BSR plugin repository. +plugin_version: v0.1.0 # Change me to your version. +output_languages: + - go +registry: + # Add the runtime deps required by your plugins for the generated SDK. + go: + deps: + - module: google.golang.org/protobuf + version: v1.32 + - module: google.golang.org/grpc + version: v1.3 + - module: github.com/grpc-ecosystem/grpc-gateway/v2 + version: v2.19 + # Add the options to invoke each plugin for the generated SDK. + opts: + - --go_out=. + - --go_opt=paths=source_relative + - --go-grpc_out=. + - --go-grpc_opt=paths=source_relative + - --go-vtproto_out=. + - --go-vtproto_opt=paths=source_relative,features=marshal+unmarshal+size + - --grpc-gateway_out=. + - --grpc-gateway_opt=paths=source_relative,generate_unbound_methods=true diff --git a/cmd/protoc-gen-multi/example/buf.yaml b/cmd/protoc-gen-multi/example/buf.yaml new file mode 100644 index 0000000..c126332 --- /dev/null +++ b/cmd/protoc-gen-multi/example/buf.yaml @@ -0,0 +1 @@ +version: v1 diff --git a/cmd/protoc-gen-multi/example/proto/example/example.proto b/cmd/protoc-gen-multi/example/proto/example/example.proto new file mode 100644 index 0000000..a511af1 --- /dev/null +++ b/cmd/protoc-gen-multi/example/proto/example/example.proto @@ -0,0 +1,28 @@ +// Copyright 2023 Buf Technologies, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package acme.example; + +message GreetRequest { + string name = 1; +} +message GreetResponse { + string message = 1; +} + +service GreeterServier { + rpc Greet(GreetRequest) returns (GreetResponse); +} diff --git a/cmd/protoc-gen-multi/main.go b/cmd/protoc-gen-multi/main.go index 7558411..45255c4 100644 --- a/cmd/protoc-gen-multi/main.go +++ b/cmd/protoc-gen-multi/main.go @@ -144,7 +144,10 @@ func parsePlugins(args []string) ([]plugin, error) { name := strings.TrimSuffix(value, "_opt") plugin := getPlugin(name) plugin.name = name - plugin.opt = arg + if plugin.opt != "" { + plugin.opt += "," // Separate multiple opt flags with a comma. + } + plugin.opt += arg } else { return nil, fmt.Errorf("expected suffix \"_opt\" or \"_out\": %q", flag) } diff --git a/cmd/protoc-gen-multi/main_test.go b/cmd/protoc-gen-multi/main_test.go index d0c55c8..6535101 100644 --- a/cmd/protoc-gen-multi/main_test.go +++ b/cmd/protoc-gen-multi/main_test.go @@ -57,7 +57,7 @@ func TestGenerateMulti(t *testing.T) { if err := protojson.Unmarshal(requestExample, &request); err != nil { t.Fatal(err) } - request.Parameter = proto.String("--go_out=gen --go_opt=paths=source_relative --go-vtproto_out=gen --go-vtproto_opt=paths=source_relative") + request.Parameter = proto.String("--go_out=gen --go_opt=paths=source_relative --go-vtproto_out=gen --go-vtproto_opt=paths=source_relative --go-vtproto_opt=features=marshal+unmarshal+size") var response pluginpb.CodeGeneratorResponse if err := generate(context.Background(), nil, &request, &response); err != nil { t.Fatal(err) diff --git a/cmd/protoc-gen-multi/Dockerfile b/cmd/protoc-gen-multi/testdata/Dockerfile similarity index 100% rename from cmd/protoc-gen-multi/Dockerfile rename to cmd/protoc-gen-multi/testdata/Dockerfile diff --git a/cmd/protoc-gen-multi/buf.plugin.yaml b/cmd/protoc-gen-multi/testdata/buf.plugin.yaml similarity index 95% rename from cmd/protoc-gen-multi/buf.plugin.yaml rename to cmd/protoc-gen-multi/testdata/buf.plugin.yaml index b3771e6..2d71f2f 100644 --- a/cmd/protoc-gen-multi/buf.plugin.yaml +++ b/cmd/protoc-gen-multi/testdata/buf.plugin.yaml @@ -1,6 +1,6 @@ version: v1 name: bufbuild.internal/local/multi -plugin_version: v1.0.0 +plugin_version: v0.1.0 output_languages: - go registry: