Skip to content

Commit 5f857ec

Browse files
authored
Merge branch 'main' into fix-fast-sql-query-b467064659
2 parents 3024faa + 79e26b8 commit 5f857ec

746 files changed

Lines changed: 3176 additions & 435 deletions

File tree

Some content is hidden

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

.github/workflows/librarian_generation_check.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,9 @@ jobs:
7373
run: |
7474
if [ -n "$(git status --porcelain)" ]; then
7575
git status
76+
echo "==================== GIT DIFF ===================="
77+
git diff
78+
echo "=================================================="
7679
echo "Regeneration produced code changes! Please run 'librarian generate --all' to update the generated files."
7780
exit 1
7881
fi

.github/workflows/generated_files_sync.yaml renamed to .github/workflows/repository_sanity.yaml

Lines changed: 1 addition & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -15,73 +15,8 @@
1515
# downstream client libraries before they are released.
1616
on:
1717
pull_request:
18-
name: generation diff
19-
env:
20-
library_generation_image_tag: 2.73.0 # {x-version-update:gapic-generator-java:current}
18+
name: Repository Config & Code Sanity
2119
jobs:
22-
root-pom:
23-
# root pom.xml does not have diff from generated one
24-
runs-on: ubuntu-latest
25-
steps:
26-
- uses: actions/checkout@v4
27-
- name: Generate root pom.xml file
28-
shell: bash
29-
run: |
30-
bash generation/run_generator_docker.sh "${library_generation_image_tag}" "${{ github.base_ref }}" \
31-
--quiet \
32-
-u "$(id -u):$(id -g)" \
33-
-v "$(pwd):/workspace" \
34-
--entrypoint python \
35-
-- \
36-
/src/library_generation/cli/generate_monorepo_root_pom.py \
37-
generate \
38-
--repository-path=/workspace
39-
- name: Fail if there's any difference
40-
run: git --no-pager diff --exit-code
41-
42-
gapic-bom:
43-
# gapic-libraries-bom does not have diff from generated one
44-
runs-on: ubuntu-latest
45-
steps:
46-
- uses: actions/checkout@v4
47-
- name: Generate gapic-libraries-bom/pom.xml
48-
shell: bash
49-
run: |
50-
bash generation/run_generator_docker.sh "${library_generation_image_tag}" "${{ github.base_ref }}" \
51-
--quiet \
52-
-u "$(id -u):$(id -g)" \
53-
-v "$(pwd):/workspace" \
54-
--entrypoint python \
55-
-- \
56-
/src/library_generation/cli/generate_monorepo_gapic_bom.py \
57-
generate \
58-
--repository-path=/workspace \
59-
--versions-file=/workspace/versions.txt
60-
- name: Fail if there's any difference
61-
run: git --no-pager diff --exit-code
62-
63-
owlbot-py:
64-
# applying templated owlbot.py config doesn't create a diff
65-
runs-on: ubuntu-latest
66-
steps:
67-
- uses: actions/checkout@v4
68-
- name: Generate owlbot.py files
69-
run: |
70-
bash generation/update_owlbot_postprocessor_config.sh
71-
- name: Fail if there's any difference (To fix, run generation/update_owlbot_postprocessor_config.sh)
72-
run: git --no-pager diff --exit-code
73-
74-
owlbot-yaml:
75-
# Each module's .Owlbot-hermetic.yaml config is configured according to set_owlbot_config.sh
76-
runs-on: ubuntu-latest
77-
steps:
78-
- uses: actions/checkout@v4
79-
- name: Check if .Owlbot-hermetic.yaml files are correctly configured
80-
run: |
81-
bash generation/set_owlbot_config.sh
82-
- name: Fail if there's any difference (To fix, run generation/set_owlbot_config.sh)
83-
run: git --no-pager diff --exit-code
84-
8520
gitignore_correctness:
8621
# Generated files should not match .gitignore
8722
runs-on: ubuntu-latest

.github/workflows/update_librarian_googleapis.yaml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,10 @@ jobs:
128128
env:
129129
GH_TOKEN: ${{ secrets.CLOUD_JAVA_BOT_GITHUB_TOKEN }}
130130
PR_TITLE: "chore: update googleapis commitish to ${{ steps.commit.outputs.short_commit }}"
131-
PR_BODY: "Updated googleapis commitish in librarian.yaml and generation_config.yaml to https://github.com/googleapis/googleapis/commit/${{ steps.commit.outputs.new_commit }}"
131+
PR_BODY: |
132+
Updated googleapis commitish in librarian.yaml and generation_config.yaml to https://github.com/googleapis/googleapis/commit/${{ steps.commit.outputs.new_commit }}
133+
134+
💡 **Note:** Please merge or close this PR so that the daily update workflow can continue to run successfully the next day. Alternatively, you can manually trigger the workflow once this PR is merged or closed.
132135
run: |
133136
set -x
134137

.release-please-manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
{
2-
".": "1.87.0"
2+
".": "1.87.1"
33
}

gapic-libraries-bom/pom.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<groupId>com.google.cloud</groupId>
55
<artifactId>gapic-libraries-bom</artifactId>
66
<packaging>pom</packaging>
7-
<version>1.87.0</version><!-- {x-version-update:google-cloud-java:current} -->
7+
<version>1.87.1</version><!-- {x-version-update:google-cloud-java:current} -->
88
<name>Google Cloud Java BOM</name>
99
<description>
1010
BOM for the libraries in google-cloud-java repository. Users should not
@@ -241,7 +241,7 @@
241241
<dependency>
242242
<groupId>com.google.cloud</groupId>
243243
<artifactId>google-cloud-biglake-bom</artifactId>
244-
<version>0.81.0</version><!-- {x-version-update:google-cloud-biglake:current} -->
244+
<version>0.81.1</version><!-- {x-version-update:google-cloud-biglake:current} -->
245245
<type>pom</type>
246246
<scope>import</scope>
247247
</dependency>

google-auth-library-java/cab-token-generator/java/com/google/auth/credentialaccessboundary/ClientSideCredentialAccessBoundaryFactory.java

Lines changed: 40 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ public class ClientSideCredentialAccessBoundaryFactory {
146146
private final Duration refreshMargin;
147147
private RefreshTask refreshTask;
148148
private final Object refreshLock = new byte[0];
149-
private IntermediateCredentials intermediateCredentials = null;
149+
private volatile IntermediateCredentials intermediateCredentials = null;
150150
private final Clock clock;
151151
private final CelCompiler celCompiler;
152152

@@ -234,8 +234,26 @@ void refreshCredentialsIfRequired() throws IOException {
234234
return;
235235
}
236236

237-
// If a refresh is required, create or retrieve the refresh task.
238-
RefreshTask currentRefreshTask = getOrCreateRefreshTask();
237+
RefreshTask currentRefreshTask;
238+
// Synchronize both the decision to refresh and the task creation to prevent a race
239+
// condition. Without this, multiple threads might concurrently determine a refresh is
240+
// needed (e.g., in ASYNC mode) and return ASYNC. The first thread would start the refresh
241+
// task. If that task completes quickly and clears the `refreshTask` reference, a subsequent
242+
// thread that also determined a refresh was needed would then see `refreshTask` as null
243+
// and incorrectly start a second, redundant refresh task.
244+
synchronized (refreshLock) {
245+
// Re-evaluate the refresh type under the lock, as another thread might have completed
246+
// the refresh while this thread was waiting for the lock.
247+
refreshType = determineRefreshType();
248+
249+
if (refreshType == RefreshType.NONE) {
250+
// No refresh needed, token is still valid.
251+
return;
252+
}
253+
254+
// If a refresh is required, create or retrieve the refresh task.
255+
currentRefreshTask = getOrCreateRefreshTask();
256+
}
239257

240258
// Handle the refresh based on the determined refresh type.
241259
switch (refreshType) {
@@ -283,16 +301,14 @@ void refreshCredentialsIfRequired() throws IOException {
283301
}
284302
}
285303

304+
// Assumes the caller holds refreshLock.
286305
private RefreshType determineRefreshType() {
287-
AccessToken intermediateAccessToken;
288-
synchronized (refreshLock) {
289-
if (intermediateCredentials == null
290-
|| intermediateCredentials.intermediateAccessToken == null) {
291-
// A blocking refresh is needed if the intermediate access token doesn't exist.
292-
return RefreshType.BLOCKING;
293-
}
294-
intermediateAccessToken = intermediateCredentials.intermediateAccessToken;
306+
if (intermediateCredentials == null
307+
|| intermediateCredentials.intermediateAccessToken == null) {
308+
// A blocking refresh is needed if the intermediate access token doesn't exist.
309+
return RefreshType.BLOCKING;
295310
}
311+
AccessToken intermediateAccessToken = intermediateCredentials.intermediateAccessToken;
296312

297313
Date expirationTime = intermediateAccessToken.getExpirationTime();
298314
if (expirationTime == null) {
@@ -322,23 +338,22 @@ private RefreshType determineRefreshType() {
322338
* responsibility of the caller to execute it. The task will clear the single flight slot upon
323339
* completion.
324340
*/
341+
// Assumes the caller holds refreshLock.
325342
private RefreshTask getOrCreateRefreshTask() {
326-
synchronized (refreshLock) {
327-
if (refreshTask != null) {
328-
// An existing refresh task is already in progress. Return a NEW RefreshTask instance with
329-
// the existing task, but set isNew to false. This indicates to the caller that a new
330-
// refresh task was NOT created.
331-
return new RefreshTask(refreshTask.task, false);
332-
}
343+
if (refreshTask != null) {
344+
// An existing refresh task is already in progress. Return a NEW RefreshTask instance with
345+
// the existing task, but set isNew to false. This indicates to the caller that a new
346+
// refresh task was NOT created.
347+
return new RefreshTask(refreshTask.task, false);
348+
}
333349

334-
final ListenableFutureTask<IntermediateCredentials> task =
335-
ListenableFutureTask.create(this::fetchIntermediateCredentials);
350+
final ListenableFutureTask<IntermediateCredentials> task =
351+
ListenableFutureTask.create(this::fetchIntermediateCredentials);
336352

337-
// Store the new refresh task in the refreshTask field before returning. This ensures that
338-
// subsequent calls to this method will return the existing task while it's still in progress.
339-
refreshTask = new RefreshTask(task, true);
340-
return refreshTask;
341-
}
353+
// Store the new refresh task in the refreshTask field before returning. This ensures that
354+
// subsequent calls to this method will return the existing task while it's still in progress.
355+
refreshTask = new RefreshTask(task, true);
356+
return refreshTask;
342357
}
343358

344359
/**

google-auth-library-java/cab-token-generator/javatests/com/google/auth/credentialaccessboundary/ClientSideCredentialAccessBoundaryFactoryTest.java

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,6 @@
7070
import java.util.Map;
7171
import java.util.concurrent.CountDownLatch;
7272
import org.junit.jupiter.api.BeforeEach;
73-
import org.junit.jupiter.api.Disabled;
7473
import org.junit.jupiter.api.Test;
7574

7675
/**
@@ -325,7 +324,6 @@ void refreshCredentialsIfRequired_blockingMultiThread() throws IOException, Inte
325324
}
326325

327326
@Test
328-
@Disabled("Flaky test: https://github.com/googleapis/google-cloud-java/issues/12871")
329327
void refreshCredentialsIfRequired_asyncMultiThread() throws IOException, InterruptedException {
330328
final ClientSideCredentialAccessBoundaryFactory factory =
331329
getClientSideCredentialAccessBoundaryFactory(RefreshType.ASYNC);
@@ -623,10 +621,16 @@ private Clock createMockClock(RefreshType refreshType, GoogleCredentials sourceC
623621
// (within the refresh margin).
624622
mockedTimeInMillis = expirationTimeInMillis - refreshMarginInMillis + 60000;
625623
when(mockClock.currentTimeMillis())
626-
.thenReturn(
627-
mockedTimeInMillis, // First call: Stale (triggers the async refresh)
628-
currentTimeInMillis // Subsequent calls: Fresh (skips redundant refreshes)
629-
);
624+
.thenAnswer(
625+
invocation -> {
626+
// If the async refresh has already been triggered (request count >= 2),
627+
// return the fresh time to skip redundant refreshes.
628+
// Note: 1st request was the initial blocking refresh.
629+
if (mockStsTransportFactory.transport.getRequestCount() >= 2) {
630+
return currentTimeInMillis;
631+
}
632+
return mockedTimeInMillis;
633+
});
630634
break;
631635
case BLOCKING:
632636
// Set mocked time so that the token requires immediate refresh (just after the minimum

java-accessapproval/google-cloud-accessapproval-bom/pom.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
<dependencyManagement>
2222
<dependencies>
23+
<!-- {x-generated-dependencies-start} -->
2324
<dependency>
2425
<groupId>com.google.cloud</groupId>
2526
<artifactId>google-cloud-accessapproval</artifactId>
@@ -35,6 +36,7 @@
3536
<artifactId>proto-google-cloud-accessapproval-v1</artifactId>
3637
<version>2.94.0</version><!-- {x-version-update:proto-google-cloud-accessapproval-v1:current} -->
3738
</dependency>
39+
<!-- {x-generated-dependencies-end} -->
3840
</dependencies>
3941
</dependencyManagement>
4042
</project>

java-accessapproval/google-cloud-accessapproval/pom.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,12 @@
4040
<groupId>com.google.api.grpc</groupId>
4141
<artifactId>proto-google-common-protos</artifactId>
4242
</dependency>
43+
<!-- {x-generated-proto-dependencies-start} -->
4344
<dependency>
4445
<groupId>com.google.api.grpc</groupId>
4546
<artifactId>proto-google-cloud-accessapproval-v1</artifactId>
4647
</dependency>
48+
<!-- {x-generated-proto-dependencies-end} -->
4749
<dependency>
4850
<groupId>com.google.guava</groupId>
4951
<artifactId>guava</artifactId>
@@ -71,11 +73,13 @@
7173
<artifactId>junit</artifactId>
7274
<scope>test</scope>
7375
</dependency>
76+
<!-- {x-generated-grpc-dependencies-start} -->
7477
<dependency>
7578
<groupId>com.google.api.grpc</groupId>
7679
<artifactId>grpc-google-cloud-accessapproval-v1</artifactId>
7780
<scope>test</scope>
7881
</dependency>
82+
<!-- {x-generated-grpc-dependencies-end} -->
7983
<!-- Need testing utility classes for generated gRPC clients tests -->
8084
<dependency>
8185
<groupId>com.google.api</groupId>

java-accessapproval/pom.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626

2727
<dependencyManagement>
2828
<dependencies>
29+
<!-- {x-generated-dependencies-start} -->
2930
<dependency>
3031
<groupId>com.google.api.grpc</groupId>
3132
<artifactId>proto-google-cloud-accessapproval-v1</artifactId>
@@ -41,15 +42,18 @@
4142
<artifactId>google-cloud-accessapproval</artifactId>
4243
<version>2.94.0</version><!-- {x-version-update:google-cloud-accessapproval:current} -->
4344
</dependency>
45+
<!-- {x-generated-dependencies-end} -->
4446

4547
<!-- Test dependencies -->
4648
</dependencies>
4749
</dependencyManagement>
4850

4951
<modules>
52+
<!-- {x-generated-modules-start} -->
5053
<module>google-cloud-accessapproval</module>
5154
<module>grpc-google-cloud-accessapproval-v1</module>
5255
<module>proto-google-cloud-accessapproval-v1</module>
56+
<!-- {x-generated-modules-end} -->
5357
<module>google-cloud-accessapproval-bom</module>
5458
</modules>
5559

0 commit comments

Comments
 (0)