Skip to content

Commit 11741bf

Browse files
authored
Merge branch 'main' into bigtable-admin-client
2 parents 6529ca3 + b2bc2d4 commit 11741bf

2,010 files changed

Lines changed: 252267 additions & 27351 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.
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
---
2+
name: api-lifecycle
3+
description: Guidelines and playbooks for managing the API lifecycle (BetaApi, GA, ObsoleteApi, Deprecated, and Removal) in the Google Cloud Java SDK. Use this skill when modifying, deprecating, or introducing new public API surfaces.
4+
---
5+
6+
# API Lifecycle & Stability Guide
7+
8+
This guide defines the lifecycle phases and stability annotations of public APIs inside the Google Cloud Java SDK. Use this to ensure all public methods, classes, and fields correctly adhere to Semantic Versioning (Semver) and safely transition through deprecation phases.
9+
10+
> [!IMPORTANT]
11+
> **Scope & Visibility Rule**
12+
> This guideline applies **ONLY to public API surfaces** (e.g., `public` classes, interfaces, methods, and fields) that are exposed to external/downstream consumers. It does **NOT** apply to private, package-private, or internal implementation details.
13+
14+
---
15+
16+
## Design Principle: Minimize Public API Surface
17+
18+
To reduce maintenance overhead and ensure long-term flexibility, developers should actively avoid creating public APIs unless absolutely necessary.
19+
20+
* **Default to Restrictive Visibility**: Always default to the most restrictive access modifier (`private`, `package-private`, or `@InternalApi`) for new classes, methods, and fields. Only expose an API as `public` if there is a clear, justified requirement for external consumers.
21+
* **Exposing Public APIs Commits Us**: Every public class, method, or field represents a strict compatibility contract under Semantic Versioning. Once public, modifying or removing it requires a long, multi-phase deprecation cycle.
22+
* Prefer Internal Utilities: If functionality is only needed within the same package or module, keep it private or package-private. Do not make it public "just in case".
23+
24+
---
25+
26+
## The API Lifecycle Flow
27+
28+
An API does **not** have to start with `@BetaApi`. Stable, well-designed features can be introduced directly as General Availability (GA). The `@BetaApi` annotation is reserved for experimental, preview, or unstable APIs.
29+
30+
Below is the transition flow for public APIs:
31+
32+
**Standard Lifecycle (Direct to GA):**
33+
`General Availability (GA) ──> @ObsoleteApi (Staged Deprecation) ──> @Deprecated (Official) ──> Removed`
34+
35+
**Experimental Lifecycle (Beta first):**
36+
`@BetaApi (Experimental) ──> General Availability (GA) ──> @ObsoleteApi (Staged Deprecation) ──> @Deprecated (Official) ──> Removed`
37+
38+
---
39+
40+
## API Lifecycle Stages
41+
42+
### 1. `@BetaApi` (Experimental Phase)
43+
* **Purpose**: Used for experimental, preview, or unstable API surfaces.
44+
* **Semver Policy**: Treated as a **"0.x" feature inside a "1.x" library**. Subject to incompatible changes or removal between minor and patch releases at any time.
45+
* **Graduation Policy**: Not all APIs start here. Many APIs go directly to GA. If an API does start as `@BetaApi`, it is intended to eventually graduate to a GA feature by removing the `@BetaApi` annotation.
46+
* **Usage Rule**: Do **NOT** depend on `@BetaApi` features inside a public library `B` that has downstream consumers, *unless* the consuming components of library `B` are also marked with `@BetaApi`.
47+
* **Exception**: `google-cloud-java` is allowed to depend on `@BetaApi` features in `gax-java` without declaring the consuming code `@BetaApi`, as they move in lockstep.
48+
49+
### 2. General Availability (GA)
50+
* **Purpose**: Stable API surfaces intended for production use.
51+
* Policy: Deprecation or breaking changes to GA APIs are considered breaking changes and should generally not be performed under a minor version release using standard @Deprecated.
52+
53+
### 3. `@ObsoleteApi` (Staged Deprecation)
54+
* **Purpose**: Signals to users that an API will be deprecated in a future version, allowing them to transition to alternative methods before official deprecation.
55+
* **Policy**: Used during minor version releases.
56+
* **Usage Guidelines**:
57+
* **Annotation**: Apply `@ObsoleteApi("Reason or alternative instructions")`. A descriptive reason is required.
58+
* **Javadoc**: Detail the replacement or migration path, referencing alternative methods via `{@link}`.
59+
* **IDE Impact**: Does not trigger IDE compilation/strike-through warnings, keeping downstream builds warning-free.
60+
61+
### 4. `@Deprecated` (Official Deprecation)
62+
* **Purpose**: Officially deprecates the API in the editor/IDE, producing compiler warnings and strike-throughs.
63+
* **Policy**: Strongly recommended to be applied during **Major Version Releases** (e.g., `v2.0.0`), or in rare emergency cases to fix critical security vulnerabilities. However, it can be acceptable in minor version releases if the library owners explicitly review and determine that the deprecation is low-risk for downstream consumers.
64+
* **Usage Guidelines**:
65+
* **Annotation**: Apply Java's standard `@Deprecated` annotation to the code element.
66+
* **Javadoc**: Add the standard `@deprecated` Javadoc tag describing alternative APIs or transition steps.
67+
68+
### 5. Removal
69+
* **Purpose**: Complete removal of the API from the codebase.
70+
* **Policy**: Performed in a subsequent major version release following official deprecation.
71+
* **Usage Guidelines**:
72+
* **Action**: Completely delete the class, interface, method, or field, along with its Javadoc and annotations.
73+
* **Validation**: Verify that all internal usages, references, and tests within the monorepo are fully cleaned up or migrated.
74+
75+
---
76+
77+
## API Stability & Visibility Annotations
78+
79+
While the standard **API Lifecycle Stages** section above defines how public APIs transition over time, the SDK also utilizes specialized stability annotations. These annotations serve as "exceptions" or "special contracts" that dictate how Semantic Versioning applies to public elements:
80+
81+
### 1. `@InternalApi`
82+
* **Definition**: Technically `public` because of Java's access modifier limitations, but intended **only** for internal use.
83+
* **Semver Policy**: For the purposes of semver, these are considered **private**. They can be modified or deleted in any minor or patch release without breaking compatibility.
84+
85+
### 2. `@InternalExtensionOnly`
86+
* **Definition**: A `public` interface that is only intended to be implemented by internal SDK classes, though it can be consumed publicly.
87+
* **Semver Policy**: We reserve the right to add new methods to these interfaces without providing default implementations in minor/patch releases. Downstream consumers should **not** write custom implementations of these interfaces.
88+
89+
*(Note: For experimental public APIs, see the `@BetaApi` stage in the Lifecycle Stages section above.)*
90+
91+
---
92+
93+
## Checklist for API Modifiers & Code Reviewers
94+
95+
- [ ] **Is the API GA?** If so, do **NOT** apply `@Deprecated` directly in a minor release. Apply `@ObsoleteApi` first.
96+
- [ ] **Is it intended only for internal use?** If so, mark it `@InternalApi` so downstream users don't rely on it.
97+
- [ ] **Is it an interface meant only for internal implementation?** Mark it `@InternalExtensionOnly` to protect future extensions.
98+
- [ ] **Does `@ObsoleteApi` or `@Deprecated` have a `value` parameter?** The string must explain *why* and *what* the user should do instead.
99+
- [ ] **Does the Javadoc link to alternatives?** Use `{@link #alternativeMethod()}` so the user can easily navigate in their IDE.

.github/CODEOWNERS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
/java-vertexai/ @googleapis/vertexai-team @googleapis/cloud-sdk-java-team
1010
/java-bigquerystorage/ @googleapis/bigquery-team @googleapis/cloud-sdk-java-team
1111
/java-bigquery/ @googleapis/bigquery-team @googleapis/cloud-sdk-java-team
12+
/java-bigquery-jdbc/ @googleapis/bigquery-developer-tools-team @googleapis/bigquery-team @googleapis/cloud-sdk-java-team
13+
/grpc-gcp-java/ @googleapis/spanner-team @googleapis/cloud-sdk-java-team
1214
/java-spanner/ @googleapis/spanner-team @googleapis/cloud-sdk-java-team
1315
/java-spanner-jdbc/ @googleapis/spanner-team @googleapis/cloud-sdk-java-team
1416
/google-auth-library-java/ @googleapis/cloud-sdk-auth-team @googleapis/cloud-sdk-java-team @googleapis/aion-team

.github/requirements.txt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -100,9 +100,9 @@ charset-normalizer==3.3.2 \
100100
--hash=sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519 \
101101
--hash=sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561
102102
# via requests
103-
idna==3.7 \
104-
--hash=sha256:028ff3aadf0609c1fd278d8ea3089299412a7a8b9bd005dd08b9f8285bcb5cfc \
105-
--hash=sha256:82fee1fc78add43492d3a1898bfa6d8a904cc97d8427f683ed8e798d07761aa0
103+
idna==3.15 \
104+
--hash=sha256:048adeaf8c2d788c40fee287673ccaa74c24ffd8dcf09ffa555a2fbb59f10ac8 \
105+
--hash=sha256:ca962446ea538f7092a95e057da437618e886f4d349216d2b1e294abfdb65fdc
106106
# via requests
107107
requests==2.33.0 \
108108
--hash=sha256:3324635456fa185245e24865e810cecec7b4caf933d7eb133dcde67d48cee69b \

.github/workflows/ci.yaml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,8 @@ jobs:
3636
with:
3737
filters: |
3838
src:
39-
- '!(google-auth-library-java|java-bigquery|java-bigquerystorage|java-bigtable|java-datastore|java-firestore|java-logging|java-logging-logback|java-pubsub|java-spanner|java-storage)/**/*.java'
40-
- '!(google-auth-library-java|java-bigquery|java-bigquerystorage|java-bigtable|java-datastore|java-firestore|java-logging|java-logging-logback|java-pubsub|java-spanner|java-storage)/**/pom.xml'
39+
- '!(google-auth-library-java|grpc-gcp-java|java-bigquery|java-bigquery-jdbc|java-bigquerystorage|java-bigtable|java-datastore|java-firestore|java-logging|java-logging-logback|java-pubsub|java-spanner|java-storage)/**/*.java'
40+
- '!(google-auth-library-java|grpc-gcp-java|java-bigquery|java-bigquery-jdbc|java-bigquerystorage|java-bigtable|java-datastore|java-firestore|java-logging|java-logging-logback|java-pubsub|java-spanner|java-storage)/**/pom.xml'
4141
- 'pom.xml'
4242
ci:
4343
- '.github/workflows/ci.yaml'
@@ -123,6 +123,8 @@ jobs:
123123
filters: |
124124
google-auth-library-java:
125125
- 'google-auth-library-java/**'
126+
grpc-gcp-java:
127+
- 'grpc-gcp-java/**'
126128
java-bigquery:
127129
- 'java-bigquery/**'
128130
- 'google-auth-library-java/**/*.java'
@@ -160,6 +162,7 @@ jobs:
160162
- 'sdk-platform-java/gapic-generator-java-pom-parent/pom.xml'
161163
java-spanner:
162164
- 'java-spanner/**'
165+
- 'grpc-gcp-java/**'
163166
- 'google-auth-library-java/**/*.java'
164167
- 'google-auth-library-java/**/pom.xml'
165168
- 'sdk-platform-java/**/*.java'
Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
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+
# Github action job to test core java library features on
15+
# downstream client libraries before they are released.
16+
on:
17+
push:
18+
branches:
19+
- main
20+
pull_request:
21+
name: java-bigquery-jdbc ci
22+
env:
23+
BUILD_SUBDIR: java-bigquery-jdbc
24+
jobs:
25+
filter:
26+
runs-on: ubuntu-latest
27+
outputs:
28+
library: ${{ steps.filter.outputs.library }}
29+
steps:
30+
- uses: actions/checkout@v4
31+
- uses: dorny/paths-filter@fbd0ab8f3e69293af611ebaee6363fc25e6d187d # v4.0.1
32+
id: filter
33+
with:
34+
filters: |
35+
library:
36+
- 'java-bigquery/**'
37+
- 'java-bigquery-jdbc/**'
38+
- 'java-bigquerystorage/**'
39+
- '.github/workflows/java-bigquery-jdbc-ci.yaml'
40+
- 'google-auth-library-java/**/*.java'
41+
- 'google-auth-library-java/**/pom.xml'
42+
- 'sdk-platform-java/**/*.java'
43+
- 'sdk-platform-java/java-shared-dependencies/**/pom.xml'
44+
- 'sdk-platform-java/gapic-generator-java-pom-parent/pom.xml'
45+
units:
46+
needs: filter
47+
if: ${{ needs.filter.outputs.library == 'true' }}
48+
runs-on: ubuntu-latest
49+
strategy:
50+
fail-fast: false
51+
matrix:
52+
java: [11, 17, 21, 25]
53+
steps:
54+
- uses: actions/checkout@v4
55+
- uses: actions/setup-java@v4
56+
with:
57+
distribution: temurin
58+
java-version: ${{matrix.java}}
59+
- run: java -version
60+
- run: .kokoro/build.sh
61+
env:
62+
JOB_TYPE: test
63+
units-java8:
64+
needs: filter
65+
if: ${{ needs.filter.outputs.library == 'true' }}
66+
# Building using Java 17 and run the tests with Java 8 runtime
67+
name: "units (8)"
68+
runs-on: ubuntu-latest
69+
steps:
70+
- uses: actions/checkout@v4
71+
- uses: actions/setup-java@v4
72+
with:
73+
java-version: 8
74+
distribution: temurin
75+
- name: "Set jvm system property environment variable for surefire plugin (unit tests)"
76+
# Maven surefire plugin (unit tests) allows us to specify JVM to run the tests.
77+
# https://maven.apache.org/surefire/maven-surefire-plugin/test-mojo.html#jvm
78+
run: echo "SUREFIRE_JVM_OPT=-Djvm=${JAVA_HOME}/bin/java -P !java17" >> $GITHUB_ENV
79+
shell: bash
80+
- uses: actions/setup-java@v4
81+
with:
82+
java-version: 17
83+
distribution: temurin
84+
- run: .kokoro/build.sh
85+
env:
86+
JOB_TYPE: test
87+
windows:
88+
needs: filter
89+
if: ${{ needs.filter.outputs.library == 'true' }}
90+
runs-on: windows-latest
91+
steps:
92+
- name: Support longpaths
93+
run: git config --system core.longpaths true
94+
- name: Support longpaths
95+
run: git config --system core.longpaths true
96+
- uses: actions/checkout@v4
97+
- uses: actions/setup-java@v4
98+
with:
99+
distribution: temurin
100+
java-version: 8
101+
- run: java -version
102+
- run: .kokoro/build.sh
103+
env:
104+
JOB_TYPE: test
105+
dependencies:
106+
needs: filter
107+
if: ${{ needs.filter.outputs.library == 'true' }}
108+
runs-on: ubuntu-latest
109+
steps:
110+
- uses: actions/checkout@v4
111+
- uses: actions/setup-java@v4
112+
with:
113+
distribution: temurin
114+
java-version: 17
115+
- run: .kokoro/dependencies.sh
116+
javadoc:
117+
needs: filter
118+
if: ${{ needs.filter.outputs.library == 'true' }}
119+
runs-on: ubuntu-latest
120+
steps:
121+
- uses: actions/checkout@v4
122+
- uses: actions/setup-java@v4
123+
with:
124+
distribution: temurin
125+
java-version: 17
126+
- run: java -version
127+
- run: .kokoro/build.sh
128+
env:
129+
JOB_TYPE: javadoc
130+
lint:
131+
needs: filter
132+
if: ${{ needs.filter.outputs.library == 'true' }}
133+
runs-on: ubuntu-latest
134+
steps:
135+
- uses: actions/checkout@v4
136+
with:
137+
fetch-depth: 0
138+
- uses: actions/setup-java@v4
139+
with:
140+
distribution: temurin
141+
java-version: 17
142+
- run: java -version
143+
- run: .kokoro/build.sh
144+
env:
145+
JOB_TYPE: lint
146+
HEAD_SHA: ${{ github.event.pull_request.head.sha || github.sha }}
147+
BASE_SHA: ${{ github.event.pull_request.base.sha || github.event.before }}
148+
required:
149+
needs: [ units, units-java8, windows, dependencies, javadoc, lint ]
150+
name: conditional-required-check
151+
if: ${{ always() }} # Always run even if any "needs" jobs fail
152+
runs-on: ubuntu-22.04
153+
steps:
154+
- name: Fail if any previous failure
155+
if: ${{ contains(needs.*.result, 'failure') }}
156+
run: exit 1
157+
- name: Success otherwise
158+
run: echo "Success!"

.github/workflows/sdk-platform-java-shared_dependencies.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,4 +40,4 @@ jobs:
4040
mvn install -B -ntp -DskipTests -Pquick-build
4141
- name: Check the BOM content satisfies the upper-bound-check test case
4242
run: mvn -B -V -ntp verify -Pquick-build
43-
working-directory: sdk-plaform-java/java-shared-dependencies/upper-bound-check
43+
working-directory: sdk-platform-java/java-shared-dependencies/upper-bound-check

.github/workflows/sdk-platform-java-sonar.yaml

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,7 @@ jobs:
7979
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any
8080
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN_FOR_GENERATOR }}
8181
run: |
82-
mvn -B verify -Pquick-build \
83-
-DenableFullTestCoverage \
82+
mvn -B verify -Pquick-build -Djacoco.skip=false \
8483
-Penable-integration-tests \
8584
org.sonarsource.scanner.maven:sonar-maven-plugin:sonar \
8685
-Dsonar.projectKey=googleapis_google-cloud-java_generator \
@@ -92,7 +91,7 @@ jobs:
9291
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any
9392
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN_FOR_SHOWCASE }}
9493
run: |
95-
mvn -B clean verify -Pquick-build \
94+
mvn -B clean verify -Pquick-build -Djacoco.skip=false \
9695
-DskipUnitTests \
9796
-Penable-integration-tests \
9897
-DenableShowcaseTestCoverage \

.kokoro/bigtable-conformance.sh

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ retry_with_backoff 3 10 \
3737
-DskipTests=true \
3838
-Dclirr.skip=true \
3939
-Denforcer.skip=true \
40+
-Dcheckstyle.skip=true \
4041
-Dmaven.javadoc.skip=true \
4142
-Dgcloud.download.skip=true \
4243
-T 1C
@@ -48,7 +49,7 @@ set +e
4849
# Build the proxy
4950
pushd .
5051
cd java-bigtable/test-proxy
51-
mvn clean install -U -DskipTests
52+
mvn clean install -U -DskipTests -Dcheckstyle.skip=true
5253
popd
5354

5455
declare -a configs=("default" "enable_all")

.kokoro/common.sh

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ excluded_modules=(
2121
'java-vertexai'
2222
'java-logging'
2323
'java-bigquery'
24+
'java-bigquery-jdbc'
2425
'java-bigquerystorage'
2526
'java-datastore'
2627
'java-logging-logback'
@@ -39,6 +40,8 @@ excluded_modules=(
3940
'java-firestore'
4041
'java-bigtable'
4142
'java-pubsub'
43+
'java-common-protos'
44+
'java-iam'
4245
)
4346

4447
function retry_with_backoff {

.kokoro/presubmit/bigquery-graalvm-native-presubmit.cfg

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,4 @@ env_vars: {
4141
value: "java-bigquery"
4242
}
4343

44-
env_vars: {
45-
key: "INTEGRATION_TEST_ARGS"
46-
value: "-pl !google-cloud-bigquery-jdbc"
47-
}
44+

0 commit comments

Comments
 (0)