Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 7 additions & 15 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,26 +49,18 @@ jobs:
key: ${{ runner.os }}-java-${{ matrix.java }}-sonar
restore-keys: ${{ runner.os }}-java-${{ matrix.java }}-sonar

- name: Build with Java ${{ matrix.java }} with configuration cache
run: ./gradlew build --warning-mode all --exclude-task ossIndexAudit -PenableConfigurationCache=true -PjavaVersion=${{ matrix.java }}
- name: Build with Java ${{ matrix.java }}
run: |
./gradlew build --warning-mode fail \
--configuration-cache --configuration-cache-problems=fail \
--exclude-task ossIndexAudit \
Comment thread
kaklakariada marked this conversation as resolved.
-PjavaVersion=${{ matrix.java }}

- name: Upload reports
uses: actions/upload-artifact@v7
if: ${{ always() }}
with:
name: reports-${{ runner.os }}-java-${{ matrix.java }}-with-configuration-cache
path: build/reports/

- name: Build with Java ${{ matrix.java }} without configuration cache
if: ${{ always() }}
# Required to get jacoco test coverage reports for SonarQube, which doesn't work with configuration cache enabled, see https://github.com/gradle/gradle/issues/25979
run: ./gradlew clean build --warning-mode all --exclude-task ossIndexAudit -PenableConfigurationCache=false -PjavaVersion=${{ matrix.java }}

- name: Upload reports
uses: actions/upload-artifact@v7
if: ${{ always() }}
with:
name: reports-${{ runner.os }}-java-${{ matrix.java }}-without-configuration-cache
name: reports-${{ runner.os }}-java-${{ matrix.java }}
path: build/reports/

- name: Sonar analysis
Expand Down
6 changes: 3 additions & 3 deletions .settings/org.eclipse.jdt.core.prefs
Original file line number Diff line number Diff line change
Expand Up @@ -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=21
org.eclipse.jdt.core.compiler.compliance=21
org.eclipse.jdt.core.compiler.codegen.targetPlatform=17
org.eclipse.jdt.core.compiler.compliance=17
org.eclipse.jdt.core.compiler.problem.APILeak=warning
org.eclipse.jdt.core.compiler.problem.annotatedTypeArgumentToUnannotated=info
org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
Expand Down Expand Up @@ -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=21
org.eclipse.jdt.core.compiler.source=17
org.eclipse.jdt.core.formatter.align_arrows_in_switch_on_columns=false
org.eclipse.jdt.core.formatter.align_assignment_statements_on_columns=false
org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines=2147483647
Expand Down
3 changes: 1 addition & 2 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
"source.generate.finalModifiers": "explicit",
"source.fixAll": "explicit"
},
"java.saveActions.organizeImports": true,
"java.sources.organizeImports.starThreshold": 3,
"java.sources.organizeImports.staticStarThreshold": 3,
"java.configuration.updateBuildConfiguration": "automatic",
Expand All @@ -16,4 +15,4 @@
"projectKey": "org.itsallcode:openfasttrace-gradle"
},
"java.jdt.ls.vmargs": "-XX:+UseParallelGC -XX:GCTimeRatio=4 -XX:AdaptiveSizePolicyWeight=90 -Dsun.zip.disableMemoryMapping=true -Xmx12G -Xms100m"
}
}
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Upgrade to Gradle 9.7.1
- Update Eclipse formatter settings to latest version
- Remove unused Eclipse Save Actions configuration
- [#81](https://github.com/itsallcode/openfasttrace-gradle/issues/81):
- Ensure compatibility with Gradle configuration cache
- Mark plugin as compatible with configuration cache

## [3.2.0] - 2026-08-18

Expand Down
20 changes: 6 additions & 14 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ dependencies {
}

def getJavaVersion = {
return project.hasProperty('javaVersion') ? project.getProperty('javaVersion') : 21
return project.hasProperty('javaVersion') ? project.getProperty('javaVersion') : 17
}

java {
Expand Down Expand Up @@ -109,6 +109,11 @@ gradlePlugin {
displayName = 'OpenFastTrace requirements tracing plugin'
description = 'Gradle plugin for tracing requirements using OpenFastTrace'
tags.addAll(['requirementstracing', 'requirements', 'tracing', 'reqtracing', 'openfasttrace', 'oft'])
compatibility {
features {
configurationCache = true
}
}
}
}
}
Expand All @@ -128,23 +133,10 @@ testing {
implementation "org.hamcrest:hamcrest-core:3.0"
implementation "com.jparams:to-string-verifier:1.4.8"
}
targets {
all {
testTask.configure {
if (project.hasProperty('enableConfigurationCache')) {
def enableConfigurationCache = project.getProperty("enableConfigurationCache")
logger.lifecycle "Setting system property 'enableConfigurationCache' to $enableConfigurationCache for test task '${name}'"
systemProperty "enableConfigurationCache", enableConfigurationCache
}
}
}
}
}
}
}

test.onlyIf { rootProject.name == 'openfasttrace-gradle' }

jacocoTestReport {
dependsOn test
reports {
Expand Down
3 changes: 3 additions & 0 deletions settings.gradle
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
plugins {
id 'org.gradle.toolchains.foojay-resolver-convention' version '1.0.0'
}
rootProject.name = 'openfasttrace-gradle'
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@

import java.io.File;
import java.util.*;
import java.util.stream.Stream;

import org.gradle.api.Plugin;
import org.gradle.api.Project;
import org.gradle.api.artifacts.Configuration;
import org.gradle.api.file.ConfigurableFileCollection;
import org.gradle.api.logging.Logging;
import org.gradle.api.plugins.ExtensionAware;
import org.gradle.api.tasks.TaskProvider;
Expand Down Expand Up @@ -70,9 +70,8 @@ private static TaskProvider<CollectTask> createCollectTask(final Project rootPro
task.setGroup(TASK_GROUP_NAME);
task.setDescription("Collect requirements and generate specobject file");
task.getInputDirectories().set(getAllInputDirectories(rootProject.getAllprojects()));
task.getOutputFile()
.set(new File(rootProject.getLayout().getBuildDirectory().getAsFile().get(),
"reports/requirements.xml"));
task.getOutputFile().set(
rootProject.getLayout().getBuildDirectory().file("reports/requirements.xml"));
task.getPathConfig().set(getPathConfig(rootProject.getAllprojects()));
});
}
Expand All @@ -92,21 +91,22 @@ private static void configureTask(final Project rootProject,
task.dependsOn(collectTask);
final TracingConfig config = getConfig(rootProject);
task.getFailBuild().set(config.getFailBuild());
task.getRequirementsFile().set(collectTask.get().getOutputFile());
task.getRequirementsFile().set(collectTask.flatMap(CollectTask::getOutputFile));
if (config.getReportFile().isPresent())
{
task.getOutputFile().set(config.getReportFile());
}
else
{
final String extension = "html".equals(config.getReportFormat().get()) ? "html" : "txt";
task.getOutputFile()
.set(new File(rootProject.getLayout().getBuildDirectory().getAsFile().get(),
"reports/tracing." + extension));
task.getOutputFile().set(config.getReportFormat().map(format -> rootProject.getLayout()
.getBuildDirectory()
.file("reports/tracing." + ("html".equals(format) ? "html" : "txt"))
.get()));
}
task.getReportVerbosity().set(config.getReportVerbosity());
task.getReportFormat().set(config.getReportFormat());
task.getImportedRequirements().set(getImportedRequirements(rootProject.getAllprojects()));
task.getImportedRequirements()
.from(getImportedRequirements(rootProject, rootProject.getAllprojects()));
task.getFilteredArtifactTypes().set(config.getFilteredArtifactTypes());
task.getFilteredTags().set(config.getFilteredTags());
task.getFilterAcceptsItemsWithoutTag().set(config.getFilterAcceptsItemsWithoutTag());
Expand Down Expand Up @@ -144,14 +144,15 @@ private static Set<File> getAllInputDirectories(final Set<Project> allProjects)
.collect(toSet());
}

private static Set<File> getImportedRequirements(final Set<Project> allProjects)
private static ConfigurableFileCollection getImportedRequirements(final Project rootProject,
final Set<Project> allProjects)
{
return allProjects.stream() //
.flatMap(OpenFastTracePlugin::getImportedRequirements) //
.collect(toSet());
return rootProject.files(allProjects.stream() //
.map(OpenFastTracePlugin::getImportedRequirements) //
.toList());
}

private static Stream<File> getImportedRequirements(final Project project)
private static Configuration getImportedRequirements(final Project project)
{
final String CONFIG_NAME = "oftRequirementConfig";
final Configuration configuration = project.getConfigurations().create(CONFIG_NAME);
Expand All @@ -160,9 +161,7 @@ private static Stream<File> getImportedRequirements(final Project project)
CONFIG_NAME, project);
project.getDependencies().add(CONFIG_NAME, dependency);
});
final Set<File> files = configuration.getFiles();
LOG.info("Found {} dependency files: {}", files.size(), files);
return files.stream();
return configuration;
}

private static List<SerializableTagPathConfig> getPathConfig(final Set<Project> allProjects)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import java.util.stream.Stream;

import org.gradle.api.DefaultTask;
import org.gradle.api.file.ConfigurableFileCollection;
import org.gradle.api.file.RegularFileProperty;
import org.gradle.api.provider.Property;
import org.gradle.api.provider.SetProperty;
Expand All @@ -31,8 +32,7 @@ public class TraceTask extends DefaultTask
private final Property<String> reportFormat = getProject().getObjects().property(String.class);
private final Property<DetailsSectionDisplay> detailsSectionDisplay = getProject().getObjects()
.property(DetailsSectionDisplay.class);
private final SetProperty<File> importedRequirements = getProject().getObjects()
.setProperty(File.class);
private final ConfigurableFileCollection importedRequirements = getProject().files();
private final SetProperty<String> filteredArtifactTypes = getProject().getObjects()
.setProperty(String.class);
private final SetProperty<String> filteredTags = getProject().getObjects()
Expand Down Expand Up @@ -99,8 +99,9 @@ public Property<String> getReportFormat()
*
* @return the imported requirements property
*/
@Input
public SetProperty<File> getImportedRequirements()
@InputFiles
@PathSensitive(PathSensitivity.ABSOLUTE)
public ConfigurableFileCollection getImportedRequirements()
{
return importedRequirements;
}
Expand Down Expand Up @@ -247,7 +248,7 @@ private FilterSettings getFilterSettings()

private List<Path> getAllImportFiles()
{
final Stream<Path> importedRequirementPaths = importedRequirements.get().stream()
final Stream<Path> importedRequirementPaths = importedRequirements.getFiles().stream()
.map(File::toPath);
final Stream<Path> inputDirPaths = Stream.of(requirementsFile.getAsFile().get().toPath());
return Stream.concat(importedRequirementPaths, inputDirPaths).toList();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import static java.util.stream.Collectors.joining;
import static org.hamcrest.CoreMatchers.*;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.allOf;
import static org.hamcrest.Matchers.either;
import static org.junit.jupiter.api.Assertions.*;

Expand Down Expand Up @@ -46,26 +45,60 @@ void tracingTaskAddedToProject()
@Test
void pluginUsesConfigurationCache()
{
testConfigurationCache(PROJECT_DEFAULT_CONFIG_DIR);
testConfigurationCache(PROJECT_CUSTOM_CONFIG_DIR,
Path.of("build/custom-report.txt"),
"not ok [ in: 1 / 1 ✔ | out: 0 / 0 ] dsn~exampleB~1 [draft] (impl, -utest)",
"not ok - 2 total, 1 direct, 0 transitive defects");
}

@Test
void pluginUsesConfigurationCacheWithMultiModuleProject()
{
testConfigurationCache(MULTI_PROJECT_DIR);
testConfigurationCache(MULTI_PROJECT_DIR, Path.of("build/custom-report.txt"),
"ok - 6 total");
}

private void testConfigurationCache(final Path projectDir)
@Test
void pluginUsesConfigurationCacheWithImportedRequirements()
{
PluginTestFixture.assumeConfigurationCacheEnabled();
final PluginTestFixture fixture = fixture(projectDir).withArgs("tasks");
final PluginTestFixture fixture = fixture(DEPENDENCY_CONFIG_DIR);
fixture.withArgs("clean").run()
.assertOutcome(":clean",
either(is(TaskOutcome.SUCCESS))
.or(is(TaskOutcome.UP_TO_DATE)));

fixture.run().assertOutput(containsString(
"traceRequirements - Trace requirements and generate tracing report"));
final Path dependencyZip = DEPENDENCY_CONFIG_DIR
.resolve("build/repo/requirements-1.0.zip");
createDependencyZip(dependencyZip);

testConfigurationCache(fixture,
Path.of("build/reports/tracing.txt"),
"requirements-1.0.zip!spec.md:2",
"requirements-1.0.zip!source.java:1",
"not ok - 2 total, 1 direct, 0 transitive defects");
}

fixture.run().assertOutput(allOf(containsString(
"traceRequirements - Trace requirements and generate tracing report"),
containsString("Reusing configuration cache.")));
private void testConfigurationCache(final Path projectDir, final Path reportFile,
final String... lines)
{
testConfigurationCache(fixture(projectDir), reportFile, lines);
}

private void testConfigurationCache(final PluginTestFixture fixture, final Path reportFile,
final String... lines)
{
fixture.withArgs("traceRequirements")
.withReportFile(reportFile)
.run()
.assertTraceOutcomeSuccessFromCacheOrUpToDate()
.assertReportFileLines(lines);

fixture.withArgs("traceRequirements")
.withReportFile(reportFile)
.run()
.assertTraceOutcomeSuccessFromCacheOrUpToDate()
.assertReportFileLines(lines)
.assertOutput(containsString("Reusing configuration cache."));
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import static org.hamcrest.CoreMatchers.*;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assumptions.assumeTrue;

import java.nio.file.Path;
import java.util.*;
Expand Down Expand Up @@ -66,11 +65,8 @@ private GradleRunner createGradleRunner()
final List<String> allArgs = new ArrayList<>();
allArgs.addAll(List.of(arguments));
allArgs.addAll(List.of("--info", "--stacktrace", "--build-cache"));
if (configurationCacheEnabled())
{
allArgs.add("--configuration-cache");
}
allArgs.addAll(List.of("--warning-mode", "all"));
allArgs.addAll(List.of("--configuration-cache", "--configuration-cache-problems=fail"));
allArgs.addAll(List.of("--warning-mode", "fail"));
final GradleRunner runner = GradleRunner.create()
.withProjectDir(projectDir.toFile())
.withPluginClasspath()
Expand All @@ -83,17 +79,6 @@ private GradleRunner createGradleRunner()
return runner;
}

static void assumeConfigurationCacheEnabled()
{
assumeTrue(configurationCacheEnabled(), "Configuration cache is not enabled");
}

static boolean configurationCacheEnabled()
{
return System.getProperty("enableConfigurationCache", "false")
.equalsIgnoreCase("true");
}

private static void configureJacoco(final Path projectDir)
{
final Optional<String> testkitGradleConfig = TestUtil
Expand Down Expand Up @@ -129,6 +114,14 @@ Result assertTraceOutcomeSuccessOrFromCache()
return assertOutcomeSuccessOrFromCache(":traceRequirements");
}

Result assertTraceOutcomeSuccessFromCacheOrUpToDate()
{
return assertOutcome(":traceRequirements",
either(is(TaskOutcome.SUCCESS))
.or(is(TaskOutcome.FROM_CACHE))
.or(is(TaskOutcome.UP_TO_DATE)));
}

Result assertCollectOutcomeUpToDate()
{
return this.assertOutcome(":collectRequirements", TaskOutcome.UP_TO_DATE);
Expand Down
Loading