diff --git a/.github/workflows/ci-build.yml b/.github/workflows/ci-build.yml index 30af506..bb46424 100644 --- a/.github/workflows/ci-build.yml +++ b/.github/workflows/ci-build.yml @@ -12,7 +12,7 @@ jobs: strategy: fail-fast: false matrix: - java: [11,17,21] + java: [17,21] steps: - uses: actions/checkout@v4 - name: Set up JDK ${{ matrix.java }} @@ -58,7 +58,7 @@ jobs: SONAR_TOKEN: ${{ secrets.SONARCLOUD_TOKEN }} SONAR_ORGANIZATION: ${{ secrets.SONARCLOUD_ORGANIZATION }} - uses: actions/upload-artifact@v4 - if: matrix.java == 11 && success() + if: matrix.java == 17 && success() with: path: target/dependency-track.hpi name: dependency-track.hpi diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 46f9ee2..ed8073e 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -32,7 +32,7 @@ jobs: # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ] # Learn more: # https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed - java: [11] + java: [17] steps: - name: Checkout repository diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 9db436a..96f28f5 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -23,7 +23,7 @@ jobs: - name: Set up JDK uses: actions/setup-java@v4 with: - java-version: 11 + java-version: 17 distribution: 'zulu' cache: 'maven' server-id: 'maven.jenkins-ci.org' diff --git a/CHANGELOG.md b/CHANGELOG.md index bb8eee2..c1e25fa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,9 @@ ## Unreleased ### ⚠ Breaking +- require Jenkins 2.479.1 or newer +- require Java 17 or newer (required since Jenkins 2.479.1) + ### ⭐ New Features ### 🐞 Bugs Fixed diff --git a/Jenkinsfile b/Jenkinsfile index 936cd52..49b6076 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -2,6 +2,6 @@ buildPlugin( forkCount: '1C', useContainerAgent: true, useArtifactCachingProxy: false, // workaround for https://github.com/jenkins-infra/pipeline-library/issues/891 - jdkVersions: [11], + jdkVersions: [17], platforms: ['linux'], ) diff --git a/pom.xml b/pom.xml index bb2cf1e..67df29b 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ org.jenkins-ci.plugins plugin - 4.88 + 5.3 @@ -37,9 +37,9 @@ - 2.440.1 + 2.479.1 3.0.0 - 1836.vccda_4a_122a_a_e + 1850.va_a_8c31d3158b_ 1.15.3 UTF-8 UTF-8 @@ -370,28 +370,6 @@ true - - display-info - - - - - com.google.code.findbugs:annotations - com.google.code.findbugs:jsr305 - com.google.guava:guava - commons-logging:commons-logging - javax.servlet:javax.servlet-api - javax.servlet:servlet-api - net.java.dev.jna:jna - org.kohsuke:access-modifier-annotation - com.github.spotbugs:spotbugs-annotations - org.ow2.asm:asm - net.bytebuddy:byte-buddy - - - - - @@ -399,7 +377,7 @@ false - 3.0 + 3.0.2 false true true @@ -456,7 +434,7 @@ org.jenkins-ci.plugins credentials - 1378.v81ef4269d764 + 1393.v6017143c1763 org.jenkins-ci.plugins @@ -466,12 +444,12 @@ io.jenkins.plugins okhttp-api - 4.11.0-172.vda_da_1feeb_c6e + 4.11.0-181.v1de5b_83857df org.springframework.retry spring-retry - 1.3.4 + 2.0.10 io.jenkins diff --git a/src/main/java/org/jenkinsci/plugins/DependencyTrack/ApiClient.java b/src/main/java/org/jenkinsci/plugins/DependencyTrack/ApiClient.java index 6f96484..ba0c18d 100644 --- a/src/main/java/org/jenkinsci/plugins/DependencyTrack/ApiClient.java +++ b/src/main/java/org/jenkinsci/plugins/DependencyTrack/ApiClient.java @@ -28,7 +28,6 @@ import java.util.Base64; import java.util.List; import java.util.Map; -import java.util.stream.Collectors; import net.sf.json.JSONArray; import net.sf.json.JSONObject; import okhttp3.MediaType; @@ -204,7 +203,7 @@ private List getProjectsPaged(final int page) throws ApiClientException return JSONArray.fromObject(response.body().string()).stream() .map(JSONObject.class::cast) .map(ProjectParser::parse) - .collect(Collectors.toList()); + .toList(); } return List.of(); } catch (IOException e) { @@ -355,7 +354,7 @@ public void updateProjectProperties(@NonNull final String projectUuid, @NonNull final var updates = new JSONObject(); final var tags = properties.getTags().stream() .map(tag -> Map.of("name", tag)) - .collect(Collectors.toList()); + .toList(); // overwrite tags if needed if (!tags.isEmpty()) { updates.element("tags", tags); diff --git a/src/main/java/org/jenkinsci/plugins/DependencyTrack/DependencyTrackPublisher.java b/src/main/java/org/jenkinsci/plugins/DependencyTrack/DependencyTrackPublisher.java index 043edac..e807013 100644 --- a/src/main/java/org/jenkinsci/plugins/DependencyTrack/DependencyTrackPublisher.java +++ b/src/main/java/org/jenkinsci/plugins/DependencyTrack/DependencyTrackPublisher.java @@ -32,8 +32,6 @@ import hudson.tasks.Recorder; import hudson.util.Secret; import java.util.Optional; -import java.util.stream.Collectors; -import jenkins.model.RunAction2; import jenkins.tasks.SimpleBuildStep; import lombok.AccessLevel; import lombok.EqualsAndHashCode; @@ -345,11 +343,11 @@ public void perform(@NonNull final Run run, @NonNull final FilePath worksp if (synchronous && StringUtils.isNotBlank(uploadResult.getToken())) { final var resultActions = publishAnalysisResult(logger, apiClient, uploadResult.getToken(), run, effectiveProjectName, effectiveProjectVersion); if (thresholds.hasValues()) { - final var resultAction = resultActions.get(0).map(ResultAction.class::cast).get(); + final var resultAction = resultActions.findingsAction; evaluateRiskGates(run, logger, resultAction.getSeverityDistribution(), thresholds); } - if (resultActions.get(1).isPresent()) { - final var violationsAction = resultActions.get(1).map(ViolationsRunAction.class::cast).get(); + if (resultActions.violationsAction != null) { + final var violationsAction = resultActions.violationsAction; evaluateViolations(run, logger, violationsAction.getViolations()); } } @@ -358,7 +356,7 @@ public void perform(@NonNull final Run run, @NonNull final FilePath worksp } } - private List> publishAnalysisResult(final ConsoleLogger logger, final ApiClient apiClient, final String token, final Run build, final String effectiveProjectName, final String effectiveProjectVersion) throws InterruptedException, ApiClientException, AbortException { + private PublishAnalysisResult publishAnalysisResult(final ConsoleLogger logger, final ApiClient apiClient, final String token, final Run build, final String effectiveProjectName, final String effectiveProjectVersion) throws InterruptedException, ApiClientException, AbortException { final long timeout = System.currentTimeMillis() + (60000L * getEffectivePollingTimeout()); final long interval = 1000L * getEffectivePollingInterval(); logger.log(Messages.Builder_Polling()); @@ -401,8 +399,7 @@ private List> publishAnalysisResult(final ConsoleLogger log linkAction.setProjectVersion(effectiveProjectVersion); build.addOrReplaceAction(linkAction); - // replace with record when using Java 17 - return List.of(Optional.of(findingsAction), Optional.ofNullable(violationsAction)); + return new PublishAnalysisResult(findingsAction, violationsAction); } private void evaluateRiskGates(final Run build, final ConsoleLogger logger, final SeverityDistribution currentDistribution, final Thresholds thresholds) throws AbortException { @@ -648,9 +645,11 @@ private ProjectProperties expandProjectProperties(final EnvVars env) { Optional.ofNullable(projectProperties.getParentName()).map(env::expand).ifPresent(expandedProperties::setParentName); Optional.ofNullable(projectProperties.getParentVersion()).map(env::expand).ifPresent(expandedProperties::setParentVersion); Optional.ofNullable(projectProperties.getSwidTagId()).map(env::expand).ifPresent(expandedProperties::setSwidTagId); - expandedProperties.setTags(projectProperties.getTags().stream().map(env::expand).collect(Collectors.toList())); + expandedProperties.setTags(projectProperties.getTags().stream().map(env::expand).toList()); return expandedProperties; } return null; } + + private static record PublishAnalysisResult(@NonNull ResultAction findingsAction, @Nullable ViolationsRunAction violationsAction) {} } diff --git a/src/main/java/org/jenkinsci/plugins/DependencyTrack/DescriptorImpl.java b/src/main/java/org/jenkinsci/plugins/DependencyTrack/DescriptorImpl.java index 7b84022..a557b9c 100644 --- a/src/main/java/org/jenkinsci/plugins/DependencyTrack/DescriptorImpl.java +++ b/src/main/java/org/jenkinsci/plugins/DependencyTrack/DescriptorImpl.java @@ -53,7 +53,7 @@ import org.kohsuke.stapler.AncestorInPath; import org.kohsuke.stapler.DataBoundSetter; import org.kohsuke.stapler.QueryParameter; -import org.kohsuke.stapler.StaplerRequest; +import org.kohsuke.stapler.StaplerRequest2; import org.kohsuke.stapler.verb.POST; import static org.jenkinsci.plugins.DependencyTrack.model.Permissions.*; @@ -176,7 +176,7 @@ public ListBoxModel doFillProjectIdItems(@QueryParameter final String dependency final List options = apiClient.getProjects().stream() .map(p -> new ListBoxModel.Option(p.getName().concat(" ").concat(Optional.ofNullable(p.getVersion()).orElse(StringUtils.EMPTY)).trim(), p.getUuid())) .sorted(Comparator.comparing(o -> o.name)) - .collect(Collectors.toList()); + .toList(); projects.add(new ListBoxModel.Option(Messages.Publisher_ProjectList_Placeholder(), StringUtils.EMPTY)); projects.addAll(options); } catch (ApiClientException e) { @@ -338,15 +338,9 @@ private FormValidation checkTeamPermissions(final ApiClient apiClient, final Str } sb.append(""); switch (worst) { - case OK: - sb.insert(0, Messages.Publisher_ConnectionTest_Success(poweredBy)); - break; - case WARNING: - sb.insert(0, Messages.Publisher_ConnectionTest_Warning(poweredBy)); - break; - case ERROR: - sb.insert(0, Messages.Publisher_ConnectionTest_Error(poweredBy)); - break; + case OK -> sb.insert(0, Messages.Publisher_ConnectionTest_Success(poweredBy)); + case WARNING -> sb.insert(0, Messages.Publisher_ConnectionTest_Warning(poweredBy)); + case ERROR -> sb.insert(0, Messages.Publisher_ConnectionTest_Error(poweredBy)); } return FormValidation.respond(worst, String.format("
%s
", worst.name().toLowerCase(Locale.ENGLISH), sb)); } @@ -360,7 +354,7 @@ private FormValidation checkTeamPermissions(final ApiClient apiClient, final Str * @throws FormException an exception validating form input */ @Override - public boolean configure(final StaplerRequest req, final JSONObject formData) throws Descriptor.FormException { + public boolean configure(final StaplerRequest2 req, final JSONObject formData) throws Descriptor.FormException { req.bindJSON(this, formData); save(); return super.configure(req, formData); diff --git a/src/main/java/org/jenkinsci/plugins/DependencyTrack/FindingParser.java b/src/main/java/org/jenkinsci/plugins/DependencyTrack/FindingParser.java index b7b12c4..3684eca 100644 --- a/src/main/java/org/jenkinsci/plugins/DependencyTrack/FindingParser.java +++ b/src/main/java/org/jenkinsci/plugins/DependencyTrack/FindingParser.java @@ -19,7 +19,6 @@ import java.util.List; import java.util.Optional; import java.util.function.Predicate; -import java.util.stream.Collectors; import lombok.experimental.UtilityClass; import net.sf.json.JSONArray; import net.sf.json.JSONNull; @@ -87,7 +86,7 @@ private List parseAliases(JSONObject json, String vulnId) { .map(alias::getString) .filter(Predicate.not(vulnId::equalsIgnoreCase))) .distinct() - .collect(Collectors.toList()) + .toList() : null; } } diff --git a/src/main/java/org/jenkinsci/plugins/DependencyTrack/JobAction.java b/src/main/java/org/jenkinsci/plugins/DependencyTrack/JobAction.java index d7b8c5a..9829189 100644 --- a/src/main/java/org/jenkinsci/plugins/DependencyTrack/JobAction.java +++ b/src/main/java/org/jenkinsci/plugins/DependencyTrack/JobAction.java @@ -20,7 +20,6 @@ import java.util.Comparator; import java.util.List; import java.util.Objects; -import java.util.stream.Collectors; import lombok.Getter; import lombok.NonNull; import lombok.RequiredArgsConstructor; @@ -65,7 +64,7 @@ public JSONArray getSeverityDistributionTrend() { .sorted(Comparator.naturalOrder()) .map(run -> run.getAction(ResultAction.class)).filter(Objects::nonNull) .map(ResultAction::getSeverityDistribution) - .collect(Collectors.toList()); + .toList(); return JSONArray.fromObject(severityDistributions); } diff --git a/src/main/java/org/jenkinsci/plugins/DependencyTrack/ProjectParser.java b/src/main/java/org/jenkinsci/plugins/DependencyTrack/ProjectParser.java index 2997317..697ef3d 100644 --- a/src/main/java/org/jenkinsci/plugins/DependencyTrack/ProjectParser.java +++ b/src/main/java/org/jenkinsci/plugins/DependencyTrack/ProjectParser.java @@ -17,7 +17,6 @@ import java.time.LocalDateTime; import java.util.List; -import java.util.stream.Collectors; import lombok.experimental.UtilityClass; import net.sf.json.JSONArray; import net.sf.json.JSONObject; @@ -58,6 +57,6 @@ private List parseTags(JSONArray tagArray) { return tagArray.stream() .map(o -> getKeyOrNull((JSONObject) o, "name")) .filter(StringUtils::isNotBlank) - .collect(Collectors.toList()); + .toList(); } } diff --git a/src/main/java/org/jenkinsci/plugins/DependencyTrack/ProjectProperties.java b/src/main/java/org/jenkinsci/plugins/DependencyTrack/ProjectProperties.java index 0b50582..564d3f0 100644 --- a/src/main/java/org/jenkinsci/plugins/DependencyTrack/ProjectProperties.java +++ b/src/main/java/org/jenkinsci/plugins/DependencyTrack/ProjectProperties.java @@ -101,12 +101,12 @@ public List getTags() { @DataBoundSetter @SuppressWarnings("unchecked") public void setTags(final Object value) { - if (value instanceof String) { - setTagsIntern((String) value); - } else if (value instanceof String[]) { - setTagsIntern((String[]) value); - } else if (value instanceof Collection && areAllElementsOfType((Collection) value, String.class)) { - setTagsIntern((Collection) value); + if (value instanceof String string) { + setTagsIntern(string); + } else if (value instanceof String[] strings) { + setTagsIntern(strings); + } else if (value instanceof Collection collection && areAllElementsOfType(collection, String.class)) { + setTagsIntern(collection); } else if (value == null) { tags = null; } else { @@ -169,7 +169,7 @@ private List normalizeTags(final Collection values) { .map(String::toLowerCase) .distinct() .sorted() - .collect(Collectors.toList()); + .toList(); } @Extension diff --git a/src/main/java/org/jenkinsci/plugins/DependencyTrack/ViolationParser.java b/src/main/java/org/jenkinsci/plugins/DependencyTrack/ViolationParser.java index ae7bcf5..9c6ed62 100644 --- a/src/main/java/org/jenkinsci/plugins/DependencyTrack/ViolationParser.java +++ b/src/main/java/org/jenkinsci/plugins/DependencyTrack/ViolationParser.java @@ -16,7 +16,6 @@ package org.jenkinsci.plugins.DependencyTrack; import java.util.List; -import java.util.stream.Collectors; import lombok.experimental.UtilityClass; import net.sf.json.JSONArray; import net.sf.json.JSONObject; @@ -32,7 +31,7 @@ List parse(final String jsonResponse) { return jsonArray.stream() .map(JSONObject.class::cast) .map(ViolationParser::parseViolation) - .collect(Collectors.toList()); + .toList(); } private Violation parseViolation(JSONObject json) { diff --git a/src/main/java/org/jenkinsci/plugins/DependencyTrack/ViolationsJobAction.java b/src/main/java/org/jenkinsci/plugins/DependencyTrack/ViolationsJobAction.java index 8b2c9d6..4224593 100644 --- a/src/main/java/org/jenkinsci/plugins/DependencyTrack/ViolationsJobAction.java +++ b/src/main/java/org/jenkinsci/plugins/DependencyTrack/ViolationsJobAction.java @@ -82,7 +82,7 @@ public JSONArray getViolationsTrend() { item.putIfAbsent(ViolationState.FAIL.name().toLowerCase(), 0); return item; }) - .collect(Collectors.toList()); + .toList(); return JSONArray.fromObject(distributions); } diff --git a/src/test/java/org/jenkinsci/plugins/DependencyTrack/DescriptorImplTest.java b/src/test/java/org/jenkinsci/plugins/DependencyTrack/DescriptorImplTest.java index 44bffa0..5415caf 100644 --- a/src/test/java/org/jenkinsci/plugins/DependencyTrack/DescriptorImplTest.java +++ b/src/test/java/org/jenkinsci/plugins/DependencyTrack/DescriptorImplTest.java @@ -47,7 +47,7 @@ import org.jvnet.hudson.test.JenkinsRule; import org.jvnet.hudson.test.MockAuthorizationStrategy; import org.jvnet.hudson.test.junit.jupiter.WithJenkins; -import org.kohsuke.stapler.StaplerRequest; +import org.kohsuke.stapler.StaplerRequest2; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; @@ -384,7 +384,7 @@ void getDependencyTrackPollingTimeoutTest() { @Test void configureTest() throws Descriptor.FormException { - StaplerRequest req = mock(StaplerRequest.class); + var req = mock(StaplerRequest2.class); JSONObject formData = new JSONObject() .element("dependencyTrackUrl", "https://foo.bar/") .element("dependencyTrackApiKey", "api-key") diff --git a/src/test/java/org/jenkinsci/plugins/DependencyTrack/ProjectPropertiesTest.java b/src/test/java/org/jenkinsci/plugins/DependencyTrack/ProjectPropertiesTest.java index 7b1704f..1cdcc5c 100644 --- a/src/test/java/org/jenkinsci/plugins/DependencyTrack/ProjectPropertiesTest.java +++ b/src/test/java/org/jenkinsci/plugins/DependencyTrack/ProjectPropertiesTest.java @@ -52,7 +52,7 @@ void testSetTags() { uut.setTags(new String[]{"tag2", "tag1"}); assertThat(uut.getTags()).containsExactly("tag1", "tag2"); - uut.setTags(Stream.of("TAG2", "tag2").collect(Collectors.toList())); + uut.setTags(Stream.of("TAG2", "tag2").toList()); assertThat(uut.getTags()).containsExactly("tag2"); uut.setTags(Stream.of("TAG2", "tag2").collect(Collectors.toSet()));