Skip to content

Commit

Permalink
Jenkins core version requirement probe (#154)
Browse files Browse the repository at this point in the history
  • Loading branch information
alecharp authored Dec 7, 2022
1 parent 5b1e015 commit dd00582
Show file tree
Hide file tree
Showing 8 changed files with 197 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@

public record Plugin(String name, VersionNumber version, String scm,
ZonedDateTime releaseTimestamp, List<String> labels,
int popularity) {
int popularity, String requiredCore) {
public io.jenkins.pluginhealth.scoring.model.Plugin toPlugin() {
return new io.jenkins.pluginhealth.scoring.model.Plugin(this.name(), this.version(), this.scm(), this.releaseTimestamp());
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/*
* MIT License
*
* Copyright (c) 2022 Jenkins Infra
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/

package io.jenkins.pluginhealth.scoring.probes;

import io.jenkins.pluginhealth.scoring.model.Plugin;
import io.jenkins.pluginhealth.scoring.model.ProbeResult;
import io.jenkins.pluginhealth.scoring.model.updatecenter.UpdateCenter;

import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

@Component
@Order(JenkinsCoreProbe.ORDER)
public class JenkinsCoreProbe extends Probe {
public static final String KEY = "jenkins-version";
public static final int ORDER = InstallationStatProbe.ORDER + 1;

@Override
protected ProbeResult doApply(Plugin plugin, ProbeContext context) {
final UpdateCenter uc = context.getUpdateCenter();
final io.jenkins.pluginhealth.scoring.model.updatecenter.Plugin ucPlugin = uc.plugins().get(plugin.getName());

if (ucPlugin == null) {
return ProbeResult.failure(KEY, "Plugin is not in the update-center");
}
return ProbeResult.success(KEY, ucPlugin.requiredCore());
}

@Override
public String key() {
return KEY;
}

@Override
public String getDescription() {
return "This probe registers the Jenkins core version requirement for each plugin.";
}

@Override
protected boolean requiresRelease() {
return true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@

import io.jenkins.pluginhealth.scoring.model.updatecenter.UpdateCenter;
import io.jenkins.pluginhealth.scoring.probes.InstallationStatProbe;
import io.jenkins.pluginhealth.scoring.probes.JenkinsCoreProbe;
import io.jenkins.pluginhealth.scoring.probes.LastCommitDateProbe;
import io.jenkins.pluginhealth.scoring.probes.Probe;
import io.jenkins.pluginhealth.scoring.probes.ProbeContext;
Expand Down Expand Up @@ -59,6 +60,7 @@ public Map<String, Long> getProbesFinalResults() {
.filter(probe ->
!probe.key().equals(LastCommitDateProbe.KEY)
&& !probe.key().equals(InstallationStatProbe.KEY)
&& !probe.key().equals(JenkinsCoreProbe.KEY)
)
.collect(Collectors.toMap(Probe::key, probe -> getProbesRawResultsFromDatabase(probe.key())));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ public void shouldBeAbleToDetectNonDeprecatedPlugin() {

when(plugin.getName()).thenReturn("foo");
when(ctx.getUpdateCenter()).thenReturn(new UpdateCenter(
Map.of("foo", new Plugin("foo", new VersionNumber("1.0"), "scm", ZonedDateTime.now().minusDays(1), Collections.emptyList(), 0)),
Map.of("foo", new Plugin("foo", new VersionNumber("1.0"), "scm", ZonedDateTime.now().minusDays(1), Collections.emptyList(), 0, "")),
Map.of("bar", new Deprecation("find-the-reason-here")),
Collections.emptyList()
));
Expand All @@ -78,7 +78,7 @@ public void shouldBeAbleToDetectDeprecatedPlugin() {

when(plugin.getName()).thenReturn("foo");
when(ctx.getUpdateCenter()).thenReturn(new UpdateCenter(
Map.of("foo", new Plugin("foo", new VersionNumber("1.0"), "scm", ZonedDateTime.now().minusDays(1), Collections.emptyList(), 0)),
Map.of("foo", new Plugin("foo", new VersionNumber("1.0"), "scm", ZonedDateTime.now().minusDays(1), Collections.emptyList(), 0, "")),
Map.of("bar", new Deprecation("find-the-reason-here"), "foo", new Deprecation("this-is-the-reason")),
Collections.emptyList()
));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ public void shouldBeAbleToFindInstallationCountInUpdateCenter() {
when(ctx.getUpdateCenter()).thenReturn(new UpdateCenter(
Map.of(
pluginName,
new io.jenkins.pluginhealth.scoring.model.updatecenter.Plugin(pluginName, null, null, null, List.of(), 100)
new io.jenkins.pluginhealth.scoring.model.updatecenter.Plugin(pluginName, null, null, null, List.of(), 100, "")
),
Map.of(),
List.of()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
/*
* MIT License
*
* Copyright (c) 2022 Jenkins Infra
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/

package io.jenkins.pluginhealth.scoring.probes;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;

import java.util.List;
import java.util.Map;

import io.jenkins.pluginhealth.scoring.model.Plugin;
import io.jenkins.pluginhealth.scoring.model.ProbeResult;
import io.jenkins.pluginhealth.scoring.model.ResultStatus;
import io.jenkins.pluginhealth.scoring.model.updatecenter.UpdateCenter;

import org.assertj.core.api.SoftAssertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.junit.jupiter.MockitoExtension;

@ExtendWith(MockitoExtension.class)
class JenkinsCoreProbeTest {
@Test
public void shouldBeUsingJenkinsVersionKey() {
final JenkinsCoreProbe probe = spy(JenkinsCoreProbe.class);
assertThat(probe.key()).isEqualTo("jenkins-version");
}

@Test
public void shouldRequireRelease() {
final JenkinsCoreProbe probe = spy(JenkinsCoreProbe.class);
assertThat(probe.requiresRelease()).isTrue();
}

@Test
public void shouldNotRequireSourceCodeChange() {
final JenkinsCoreProbe probe = spy(JenkinsCoreProbe.class);
assertThat(probe.isSourceCodeRelated()).isFalse();
}

@Test
public void shouldHaveDescription() {
final JenkinsCoreProbe probe = spy(JenkinsCoreProbe.class);
assertThat(probe.getDescription()).isNotBlank();
}

@Test
public void shouldFailIfPluginNotInUpdateCenter() {
final String pluginName = "plugin";
final Plugin plugin = mock(Plugin.class);
final ProbeContext ctx = mock(ProbeContext.class);

when(plugin.getName()).thenReturn(pluginName);
when(ctx.getUpdateCenter()).thenReturn(new UpdateCenter(
Map.of(),
Map.of(),
List.of()
));

final JenkinsCoreProbe probe = spy(JenkinsCoreProbe.class);
final ProbeResult result = probe.apply(plugin, ctx);

assertThat(result).isNotNull();
SoftAssertions.assertSoftly(softly -> {
softly.assertThat(result).extracting("id").isEqualTo(probe.key());
softly.assertThat(result).extracting("status").isEqualTo(ResultStatus.FAILURE);
softly.assertThat(result).extracting("message").isEqualTo("Plugin is not in the update-center");
});
}

@Test
public void shouldBeAbleToExtractJenkinsVersionFromUpdateCenter() {
final String pluginName = "plugin";
final Plugin plugin = mock(Plugin.class);
final ProbeContext ctx = mock(ProbeContext.class);

when(plugin.getName()).thenReturn(pluginName);
when(ctx.getUpdateCenter()).thenReturn(new UpdateCenter(
Map.of(
pluginName,
new io.jenkins.pluginhealth.scoring.model.updatecenter.Plugin(
pluginName, null, null, null, List.of(), 0, "2.361.1"
)
),
Map.of(),
List.of()
));

final JenkinsCoreProbe probe = spy(JenkinsCoreProbe.class);
final ProbeResult result = probe.apply(plugin, ctx);

assertThat(result).isNotNull();
SoftAssertions.assertSoftly(softly -> {
softly.assertThat(result).extracting("id").isEqualTo(probe.key());
softly.assertThat(result).extracting("status").isEqualTo(ResultStatus.SUCCESS);
softly.assertThat(result).extracting("message").isEqualTo("2.361.1");
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ public void shouldBeOKWithNoSecurityWarning() {
public void shouldBeOKWithWarningOnDifferentPlugin() {
final String pluginName = "foo-bar";
final VersionNumber pluginVersion = new VersionNumber("1.0");
final var pluginInUC = new Plugin(pluginName, pluginVersion, "scm", ZonedDateTime.now().minusHours(1), List.of(), 0);
final var pluginInUC = new Plugin(pluginName, pluginVersion, "scm", ZonedDateTime.now().minusHours(1), List.of(), 0, "");
final var plugin = mock(io.jenkins.pluginhealth.scoring.model.Plugin.class);
final ProbeContext ctx = mock(ProbeContext.class);
final KnownSecurityVulnerabilityProbe probe = new KnownSecurityVulnerabilityProbe();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ public void shouldBeAbleToDetectPluginForAdoption() {

when(plugin.getName()).thenReturn("foo");
when(ctx.getUpdateCenter()).thenReturn(new UpdateCenter(
Map.of("foo", new Plugin("foo", new VersionNumber("1.0"), "not-a-scm", ZonedDateTime.now().minusDays(1), List.of("builder", "adopt-this-plugin"), 0)),
Map.of("foo", new Plugin("foo", new VersionNumber("1.0"), "not-a-scm", ZonedDateTime.now().minusDays(1), List.of("builder", "adopt-this-plugin"), 0, "")),
Collections.emptyMap(),
Collections.emptyList()
));
Expand All @@ -78,7 +78,7 @@ public void shouldBeAbleToDetectPluginNotForAdoption() {

when(plugin.getName()).thenReturn("foo");
when(ctx.getUpdateCenter()).thenReturn(new UpdateCenter(
Map.of("foo", new Plugin("foo", new VersionNumber("1.0"), "not-a-scm", ZonedDateTime.now().minusDays(1), List.of("builder"), 0)),
Map.of("foo", new Plugin("foo", new VersionNumber("1.0"), "not-a-scm", ZonedDateTime.now().minusDays(1), List.of("builder"), 0, "")),
Collections.emptyMap(),
Collections.emptyList()
));
Expand Down

0 comments on commit dd00582

Please sign in to comment.