Repository: googleapis/gapic-generator-go
Pull request #1624 (2025-05-16 20:26:35)

feat: add proto runtime version in header
We are adding the version of google.golang.org/protobuf that we are using in the x-goog header. The library currently only exposes their minor version. If they ever take a v2 we will need to update this code accordingly and/or ask them to expose the major version as well.

MaxVersion is documented as: "It is always the current version of the module."

Internal Bug: 415822167

codyoss: cc @parthea 

Patch:
diff --git a/internal/gengapic/gengapic.go b/internal/gengapic/gengapic.go
index 127f41c..38e90dc 100644
--- a/internal/gengapic/gengapic.go
+++ b/internal/gengapic/gengapic.go
@@ -232,9 +232,15 @@ func (g *generator) genAndCommitHelpers(scopes []string) error {
 	p := g.printf
 	g.reset()
 	g.imports[pbinfo.ImportSpec{Path: "context"}] = true
+	g.imports[pbinfo.ImportSpec{Path: "fmt"}] = true
 	g.imports[pbinfo.ImportSpec{Path: "google.golang.org/api/option"}] = true
+	g.imports[pbinfo.ImportSpec{Path: "google.golang.org/protobuf/runtime/protoimpl"}] = true
 
 	p("const serviceName = %q", g.serviceConfig.GetName())
+	// Note: protoimpl currently only exposes their minor version. If they ever
+	// take a v2 we will need to update this code accordingly and/or ask them to
+	// expose the major version as well.
+	p(`var protoVersion = fmt.Sprintf("1.%%d", protoimpl.MaxVersion)`)
 	p("")
 
 	p("// For more information on implementing a client constructor hook, see")
diff --git a/internal/gengapic/gengrpc.go b/internal/gengapic/gengrpc.go
index 5baf1d6..1bc8e06 100644
--- a/internal/gengapic/gengrpc.go
+++ b/internal/gengapic/gengrpc.go
@@ -393,7 +393,7 @@ func (g *generator) grpcClientUtilities(serv *descriptorpb.ServiceDescriptorProt
 	p("// use by Google-written clients.")
 	p("func (c *%s) setGoogleClientInfo(keyval ...string) {", lowcaseServName)
 	p(`  kv := append([]string{"gl-go", gax.GoVersion}, keyval...)`)
-	p(`  kv = append(kv, "gapic", getVersionClient(), "gax", gax.Version, "grpc", grpc.Version)`)
+	p(`  kv = append(kv, "gapic", getVersionClient(), "gax", gax.Version, "grpc", grpc.Version, "pb", protoVersion)`)
 	p(`  c.xGoogHeaders = []string{`)
 	p(`    "x-goog-api-client", gax.XGoogHeader(kv...),`)
 	if apiVersion != "" {
diff --git a/internal/gengapic/genrest.go b/internal/gengapic/genrest.go
index 7faddf5..dc3bceb 100644
--- a/internal/gengapic/genrest.go
+++ b/internal/gengapic/genrest.go
@@ -218,7 +218,7 @@ func (g *generator) restClientUtilities(serv *descriptorpb.ServiceDescriptorProt
 	p("// use by Google-written clients.")
 	p("func (c *%s) setGoogleClientInfo(keyval ...string) {", lowcaseServName)
 	p(`  kv := append([]string{"gl-go", gax.GoVersion}, keyval...)`)
-	p(`  kv = append(kv, "gapic", getVersionClient(), "gax", gax.Version, "rest", "UNKNOWN")`)
+	p(`  kv = append(kv, "gapic", getVersionClient(), "gax", gax.Version, "rest", "UNKNOWN", "pb", protoVersion)`)
 	p(`  c.xGoogHeaders = []string{`)
 	p(`    "x-goog-api-client", gax.XGoogHeader(kv...),`)
 	if apiVersion != "" {


Test patch:
diff --git a/internal/gengapic/testdata/custom_op_init.want b/internal/gengapic/testdata/custom_op_init.want
index 1a190c4..2267094 100644
--- a/internal/gengapic/testdata/custom_op_init.want
+++ b/internal/gengapic/testdata/custom_op_init.want
@@ -104,7 +104,7 @@ func NewRESTClient(ctx context.Context, opts ...option.ClientOption) (*Client, e
 // use by Google-written clients.
 func (c *restClient) setGoogleClientInfo(keyval ...string) {
 	kv := append([]string{"gl-go", gax.GoVersion}, keyval...)
-	kv = append(kv, "gapic", getVersionClient(), "gax", gax.Version, "rest", "UNKNOWN")
+	kv = append(kv, "gapic", getVersionClient(), "gax", gax.Version, "rest", "UNKNOWN", "pb", protoVersion)
 	c.xGoogHeaders = []string{
 		"x-goog-api-client", gax.XGoogHeader(kv...),
 	}
diff --git a/internal/gengapic/testdata/deprecated_client_init.want b/internal/gengapic/testdata/deprecated_client_init.want
index c45be8d..ae2a246 100644
--- a/internal/gengapic/testdata/deprecated_client_init.want
+++ b/internal/gengapic/testdata/deprecated_client_init.want
@@ -117,7 +117,7 @@ func (c *gRPCClient) Connection() *grpc.ClientConn {
 // use by Google-written clients.
 func (c *gRPCClient) setGoogleClientInfo(keyval ...string) {
 	kv := append([]string{"gl-go", gax.GoVersion}, keyval...)
-	kv = append(kv, "gapic", getVersionClient(), "gax", gax.Version, "grpc", grpc.Version)
+	kv = append(kv, "gapic", getVersionClient(), "gax", gax.Version, "grpc", grpc.Version, "pb", protoVersion)
 	c.xGoogHeaders = []string{
 		"x-goog-api-client", gax.XGoogHeader(kv...),
 	}
@@ -175,7 +175,7 @@ func NewRESTClient(ctx context.Context, opts ...option.ClientOption) (*Client, e
 // use by Google-written clients.
 func (c *restClient) setGoogleClientInfo(keyval ...string) {
 	kv := append([]string{"gl-go", gax.GoVersion}, keyval...)
-	kv = append(kv, "gapic", getVersionClient(), "gax", gax.Version, "rest", "UNKNOWN")
+	kv = append(kv, "gapic", getVersionClient(), "gax", gax.Version, "rest", "UNKNOWN", "pb", protoVersion)
 	c.xGoogHeaders = []string{
 		"x-goog-api-client", gax.XGoogHeader(kv...),
 	}
diff --git a/internal/gengapic/testdata/empty_client_init.want b/internal/gengapic/testdata/empty_client_init.want
index 1fec834..ad37c87 100644
--- a/internal/gengapic/testdata/empty_client_init.want
+++ b/internal/gengapic/testdata/empty_client_init.want
@@ -113,7 +113,7 @@ func (c *gRPCClient) Connection() *grpc.ClientConn {
 // use by Google-written clients.
 func (c *gRPCClient) setGoogleClientInfo(keyval ...string) {
 	kv := append([]string{"gl-go", gax.GoVersion}, keyval...)
-	kv = append(kv, "gapic", getVersionClient(), "gax", gax.Version, "grpc", grpc.Version)
+	kv = append(kv, "gapic", getVersionClient(), "gax", gax.Version, "grpc", grpc.Version, "pb", protoVersion)
 	c.xGoogHeaders = []string{
 		"x-goog-api-client", gax.XGoogHeader(kv...),
 		"x-goog-api-version", "v1_20240425",
@@ -170,7 +170,7 @@ func NewRESTClient(ctx context.Context, opts ...option.ClientOption) (*Client, e
 // use by Google-written clients.
 func (c *restClient) setGoogleClientInfo(keyval ...string) {
 	kv := append([]string{"gl-go", gax.GoVersion}, keyval...)
-	kv = append(kv, "gapic", getVersionClient(), "gax", gax.Version, "rest", "UNKNOWN")
+	kv = append(kv, "gapic", getVersionClient(), "gax", gax.Version, "rest", "UNKNOWN", "pb", protoVersion)
 	c.xGoogHeaders = []string{
 		"x-goog-api-client", gax.XGoogHeader(kv...),
 		"x-goog-api-version", "v1_20240425",
diff --git a/internal/gengapic/testdata/foo_client_init.want b/internal/gengapic/testdata/foo_client_init.want
index 9a5f5e7..0b4a655 100644
--- a/internal/gengapic/testdata/foo_client_init.want
+++ b/internal/gengapic/testdata/foo_client_init.want
@@ -144,7 +144,7 @@ func (c *fooGRPCClient) Connection() *grpc.ClientConn {
 // use by Google-written clients.
 func (c *fooGRPCClient) setGoogleClientInfo(keyval ...string) {
 	kv := append([]string{"gl-go", gax.GoVersion}, keyval...)
-	kv = append(kv, "gapic", getVersionClient(), "gax", gax.Version, "grpc", grpc.Version)
+	kv = append(kv, "gapic", getVersionClient(), "gax", gax.Version, "grpc", grpc.Version, "pb", protoVersion)
 	c.xGoogHeaders = []string{
 		"x-goog-api-client", gax.XGoogHeader(kv...),
 		"x-goog-api-version", "v1_20240425",
diff --git a/internal/gengapic/testdata/foo_rest_client_init.want b/internal/gengapic/testdata/foo_rest_client_init.want
index e69085c..d15cca9 100644
--- a/internal/gengapic/testdata/foo_rest_client_init.want
+++ b/internal/gengapic/testdata/foo_rest_client_init.want
@@ -116,7 +116,7 @@ func NewFooRESTClient(ctx context.Context, opts ...option.ClientOption) (*FooCli
 // use by Google-written clients.
 func (c *fooRESTClient) setGoogleClientInfo(keyval ...string) {
 	kv := append([]string{"gl-go", gax.GoVersion}, keyval...)
-	kv = append(kv, "gapic", getVersionClient(), "gax", gax.Version, "rest", "UNKNOWN")
+	kv = append(kv, "gapic", getVersionClient(), "gax", gax.Version, "rest", "UNKNOWN", "pb", protoVersion)
 	c.xGoogHeaders = []string{
 		"x-goog-api-client", gax.XGoogHeader(kv...),
 		"x-goog-api-version", "v1_20240425",
diff --git a/internal/gengapic/testdata/helpers_default_scope.want b/internal/gengapic/testdata/helpers_default_scope.want
index 9182ed6..7fd506d 100644
--- a/internal/gengapic/testdata/helpers_default_scope.want
+++ b/internal/gengapic/testdata/helpers_default_scope.want
@@ -1,4 +1,5 @@
 const serviceName = "secretmanager.googleapis.com"
+var protoVersion = fmt.Sprintf("1.%d", protoimpl.MaxVersion)
 
 // For more information on implementing a client constructor hook, see
 // https://github.com/googleapis/google-cloud-go/wiki/Customizing-constructors.
diff --git a/internal/gengapic/testdata/helpers_multiple_scopes.want b/internal/gengapic/testdata/helpers_multiple_scopes.want
index 8490d49..692a5f8 100644
--- a/internal/gengapic/testdata/helpers_multiple_scopes.want
+++ b/internal/gengapic/testdata/helpers_multiple_scopes.want
@@ -1,4 +1,5 @@
 const serviceName = "secretmanager.googleapis.com"
+var protoVersion = fmt.Sprintf("1.%d", protoimpl.MaxVersion)
 
 // For more information on implementing a client constructor hook, see
 // https://github.com/googleapis/google-cloud-go/wiki/Customizing-constructors.
diff --git a/internal/gengapic/testdata/helpers_no_scopes.want b/internal/gengapic/testdata/helpers_no_scopes.want
index 2bf4182..98a8c2b 100644
--- a/internal/gengapic/testdata/helpers_no_scopes.want
+++ b/internal/gengapic/testdata/helpers_no_scopes.want
@@ -1,4 +1,5 @@
 const serviceName = "secretmanager.googleapis.com"
+var protoVersion = fmt.Sprintf("1.%d", protoimpl.MaxVersion)
 
 // For more information on implementing a client constructor hook, see
 // https://github.com/googleapis/google-cloud-go/wiki/Customizing-constructors.
diff --git a/internal/gengapic/testdata/lro_client_init.want b/internal/gengapic/testdata/lro_client_init.want
index 619eae0..7057842 100644
--- a/internal/gengapic/testdata/lro_client_init.want
+++ b/internal/gengapic/testdata/lro_client_init.want
@@ -169,7 +169,7 @@ func (c *fooGRPCClient) Connection() *grpc.ClientConn {
 // use by Google-written clients.
 func (c *fooGRPCClient) setGoogleClientInfo(keyval ...string) {
 	kv := append([]string{"gl-go", gax.GoVersion}, keyval...)
-	kv = append(kv, "gapic", getVersionClient(), "gax", gax.Version, "grpc", grpc.Version)
+	kv = append(kv, "gapic", getVersionClient(), "gax", gax.Version, "grpc", grpc.Version, "pb", protoVersion)
 	c.xGoogHeaders = []string{
 		"x-goog-api-client", gax.XGoogHeader(kv...),
 		"x-goog-api-version", "v1_20240425",
diff --git a/internal/gengapic/testdata/service_rename.want b/internal/gengapic/testdata/service_rename.want
index d452b94..cc505cd 100644
--- a/internal/gengapic/testdata/service_rename.want
+++ b/internal/gengapic/testdata/service_rename.want
@@ -62,7 +62,7 @@ func (c *barGRPCClient) Connection() *grpc.ClientConn {
 // use by Google-written clients.
 func (c *barGRPCClient) setGoogleClientInfo(keyval ...string) {
 	kv := append([]string{"gl-go", gax.GoVersion}, keyval...)
-	kv = append(kv, "gapic", getVersionClient(), "gax", gax.Version, "grpc", grpc.Version)
+	kv = append(kv, "gapic", getVersionClient(), "gax", gax.Version, "grpc", grpc.Version, "pb", protoVersion)
 	c.xGoogHeaders = []string{
 		"x-goog-api-client", gax.XGoogHeader(kv...),
 	}