From 8de69573f8efe11945c97060359ffc6ea4bbc4bf Mon Sep 17 00:00:00 2001 From: William Johansson Date: Mon, 1 Aug 2022 16:00:17 +0200 Subject: [PATCH] feat: format JSON output to stabilize its output protojson doesn't guarantee stable JSON output, and deliberately introduce minor differences in output to prevent the illusion of this, see [1]. As this tool generates code, we'd like to keep the output as stable as possible, use the advice in [1] and [2] (at the end) and run the generated JSON through a formatter before including it in the generated code. This also changes from using the error ignoring Format() function to Marshal(). [1]: https://developers.google.com/protocol-buffers/docs/reference/go/faq#unstable-json [2]: https://github.com/golang/protobuf/issues/1121#issuecomment-627554847 --- cmd/protoc-gen-go-grpc-service-config/main.go | 19 +++++++++++++++---- .../v1/example_grpc_service_config.pb.go | 18 +++++++++--------- 2 files changed, 24 insertions(+), 13 deletions(-) diff --git a/cmd/protoc-gen-go-grpc-service-config/main.go b/cmd/protoc-gen-go-grpc-service-config/main.go index 288bd8d..829ae53 100644 --- a/cmd/protoc-gen-go-grpc-service-config/main.go +++ b/cmd/protoc-gen-go-grpc-service-config/main.go @@ -1,6 +1,7 @@ package main import ( + "bytes" "encoding/json" "flag" "fmt" @@ -80,6 +81,19 @@ func (p *plugin) generateFromProto() error { if generatedPackages[file.Desc.Package()] { return fmt.Errorf("package %s has multiple default_service_config annotations", file.Desc.Package()) } + + jsonServiceConfig, err := protojson.MarshalOptions{ + Multiline: true, + }.Marshal(defaultServiceConfig) + if err != nil { + return err + } + + var formattedServiceConfig bytes.Buffer + if err := json.Indent(&formattedServiceConfig, jsonServiceConfig, "", " "); err != nil { + return err + } + generatedPackages[file.Desc.Package()] = true g := p.gen.NewGeneratedFile( filepath.Dir(file.GeneratedFilenamePrefix)+ @@ -92,10 +106,7 @@ func (p *plugin) generateFromProto() error { g.P() g.P("// DefaultServiceConfig is the default service config for all services in the package.") g.P("// Source: ", file.Desc.Path(), ".") - g.P("const DefaultServiceConfig = `", protojson.MarshalOptions{ - Multiline: true, - Indent: " ", - }.Format(defaultServiceConfig), "`") + g.P("const DefaultServiceConfig = `", formattedServiceConfig.String(), "`") } return nil } diff --git a/internal/gen/proto/einride/serviceconfig/example/v1/example_grpc_service_config.pb.go b/internal/gen/proto/einride/serviceconfig/example/v1/example_grpc_service_config.pb.go index 7421ee5..b997944 100644 --- a/internal/gen/proto/einride/serviceconfig/example/v1/example_grpc_service_config.pb.go +++ b/internal/gen/proto/einride/serviceconfig/example/v1/example_grpc_service_config.pb.go @@ -4,18 +4,18 @@ package examplev1 // DefaultServiceConfig is the default service config for all services in the package. // Source: einride/serviceconfig/example/v1/default_service_config.proto. const DefaultServiceConfig = `{ - "methodConfig": [ + "methodConfig": [ { - "name": [ + "name": [ {} ], - "timeout": "10s", - "retryPolicy": { - "maxAttempts": 5, - "initialBackoff": "0.200s", - "maxBackoff": "60s", - "backoffMultiplier": 2, - "retryableStatusCodes": [ + "timeout": "10s", + "retryPolicy": { + "maxAttempts": 5, + "initialBackoff": "0.200s", + "maxBackoff": "60s", + "backoffMultiplier": 2, + "retryableStatusCodes": [ "UNAVAILABLE", "UNKNOWN" ]