From 3b184efd007f736baa8571d537f9e26e6614a263 Mon Sep 17 00:00:00 2001 From: Sergey Chernov Date: Thu, 3 Sep 2026 14:19:40 -0700 Subject: [PATCH 1/6] added workflow update --- .github/jwks.json | 14 ++++++++ .github/scripts/.gitignore | 5 +++ .github/scripts/generate_jwt.py | 60 ++++++++++++++++++++++++++++++++ .github/scripts/requirements.txt | 2 ++ .github/workflows/build.yml | 8 ++++- docs/clickhouse-docs/client.mdx | 44 +++++++++++++++++++++-- docs/clickhouse-docs/jdbc.mdx | 49 ++++++++++++++++++++++++++ 7 files changed, 179 insertions(+), 3 deletions(-) create mode 100644 .github/jwks.json create mode 100644 .github/scripts/.gitignore create mode 100644 .github/scripts/generate_jwt.py create mode 100644 .github/scripts/requirements.txt diff --git a/.github/jwks.json b/.github/jwks.json new file mode 100644 index 000000000..ba11d4653 --- /dev/null +++ b/.github/jwks.json @@ -0,0 +1,14 @@ +{ + "keys": [ + { + "e": "AQAB", + "kid": "ZoA8VvkIi_fBxd5DEx9xekutcCztcanNFIHOTQp5aDo", + "kty": "RSA", + "n": "q-qV7VPWHe0-Pj-sgmq0_szurrPPwAsq3BPTllfFNQcQq5967SdS5jiCKhpVKYeXng468e9yimOMPzLIVBoCkV9ul9ruZDDJiPBoQ-_Pp5IuQQWTFUmnJ-ONkczVdb-FdkfQz4z1NVz_blCdOVyVPmeE9gh1S1V4g3kQazznwxKgOlJM4mO23j8xOmhGIL0w1IktP09vqicZoOsq3-RgN0x6jXdiv5BnTAh1yDKIFRRqIa7idz55Bv_AGosH7hsKHYoCwfiPSCeVc4StYIhokj9HZswnMyAStELfQWen2Ev3pDuiANI4TuE34TOx0LsinVoWeEtiMaRi67mYFk5JIQ", + "use": "sig", + "x5c": [ + "MIIDYjCCAkqgAwIBAgIUH0aS9zvv7N9L9UR/HmOaA5k9l/4wDQYJKoZIhvcNAQELBQAwazELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDVNhbiBGcmFuY2lzY28xGDAWBgNVBAoMD015IE9yZ2FuaXphdGlvbjEVMBMGA1UEAwwMbXlkb21haW4uY29tMB4XDTI2MDkwMzIxMDgxOFoXDTI3MDkwMzIxMDgxOFowazELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDVNhbiBGcmFuY2lzY28xGDAWBgNVBAoMD015IE9yZ2FuaXphdGlvbjEVMBMGA1UEAwwMbXlkb21haW4uY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAq+qV7VPWHe0+Pj+sgmq0/szurrPPwAsq3BPTllfFNQcQq5967SdS5jiCKhpVKYeXng468e9yimOMPzLIVBoCkV9ul9ruZDDJiPBoQ+/Pp5IuQQWTFUmnJ+ONkczVdb+FdkfQz4z1NVz/blCdOVyVPmeE9gh1S1V4g3kQazznwxKgOlJM4mO23j8xOmhGIL0w1IktP09vqicZoOsq3+RgN0x6jXdiv5BnTAh1yDKIFRRqIa7idz55Bv/AGosH7hsKHYoCwfiPSCeVc4StYIhokj9HZswnMyAStELfQWen2Ev3pDuiANI4TuE34TOx0LsinVoWeEtiMaRi67mYFk5JIQIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQCD5HRitEaurh0QOv/sqH0eFZ5KWAWbr4gP3EU9tgEAGAo0DQz2v7ov+wey4aTplXKtXIxB7aPobXFqTBEI6yD+to2UgmC35U+0tHZTgDG+BSmDEERoj+/Guk55LuUwODvQJviFUzEM9q7I9fLANPVkhY/SJ2/hl1ftxqxNFAH8mVzUbBNb2DMDc30eicHvsJUg0bqKoB5pLciyYqFsyA9z0x8ZaVpPVbXnVOHbzilp0jnhHeyLr+JCYH2UKfH/zFjxvcMP/q3M+HHCYyHXgdhMIFGBRE7xUMZjRnir28aUyet6hB5iV4wM8Yjd2mVaAsYtPqY8GnQxISzhUJ9rugie" + ] + } + ] +} diff --git a/.github/scripts/.gitignore b/.github/scripts/.gitignore new file mode 100644 index 000000000..6c7e7b783 --- /dev/null +++ b/.github/scripts/.gitignore @@ -0,0 +1,5 @@ +__pycache__ +.venv +*.token +*.json +*.pem diff --git a/.github/scripts/generate_jwt.py b/.github/scripts/generate_jwt.py new file mode 100644 index 000000000..4bc65bb01 --- /dev/null +++ b/.github/scripts/generate_jwt.py @@ -0,0 +1,60 @@ +import os +import sys +import time + +from jwcrypto.jwk import JWK +from jwcrypto.jwt import JWT + + +def get_private_key_pem(private_key_pem=None): + """Retrieve private key PEM string from parameter or JWT_PKEY environment variable.""" + pkey = private_key_pem or os.getenv("JWT_PKEY") + if pkey: + return pkey + + raise ValueError( + "Private key not found. Please set JWT_PKEY environment variable." + ) + + +def generate_jwt_token( + private_key_pem=None, + audience="ci-test-service", + issuer="mydomain.com", + subject="ci-test", + expiration_seconds=300, # Valid for 5 minutes by default + output_file=None, +): + """Generate a signed JWT token valid for a few minutes using the private key.""" + private_key_pem = get_private_key_pem(private_key_pem) + jwk_key = JWK.from_pem(private_key_pem.encode("utf-8")) + + now = int(time.time()) + payload = { + "iss": issuer, + "sub": subject, + "aud": audience, + "iat": now, + "exp": now + expiration_seconds, + } + + header = { + "alg": "RS256", + "typ": "JWT", + "kid": jwk_key.key_id, + } + + token = JWT(header=header, claims=payload) + token.make_signed_token(jwk_key) + jwt_str = token.serialize() + + if output_file: + with open(output_file, "w", encoding="utf-8") as f: + f.write(jwt_str) + + return jwt_str + + +if __name__ == "__main__": + out_file = sys.argv[1] if len(sys.argv) > 1 else "jwt.token" + generate_jwt_token(output_file=out_file) diff --git a/.github/scripts/requirements.txt b/.github/scripts/requirements.txt new file mode 100644 index 000000000..dacef4771 --- /dev/null +++ b/.github/scripts/requirements.txt @@ -0,0 +1,2 @@ +jwcrypto + diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ccec4fb70..54c3229a4 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -271,9 +271,15 @@ jobs: env: CLICKHOUSE_CLOUD_HOST: ${{ secrets.INTEGRATIONS_TEAM_TESTS_CLOUD_HOST_SMT_PROD }} CLICKHOUSE_CLOUD_PASSWORD: ${{ secrets.INTEGRATIONS_TEAM_TESTS_CLOUD_PASSWORD_SMT_PROD }} - CLIENT_JWT: ${{ secrets.INTEGRATIONS_TEAM_TESTS_CLOUD_JWT_DESERT_VM_43 }} + JWT_PKEY: ${{ secrets.INTEGRATIONS_TEAM_TESTS_CLOUD_JWT_DESERT_VM_43 }} JWT_TEST_HOST: ${{ secrets.INTEGRATIONS_TEAM_TESTS_CLOUD_HOST_SMT }} run: | + python3 -m pip install -r .github/scripts/requirements.txt + python3 .github/scripts/generate_jwt.py jwt.token + CLIENT_JWT=$(cat jwt.token) + rm -f jwt.token + echo "::add-mask::$CLIENT_JWT" + export CLIENT_JWT mvn --batch-mode --no-transfer-progress --projects ${{ matrix.project }} -DclickhouseVersion=${{ matrix.clickhouse }} -Dprotocol=http -Dmaven.javadoc.skip=true verify - name: Upload test results uses: actions/upload-artifact@v4 diff --git a/docs/clickhouse-docs/client.mdx b/docs/clickhouse-docs/client.mdx index 6a2ff98b2..fb9e95131 100644 --- a/docs/clickhouse-docs/client.mdx +++ b/docs/clickhouse-docs/client.mdx @@ -85,11 +85,11 @@ Authentication by a password requires setting user name password by calling `set .build(); ``` -Authentication by an access token requires setting access token by calling `setAccessToken(String)`: +Authentication by an access token or Bearer token (such as a JWT) requires setting the token by calling `useBearerTokenAuth(String)` (or `setAccessToken(String)` for raw access tokens): ```java showLineNumbers Client client = new Client.Builder() .addEndpoint("https://clickhouse-cloud-instance:8443/") - .setAccessToken(userAccessToken) + .useBearerTokenAuth(userAccessToken) .build(); ``` @@ -377,6 +377,46 @@ try (Client client = new Client.Builder() To configure per operation, set the header on `QuerySettings`, `InsertSettings`, or `CommandSettings` instead of the client builder. +### JWT Authentication (CLOUD) {#jwt-authentication} + +[JWT Authentication](/concepts/features/security/external-authenticators/jwt) allows authenticating users with JSON Web Tokens (JWTs) in ClickHouse Cloud. Instead of pre-existing database users, ClickHouse dynamically creates **ephemeral users** derived from claims embedded in each token. + +#### Initial Configuration + +To configure initial JWT authentication on the client, use `useBearerTokenAuth(token)` when building the `Client` instance: + +```java showLineNumbers +import com.clickhouse.client.api.Client; + +public Client createJwtClient(String jwtToken) { + return new Client.Builder() + .addEndpoint("https://your-service.clickhouse.cloud:8443") + .useBearerTokenAuth(jwtToken) + .build(); +} +``` + + +`useBearerTokenAuth(token)` automatically prepends the `Bearer ` prefix to the `Authorization` HTTP header. + + +#### Updating Token at Runtime + +Because JWTs are short-lived and ephemeral users exist only for the token's lifetime, new JWT tokens should be set **before** the current token expires so no operations fail. + +You can update the bearer token on an existing `Client` instance at runtime without recreating the client: + +```java showLineNumbers +import com.clickhouse.client.api.Client; + +public void refreshJwtToken(Client client, String newJwtToken) { + // Set the new JWT before the current token expires + client.updateBearerToken(newJwtToken); +} +``` + +All subsequent requests on the `Client` instance will use the updated JWT token. + ## Common Definitions {#common-definitions} ### ClickHouseFormat {#clickhouseformat} diff --git a/docs/clickhouse-docs/jdbc.mdx b/docs/clickhouse-docs/jdbc.mdx index b70c83009..0308676fc 100644 --- a/docs/clickhouse-docs/jdbc.mdx +++ b/docs/clickhouse-docs/jdbc.mdx @@ -227,6 +227,55 @@ Connection conn = Driver.connect("jdbc:ch:https://your-service.clickhouse.cloud: // jdbc:ch:https://your-service.clickhouse.cloud:8443?http_header_X-CLICKHOUSE-REPLICA-TAG=my-app-session-1 ``` +### JWT Authentication (CLOUD) {#jwt-authentication} + +[JWT Authentication](/concepts/features/security/external-authenticators/jwt) allows authenticating with JSON Web Tokens (JWTs) in ClickHouse Cloud. ClickHouse dynamically creates **ephemeral users** derived from token claims. + +#### Initial Configuration + +To configure initial JWT authentication in JDBC, pass the `bearer_token` property in connection properties or directly in the JDBC URL: + +```java showLineNumbers +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.SQLException; +import java.util.Properties; + +public Connection createJwtConnection(String jwtToken) throws SQLException { + Properties properties = new Properties(); + properties.setProperty("bearer_token", jwtToken); + + return DriverManager.getConnection("jdbc:ch:https://your-service.clickhouse.cloud:8443", properties); +} +``` + +URL equivalent: +```plaintext +jdbc:ch:https://your-service.clickhouse.cloud:8443?bearer_token= +``` + +#### Updating Token at Runtime + +Because JWTs have a limited validity period, new JWT tokens should be set **before** the current token expires so no operations fail. + +To update the JWT token on an active JDBC connection at runtime, unwrap the connection to access the underlying `com.clickhouse.client.api.Client` instance and call `updateBearerToken`: + +```java showLineNumbers +import com.clickhouse.jdbc.ConnectionImpl; +import java.sql.Connection; +import java.sql.SQLException; + +public void refreshJwtToken(Connection connection, String newJwtToken) throws SQLException { + // Unwrap the connection to get the underlying Client instance + ConnectionImpl connImpl = connection.unwrap(ConnectionImpl.class); + + // Set the new JWT before the current token expires + connImpl.getClient().updateBearerToken(newJwtToken); +} +``` + +Subsequent statements executed on this JDBC connection will use the updated JWT token. + ## Supported data types {#supported-data-types} JDBC driver supports the same data formats as the underlying [java client](/integrations/language-clients/java/index#supported-data-types). From 3137835e65cda070591f997095ed1f4c01420d47 Mon Sep 17 00:00:00 2001 From: Sergey Chernov Date: Thu, 3 Sep 2026 14:41:20 -0700 Subject: [PATCH 2/6] Updated JWT tests in JDBC and client --- .github/workflows/build.yml | 7 +++-- .../com/clickhouse/client/ClientTests.java | 27 +++++++++++++++++++ .../clickhouse/client/HttpTransportTests.java | 27 ------------------- .../com/clickhouse/jdbc/ConnectionTest.java | 27 +++++++++---------- 4 files changed, 42 insertions(+), 46 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 54c3229a4..07ecbac98 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -272,14 +272,13 @@ jobs: CLICKHOUSE_CLOUD_HOST: ${{ secrets.INTEGRATIONS_TEAM_TESTS_CLOUD_HOST_SMT_PROD }} CLICKHOUSE_CLOUD_PASSWORD: ${{ secrets.INTEGRATIONS_TEAM_TESTS_CLOUD_PASSWORD_SMT_PROD }} JWT_PKEY: ${{ secrets.INTEGRATIONS_TEAM_TESTS_CLOUD_JWT_DESERT_VM_43 }} - JWT_TEST_HOST: ${{ secrets.INTEGRATIONS_TEAM_TESTS_CLOUD_HOST_SMT }} run: | python3 -m pip install -r .github/scripts/requirements.txt python3 .github/scripts/generate_jwt.py jwt.token - CLIENT_JWT=$(cat jwt.token) + JWT_TOKEN=$(cat jwt.token) rm -f jwt.token - echo "::add-mask::$CLIENT_JWT" - export CLIENT_JWT + echo "::add-mask::$JWT_TOKEN" + export JWT_TOKEN mvn --batch-mode --no-transfer-progress --projects ${{ matrix.project }} -DclickhouseVersion=${{ matrix.clickhouse }} -Dprotocol=http -Dmaven.javadoc.skip=true verify - name: Upload test results uses: actions/upload-artifact@v4 diff --git a/client-v2/src/test/java/com/clickhouse/client/ClientTests.java b/client-v2/src/test/java/com/clickhouse/client/ClientTests.java index b50d3700b..1d5c48468 100644 --- a/client-v2/src/test/java/com/clickhouse/client/ClientTests.java +++ b/client-v2/src/test/java/com/clickhouse/client/ClientTests.java @@ -27,6 +27,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.testng.Assert; +import org.testng.SkipException; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import org.testng.util.Strings; @@ -767,6 +768,32 @@ private void assertTableNotFoundInSession(Client client, String tableName, Query } } + @Test(groups = { "integration" }) + public void testJWTWithCloud() throws Exception { + String jwt = System.getenv("JWT_TOKEN"); + if (jwt == null || jwt.trim().isEmpty()) { + throw new SkipException("JWT_TOKEN environment variable is not set. Skipping JWT test."); + } + ClickHouseNode node = getServer(ClickHouseProtocol.HTTP); + Assert.assertFalse(jwt.contains("\n") || jwt.contains("-----"), "JWT should be single string ready for HTTP header"); + try (Client client = new Client.Builder() + .addEndpoint(Protocol.HTTP, node.getHost(), node.getPort(), isCloud()) + .compressClientRequest(false) + .setDefaultDatabase(ClickHouseServerForTest.getDatabase()) + .serverSetting(ServerSettings.WAIT_END_OF_QUERY, "1") + .useBearerTokenAuth(jwt).build()) { + try { + List response = client.queryAll("SELECT currentUser()"); + String username = response.get(0).getString(1); + Assert.assertTrue(username != null && username.matches("^JWT::.+::.+$"), + "Expected username in format JWT::::, but actual username was: '" + username + "'"); + } catch (Exception e) { + e.printStackTrace(); + throw e; + } + } + } + protected Client.Builder newClient() { ClickHouseNode node = getServer(ClickHouseProtocol.HTTP); boolean isSecure = isCloud(); diff --git a/client-v2/src/test/java/com/clickhouse/client/HttpTransportTests.java b/client-v2/src/test/java/com/clickhouse/client/HttpTransportTests.java index 6f357fddc..b71435783 100644 --- a/client-v2/src/test/java/com/clickhouse/client/HttpTransportTests.java +++ b/client-v2/src/test/java/com/clickhouse/client/HttpTransportTests.java @@ -1562,33 +1562,6 @@ public void testSetCredentialsAfterClientCreation() throws Exception { } } - @Test(groups = { "integration" }) - public void testJWTWithCloud() throws Exception { - if (!isCloud()) { - return; // only for cloud - } - final String jwt = System.getenv("CLIENT_JWT"); - final String host = System.getenv("JWT_TEST_HOST"); - Assert.assertTrue(jwt != null && !jwt.trim().isEmpty(), "CLIENT_JWT is not set."); - Assert.assertTrue(host != null && !host.trim().isEmpty(), "JWT_TEST_HOST is not set"); - Assert.assertFalse(jwt.contains("\n") || jwt.contains("-----"), "JWT should be single string ready for HTTP header"); - try (Client client = new Client.Builder() - .addEndpoint(Protocol.HTTP, host, 8443, true) - .setUsername("default") - .compressClientRequest(false) - .setDefaultDatabase("default") - .serverSetting(ServerSettings.WAIT_END_OF_QUERY, "1") - .useBearerTokenAuth(jwt).build()) { - try { - List response = client.queryAll("SELECT user(), now()"); - System.out.println("response: " + response.get(0).getString(1) + " time: " + response.get(0).getString(2)); - } catch (Exception e) { - e.printStackTrace(); - throw e; - } - } - } - @Test(groups = { "integration" }) public void testWithDefaultTimeouts() { if (isCloud()) { diff --git a/jdbc-v2/src/test/java/com/clickhouse/jdbc/ConnectionTest.java b/jdbc-v2/src/test/java/com/clickhouse/jdbc/ConnectionTest.java index d52adc967..686b5baff 100644 --- a/jdbc-v2/src/test/java/com/clickhouse/jdbc/ConnectionTest.java +++ b/jdbc-v2/src/test/java/com/clickhouse/jdbc/ConnectionTest.java @@ -1013,27 +1013,24 @@ public void testBearerTokenAuth() throws Exception { } } - private static final String SAMPLE_JWT_TOKEN_FOR_TESTS = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"; - @Test(groups = { "integration" }) public void testJWTWithCloud() throws Exception { - - final String jwt = isCloud() ? System.getenv("CLIENT_JWT") : SAMPLE_JWT_TOKEN_FOR_TESTS; - final String url = isCloud() ? "jdbc:ch:https://" + System.getenv("JWT_TEST_HOST") + "/default": getEndpointString(); - Assert.assertTrue(jwt != null && !jwt.trim().isEmpty(), "CLIENT_JWT is not set."); - Assert.assertTrue(url != null && !url.trim().isEmpty(), "JWT_TEST_HOST is not set"); + String jwt = System.getenv("JWT_TOKEN"); + if (jwt == null || jwt.trim().isEmpty()) { + throw new SkipException("JWT_TOKEN environment variable is not set. Skipping JWT test."); + } + String url = getEndpointString(); Properties properties = new Properties(); properties.put(ClientConfigProperties.BEARERTOKEN_AUTH.getKey(), jwt); - properties.put(ClientConfigProperties.USER.getKey(), "default"); - try (Connection conn = new ConnectionImpl(url, properties)) { - if (isCloud()) { // else check configuration only - try (Statement stmt = conn.createStatement(); - ResultSet rs = stmt.executeQuery("SELECT 1")) { - Assert.assertTrue(rs.next()); - } - } + try (Connection conn = new ConnectionImpl(url, properties); + Statement stmt = conn.createStatement(); + ResultSet rs = stmt.executeQuery("SELECT currentUser()")) { + Assert.assertTrue(rs.next()); + String username = rs.getString(1); + Assert.assertTrue(username != null && username.matches("^JWT::.+::.+$"), + "Expected username in format JWT::::, but actual username was: '" + username + "'"); } } From ed8148ce2b8f4b65cffe46612495f849b8f6c1ec Mon Sep 17 00:00:00 2001 From: Sergey Chernov Date: Thu, 3 Sep 2026 14:47:26 -0700 Subject: [PATCH 3/6] Enabled Cloud tests after compile --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 07ecbac98..07ad58729 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -207,7 +207,7 @@ jobs: test-with-cloud: runs-on: ubuntu-latest - needs: test-jdbc-driver + needs: compile strategy: matrix: # most recent LTS releases as well as latest stable builds From 9b61ec085b54c5a34e75fd30159ed0f6fc1ac342 Mon Sep 17 00:00:00 2001 From: Sergey Chernov Date: Thu, 3 Sep 2026 14:58:11 -0700 Subject: [PATCH 4/6] Fixed JWT variable in build workflow --- .github/workflows/build.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 07ad58729..0c741516c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -271,13 +271,12 @@ jobs: env: CLICKHOUSE_CLOUD_HOST: ${{ secrets.INTEGRATIONS_TEAM_TESTS_CLOUD_HOST_SMT_PROD }} CLICKHOUSE_CLOUD_PASSWORD: ${{ secrets.INTEGRATIONS_TEAM_TESTS_CLOUD_PASSWORD_SMT_PROD }} - JWT_PKEY: ${{ secrets.INTEGRATIONS_TEAM_TESTS_CLOUD_JWT_DESERT_VM_43 }} + JWT_PKEY: ${{ secrets.JWT_PKEY }} run: | python3 -m pip install -r .github/scripts/requirements.txt python3 .github/scripts/generate_jwt.py jwt.token - JWT_TOKEN=$(cat jwt.token) + JWT_TOKEN="$(cat jwt.token)" rm -f jwt.token - echo "::add-mask::$JWT_TOKEN" export JWT_TOKEN mvn --batch-mode --no-transfer-progress --projects ${{ matrix.project }} -DclickhouseVersion=${{ matrix.clickhouse }} -Dprotocol=http -Dmaven.javadoc.skip=true verify - name: Upload test results From 39c2f24e4a2e69e681b7d5f52e0038fbb3de1750 Mon Sep 17 00:00:00 2001 From: Sergey Chernov Date: Thu, 3 Sep 2026 15:25:18 -0700 Subject: [PATCH 5/6] Trying another clous instance --- .github/workflows/build.yml | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 0c741516c..ba10afc95 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -262,15 +262,19 @@ jobs: echo "Generated database name: $RANDOM_DB" - name: Create Temporary Database env: - CLICKHOUSE_CLOUD_HOST: ${{ secrets.INTEGRATIONS_TEAM_TESTS_CLOUD_HOST_SMT_PROD }} - CLICKHOUSE_CLOUD_PASSWORD: ${{ secrets.INTEGRATIONS_TEAM_TESTS_CLOUD_PASSWORD_SMT_PROD }} + CLICKHOUSE_CLOUD_HOST: ${{ secrets.CLICKHOUSE_CLOUD_HOST }} + CLICKHOUSE_CLOUD_PASSWORD: ${{ secrets.CLICKHOUSE_CLOUD_PASSWORD }} + # CLICKHOUSE_CLOUD_HOST: ${{ secrets.INTEGRATIONS_TEAM_TESTS_CLOUD_HOST_SMT_PROD }} + # CLICKHOUSE_CLOUD_PASSWORD: ${{ secrets.INTEGRATIONS_TEAM_TESTS_CLOUD_PASSWORD_SMT_PROD }} run: | echo "Creating database: \`$TEST_DB_NAME\`" curl --fail-with-body -s -u "default:$CLICKHOUSE_CLOUD_PASSWORD" "https://$CLICKHOUSE_CLOUD_HOST:8443" --data-binary "CREATE DATABASE IF NOT EXISTS $TEST_DB_NAME" - name: Test http client env: - CLICKHOUSE_CLOUD_HOST: ${{ secrets.INTEGRATIONS_TEAM_TESTS_CLOUD_HOST_SMT_PROD }} - CLICKHOUSE_CLOUD_PASSWORD: ${{ secrets.INTEGRATIONS_TEAM_TESTS_CLOUD_PASSWORD_SMT_PROD }} + # CLICKHOUSE_CLOUD_HOST: ${{ secrets.INTEGRATIONS_TEAM_TESTS_CLOUD_HOST_SMT_PROD }} + # CLICKHOUSE_CLOUD_PASSWORD: ${{ secrets.INTEGRATIONS_TEAM_TESTS_CLOUD_PASSWORD_SMT_PROD }} + CLICKHOUSE_CLOUD_HOST: ${{ secrets.CLICKHOUSE_CLOUD_HOST }} + CLICKHOUSE_CLOUD_PASSWORD: ${{ secrets.CLICKHOUSE_CLOUD_PASSWORD }} JWT_PKEY: ${{ secrets.JWT_PKEY }} run: | python3 -m pip install -r .github/scripts/requirements.txt @@ -290,8 +294,10 @@ jobs: - name: Cleanup Database Unconditionally if: always() # CRITICAL: This ensures the step runs regardless of previous success/failure env: - CLICKHOUSE_CLOUD_HOST: ${{ secrets.INTEGRATIONS_TEAM_TESTS_CLOUD_HOST_SMT_PROD }} - CLICKHOUSE_CLOUD_PASSWORD: ${{ secrets.INTEGRATIONS_TEAM_TESTS_CLOUD_PASSWORD_SMT_PROD }} + CLICKHOUSE_CLOUD_HOST: ${{ secrets.CLICKHOUSE_CLOUD_HOST }} + CLICKHOUSE_CLOUD_PASSWORD: ${{ secrets.CLICKHOUSE_CLOUD_PASSWORD }} + # CLICKHOUSE_CLOUD_HOST: ${{ secrets.INTEGRATIONS_TEAM_TESTS_CLOUD_HOST_SMT_PROD }} + # CLICKHOUSE_CLOUD_PASSWORD: ${{ secrets.INTEGRATIONS_TEAM_TESTS_CLOUD_PASSWORD_SMT_PROD }} run: | # Verify we actually generated a DB name to avoid dropping something accidentally if [ -n "$TEST_DB_NAME" ]; then From 8a2ddc9f7f71e214cce6c28657a11854e9330bcc Mon Sep 17 00:00:00 2001 From: Sergey Chernov Date: Thu, 3 Sep 2026 15:45:29 -0700 Subject: [PATCH 6/6] Reverted using another instance for cloud tests --- .github/scripts/generate_jwt.py | 2 +- .github/workflows/build.yml | 18 ++++++------------ 2 files changed, 7 insertions(+), 13 deletions(-) diff --git a/.github/scripts/generate_jwt.py b/.github/scripts/generate_jwt.py index 4bc65bb01..01dd1df58 100644 --- a/.github/scripts/generate_jwt.py +++ b/.github/scripts/generate_jwt.py @@ -22,7 +22,7 @@ def generate_jwt_token( audience="ci-test-service", issuer="mydomain.com", subject="ci-test", - expiration_seconds=300, # Valid for 5 minutes by default + expiration_seconds=600, # Valid for 10 minutes by default output_file=None, ): """Generate a signed JWT token valid for a few minutes using the private key.""" diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ba10afc95..0c741516c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -262,19 +262,15 @@ jobs: echo "Generated database name: $RANDOM_DB" - name: Create Temporary Database env: - CLICKHOUSE_CLOUD_HOST: ${{ secrets.CLICKHOUSE_CLOUD_HOST }} - CLICKHOUSE_CLOUD_PASSWORD: ${{ secrets.CLICKHOUSE_CLOUD_PASSWORD }} - # CLICKHOUSE_CLOUD_HOST: ${{ secrets.INTEGRATIONS_TEAM_TESTS_CLOUD_HOST_SMT_PROD }} - # CLICKHOUSE_CLOUD_PASSWORD: ${{ secrets.INTEGRATIONS_TEAM_TESTS_CLOUD_PASSWORD_SMT_PROD }} + CLICKHOUSE_CLOUD_HOST: ${{ secrets.INTEGRATIONS_TEAM_TESTS_CLOUD_HOST_SMT_PROD }} + CLICKHOUSE_CLOUD_PASSWORD: ${{ secrets.INTEGRATIONS_TEAM_TESTS_CLOUD_PASSWORD_SMT_PROD }} run: | echo "Creating database: \`$TEST_DB_NAME\`" curl --fail-with-body -s -u "default:$CLICKHOUSE_CLOUD_PASSWORD" "https://$CLICKHOUSE_CLOUD_HOST:8443" --data-binary "CREATE DATABASE IF NOT EXISTS $TEST_DB_NAME" - name: Test http client env: - # CLICKHOUSE_CLOUD_HOST: ${{ secrets.INTEGRATIONS_TEAM_TESTS_CLOUD_HOST_SMT_PROD }} - # CLICKHOUSE_CLOUD_PASSWORD: ${{ secrets.INTEGRATIONS_TEAM_TESTS_CLOUD_PASSWORD_SMT_PROD }} - CLICKHOUSE_CLOUD_HOST: ${{ secrets.CLICKHOUSE_CLOUD_HOST }} - CLICKHOUSE_CLOUD_PASSWORD: ${{ secrets.CLICKHOUSE_CLOUD_PASSWORD }} + CLICKHOUSE_CLOUD_HOST: ${{ secrets.INTEGRATIONS_TEAM_TESTS_CLOUD_HOST_SMT_PROD }} + CLICKHOUSE_CLOUD_PASSWORD: ${{ secrets.INTEGRATIONS_TEAM_TESTS_CLOUD_PASSWORD_SMT_PROD }} JWT_PKEY: ${{ secrets.JWT_PKEY }} run: | python3 -m pip install -r .github/scripts/requirements.txt @@ -294,10 +290,8 @@ jobs: - name: Cleanup Database Unconditionally if: always() # CRITICAL: This ensures the step runs regardless of previous success/failure env: - CLICKHOUSE_CLOUD_HOST: ${{ secrets.CLICKHOUSE_CLOUD_HOST }} - CLICKHOUSE_CLOUD_PASSWORD: ${{ secrets.CLICKHOUSE_CLOUD_PASSWORD }} - # CLICKHOUSE_CLOUD_HOST: ${{ secrets.INTEGRATIONS_TEAM_TESTS_CLOUD_HOST_SMT_PROD }} - # CLICKHOUSE_CLOUD_PASSWORD: ${{ secrets.INTEGRATIONS_TEAM_TESTS_CLOUD_PASSWORD_SMT_PROD }} + CLICKHOUSE_CLOUD_HOST: ${{ secrets.INTEGRATIONS_TEAM_TESTS_CLOUD_HOST_SMT_PROD }} + CLICKHOUSE_CLOUD_PASSWORD: ${{ secrets.INTEGRATIONS_TEAM_TESTS_CLOUD_PASSWORD_SMT_PROD }} run: | # Verify we actually generated a DB name to avoid dropping something accidentally if [ -n "$TEST_DB_NAME" ]; then