Message-ID: From: "vlsi (@vlsi)" To: "pgjdbc/pgjdbc" Date: Thu, 04 Jun 2026 07:36:37 +0000 Subject: [pgjdbc/pgjdbc] PR #4152: build: 42.6 compile with a Java 17 toolchain, run tests on multiple JDKs List-Id: X-GitHub-Additions: 53 X-GitHub-Author-Id: 213894 X-GitHub-Author-Login: vlsi X-GitHub-Base: release/42.6.x X-GitHub-Changed-Files: 5 X-GitHub-Commits: 1 X-GitHub-Deletions: 18 X-GitHub-Head-Branch: claude/toolchain-42.6 X-GitHub-Head-SHA: 668d3177dcc69bac68cd5a4a16e8adde14b463c5 X-GitHub-Issue: 4152 X-GitHub-Merge-SHA: 321f1f2a124339e9014f7ad5682d12653264e59d X-GitHub-Merged-By: vlsi X-GitHub-Repo: pgjdbc/pgjdbc X-GitHub-State: merged X-GitHub-Type: pull_request X-GitHub-Url: https://github.com/pgjdbc/pgjdbc/pull/4152 Content-Type: text/plain; charset=utf-8 ## Why On the 42.6 branch the build compiled with whatever JVM ran Gradle and pinned source/target compatibility to Java 8, so the build JDK and the test JDK were always the same. That makes it impossible to compile on a modern JDK while still running the test suite on the older JDKs we support. This backports master's `build-logic` toolchain approach to 42.6. ## What - `build-logic/build-parameters`: add `jdkBuildVersion` (default 17) and `jdkTestVersion` (default 0) parameters. - `build-logic.java.gradle.kts`: replace the fixed `sourceCompatibility`/`targetCompatibility` with a Gradle toolchain selected by `jdkBuildVersion`. `JavaCompile` emits Java 8 bytecode via `--release 8` when the compiler is javac 9+. - `build-logic.test-base.gradle.kts`: select a test JDK via a toolchain launcher when `jdkTestVersion` is set, and forward only `pgjdbc.*` system properties to the test JVM (the build JVM's `java.*` properties must not leak into a test JVM on a different Java version). - CI (`main.yml`): run Gradle on JDK 17 and run tests on the matrix JDK via `jdkTestVersion=${{ matrix.java_version }}`. Build JDK moves from 11 to 17 for `linux-checkerframework` and `source-distribution-check`. `buildcache.yml` seeds on JDK 17. The build JDK is **17** and the produced bytecode targets **Java 8** (`--release 8`). ## How to verify Verified locally with `JAVA_HOME` set to JDK 17: - `./gradlew :postgresql:compileJava` compiles with the JDK 17 toolchain (`--info` shows `Compiling with toolchain '.../17.0.10-librca'`). - `org/postgresql/Driver.class` has bytecode major version **52** (Java 8), confirming `--release 8` works while compiling on JDK 17. - `./gradlew :postgresql:test -PjdkTestVersion=8 --tests 'org.postgresql.util.PGtokenizerTest'` runs the test on JDK 8 — the Gradle Test Executor launched `.../8.0.402-librca/bin/java` and the suite passed (5 tests, 0 failures). CI changes were verified by reading only; all edited YAML files pass `yaml.safe_load`. ## Notes - This backports master's `build-logic` toolchain mechanism, adapted to 42.6's simpler `build-parameters` setup. - ARM64: the x64 path (the one CI uses) is the focus. On ARM64 the workflow now installs both the test JDK and JDK 17, but `org.gradle.java.installations.fromEnv` is x64-named (`JAVA_HOME_*_X64`); wiring ARM64 toolchain discovery is left as a best-effort follow-up. 🤖 Generated with [Claude Code](https://claude.com/claude-code) diff --git a/.github/workflows/buildcache.yml b/.github/workflows/buildcache.yml index 9386ef4b36..5a0179f33a 100644 --- a/.github/workflows/buildcache.yml +++ b/.github/workflows/buildcache.yml @@ -43,7 +43,7 @@ jobs: strategy: matrix: os: [ubuntu, macos, windows] - jdk: [8, 11] + jdk: [17] name: '${{ matrix.os }}, ${{ matrix.jdk }} seed build cache' runs-on: ${{ matrix.os }}-latest @@ -56,10 +56,6 @@ jobs: with: java-version: ${{ matrix.jdk }} distribution: liberica - - name: Skip javadoc with Java 11 - if: ${{ matrix.jdk == '11' }} - run: | - echo "skipJavadoc=-PskipJavadoc" >> $GITHUB_ENV - uses: burrunan/gradle-cache-action@v1 name: Build pgjdbc env: @@ -67,4 +63,4 @@ jobs: S3_BUILD_CACHE_SECRET_KEY: ${{ secrets.S3_BUILD_CACHE_SECRET_KEY }} with: job-id: jdk${{ matrix.jdk }} - arguments: build -x test --scan -i ${{ env.skipJavadoc }} + arguments: build -x test --scan -i diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index a97b958efa..fe31ac6dd4 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -44,7 +44,7 @@ jobs: - uses: actions/checkout@v4 with: fetch-depth: 50 - - name: 'Set up JDK 8' + - name: 'Set up JDK 17' uses: actions/setup-java@v3 with: distribution: zulu @@ -65,11 +65,11 @@ jobs: - uses: actions/checkout@v4 with: fetch-depth: 50 - - name: 'Set up JDK 11' + - name: 'Set up JDK 17' uses: actions/setup-java@v3 with: distribution: zulu - java-version: 11 + java-version: 17 - uses: burrunan/gradle-cache-action@v1 name: Run CheckerFramework env: @@ -81,7 +81,7 @@ jobs: arguments: --scan --no-parallel --no-daemon -PenableCheckerframework classes source-distribution-check: - name: 'Source distribution (JDK 11)' + name: 'Source distribution (JDK 17)' runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 @@ -90,11 +90,11 @@ jobs: - name: Start PostgreSQL working-directory: docker/postgres-server run: docker compose up -d && docker compose logs - - name: 'Set up JDK 11' + - name: 'Set up JDK 17' uses: actions/setup-java@v3 with: distribution: zulu - java-version: 11 + java-version: 17 - uses: burrunan/gradle-cache-action@v1 name: Prepare source distribution env: @@ -166,20 +166,30 @@ jobs: - name: 'Get test node ARCH' run: echo "arch_name=$(uname -i)" >> $GITHUB_OUTPUT id: get_arch_name - - name: Set up Java ${{ matrix.java_version }}, ${{ matrix.java_distribution }} + - name: Set up test JDK ${{ matrix.java_version }} and build JDK 17, ${{ matrix.java_distribution }} if: ${{ steps.get_arch_name.outputs.arch_name != 'aarch64' }} uses: actions/setup-java@v3 with: - java-version: ${{ matrix.java_version }} + # Gradle runs on the last entry (JDK 17), and the toolchain runs the tests on matrix.java_version + java-version: | + ${{ matrix.java_version }} + 17 distribution: ${{ matrix.java_distribution }} architecture: x64 - - name: 'Setup JDK ${{ matrix.java_version }} on ARM64' + - name: 'Setup test JDK ${{ matrix.java_version }} on ARM64' if: ${{ steps.get_arch_name.outputs.arch_name == 'aarch64' }} uses: AdoptOpenJDK/install-jdk@v1 with: impl: hotspot # or openj9 version: ${{ matrix.java_version }} architecture: aarch64 + - name: 'Setup build JDK 17 on ARM64' + if: ${{ steps.get_arch_name.outputs.arch_name == 'aarch64' }} + uses: AdoptOpenJDK/install-jdk@v1 + with: + impl: hotspot # or openj9 + version: '17' + architecture: aarch64 - name: Prepare local properties run: | # See https://github.com/actions/runner/issues/409 @@ -203,6 +213,11 @@ jobs: properties: | includeTestTags=${{ matrix.includeTestTags }} testExtraJvmArgs=${{ matrix.testExtraJvmArgs }} + jdkBuildVersion=17 + jdkTestVersion=${{ matrix.java_version }} + org.gradle.java.installations.fromEnv=JAVA_HOME_${{ matrix.java_version }}_X64,JAVA_HOME_17_X64 + # We provision JDKs with GitHub Actions for caching purposes, so Gradle should rather fail in case JDK is not found + org.gradle.java.installations.auto-download=false - name: 'Install krb5 for GSS tests' if: ${{ matrix.gss == 'yes' }} diff --git a/build-logic/build-parameters/build.gradle.kts b/build-logic/build-parameters/build.gradle.kts index 82383dcce4..bc69b1682a 100644 --- a/build-logic/build-parameters/build.gradle.kts +++ b/build-logic/build-parameters/build.gradle.kts @@ -16,6 +16,14 @@ buildParameters { defaultValue.set(false) description.set("Collect test coverage") } + integer("jdkBuildVersion") { + defaultValue.set(17) + description.set("Java version used to compile the driver via a Gradle toolchain. 0 uses the JVM that runs Gradle.") + } + integer("jdkTestVersion") { + defaultValue.set(0) + description.set("Java version used to run tests via a Gradle toolchain. 0 reuses the build JVM.") + } bool("spotbugs") { defaultValue.set(false) description.set("Run SpotBugs verifications") diff --git a/build-logic/jvm/src/main/kotlin/build-logic.java.gradle.kts b/build-logic/jvm/src/main/kotlin/build-logic.java.gradle.kts index 901e91de02..adadd42d55 100644 --- a/build-logic/jvm/src/main/kotlin/build-logic.java.gradle.kts +++ b/build-logic/jvm/src/main/kotlin/build-logic.java.gradle.kts @@ -2,6 +2,7 @@ import com.github.vlsi.gradle.crlf.CrLfSpec import com.github.vlsi.gradle.crlf.LineEndings import com.github.vlsi.gradle.dsl.configureEach import com.github.vlsi.gradle.properties.dsl.props +import org.gradle.jvm.toolchain.JavaLanguageVersion import java.time.LocalDate plugins { @@ -16,8 +17,11 @@ plugins { } java { - sourceCompatibility = JavaVersion.VERSION_1_8 - targetCompatibility = JavaVersion.VERSION_1_8 + buildParameters.jdkBuildVersion.takeIf { it != 0 }?.let { + toolchain { + languageVersion.set(JavaLanguageVersion.of(it)) + } + } } sourceSets { @@ -48,6 +52,8 @@ tasks.configureEach { inputs.property("java.vm.version", System.getProperty("java.vm.version")) options.apply { encoding = "UTF-8" + // Target Java 8 bytecode without referencing Java 9+ API (--release needs javac 9+). + release.set(provider { 8.takeIf { javaCompiler.get().metadata.languageVersion.asInt() > 9 } }) compilerArgs.add("-Xlint:deprecation") if (JavaVersion.current().isJava9Compatible) { // See https://bugs.openjdk.org/browse/JDK-8032211 diff --git a/build-logic/jvm/src/main/kotlin/build-logic.test-base.gradle.kts b/build-logic/jvm/src/main/kotlin/build-logic.test-base.gradle.kts index dec93446ca..97c7fa4751 100644 --- a/build-logic/jvm/src/main/kotlin/build-logic.test-base.gradle.kts +++ b/build-logic/jvm/src/main/kotlin/build-logic.test-base.gradle.kts @@ -3,10 +3,18 @@ import com.github.vlsi.gradle.properties.dsl.props import org.gradle.api.tasks.testing.Test plugins { + id("java-library") id("build-logic.build-params") } tasks.configureEach { + buildParameters.jdkTestVersion.takeIf { it != 0 }?.let { + javaLauncher.set( + javaToolchains.launcherFor { + languageVersion.set(org.gradle.jvm.toolchain.JavaLanguageVersion.of(it)) + } + ) + } inputs.file("../build.properties") if (file("../build.local.properties").exists()) { inputs.file("../build.local.properties") @@ -36,7 +44,9 @@ tasks.configureEach { val props = System.getProperties() @Suppress("UNCHECKED_CAST") for (e in props.propertyNames() as `java.util`.Enumeration) { - if (e.startsWith("pgjdbc.") || e.startsWith("java")) { + // Forward only pgjdbc.* properties; the build JVM's java.* props must not leak into a + // test JVM that may run on a different Java version. + if (e.startsWith("pgjdbc.")) { passProperty(e) } }