diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 7a7ae27..2b7d69f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -19,7 +19,7 @@ jobs: strategy: fail-fast: false matrix: - java: [17, 21] + java: [17, 21, 25] concurrency: group: ${{ github.workflow }}-${{ github.ref }}-java-${{ matrix.java }} cancel-in-progress: true @@ -41,7 +41,7 @@ jobs: uses: gradle/actions/setup-gradle@v5 - name: Cache SonarQube packages - uses: actions/cache@v4 + uses: actions/cache@v5 with: path: ~/.sonar/cache key: ${{ runner.os }}-java-${{ matrix.java }}-sonar @@ -53,6 +53,12 @@ jobs: ORG_GRADLE_PROJECT_ossIndexUsername: ${{ secrets.OSSINDEX_USERNAME }} ORG_GRADLE_PROJECT_ossIndexToken: ${{ secrets.OSSINDEX_TOKEN }} + - name: Upload reports + uses: actions/upload-artifact@v6 + if: ${{ always() }} + with: + name: reports-java-${{ matrix.java }} + path: build/reports/ - name: Sonar analysis if: ${{ env.DEFAULT_JAVA == matrix.java && env.SONAR_TOKEN != null }} diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs index 862d438..220578d 100644 --- a/.settings/org.eclipse.jdt.core.prefs +++ b/.settings/org.eclipse.jdt.core.prefs @@ -10,8 +10,8 @@ org.eclipse.jdt.core.compiler.annotation.nonnullbydefault.secondary= org.eclipse.jdt.core.compiler.annotation.nullable=javax.annotation.Nullable org.eclipse.jdt.core.compiler.annotation.nullable.secondary= org.eclipse.jdt.core.compiler.annotation.nullanalysis=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=17 -org.eclipse.jdt.core.compiler.compliance=17 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=21 +org.eclipse.jdt.core.compiler.compliance=21 org.eclipse.jdt.core.compiler.problem.APILeak=warning org.eclipse.jdt.core.compiler.problem.annotatedTypeArgumentToUnannotated=info org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning @@ -105,7 +105,7 @@ org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning -org.eclipse.jdt.core.compiler.source=17 +org.eclipse.jdt.core.compiler.source=21 org.eclipse.jdt.core.formatter.align_assignment_statements_on_columns=false org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines=2147483647 org.eclipse.jdt.core.formatter.align_selector_in_method_invocation_on_expression_first_line=false diff --git a/CHANGELOG.md b/CHANGELOG.md index 21c2ab2..e89b073 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [3.2.0] - 2026-02-14 + +- [PR #64](https://github.com/itsallcode/openfasttrace-gradle/pull/64) + - Upgrade to OpenFastTrace [4.2.1](https://github.com/itsallcode/openfasttrace/releases/tag/4.2.1) + - Upgrade integration tests to use Gradle 9.3.1 and 8.14.4 - [PR #58](https://github.com/itsallcode/openfasttrace-gradle/pull/58) - Upgrade dependencies - Specify credentials for OssIndex diff --git a/build.gradle b/build.gradle index b6d6aa6..85908b0 100644 --- a/build.gradle +++ b/build.gradle @@ -3,8 +3,9 @@ plugins { id 'jacoco' id 'signing' id 'com.gradle.plugin-publish' version '2.0.0' - id 'org.sonarqube' version '7.0.1.6134' - id 'pl.droidsonroids.jacoco.testkit' version '1.0.12' + id 'org.sonarqube' version '7.2.2.6593' + // Deactivate testkit jacoco plugin for now due to https://github.com/gradle/gradle/issues/25979 + //id 'pl.droidsonroids.jacoco.testkit' version '1.0.12' id 'com.github.ben-manes.versions' version '0.53.0' id 'org.sonatype.gradle.plugins.scan' version '3.1.4' } @@ -15,13 +16,13 @@ repositories { apply from: 'gradle/workAroundJacocoGradleTestKitIssueOnWindows.gradle' -version = '3.1.0' +version = '3.1.1' group = 'org.itsallcode' ext { gradlePluginId = 'org.itsallcode.openfasttrace' - oftVersion = '4.2.0' - junitVersion = '6.0.0' + oftVersion = '4.2.1' + junitVersion = '6.0.2' if (project.hasProperty('oftSourceDir')) { oftSourceDir = file(project.oftSourceDir) useOftSources = oftSourceDir.exists() @@ -60,7 +61,7 @@ dependencies { } def getJavaVersion = { - return project.hasProperty('javaVersion') ? project.getProperty('javaVersion') : 17 + return project.hasProperty('javaVersion') ? project.getProperty('javaVersion') : 21 } java { diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 1b33c55..61285a6 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index d4081da..37f78a6 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.3.1-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew b/gradlew index 23d15a9..adff685 100755 --- a/gradlew +++ b/gradlew @@ -1,7 +1,7 @@ #!/bin/sh # -# Copyright © 2015-2021 the original authors. +# Copyright © 2015 the original authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -114,7 +114,6 @@ case "$( uname )" in #( NONSTOP* ) nonstop=true ;; esac -CLASSPATH="\\\"\\\"" # Determine the Java command to use to start the JVM. @@ -172,7 +171,6 @@ fi # For Cygwin or MSYS, switch paths to Windows format before running java if "$cygwin" || "$msys" ; then APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) - CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) JAVACMD=$( cygpath --unix "$JAVACMD" ) @@ -212,7 +210,6 @@ DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ - -classpath "$CLASSPATH" \ -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ "$@" diff --git a/gradlew.bat b/gradlew.bat index 5eed7ee..e509b2d 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -70,11 +70,10 @@ goto fail :execute @rem Setup the command line -set CLASSPATH= @rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* :end @rem End local scope for the variables with windows NT shell diff --git a/src/test/java/org/itsallcode/openfasttrace/gradle/GradleTestConfig.java b/src/test/java/org/itsallcode/openfasttrace/gradle/GradleTestConfig.java index be55c5c..356ea8c 100644 --- a/src/test/java/org/itsallcode/openfasttrace/gradle/GradleTestConfig.java +++ b/src/test/java/org/itsallcode/openfasttrace/gradle/GradleTestConfig.java @@ -4,9 +4,10 @@ public enum GradleTestConfig { THIS_VERSION(null), /** - * We support the latest Gradle version and the previous two. + * We support the latest Gradle version and the previous two. Older Gradle + * versions do not work with Java 21 and above. */ - PREVIOUS_VERSION_MINUS_ONE("8.12"), PREVIOUS_VERSION("8.13"), CURRENT_VERSION("8.14"); + PREVIOUS_VERSION("8.14.4"), CURRENT_VERSION("9.3.1"); public final String gradleVersion; diff --git a/src/test/java/org/itsallcode/openfasttrace/gradle/OpenFastTracePluginTest.java b/src/test/java/org/itsallcode/openfasttrace/gradle/OpenFastTracePluginTest.java index b562a30..0cf70be 100644 --- a/src/test/java/org/itsallcode/openfasttrace/gradle/OpenFastTracePluginTest.java +++ b/src/test/java/org/itsallcode/openfasttrace/gradle/OpenFastTracePluginTest.java @@ -1,17 +1,15 @@ package org.itsallcode.openfasttrace.gradle; -import static java.util.Arrays.asList; import static java.util.stream.Collectors.joining; -import static org.hamcrest.CoreMatchers.containsString; -import static org.hamcrest.CoreMatchers.startsWith; +import static org.hamcrest.CoreMatchers.*; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.allOf; import static org.junit.jupiter.api.Assertions.*; import java.io.*; import java.nio.charset.StandardCharsets; import java.nio.file.*; -import java.util.ArrayList; -import java.util.List; +import java.util.*; import org.gradle.api.logging.Logging; import org.gradle.internal.impldep.org.apache.commons.compress.archivers.zip.ZipArchiveEntry; @@ -34,15 +32,41 @@ class OpenFastTracePluginTest private static final Path PUBLISH_CONFIG_DIR = EXAMPLES_DIR.resolve("publish-config"); private static final Path HTML_REPORT_CONFIG_DIR = EXAMPLES_DIR.resolve("html-report"); - @ParameterizedTest(name = "testTracingTaskAddedToProject {0}") + @ParameterizedTest(name = "tracingTaskAddedToProject {0}") @EnumSource - void testTracingTaskAddedToProject(final GradleTestConfig config) + void tracingTaskAddedToProject(final GradleTestConfig config) { final BuildResult buildResult = runBuild(config, PROJECT_DEFAULT_CONFIG_DIR, "tasks"); assertThat(buildResult.getOutput(), containsString( "traceRequirements - Trace requirements and generate tracing report")); } + @ParameterizedTest(name = "pluginUsesConfigurationCache {0}") + @EnumSource + void pluginUsesConfigurationCache(final GradleTestConfig config) + { + testConfigurationCache(config, PROJECT_DEFAULT_CONFIG_DIR); + } + + @ParameterizedTest(name = "pluginUsesConfigurationCacheWithMultiModuleProject {0}") + @EnumSource + void pluginUsesConfigurationCacheWithMultiModuleProject(final GradleTestConfig config) + { + testConfigurationCache(config, MULTI_PROJECT_DIR); + } + + private void testConfigurationCache(final GradleTestConfig config, final Path projectDir) + { + BuildResult buildResult = runBuild(config, projectDir, "tasks"); + assertThat(buildResult.getOutput(), containsString( + "traceRequirements - Trace requirements and generate tracing report")); + buildResult = runBuild(config, projectDir, "tasks"); + assertThat(buildResult.getOutput(), + allOf(containsString( + "traceRequirements - Trace requirements and generate tracing report"), + containsString("Reusing configuration cache."))); + } + @ParameterizedTest(name = "testTraceExampleProjectWithDefaultConfig {0}") @EnumSource void testTraceExampleProjectWithDefaultConfig(final GradleTestConfig config) throws IOException @@ -169,7 +193,7 @@ void testTraceExampleProjectWithCustomConfigFailBuild(final GradleTestConfig con @ParameterizedTest(name = "filteredArtifactTypes {0}") @EnumSource - void filteredArtifactTypes(final GradleTestConfig config) throws IOException + void filteredArtifactTypes(final GradleTestConfig config) { final BuildResult buildResult = runBuild(config, PROJECT_CUSTOM_CONFIG_DIR, "clean", "traceRequirements", "-PfailBuild=true", "-PfilteredArtifactTypes=dsn"); @@ -207,25 +231,27 @@ void testTraceMultiProject(final GradleTestConfig config) throws IOException assertFileContent(MULTI_PROJECT_DIR.resolve("build/custom-report.txt"), "ok - 6 total"); } - @ParameterizedTest(name = "testTraceDependencyProject {0}") + @ParameterizedTest(name = "traceDependencyProject {0}") @EnumSource - void testTraceDependencyProject(final GradleTestConfig config) throws IOException + void traceDependencyProject(final GradleTestConfig config) throws IOException { BuildResult buildResult = runBuild(config, DEPENDENCY_CONFIG_DIR, "clean"); + assertThat(buildResult.task(":clean").getOutcome(), + either(is(TaskOutcome.SUCCESS)).or(is(TaskOutcome.UP_TO_DATE))); final Path dependencyZip = DEPENDENCY_CONFIG_DIR.resolve("build/repo/requirements-1.0.zip"); createDependencyZip(dependencyZip); buildResult = runBuild(config, DEPENDENCY_CONFIG_DIR, "traceRequirements"); - assertEquals(TaskOutcome.SUCCESS, buildResult.task(":traceRequirements").getOutcome()); + assertThat(buildResult.task(":traceRequirements").getOutcome(), is(TaskOutcome.SUCCESS)); assertFileContent(DEPENDENCY_CONFIG_DIR.resolve("build/reports/tracing.txt"), "requirements-1.0.zip!spec.md:2", // "requirements-1.0.zip!source.java:1", // "not ok - 2 total, 1 defect"); } - @ParameterizedTest(name = "testPublishToMavenRepo {0}") + @ParameterizedTest(name = "publishToMavenRepo {0}") @EnumSource - void testPublishToMavenRepo(final GradleTestConfig config) throws IOException + void publishToMavenRepo(final GradleTestConfig config) throws IOException { final BuildResult buildResult = runBuild(config, PUBLISH_CONFIG_DIR, "clean", "publishToMavenLocal"); @@ -237,8 +263,10 @@ void testPublishToMavenRepo(final GradleTestConfig config) throws IOException try (ZipFile zip = ZipFile.builder().setFile(archive.toFile()).get()) { final String entryContent = readEntry(zip, "requirements.xml"); - assertThat(entryContent, containsString("\n" + // - "\n")); + assertThat(entryContent, containsString(""" + + + """)); assertThat(entryContent, containsString(""" @@ -311,11 +339,11 @@ private static GradleRunner createGradleRunner(final GradleTestConfig config, { configureJacoco(projectDir); final List allArgs = new ArrayList<>(); - allArgs.addAll(asList(arguments)); - allArgs.addAll(asList("--info", "--stacktrace")); + allArgs.addAll(List.of(arguments)); + allArgs.addAll(List.of("--info", "--stacktrace", "--configuration-cache", "--build-cache")); if (ENABLE_WARNINGS) { - allArgs.addAll(asList("--warning-mode", "all")); + allArgs.addAll(List.of("--warning-mode", "all")); } final GradleRunner runner = GradleRunner.create() // .withProjectDir(projectDir.toFile()) // @@ -331,11 +359,16 @@ private static GradleRunner createGradleRunner(final GradleTestConfig config, private static void configureJacoco(final Path projectDir) { - final String testkitGradleConfig = TestUtil.readResource(OpenFastTracePluginTest.class, - "/testkit-gradle.properties"); - LOG.info("Found testkit gradle config: {}", testkitGradleConfig); + final Optional testkitGradleConfig = TestUtil + .readResource(OpenFastTracePluginTest.class, "/testkit-gradle.properties"); + if (testkitGradleConfig.isEmpty()) + { + LOG.info("Testkit gradle config not available. Skipping configuration"); + return; + } + LOG.info("Found testkit gradle config: {}", testkitGradleConfig.get()); final Path gradleProperties = projectDir.resolve("gradle.properties"); LOG.info("Writing testkit gradle config to {}", gradleProperties); - TestUtil.writeFile(gradleProperties, testkitGradleConfig); + TestUtil.writeFile(gradleProperties, testkitGradleConfig.get()); } } diff --git a/src/test/java/org/itsallcode/openfasttrace/gradle/TestUtil.java b/src/test/java/org/itsallcode/openfasttrace/gradle/TestUtil.java index 5b342cd..a37e037 100644 --- a/src/test/java/org/itsallcode/openfasttrace/gradle/TestUtil.java +++ b/src/test/java/org/itsallcode/openfasttrace/gradle/TestUtil.java @@ -1,22 +1,19 @@ package org.itsallcode.openfasttrace.gradle; -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; +import java.io.*; import java.net.URL; import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.StandardOpenOption; +import java.nio.file.*; +import java.util.Optional; public class TestUtil { - public static String readResource(final Class clazz, final String resourceName) + public static Optional readResource(final Class clazz, final String resourceName) { final URL resource = clazz.getResource(resourceName); if (resource == null) { - throw new AssertionError("Resource '" + resourceName + "' not found"); + return Optional.empty(); } try (BufferedReader reader = new BufferedReader( new InputStreamReader(resource.openStream(), StandardCharsets.UTF_8.name()))) @@ -27,7 +24,7 @@ public static String readResource(final Class clazz, final String resourceNam { b.append(line).append("\n"); } - return b.toString(); + return Optional.of(b.toString()); } catch (final IOException e) {