diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 2a034776..d5a02c79 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -9,21 +9,30 @@ on: jobs: gradle: strategy: + fail-fast: false matrix: os: [ubuntu-latest, macos-latest, windows-latest] + # 11 is the baseline the published main artifact targets, 21 the runtime most + # consumers are on. Compiling to 11 on a 21 JDK cannot catch a problem that only + # appears on an 11 runtime, so both are run. + java-version: [11, 21] runs-on: ${{ matrix.os }} steps: - name: Checkout uses: actions/checkout@v4 - - name: Set up JDK 21 + # Both JDKs are installed, 21 last so it becomes JAVA_HOME and Gradle's daemon runs + # there. The matrix JDK is picked up by the toolchain to compile and run the tests. + - name: Set up JDK ${{ matrix.java-version }} and 21 uses: actions/setup-java@v4 with: distribution: 'temurin' - java-version: 21 + java-version: | + ${{ matrix.java-version }} + 21 - name: Setup Gradle uses: gradle/actions/setup-gradle@v3 - name: Build with Gradle - run: ./gradlew build + run: ./gradlew build -PjavaTestVersion=${{ matrix.java-version }} env: GITHUB_USERNAME: ${{ secrets.GITHUB_USERNAME }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/build.gradle b/build.gradle index 38d5ee39..9dec7c54 100644 --- a/build.gradle +++ b/build.gradle @@ -33,8 +33,17 @@ plugins { } java { + // Bytecode targets 11 to match the Maven main artifact, whatever JDK compiles it. + // The published jdk21 classifier is produced by Maven, which is what publishes. + sourceCompatibility = 11 + targetCompatibility = 11 + + // -PjavaTestVersion selects the JDK that compiles and runs the tests, so CI can + // exercise the same Java 11 bytecode on an 11 and a 21 runtime while Gradle itself + // stays on the launcher JDK. toolchain { - languageVersion = JavaLanguageVersion.of(21) + languageVersion = JavaLanguageVersion.of( + (project.findProperty('javaTestVersion') ?: '21') as Integer) } withJavadocJar() @@ -111,6 +120,15 @@ repositories { } } } + +// cfparser is tracked as a SNAPSHOT. Gradle treats that as a changing module and caches +// it for 24 hours, and the CI workflows restore a Gradle cache -- so a green run shortly +// after a cfparser republish can have tested the *previous* artifact. Re-resolve every +// time; it is one small jar, and a stale one is worth far more than the download. +configurations.all { + resolutionStrategy.cacheChangingModulesFor 0, 'seconds' +} + dependencies { implementation 'com.github.cfmleditor:cfml.parsing:2.16.1-SNAPSHOT' implementation 'commons-cli:commons-cli:1.2' diff --git a/pom.xml b/pom.xml index 3d965eb5..cbfe4e01 100644 --- a/pom.xml +++ b/pom.xml @@ -77,8 +77,12 @@ UTF-8 - 21 - 21 + + 11 + 21 none 2.16.1-SNAPSHOT @@ -210,6 +214,28 @@ + + + org.apache.maven.plugins + maven-compiler-plugin + 3.13.0 + + + compile-jdk21 + compile + + compile + + + ${jdk21.release} + ${project.build.directory}/classes-jdk21 + + + + org.apache.maven.plugins maven-jar-plugin @@ -229,11 +255,48 @@ + + + jar-jdk21 + package + + jar + + + jdk21 + ${project.build.directory}/classes-jdk21 + + + maven-resources-plugin 2.6 + + copy-resources-jdk21 + + process-classes + + copy-resources + + + ${project.build.directory}/classes-jdk21 + + + ${project.build.outputDirectory} + + **/*.class + + + + + copy-resources