diff --git a/.github/workflows/broken_links_checker.yml b/.github/workflows/broken_links_checker.yml index 52706173b..6bfa7a985 100644 --- a/.github/workflows/broken_links_checker.yml +++ b/.github/workflows/broken_links_checker.yml @@ -26,7 +26,7 @@ jobs: } ] }' > ./target/broken_links_checker.json - - uses: tcort/github-action-markdown-link-check@v1 + - uses: tcort/github-action-markdown-link-check@e7c7a18363c842693fadde5d41a3bd3573a7a225 with: use-quiet-mode: "yes" use-verbose-mode: "yes" diff --git a/README.md b/README.md index ef84ba30c..6e5e1c6f2 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ ## What is OpenFastTrace? -OpenFastTrace (short OFT) is a requirement tracing suite. Requirement tracing keeps track of whether you actually implemented everything you planned to in your specifications. It also identifies obsolete parts of your product and helps you to get rid of them. +OpenFastTrace (short OFT) is a requirement management and tracing suite. Requirement tracing keeps track of whether you actually implemented everything you planned to in your specifications. It also identifies obsolete parts of your product and helps you to get rid of them. You can learn more about requirement tracing and how to use OpenFastTrace in the [user guide](doc/user_guide/user_guide.md). @@ -31,29 +31,30 @@ Sonarcloud status: **User Guides and Tools** -* [📖 User Guide](doc/user_guide/user_guide.md) -* [📚 Terminology](doc/terminology.md) -* [🔌 Extending OpenFastTrace With Plugins](doc/plugins.md) +* [📖 User Guide](https://openfasttrace.itsallcode.org/user_guide/user_guide.html) +* [📚 Terminology](https://openfasttrace.itsallcode.org/terminology.html) +* [🔌 Extending OpenFastTrace With Plugins](https://openfasttrace.itsallcode.org/plugins.html) * [💲 Command Line Usage](core/src/main/resources/usage.txt) * [🛠 IntelliJ Plugin (PyCharm, Clion, etc.)](https://github.com/itsallcode/openfasttrace-intellij-plugin) * [🤖 Agent Skills](.agents/skills) * [đŸ›Ąī¸ Security Policy](SECURITY.md) -* [â™ģī¸ Project Lifecycle and Deprecations](doc/user_guide/project_lifecycle.md) +* [â™ģī¸ Project Lifecycle and Deprecations](doc/user_guide/product_lifecycle/product_lifecycle.md) **News and Discussions** +* [🌐 Homepage](https://openfasttrace.itsallcode.org) * [đŸ“ĸ Blog](https://blog.itsallcode.org/) * [➕ Changelog](doc/changes/changes.md) * [📅 Upcoming Milestones](https://github.com/orgs/itsallcode/projects/3/views/3) * [đŸ—¨ī¸ Discussion Board](https://github.com/itsallcode/openfasttrace/discussions) * [🐘 OpenFastTrace@mastodon.social](https://mastodon.social/@OpenFastTrace) * [✨ OpenFastTrace Stories](https://github.com/itsallcode/openfasttrace/wiki/OFT-Stories) -* [â„šī¸ About us](doc/about_us.md) +* [â„šī¸ About us](https://openfasttrace.itsallcode.org/about_us.html) **Information for Contributors** * [đŸŽŸī¸ Project Board](https://github.com/orgs/itsallcode/projects/3/views/1) -* [đŸĻŽ Developer Guide](doc/developer_guide/developer_guide.md) +* [đŸĻŽ Developer Guide](https://openfasttrace.itsallcode.org/developer_guide/developer_guide.html) * [🔌 Plugin Developer Guide](doc/developer_guide/plugin_developer_guide.md) * [🎁 Contributing Guide](CONTRIBUTING.md) * [🤝 Code of Conduct](CODE_OF_CONDUCT.md) @@ -94,27 +95,9 @@ Check our [developer guide](doc/developer_guide/developer_guide.md#getting-the-o OpenFastTrace 4.0.0 and above only needs a Java 17 (or later) runtime environment to run. OpenFastTrace until version 3.x.x supported Java 11. Versions prior to that ran with Java 8. Note that only the latest version of OFT is actively supported. -#### Installation of Runtime Dependencies on Linux - -##### Ubuntu or Debian - -If you just want to run OFT: - - apt-get install openjdk-17-jre - -### Installation via Homebrew - -On macOS or Linux, install OpenFastTrace with [Homebrew](https://brew.sh/): - -```shell -brew install openfasttrace -``` - -The formula installs the OpenJDK 17 runtime dependency and provides the `oft` command. For example: - -```shell -oft trace /path/to/directory/being/traced -``` +* [Installation on Linux](doc/user_guide/installation/linux.md) +* [Installation on macOS](doc/user_guide/installation/macos.md) +* [Installation on Windows](doc/user_guide/installation/windows.md) ## Running OpenFastTrace diff --git a/api/src/main/java/org/itsallcode/openfasttrace/api/core/Trace.java b/api/src/main/java/org/itsallcode/openfasttrace/api/core/Trace.java index e8928d082..9434028f6 100644 --- a/api/src/main/java/org/itsallcode/openfasttrace/api/core/Trace.java +++ b/api/src/main/java/org/itsallcode/openfasttrace/api/core/Trace.java @@ -34,6 +34,7 @@ public boolean hasNoDefects() * * @return all defect items found during tracing. */ + @SuppressWarnings("java:S2384") // LinkedSpecificationItems are currently mutable intentionally. public List getDefectItems() { return this.defectItems; @@ -44,6 +45,7 @@ public List getDefectItems() * * @return all items found during tracing. */ + @SuppressWarnings("java:S2384") // LinkedSpecificationItems are currently mutable intentionally. public List getItems() { return this.items; diff --git a/core/src/main/java/org/itsallcode/openfasttrace/core/cli/ArgumentValidator.java b/core/src/main/java/org/itsallcode/openfasttrace/core/cli/ArgumentValidator.java index 163a088e2..c257ea000 100644 --- a/core/src/main/java/org/itsallcode/openfasttrace/core/cli/ArgumentValidator.java +++ b/core/src/main/java/org/itsallcode/openfasttrace/core/cli/ArgumentValidator.java @@ -3,6 +3,7 @@ import static java.util.Arrays.asList; import java.util.List; +import java.util.Objects; import java.util.Optional; import java.util.stream.Collectors; @@ -88,17 +89,13 @@ private boolean validateTraceCommand() private boolean validateConvertCommand() { - boolean ok = false; - final String format = this.arguments.getOutputFormat(); - if (format != null && !new ExporterFactoryLoader(null).isFormatSupported(format)) + final String format = Objects.requireNonNull(this.arguments.getOutputFormat()); + if (!new ExporterFactoryLoader(null).isFormatSupported(format)) { this.error = "export format '" + format + "' is not supported."; + return false; } - else - { - ok = true; - } - return ok; + return true; } private static String listCommands() diff --git a/core/src/test/java/org/itsallcode/openfasttrace/core/cli/TestArgumentValidator.java b/core/src/test/java/org/itsallcode/openfasttrace/core/cli/TestArgumentValidator.java index e9f8d13b2..62d14d3d0 100644 --- a/core/src/test/java/org/itsallcode/openfasttrace/core/cli/TestArgumentValidator.java +++ b/core/src/test/java/org/itsallcode/openfasttrace/core/cli/TestArgumentValidator.java @@ -1,6 +1,5 @@ package org.itsallcode.openfasttrace.core.cli; -import static java.util.Arrays.asList; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; @@ -12,6 +11,8 @@ import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; +import java.util.List; + @ExtendWith(MockitoExtension.class) class TestArgumentValidator { @@ -35,14 +36,14 @@ void testNoCommandGivenIsInvalid() @Test void testTraceCommandGivenIsValid() { - cliArgs.setUnnamedValues(asList("trace")); + cliArgs.setUnnamedValues(List.of("trace")); assertValidatorResult("", ""); } @Test void testTraceCommandQuietAndNoOutputFileGivenIsValid() { - cliArgs.setUnnamedValues(asList("trace")); + cliArgs.setUnnamedValues(List.of("trace")); cliArgs.setV(ReportVerbosity.QUIET); assertValidatorResult("", ""); } @@ -50,7 +51,7 @@ void testTraceCommandQuietAndNoOutputFileGivenIsValid() @Test void testTraceCommandQuietAndOutputFileGivenIsNotValid() { - cliArgs.setUnnamedValues(asList("trace")); + cliArgs.setUnnamedValues(List.of("trace")); cliArgs.setV(ReportVerbosity.QUIET); cliArgs.setOutputFile("outputFile"); assertValidatorResult( @@ -61,7 +62,7 @@ void testTraceCommandQuietAndOutputFileGivenIsNotValid() @Test void testConvertCommandGivenIsValid() { - cliArgs.setUnnamedValues(asList("convert")); + cliArgs.setUnnamedValues(List.of("convert")); cliArgs.setOutputFormat("unsupportedFormat"); assertValidatorResult("export format 'unsupportedFormat' is not supported.", ""); } @@ -69,7 +70,7 @@ void testConvertCommandGivenIsValid() @Test void testUnknownCommandGivenIsNotValid() { - cliArgs.setUnnamedValues(asList("unknownCommand")); + cliArgs.setUnnamedValues(List.of("unknownCommand")); assertValidatorResult("'unknownCommand' is not an OFT command.", "Choose one of 'help','convert','trace'."); } diff --git a/core/src/test/java/org/itsallcode/openfasttrace/core/serviceloader/ClassPathServiceLoaderTest.java b/core/src/test/java/org/itsallcode/openfasttrace/core/serviceloader/ClassPathServiceLoaderTest.java index 8e1ae46eb..6898e67be 100644 --- a/core/src/test/java/org/itsallcode/openfasttrace/core/serviceloader/ClassPathServiceLoaderTest.java +++ b/core/src/test/java/org/itsallcode/openfasttrace/core/serviceloader/ClassPathServiceLoaderTest.java @@ -3,7 +3,6 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.*; import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import java.util.*; @@ -22,11 +21,14 @@ class ClassPathServiceLoaderTest @Test void loadingNonAccessibleServiceFails() { - final ServiceOrigin origin = ServiceOrigin.forCurrentClassPath(); - final ServiceConfigurationError error = assertThrows(ServiceConfigurationError.class, - () -> ClassPathServiceLoader.create(DummyService.class, origin)); - assertThat(error.getMessage(), equalTo( - "org.itsallcode.openfasttrace.core.serviceloader.ClassPathServiceLoaderTest$DummyService: module org.itsallcode.openfasttrace.core does not declare `uses`")); + try (final ServiceOrigin origin = ServiceOrigin.forCurrentClassPath()) + { + final ServiceConfigurationError error = assertThrows(ServiceConfigurationError.class, + () -> ClassPathServiceLoader.create(DummyService.class, origin)); + assertThat(error.getMessage(), equalTo( + "org.itsallcode.openfasttrace.core.serviceloader.ClassPathServiceLoaderTest$DummyService:" + + " module org.itsallcode.openfasttrace.core does not declare `uses`")); + } } @Test @@ -46,25 +48,26 @@ void loadingReturnsService(@Mock final ServiceLoader serviceLoader when(serviceLoaderMock.stream()).thenReturn(Stream.of(providerMock)); when(providerMock.get()).thenReturn(service); when(originMock.getClassLoader()).thenReturn(DummyServiceImpl.class.getClassLoader()); - final List services = new ClassPathServiceLoader(originMock, serviceLoaderMock) + final List services = new ClassPathServiceLoader<>(originMock, serviceLoaderMock) .load().toList(); assertThat(services, contains(sameInstance(service))); } @Test void loadingIgnoresServicesFromOtherClassLoaders(@Mock final ServiceLoader serviceLoaderMock, - @Mock final Provider providerMock, @Mock final ServiceOrigin originMock) + @Mock final Provider providerMock, @Mock final ServiceOrigin originMock, + @Mock ClassLoader classLoaderMock) { final DummyServiceImpl service = new DummyServiceImpl(); when(serviceLoaderMock.stream()).thenReturn(Stream.of(providerMock)); when(providerMock.get()).thenReturn(service); - when(originMock.getClassLoader()).thenReturn(mock(ClassLoader.class)); - final List services = new ClassPathServiceLoader(originMock, serviceLoaderMock) + when(originMock.getClassLoader()).thenReturn(classLoaderMock); + final List services = new ClassPathServiceLoader<>(originMock, serviceLoaderMock) .load().toList(); assertThat(services, empty()); } - static interface DummyService + interface DummyService { } diff --git a/doc/_config.yml b/doc/_config.yml index a6c9c25f5..e371113b3 100644 --- a/doc/_config.yml +++ b/doc/_config.yml @@ -1,5 +1,5 @@ title: OpenFastTrace -description: Requirement tracing suite for Agile Development +description: Requirement management and tracing suite remote_theme: just-the-docs/just-the-docs