diff --git a/AGENTS.md b/AGENTS.md index b232330..1d92df4 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -11,14 +11,14 @@ This file provides guidance for AI agents and LLMs working on the OpenFastTrace All commands should be run from the repository root. -| Task | Command | -|:-------------------------|:-------------------------------------------------------------------------| -| **Verify (All tests)** | `mvn verify` | -| **Build (full)** | `mvn clean package -DskipTests` | -| **Run Unit Tests** | `mvn test` | -| **Run Single Test** | `mvn test -Dtest=ClassName` | -| **Run Integration Test** | `mvn failsafe:integration-test` | -| **Check Dependencies** | `mvn versions:display-dependency-updates` | +| Task | Command | +|:-------------------------|:------------------------------------------| +| **Verify (All tests)** | `mvn verify` | +| **Build (full)** | `mvn clean package -DskipTests` | +| **Run Unit Tests** | `mvn test` | +| **Run Single Test** | `mvn test -Dtest=ClassName` | +| **Run Integration Test** | `mvn failsafe:integration-test` | +| **Check Dependencies** | `mvn versions:display-dependency-updates` | ### Agent Role & Persona diff --git a/CHANGELOG.md b/CHANGELOG.md index 0fb2c25..5b94ca5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,10 +4,16 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [2.4.0] - 2026-06-14 +## [3.0.0] - 2026-08-09 -* [PR# 88](https://github.com/itsallcode/openfasttrace-maven-plugin/pull/88) Updated to [OpenFastTrace 4.5.0](https://github.com/itsallcode/openfasttrace/releases/tag/4.5.0) +* **Breaking change**: Add `openfasttrace.` prefix to all plugin properties to avoid conflicts and allow consistent command-line overrides ([#80](https://github.com/itsallcode/openfasttrace-maven-plugin/issues/80)). Existing configurations using the old names in `pom.xml` remain compatible. +* **Breaking change**: Set default value for `statuses` to `APPROVED` to align with OpenFastTrace core behavior. Items without an explicit status are considered `APPROVED` by default. +* [PR# 88](https://github.com/itsallcode/openfasttrace-maven-plugin/pull/88) Updated to [OpenFastTrace 4.9.0](https://github.com/itsallcode/openfasttrace/releases/tag/4.9.0) * We also now generate an SPDX SBOM +* Added compatibility shim for `RegexMatchingImporterFactory` to support older OpenFastTrace plugins with OpenFastTrace 4.8.0. + +- Update OpenFastTrace to 4.9.0. +- Add support for filtering by item status using the `statuses` property. ## [2.3.1] - 2026-05-18 diff --git a/README.md b/README.md index 12b3182..e0111d1 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ Add the openfasttrace-maven-plugin to your `pom.xml`: org.itsallcode openfasttrace-maven-plugin - 2.3.1 + 3.0.0 trace-requirements @@ -54,6 +54,7 @@ Add the openfasttrace-maven-plugin to your `pom.xml`: COLLAPSE feat,req prototype,mvp + APPROVED,DRAFT ``` @@ -72,7 +73,7 @@ You can use OpenFastTrace plugins to import and export requirements in additiona org.itsallcode openfasttrace-maven-plugin - 2.3.1 + 3.0.0 true @@ -197,7 +198,21 @@ This works similar to OFT's command line argument `--wanted-tags`. You can specify the underscore `_` to import specification items without tags. -You can also specify the tags to import using CLI option `-Dtags=prototype,mvp`. +You can also specify the tags to import using CLI option `-Dopenfasttrace.tags=prototype,mvp`. + +##### Select Statuses + +The following example configuration limits import to statuses `APPROVED` and `DRAFT`. + +```xml + + APPROVED,DRAFT + +``` + +This works similar to OFT's command line argument `--wanted-statuses`. + +You can also specify the statuses to import using CLI option `-Dopenfasttrace.statuses=APPROVED,DRAFT`. #### Report @@ -215,7 +230,7 @@ The HTML report will have its details sections collapsed (i.e. hidden) by defaul #### Fail Build -By default, the build will fail when there are errors found during tracing. To continue with the build when tracing fails, use configuration `false`. +By default, the build will fail when there are errors found during tracing. To continue with the build when tracing fails, use configuration `false` or command line option `-Dopenfasttrace.failBuild=false`. #### Skipping Execution @@ -301,7 +316,7 @@ mvn --update-snapshots versions:use-latest-releases versions:update-properties #### Prepare the Release 1. Checkout the `main` branch. -2. Update version in `pom.xml`, `CHANGELOG.md` and `README.md`. +2. Update the version in `pom.xml`, `CHANGELOG.md` and `README.md`. 3. Commit and push changes. 4. Create a new pull request, have it reviewed and merged to `main`. @@ -310,5 +325,5 @@ mvn --update-snapshots versions:use-latest-releases versions:update-properties 1. Start the release workflow * Run command `gh workflow run release.yml --repo itsallcode/openfasttrace-maven-plugin --ref main` * or go to [GitHub Actions](https://github.com/itsallcode/openfasttrace-maven-plugin/actions/workflows/release.yml) and start the `release.yml` workflow on branch `main`. -2. Update title and description of the newly created [GitHub release](https://github.com/itsallcode/openfasttrace-maven-plugin/releases). +2. Update the title and description of the newly created [GitHub release](https://github.com/itsallcode/openfasttrace-maven-plugin/releases). 3. After some time the release will be available at [Maven Central](https://repo1.maven.org/maven2/org/itsallcode/openfasttrace-maven-plugin/). diff --git a/SECURITY.md b/SECURITY.md index 4161a0c..ad0f4a9 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -10,4 +10,4 @@ To report a vulnerability, please use the [GitHub Security Advisory reporting fe ## Software Bill of Materials (SBOM) -To enhance transparency and security, SPDX SBOMs (Software Bill of Materials) are included with the plugin releases starting from version 2.4.0. These files provide a comprehensive list of all components and dependencies used in the project. +To enhance transparency and security, SPDX SBOMs (Software Bill of Materials) are included with the plugin releases starting from version 3.0.0. These files provide a comprehensive list of all components and dependencies used in the project. diff --git a/pom.xml b/pom.xml index 4b1147a..ae821fd 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ org.itsallcode openfasttrace-maven-plugin - 2.4.0 + 3.0.0 maven-plugin OpenFastTrace Maven Plugin @@ -15,12 +15,12 @@ UTF-8 17 - 4.5.0 + 4.9.0 3.9.9 - + 3.15.2 - 0.8.14 + 0.8.15 itsallcode https://sonarcloud.io ${git.commit.time} @@ -134,7 +134,7 @@ org.junit.jupiter junit-jupiter - 6.1.0 + 6.1.3 test @@ -171,7 +171,7 @@ org.sonatype.central central-publishing-maven-plugin - 0.10.0 + 0.11.0 true central @@ -229,7 +229,7 @@ org.apache.maven.plugins maven-toolchains-plugin - 3.2.0 + 3.3.0 @@ -249,7 +249,7 @@ org.apache.maven.plugins maven-enforcer-plugin - 3.6.2 + 3.6.3 enforce-maven @@ -330,7 +330,7 @@ org.apache.maven.plugins maven-jar-plugin - 3.5.0 + 3.5.1 org.apache.maven.plugins @@ -416,7 +416,7 @@ org.apache.maven.plugins maven-dependency-plugin - 3.10.0 + 3.11.0 copy-jacoco @@ -436,7 +436,7 @@ org.apache.maven.plugins maven-surefire-plugin - 3.5.5 + 3.5.6 src/test/resources/logging.properties @@ -446,7 +446,7 @@ org.apache.maven.plugins maven-failsafe-plugin - 3.5.5 + 3.5.6 true @@ -555,7 +555,7 @@ org.spdx spdx-maven-plugin - 1.0.3 + 1.0.4 aggregate-spdx diff --git a/src/main/java/org/itsallcode/openfasttrace/api/importer/RegexMatchingImporterFactory.java b/src/main/java/org/itsallcode/openfasttrace/api/importer/RegexMatchingImporterFactory.java new file mode 100644 index 0000000..5b64123 --- /dev/null +++ b/src/main/java/org/itsallcode/openfasttrace/api/importer/RegexMatchingImporterFactory.java @@ -0,0 +1,30 @@ +package org.itsallcode.openfasttrace.api.importer; + +import java.util.Collection; + +/** + * Compatibility shim for RegexMatchingImporterFactory which was renamed to + * AbstractRegexMatchingImporterFactory in OpenFastTrace 4.5.0. + *

+ * Shim can be removed when the following issue is fixed: + * + * itsallcode/openffasttrace-asciidoc-plugin # 27 + * + *

+ * + * @deprecated use {@link AbstractRegexMatchingImporterFactory} instead. + */ +@Deprecated(since = "4.5.0") +@SuppressWarnings("java:S118") // Shim class. Ignore name convention. +public abstract class RegexMatchingImporterFactory extends AbstractRegexMatchingImporterFactory +{ + protected RegexMatchingImporterFactory(final String... extensions) + { + super(extensions); + } + + protected RegexMatchingImporterFactory(final Collection extensions) + { + super(extensions); + } +} diff --git a/src/main/java/org/itsallcode/openfasttrace/maven/TraceMojo.java b/src/main/java/org/itsallcode/openfasttrace/maven/TraceMojo.java index 7d3e6a5..75cf171 100644 --- a/src/main/java/org/itsallcode/openfasttrace/maven/TraceMojo.java +++ b/src/main/java/org/itsallcode/openfasttrace/maven/TraceMojo.java @@ -37,7 +37,7 @@ public class TraceMojo extends AbstractMojo *

* Default: ${project.build.directory} */ - @Parameter(property = "outputDirectory", defaultValue = "${project.build.directory}", required = true) + @Parameter(property = "openfasttrace.outputDirectory", defaultValue = "${project.build.directory}", required = true) private File outputDirectory; /** @@ -45,7 +45,7 @@ public class TraceMojo extends AbstractMojo *

* Default: {@code true} */ - @Parameter(property = "failBuild", defaultValue = "true", required = true) + @Parameter(property = "openfasttrace.failBuild", defaultValue = "true", required = true) private boolean failBuild; /** @@ -55,7 +55,7 @@ public class TraceMojo extends AbstractMojo *

  • {@code plain}: Plain text format
  • * */ - @Parameter(property = "reportOutputFormat", defaultValue = "html", required = true) + @Parameter(property = "openfasttrace.reportOutputFormat", defaultValue = "html", required = true) private String reportOutputFormat; /** @@ -70,7 +70,7 @@ public class TraceMojo extends AbstractMojo *
  • {@code ALL}
  • * */ - @Parameter(property = "reportVerbosity", defaultValue = "FAILURE_DETAILS", required = true) + @Parameter(property = "openfasttrace.reportVerbosity", defaultValue = "FAILURE_DETAILS", required = true) private ReportVerbosity reportVerbosity; /** @@ -78,7 +78,7 @@ public class TraceMojo extends AbstractMojo *

    * Default: false */ - @Parameter(property = "reportShowOrigin", defaultValue = "false", required = true) + @Parameter(property = "openfasttrace.reportShowOrigin", defaultValue = "false", required = true) private boolean reportShowOrigin; /** @@ -89,7 +89,7 @@ public class TraceMojo extends AbstractMojo *

  • {@code EXPAND}: show details section
  • * */ - @Parameter(property = "detailsSectionDisplay", defaultValue = "COLLAPSE", required = true) + @Parameter(property = "openfasttrace.detailsSectionDisplay", defaultValue = "COLLAPSE", required = true) private DetailsSectionDisplay detailsSectionDisplay; /** @@ -101,7 +101,7 @@ public class TraceMojo extends AbstractMojo * match the specified types will be imported. * */ - @Parameter(property = "artifactTypes") + @Parameter(property = "openfasttrace.artifactTypes") Set artifactTypes; /** @@ -113,9 +113,24 @@ public class TraceMojo extends AbstractMojo *

    * Default: Import all specification items. */ - @Parameter(property = "tags") + @Parameter(property = "openfasttrace.tags") Set tags; + /** + * Determines which statuses should be imported. + *

    + * Only artifacts with statuses that match the specified statuses will be + * imported. Artifacts without an explicit status are considered + * {@code APPROVED}. + *

    + * Default: {@code APPROVED} + *

    + * Valid values: {@code APPROVED}, {@code PROPOSED}, {@code DRAFT}, + * {@code REJECTED}. + */ + @Parameter(property = "openfasttrace.statuses", defaultValue = "APPROVED") + Set statuses; + /** * Skip running OFT. *

    @@ -203,6 +218,8 @@ private static String formatFilterSettings(final FilterSettings settings) ", artifact types: " + settings.getArtifactTypes() + ", tag criteria set: " + settings.isTagCriteriaSet() + ", tags: " + settings.getTags() + + ", status criteria set: " + settings.isStatusCriteriaSet() + + ", statuses: " + settings.getWantedStatuses() + ", without tags: " + settings.withoutTags() + "]"; } @@ -279,6 +296,7 @@ ImportSettings createImportSettings() final FilterSettings filterSettings = FilterSettings.builder() .artifactTypes(getFilteredArtifactTypes()) .tags(getFilteredTags()) + .wantedStatuses(getFilteredStatuses()) .withoutTags(isFilterWithoutTags()) .build(); settings.filter(filterSettings); @@ -290,6 +308,11 @@ private Set getFilteredArtifactTypes() return artifactTypes == null ? emptySet() : artifactTypes; } + private Set getFilteredStatuses() + { + return statuses == null ? emptySet() : statuses; + } + private Set getFilteredTags() { if (tags == null) diff --git a/src/test/java/org/itsallcode/openfasttrace/maven/TraceMojoIT.java b/src/test/java/org/itsallcode/openfasttrace/maven/TraceMojoIT.java index 4a83b99..3f0664a 100644 --- a/src/test/java/org/itsallcode/openfasttrace/maven/TraceMojoIT.java +++ b/src/test/java/org/itsallcode/openfasttrace/maven/TraceMojoIT.java @@ -47,6 +47,7 @@ class TraceMojoIT .resolve("html-report"); public static final Path PARTIAL_ARTIFACT_COVERAGE_PROJECT = BASE_TEST_DIR .resolve("project-with-partial-artifact-coverage"); + private static final Path PROJECT_WITH_STATUSES = BASE_TEST_DIR.resolve("project-with-statuses"); private static MavenIntegrationTestEnvironment mvnITEnv; @BeforeAll @@ -152,7 +153,7 @@ void testTracingFindsDefects() throws Exception runTracingMojo(TRACING_DEFECTS); assertThat(fileContent(TRACING_DEFECTS.resolve("target/tracing-report.txt")), - containsString("not ok - 2 total, 1 defect")); + containsString("not ok - 2 total, 1 direct, 0 transitive defects")); } @Test @@ -177,7 +178,7 @@ void testTracingFindsDefectsFailBuild() () -> runTracingMojo(TRACING_DEFECTS_FAIL_BUILD)); assertAll(() -> assertThat(exception.getMessage(), containsString("Tracing found 1 defects out of 2 items")), () -> assertThat(fileContent(TRACING_DEFECTS_FAIL_BUILD.resolve("target/tracing-report.txt")), - containsString("not ok - 2 total, 1 defect"))); + containsString("not ok - 2 total, 1 direct, 0 transitive defects"))); } @Test @@ -194,7 +195,7 @@ void testHtmlReport() throws Exception void testHtmlReportWithExpandedDetails() throws Exception { final Verifier verifier = mvnITEnv.getVerifier(HTML_REPORT_PROJECT); - verifier.addCliOption("-DdetailsSectionDisplay=EXPAND"); + verifier.addCliOption("-Dopenfasttrace.detailsSectionDisplay=EXPAND"); verifier.executeGoal(OFT_GOAL); verifier.verifyErrorFreeLog(); @@ -206,7 +207,7 @@ void testHtmlReportWithExpandedDetails() throws Exception void testTracingSelectedArtifactTypes() throws Exception { final Verifier verifier = mvnITEnv.getVerifier(PARTIAL_ARTIFACT_COVERAGE_PROJECT); - verifier.addCliOption("-DartifactTypes=one,two"); + verifier.addCliOption("-Dopenfasttrace.artifactTypes=one,two"); verifier.executeGoal(OFT_GOAL); verifier.verifyErrorFreeLog(); assertThat(fileContent(PARTIAL_ARTIFACT_COVERAGE_PROJECT.resolve("target/tracing-report.txt")), @@ -222,17 +223,17 @@ void testTracingSelectedArtifactTypes() throws Exception void testTracingSelectedTags(final String tags, final int expectedItemCount) throws Exception { final Verifier verifier = mvnITEnv.getVerifier(PROJECT_WITH_TAGS); - verifier.addCliOption("-DfailBuild=false"); + verifier.addCliOption("-Dopenfasttrace.failBuild=false"); if (tags != null) { - verifier.addCliOption("-Dtags=" + tags); + verifier.addCliOption("-Dopenfasttrace.tags=" + tags); } verifier.executeGoal(OFT_GOAL); verifier.verifyErrorFreeLog(); final String expectedResult; if (expectedItemCount > 0) { - expectedResult = "not ok - %1$d total, %1$d defect".formatted(expectedItemCount); + expectedResult = "not ok - %1$d total, %1$d direct, 0 transitive defects".formatted(expectedItemCount); } else { @@ -242,6 +243,32 @@ void testTracingSelectedTags(final String tags, final int expectedItemCount) thr containsString(expectedResult)); } + @ParameterizedTest(name = "wanted statuses {0} finds {1} items") + @CsvSource(delimiter = ';', nullValues = "NULL", value = + { "NULL; 2", "APPROVED; 2", "PROPOSED; 1", "APPROVED,PROPOSED; 3", "DRAFT; 0" }) + void testTracingSelectedStatuses(final String statuses, final int expectedItemCount) throws Exception + { + final Verifier verifier = mvnITEnv.getVerifier(PROJECT_WITH_STATUSES); + verifier.addCliOption("-Dopenfasttrace.failBuild=false"); + if (statuses != null) + { + verifier.addCliOption("-Dopenfasttrace.statuses=" + statuses); + } + verifier.executeGoal(OFT_GOAL); + verifier.verifyErrorFreeLog(); + final String expectedResult; + if (expectedItemCount > 0) + { + expectedResult = "not ok - %1$d total".formatted(expectedItemCount); + } + else + { + expectedResult = "ok - 0 total"; + } + assertThat(fileContent(PROJECT_WITH_STATUSES.resolve("target/tracing-report.txt")), + containsString(expectedResult)); + } + private static void runTracingMojo(final Path projectDir) throws Exception { LOG.info("Running tracing in " + projectDir + "..."); diff --git a/src/test/java/org/itsallcode/openfasttrace/maven/TraceMojoTest.java b/src/test/java/org/itsallcode/openfasttrace/maven/TraceMojoTest.java index 8e006ce..041ad76 100644 --- a/src/test/java/org/itsallcode/openfasttrace/maven/TraceMojoTest.java +++ b/src/test/java/org/itsallcode/openfasttrace/maven/TraceMojoTest.java @@ -15,6 +15,7 @@ import org.apache.maven.project.ProjectBuilder; import org.itsallcode.matcher.auto.AutoMatcher; import org.itsallcode.openfasttrace.api.FilterSettings; +import org.itsallcode.openfasttrace.api.core.ItemStatus; import org.itsallcode.openfasttrace.api.importer.ImportSettings; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -149,6 +150,27 @@ void createImportSettingsWithOnlyWildcardTag() assertFilterSettings(FilterSettings.builder().tags(emptySet()).withoutTags(true)); } + @Test + void createImportSettingsWithNullStatuses() + { + testee.statuses = null; + assertFilterSettings(FilterSettings.builder()); + } + + @Test + void createImportSettingsWithEmptyStatuses() + { + testee.statuses = emptySet(); + assertFilterSettings(FilterSettings.builder()); + } + + @Test + void createImportSettingsWithStatuses() + { + testee.statuses = Set.of(ItemStatus.APPROVED, ItemStatus.DRAFT); + assertFilterSettings(FilterSettings.builder().wantedStatuses(Set.of(ItemStatus.APPROVED, ItemStatus.DRAFT))); + } + private void assertImportSettings(final ImportSettings.Builder importSettingsBuilder) { assertThat(testee.createImportSettings(), AutoMatcher.equalTo(importSettingsBuilder.build())); diff --git a/src/test/resources/project-with-plugins/pom.xml b/src/test/resources/project-with-plugins/pom.xml index fb39da8..912edbf 100644 --- a/src/test/resources/project-with-plugins/pom.xml +++ b/src/test/resources/project-with-plugins/pom.xml @@ -27,7 +27,7 @@ org.itsallcode openfasttrace-asciidoc-plugin - 0.2.0 + 0.3.0 diff --git a/src/test/resources/project-with-statuses/doc/spec.md b/src/test/resources/project-with-statuses/doc/spec.md new file mode 100644 index 0000000..4e9ae13 --- /dev/null +++ b/src/test/resources/project-with-statuses/doc/spec.md @@ -0,0 +1,13 @@ +# Approved Status +`dsn~approved~1` +Status: approved +Needs: impl + +# No Status +`dsn~no-status~1` +Needs: impl + +# Proposed Status +`dsn~proposed~1` +Status: proposed +Needs: impl diff --git a/src/test/resources/project-with-statuses/pom.xml b/src/test/resources/project-with-statuses/pom.xml new file mode 100644 index 0000000..fc42c08 --- /dev/null +++ b/src/test/resources/project-with-statuses/pom.xml @@ -0,0 +1,36 @@ + + + 4.0.0 + + org.itsallcode + openfasttrace-maven-plugin-test-statuses + 0.0.0 + jar + + + 17 + 17 + UTF-8 + + + + + + org.itsallcode + openfasttrace-maven-plugin + + + trace-requirements + + trace + + + + + plain + + + + +