Skip to content

Commit 67a2ecb

Browse files
impl(o11y): introduce gcp.client.version (#4140)
This PR introduces a new tracing attribute `gcp.client.version` to include the client library version in observability data. The changes include: - **hermetic build**: - The hermetic build scripts are updated to automatically add an entry for the new `Version.java` file in the `.OwlBot-hermetic.yaml` file for newly generated libraries. - **release-please**: - `release-please-config.json` is updated to ensure that the `Version.java` file in the showcase client is updated during the release process. - Golden files and other generated clients are updated to reflect these changes. ### Downstream Impact This change will require modifications in downstream client libraries to adopt the new `Version.java` file. Specifically: - `.OwlBot.yaml` files will need to be updated to preserve the `Version.java` file during OwlBot runs. The hermetic build scripts will handle this for new libraries, but existing libraries will need to be updated. - `release-please.config.json` files in downstream repositories will need to be updated to include the `Version.java` file in the `extra-files` section to enable version updates by `release-please`. ### Manual testing Release please does modify the version string. See https://github.com/googleapis/sdk-platform-java/pull/4141/changes#diff-7cc6cb6679ef4c6139adc5d9cdc13084773ef22e919bf2e2dce21120c76d6787
1 parent 5dce4f9 commit 67a2ecb

File tree

66 files changed

+625
-60
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

66 files changed

+625
-60
lines changed

gapic-generator-java/src/main/java/com/google/api/generator/engine/ast/ClassDefinition.java

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -203,9 +203,6 @@ public ClassDefinition build() {
203203
expr instanceof AssignmentExpr,
204204
"Class expression statement must be assignment or variable declaration");
205205
VariableExpr variableExpr = ((AssignmentExpr) expr).variableExpr();
206-
Preconditions.checkState(
207-
!variableExpr.scope().equals(ScopeNode.LOCAL),
208-
"Class variable in assignment statement cannot have a local scope");
209206
}
210207
}
211208
}

gapic-generator-java/src/main/java/com/google/api/generator/gapic/composer/Composer.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ public static List<GapicClass> generateServiceClasses(GapicContext context) {
6969
clazzes.addAll(generateClientSettingsClasses(context));
7070
clazzes.addAll(generateMockClasses(context, context.services()));
7171
clazzes.addAll(generateTestClasses(context));
72+
clazzes.addAll(generateVersionClasses(context));
7273
return clazzes;
7374
}
7475

@@ -197,6 +198,15 @@ public static List<GapicClass> generateTestClasses(GapicContext context) {
197198
return clazzes;
198199
}
199200

201+
public static List<GapicClass> generateVersionClasses(GapicContext context) {
202+
return context.services().stream()
203+
.collect(Collectors.toMap(Service::pakkage, s -> s, (s1, s2) -> s1))
204+
.values()
205+
.stream()
206+
.map(service -> LibraryVersionClassComposer.instance().generate(context, service))
207+
.collect(Collectors.toList());
208+
}
209+
200210
@VisibleForTesting
201211
static List<GapicClass> prepareExecutableSamples(List<GapicClass> clazzes) {
202212
// Include license header, apiShortName, and apiVersion
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
// Copyright 2026 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package com.google.api.generator.gapic.composer;
16+
17+
import com.google.api.generator.engine.ast.AnnotationNode;
18+
import com.google.api.generator.engine.ast.AssignmentExpr;
19+
import com.google.api.generator.engine.ast.ClassDefinition;
20+
import com.google.api.generator.engine.ast.CommentStatement;
21+
import com.google.api.generator.engine.ast.ConcreteReference;
22+
import com.google.api.generator.engine.ast.ExprStatement;
23+
import com.google.api.generator.engine.ast.LineComment;
24+
import com.google.api.generator.engine.ast.ScopeNode;
25+
import com.google.api.generator.engine.ast.StringObjectValue;
26+
import com.google.api.generator.engine.ast.TypeNode;
27+
import com.google.api.generator.engine.ast.ValueExpr;
28+
import com.google.api.generator.engine.ast.Variable;
29+
import com.google.api.generator.engine.ast.VariableExpr;
30+
import com.google.api.generator.gapic.model.GapicClass;
31+
import com.google.api.generator.gapic.model.GapicContext;
32+
import com.google.api.generator.gapic.model.Service;
33+
import java.util.Arrays;
34+
35+
public class LibraryVersionClassComposer {
36+
private static final LibraryVersionClassComposer INSTANCE = new LibraryVersionClassComposer();
37+
38+
private LibraryVersionClassComposer() {}
39+
40+
public static LibraryVersionClassComposer instance() {
41+
return INSTANCE;
42+
}
43+
44+
public GapicClass generate(GapicContext context, Service service) {
45+
String packageName = service.pakkage() + ".stub";
46+
String className = "Version";
47+
48+
String artifact = context.artifact();
49+
String artifactId = artifact;
50+
if (artifact != null && artifact.contains(":")) {
51+
artifactId = artifact.split(":")[1];
52+
}
53+
54+
VariableExpr versionVarExpr =
55+
VariableExpr.withVariable(
56+
Variable.builder().setType(TypeNode.STRING).setName("VERSION").build());
57+
AssignmentExpr versionAssignmentExpr =
58+
AssignmentExpr.builder()
59+
.setVariableExpr(
60+
versionVarExpr.toBuilder()
61+
.setIsDecl(true)
62+
.setScope(ScopeNode.LOCAL)
63+
.setIsStatic(true)
64+
.setIsFinal(true)
65+
.build())
66+
.setValueExpr(ValueExpr.withValue(StringObjectValue.withValue("0.0.0-SNAPSHOT")))
67+
.build();
68+
69+
ClassDefinition classDef =
70+
ClassDefinition.builder()
71+
.setPackageString(packageName)
72+
.setAnnotations(
73+
Arrays.asList(
74+
AnnotationNode.builder()
75+
.setType(
76+
TypeNode.withReference(
77+
ConcreteReference.withClazz(com.google.api.core.InternalApi.class)))
78+
.setDescription("For internal use only")
79+
.build()))
80+
.setScope(ScopeNode.LOCAL)
81+
.setIsFinal(true)
82+
.setName(className)
83+
.setStatements(
84+
Arrays.asList(
85+
CommentStatement.withComment(
86+
LineComment.withComment(
87+
String.format("{x-version-update-start:%s:current}", artifactId))),
88+
ExprStatement.withExpr(versionAssignmentExpr),
89+
CommentStatement.withComment(
90+
LineComment.withComment("{x-version-update-end}"))))
91+
.build();
92+
93+
return GapicClass.create(GapicClass.Kind.MAIN, classDef);
94+
}
95+
}

gapic-generator-java/src/main/java/com/google/api/generator/gapic/composer/common/AbstractServiceStubSettingsClassComposer.java

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1063,7 +1063,7 @@ private List<MethodDefinition> createClassMethods(
10631063
SettingsCommentComposer.NEW_BUILDER_METHOD_COMMENT));
10641064
javaMethods.addAll(createBuilderHelperMethods(service, typeStore));
10651065
javaMethods.add(createClassConstructor(service, methodSettingsMemberVarExprs, typeStore));
1066-
javaMethods.add(createGetLibraryMetadataMethod(context));
1066+
javaMethods.add(createGetLibraryMetadataMethod(context, service));
10671067
return javaMethods;
10681068
}
10691069

@@ -2107,7 +2107,7 @@ private static MethodDefinition createNestedClassBuildMethod(
21072107
.build();
21082108
}
21092109

2110-
private MethodDefinition createGetLibraryMetadataMethod(GapicContext context) {
2110+
private MethodDefinition createGetLibraryMetadataMethod(GapicContext context, Service service) {
21112111
TypeNode returnType = FIXED_TYPESTORE.get("LibraryMetadata");
21122112
MethodInvocationExpr libraryMetadataBuilderExpr =
21132113
MethodInvocationExpr.builder()
@@ -2133,6 +2133,23 @@ private MethodDefinition createGetLibraryMetadataMethod(GapicContext context) {
21332133
.build();
21342134
}
21352135

2136+
libraryMetadataBuilderExpr =
2137+
MethodInvocationExpr.builder()
2138+
.setExprReferenceExpr(libraryMetadataBuilderExpr)
2139+
.setMethodName("setVersion")
2140+
.setArguments(
2141+
VariableExpr.builder()
2142+
.setStaticReferenceType(
2143+
TypeNode.withReference(
2144+
VaporReference.builder()
2145+
.setName("Version")
2146+
.setPakkage(String.format("%s.stub", service.pakkage()))
2147+
.build()))
2148+
.setVariable(
2149+
Variable.builder().setName("VERSION").setType(TypeNode.STRING).build())
2150+
.build())
2151+
.build();
2152+
21362153
Expr returnExpr =
21372154
MethodInvocationExpr.builder()
21382155
.setExprReferenceExpr(libraryMetadataBuilderExpr)

gapic-generator-java/src/test/java/com/google/api/generator/engine/ast/ClassDefinitionTest.java

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -293,31 +293,6 @@ void invalidClassDefinition_extendsImplementsSameType() {
293293
});
294294
}
295295

296-
@Test
297-
void invalidClassDefinition_assignmentWithUnscopedVariableExprStatement() {
298-
Variable variable = createVariable("x", TypeNode.INT);
299-
VariableExpr variableExpr =
300-
VariableExpr.builder().setVariable(variable).setIsDecl(true).build();
301-
302-
Variable anotherVariable = createVariable("y", TypeNode.INT);
303-
Expr valueExpr = VariableExpr.builder().setVariable(anotherVariable).build();
304-
305-
AssignmentExpr assignmentExpr =
306-
AssignmentExpr.builder().setVariableExpr(variableExpr).setValueExpr(valueExpr).build();
307-
308-
List<Statement> statements = Arrays.asList(ExprStatement.withExpr(assignmentExpr));
309-
assertThrows(
310-
IllegalStateException.class,
311-
() -> {
312-
ClassDefinition.builder()
313-
.setPackageString("com.google.example.library.v1.stub")
314-
.setName("LibraryServiceStub")
315-
.setScope(ScopeNode.PUBLIC)
316-
.setStatements(statements)
317-
.build();
318-
});
319-
}
320-
321296
@Test
322297
void invalidClassDefinition_unscopedVariableExprStatement() {
323298
List<Statement> statements =
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// Copyright 2026 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package com.google.api.generator.gapic.composer;
16+
17+
import com.google.api.generator.gapic.model.GapicClass;
18+
import com.google.api.generator.gapic.model.GapicContext;
19+
import com.google.api.generator.gapic.model.Service;
20+
import com.google.api.generator.test.framework.Assert;
21+
import com.google.api.generator.test.protoloader.GrpcTestProtoLoader;
22+
import org.junit.Test;
23+
24+
public class LibraryVersionClassComposerTest {
25+
26+
@Test
27+
public void generateVersionClasses() {
28+
GapicContext context = GrpcTestProtoLoader.instance().parseShowcaseEcho();
29+
Service service = context.services().get(0);
30+
GapicClass clazz = LibraryVersionClassComposer.instance().generate(context, service);
31+
32+
Assert.assertGoldenClass(this.getClass(), clazz, "EchoVersion.golden");
33+
}
34+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package com.google.showcase.v1beta1.stub;
2+
3+
import com.google.api.core.InternalApi;
4+
5+
@InternalApi("For internal use only")
6+
final class Version {
7+
// {x-version-update-start:gapic-showcase:current}
8+
static final String VERSION = "0.0.0-SNAPSHOT";
9+
// {x-version-update-end}
10+
11+
}

gapic-generator-java/src/test/java/com/google/api/generator/gapic/composer/grpc/goldens/ApiVersionTestingStubSettings.golden

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ public class EchoWithVersionStubSettings extends StubSettings<EchoWithVersionStu
170170

171171
@Override
172172
protected LibraryMetadata getLibraryMetadata() {
173-
return LibraryMetadata.newBuilder().build();
173+
return LibraryMetadata.newBuilder().setVersion(Version.VERSION).build();
174174
}
175175

176176
/** Builder for EchoWithVersionStubSettings. */

gapic-generator-java/src/test/java/com/google/api/generator/gapic/composer/grpc/goldens/DeprecatedServiceStubSettings.golden

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ public class DeprecatedServiceStubSettings extends StubSettings<DeprecatedServic
187187

188188
@Override
189189
protected LibraryMetadata getLibraryMetadata() {
190-
return LibraryMetadata.newBuilder().build();
190+
return LibraryMetadata.newBuilder().setVersion(Version.VERSION).build();
191191
}
192192

193193
/** Builder for DeprecatedServiceStubSettings. */

gapic-generator-java/src/test/java/com/google/api/generator/gapic/composer/grpc/goldens/EchoServiceSelectiveGapicStubSettings.golden

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,7 @@ public class EchoServiceShouldGeneratePartialUsualStubSettings
224224

225225
@Override
226226
protected LibraryMetadata getLibraryMetadata() {
227-
return LibraryMetadata.newBuilder().build();
227+
return LibraryMetadata.newBuilder().setVersion(Version.VERSION).build();
228228
}
229229

230230
/** Builder for EchoServiceShouldGeneratePartialUsualStubSettings. */

0 commit comments

Comments
 (0)