From 2eb1ca65c3cc4f59ec1e15912d629716cbcff278 Mon Sep 17 00:00:00 2001 From: Dennis Fokin Date: Fri, 20 Mar 2026 11:16:48 +0100 Subject: [PATCH 1/8] Add Gradle tasks for running tests with LTS Java versions --- .github/workflows/build.yml | 44 +++++++++--------- .../kotlin/project-convention-java.gradle.kts | 45 +++++++++++++++++++ webauthn-server-attestation/build.gradle.kts | 2 +- 3 files changed, 66 insertions(+), 25 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 5c356e809..18c1aa0fe 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -19,53 +19,49 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - java: [8, 11, 17, 18] + java: [8, 11, 17, 21, 25] distribution: [temurin] include: - - java: 17 + - java: 25 distribution: zulu - - java: 17 + - java: 25 distribution: microsoft outputs: - report-java: 17 + report-java: 25 report-dist: temurin steps: - name: Check out code uses: actions/checkout@v6 - - name: Set up JDK 17 - uses: actions/setup-java@v5 - with: - java-version: 17 - distribution: ${{ matrix.distribution }} - - - name: Compile libraries and tests - run: ./gradlew clean testClasses - - name: Set up JDK ${{ matrix.java }} uses: actions/setup-java@v5 with: java-version: ${{ matrix.java }} distribution: ${{ matrix.distribution }} - - name: Run tests against JDK17-compiled code - run: ./gradlew test --exclude-task compileJava - - - name: Archive HTML test report on failure - if: ${{ failure() }} - uses: actions/upload-artifact@v5 - with: - name: test-reports-java17-java${{ matrix.java }}-${{ matrix.distribution }}-html - path: "*/build/reports/**" - - name: Build and test with JDK ${{ matrix.java }} run: ./gradlew clean test - name: Build archives run: ./gradlew assemble + - name: Run test using Java 25 runtime + run: ./gradlew testJava25 + + - name: Run test using Java 21 runtime + run: ./gradlew testJava21 + + - name: Run test using Java 17 runtime + run: ./gradlew testJava17 + + - name: Run test using Java 11 runtime + run: ./gradlew testJava11 + + - name: Run test using Java 8 runtime + run: ./gradlew testJava8 + - name: Archive HTML test report if: ${{ always() }} uses: actions/upload-artifact@v5 @@ -73,7 +69,7 @@ jobs: name: test-reports-java${{ matrix.java }}-${{ matrix.distribution }}-html path: "*/build/reports/**" - - name: Archive JUnit test report + - name: Archive JUnit test reports if: ${{ always() }} uses: actions/upload-artifact@v5 with: diff --git a/buildSrc/src/main/kotlin/project-convention-java.gradle.kts b/buildSrc/src/main/kotlin/project-convention-java.gradle.kts index bf19301ad..7836a5563 100644 --- a/buildSrc/src/main/kotlin/project-convention-java.gradle.kts +++ b/buildSrc/src/main/kotlin/project-convention-java.gradle.kts @@ -14,3 +14,48 @@ tasks.withType(JavaCompile::class) { sourceCompatibility = "1.8" } } + +tasks.register("testJava8") { + testClassesDirs = tasks.named("test").get().testClassesDirs + classpath = tasks.named("test").get().classpath + javaLauncher.set(javaToolchains.launcherFor { + languageVersion.set(JavaLanguageVersion.of(8)) + }) + tasks["check"].dependsOn(this) +} + +tasks.register("testJava11") { + testClassesDirs = tasks.named("test").get().testClassesDirs + classpath = tasks.named("test").get().classpath + javaLauncher.set(javaToolchains.launcherFor { + languageVersion.set(JavaLanguageVersion.of(11)) + }) + tasks["check"].dependsOn(this) +} + +tasks.register("testJava17") { + testClassesDirs = tasks.named("test").get().testClassesDirs + classpath = tasks.named("test").get().classpath + javaLauncher.set(javaToolchains.launcherFor { + languageVersion.set(JavaLanguageVersion.of(17)) + }) + tasks["check"].dependsOn(this) +} + +tasks.register("testJava21") { + testClassesDirs = tasks.named("test").get().testClassesDirs + classpath = tasks.named("test").get().classpath + javaLauncher.set(javaToolchains.launcherFor { + languageVersion.set(JavaLanguageVersion.of(21)) + }) + tasks["check"].dependsOn(this) +} + +tasks.register("testJava25") { + testClassesDirs = tasks.named("test").get().testClassesDirs + classpath = tasks.named("test").get().classpath + javaLauncher.set(javaToolchains.launcherFor { + languageVersion.set(JavaLanguageVersion.of(25)) + }) + tasks["check"].dependsOn(this) +} \ No newline at end of file diff --git a/webauthn-server-attestation/build.gradle.kts b/webauthn-server-attestation/build.gradle.kts index 713cd59e5..69db25c6a 100644 --- a/webauthn-server-attestation/build.gradle.kts +++ b/webauthn-server-attestation/build.gradle.kts @@ -54,7 +54,7 @@ dependencies { testRuntimeOnly("uk.org.lidalia:slf4j-test") } -val integrationTest = task("integrationTest") { +val integrationTest = tasks.register("integrationTest") { description = "Runs integration tests." group = "verification" From db3d4aaae15c9949610fdbb27388028d2377843e Mon Sep 17 00:00:00 2001 From: Dennis Fokin Date: Fri, 20 Mar 2026 14:15:15 +0100 Subject: [PATCH 2/8] Upgrade to Gradle 9 --- build.gradle | 2 +- gradle/wrapper/gradle-wrapper.properties | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 4abf68a62..a9bdcf335 100644 --- a/build.gradle +++ b/build.gradle @@ -21,7 +21,7 @@ import com.yubico.gradle.GitUtils project.ext.isCiBuild = System.env.CI == 'true' wrapper { - gradleVersion = '8.14.3' + gradleVersion = '9.0.0' } dependencies { diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index d4081da47..2a84e188b 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.0.0-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME From 224806e2843c371edba44856c5c94cce2a11611a Mon Sep 17 00:00:00 2001 From: Dennis Fokin Date: Fri, 20 Mar 2026 14:29:06 +0100 Subject: [PATCH 3/8] Gradle fixes --- buildSrc/build.gradle.kts | 4 ++-- .../com/yubico/gradle/pitest/tasks/PitestMergeTask.groovy | 1 + buildSrc/src/main/kotlin/project-convention-pitest.gradle.kts | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index 53c8a5f8f..b230e80b0 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -10,13 +10,13 @@ repositories { } dependencies { - implementation("info.solidsoft.gradle.pitest:gradle-pitest-plugin:1.15.0") + implementation("info.solidsoft.gradle.pitest:gradle-pitest-plugin:1.19.0-rc.2") implementation("io.franzbecker:gradle-lombok:5.0.0") // Spotless dropped Java 8 support in version 2.33.0 // spotless-plugin-gradle dropped Java <17 support in version 8.0.0 if (JavaVersion.current().isCompatibleWith(JavaVersion.VERSION_17)) { implementation("com.diffplug.spotless:spotless-plugin-gradle:8.2.0") - implementation("io.github.cosmicsilence:gradle-scalafix:0.2.2") + implementation("io.github.cosmicsilence:gradle-scalafix:0.2.6") } } diff --git a/buildSrc/src/main/groovy/com/yubico/gradle/pitest/tasks/PitestMergeTask.groovy b/buildSrc/src/main/groovy/com/yubico/gradle/pitest/tasks/PitestMergeTask.groovy index 720341d72..f330f7d33 100644 --- a/buildSrc/src/main/groovy/com/yubico/gradle/pitest/tasks/PitestMergeTask.groovy +++ b/buildSrc/src/main/groovy/com/yubico/gradle/pitest/tasks/PitestMergeTask.groovy @@ -1,6 +1,7 @@ package com.yubico.gradle.pitest.tasks import groovy.xml.XmlUtil +import groovy.xml.XmlParser import info.solidsoft.gradle.pitest.PitestTask import org.gradle.api.DefaultTask diff --git a/buildSrc/src/main/kotlin/project-convention-pitest.gradle.kts b/buildSrc/src/main/kotlin/project-convention-pitest.gradle.kts index 0bd7a5104..40e19a76f 100644 --- a/buildSrc/src/main/kotlin/project-convention-pitest.gradle.kts +++ b/buildSrc/src/main/kotlin/project-convention-pitest.gradle.kts @@ -4,7 +4,7 @@ plugins { } pitest { - pitestVersion.set("1.15.0") + pitestVersion.set("1.20.3") timestampedReports.set(false) outputFormats.set(listOf("XML", "HTML")) From a163a05203772cc727ec3009d30f36544fe66feb Mon Sep 17 00:00:00 2001 From: Dennis Fokin Date: Fri, 20 Mar 2026 14:32:55 +0100 Subject: [PATCH 4/8] Use io.freefair.gradle lombok plugin We keep the Lombok version pinned. This is necessary to ensure that historical builds continue to work, and to maintain binary reproducibility for historical builds. Co-authored-by: Emil Lundberg --- buildSrc/build.gradle.kts | 2 +- .../groovy/project-convention-lombok.gradle | 30 +------------------ 2 files changed, 2 insertions(+), 30 deletions(-) diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index b230e80b0..18cb5dd9f 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -11,7 +11,7 @@ repositories { dependencies { implementation("info.solidsoft.gradle.pitest:gradle-pitest-plugin:1.19.0-rc.2") - implementation("io.franzbecker:gradle-lombok:5.0.0") + implementation("io.freefair.gradle:lombok-plugin:9.2.0") // Spotless dropped Java 8 support in version 2.33.0 // spotless-plugin-gradle dropped Java <17 support in version 8.0.0 diff --git a/buildSrc/src/main/groovy/project-convention-lombok.gradle b/buildSrc/src/main/groovy/project-convention-lombok.gradle index 13ce462d1..46d7318df 100644 --- a/buildSrc/src/main/groovy/project-convention-lombok.gradle +++ b/buildSrc/src/main/groovy/project-convention-lombok.gradle @@ -1,36 +1,8 @@ -import io.franzbecker.gradle.lombok.task.DelombokTask - plugins { id "java" - id "io.franzbecker.gradle-lombok" + id "io.freefair.lombok" } lombok { version = "1.18.24" - sha256 = "d3584bc2db03f059f984fb0a9c119aac1fa0da578a448e69fc3f68b36584c749" -} - -tasks.withType(AbstractCompile.class) { - dependsOn(tasks.verifyLombok) -} - -task delombok(type: DelombokTask.class, dependsOn: tasks.classes) { - ext.outputDir = file("${buildDir}/delombok") - outputs.dir(outputDir) - project.sourceSets.main.java.srcDirs.forEach { - if (!it.exists()) { - it.mkdirs() - } - inputs.dir(it) - args(it, "-d", outputDir) - } - doFirst { - outputDir.deleteDir() - } -} - -javadoc { - dependsOn(delombok) - source = tasks.delombok.outputDir - inputs.dir(tasks.delombok.outputDir) } From 31ddbea8a4c8de71e87eb0343f59e69572951da1 Mon Sep 17 00:00:00 2001 From: Dennis Fokin Date: Fri, 20 Mar 2026 14:34:42 +0100 Subject: [PATCH 5/8] Upgrade `me.champeau.jmh` plugin Co-authored-by: Emil Lundberg --- webauthn-server-core/build.gradle.kts | 2 +- yubico-util/build.gradle.kts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/webauthn-server-core/build.gradle.kts b/webauthn-server-core/build.gradle.kts index 70b9c5a98..1091211af 100644 --- a/webauthn-server-core/build.gradle.kts +++ b/webauthn-server-core/build.gradle.kts @@ -1,6 +1,6 @@ plugins { `java-library` - id("me.champeau.jmh") version "0.6.8" + id("me.champeau.jmh") version "0.7.3" `project-convention-java` `project-convention-scala` `project-convention-lombok` diff --git a/yubico-util/build.gradle.kts b/yubico-util/build.gradle.kts index 0012ca94a..d387ff5d8 100644 --- a/yubico-util/build.gradle.kts +++ b/yubico-util/build.gradle.kts @@ -1,6 +1,6 @@ plugins { `java-library` - id("me.champeau.jmh") version "0.6.8" + id("me.champeau.jmh") version "0.7.3" `project-convention-java` `project-convention-scala` `project-convention-lombok` From 91617020feed40c2498c4218337f7f354f3fc816 Mon Sep 17 00:00:00 2001 From: Dennis Fokin Date: Thu, 2 Apr 2026 09:20:21 +0200 Subject: [PATCH 6/8] Bump CI Java version --- .github/workflows/build.yml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 18c1aa0fe..ba5dd00ac 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -19,7 +19,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - java: [8, 11, 17, 21, 25] + java: [17, 21, 25] distribution: [temurin] include: - java: 25 @@ -62,7 +62,7 @@ jobs: - name: Run test using Java 8 runtime run: ./gradlew testJava8 - - name: Archive HTML test report + - name: Archive HTML test reports if: ${{ always() }} uses: actions/upload-artifact@v5 with: @@ -77,7 +77,6 @@ jobs: path: "*/build/test-results/**/*.xml" - name: Check binary reproducibility - if: ${{ matrix.java != 8 }} # JDK 8 does not produce reproducible binaries run: | ./gradlew clean primaryPublishJar find . -name '*.jar' | grep -v buildSrc | grep -v gradle-wrapper | xargs sha256sum | tee java-webauthn-server-artifacts.sha256sum @@ -85,7 +84,6 @@ jobs: ./gradlew clean primaryPublishJar && sha256sum -c java-webauthn-server-artifacts.sha256sum - name: Archive artifact checksums - if: ${{ matrix.java != 8 }} # JDK 8 does not produce reproducible binaries uses: actions/upload-artifact@v5 with: name: artifact-checksums-java${{ matrix.java }}-${{ matrix.distribution }} From 66a79a51fe6ade8da21e7a6060a9f3094f0f041c Mon Sep 17 00:00:00 2001 From: Dennis Fokin Date: Mon, 20 Apr 2026 14:52:26 +0200 Subject: [PATCH 7/8] Bump to gradle 9.1.0, since it supports java 25 --- build.gradle | 2 +- gradle/wrapper/gradle-wrapper.properties | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index a9bdcf335..baeb81154 100644 --- a/build.gradle +++ b/build.gradle @@ -21,7 +21,7 @@ import com.yubico.gradle.GitUtils project.ext.isCiBuild = System.env.CI == 'true' wrapper { - gradleVersion = '9.0.0' + gradleVersion = '9.1.0' } dependencies { diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 2a84e188b..2e1113280 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-9.0.0-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.1.0-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME From d994099ba1a3017acd948654f3f6d808d94d6077 Mon Sep 17 00:00:00 2001 From: Dennis Fokin Date: Tue, 19 May 2026 09:58:54 +0200 Subject: [PATCH 8/8] Pin Lombok to 1.18.44, which supports Java 25 --- buildSrc/src/main/groovy/project-convention-lombok.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buildSrc/src/main/groovy/project-convention-lombok.gradle b/buildSrc/src/main/groovy/project-convention-lombok.gradle index 46d7318df..b5824b6a6 100644 --- a/buildSrc/src/main/groovy/project-convention-lombok.gradle +++ b/buildSrc/src/main/groovy/project-convention-lombok.gradle @@ -4,5 +4,5 @@ plugins { } lombok { - version = "1.18.24" + version = "1.18.44" }