From 423ce4bd79f49dbabc4e544161383ff500e1bdf1 Mon Sep 17 00:00:00 2001 From: Jagruti Tiwari Date: Wed, 6 Sep 2023 14:41:33 +0530 Subject: [PATCH] Removed folder path to fix SCMLinkValidationProbe (#351) Co-authored-by: Adrien Lecharpentier --- core/pom.xml | 4 + .../HasUnreleasedProductionChangesProbe.java | 22 +-- .../scoring/probes/LastCommitDateProbe.java | 20 +-- .../pluginhealth/scoring/probes/Probe.java | 2 +- .../scoring/probes/ProbeContext.java | 9 ++ .../probes/SCMLinkValidationProbe.java | 127 +++++++++++++---- ...sUnreleasedProductionChangesProbeTest.java | 3 + .../probes/SCMLinkValidationProbeTest.java | 132 ++++++++++++++++-- .../resources/jenkinsci/test-repo/pom.xml | 6 + .../test-incorrect-nested-dir-1/pom.xml | 6 + .../test-incorrect-nested-dir-2/pom.xml | 6 + .../test-repo/test-nested-dir-1/pom.xml | 6 + .../test-nested-dir-2/pom.xml | 6 + pom.xml | 5 + 14 files changed, 295 insertions(+), 59 deletions(-) create mode 100644 core/src/test/resources/jenkinsci/test-repo/pom.xml create mode 100644 core/src/test/resources/jenkinsci/test-repo/test-incorrect-nested-dir-1/pom.xml create mode 100644 core/src/test/resources/jenkinsci/test-repo/test-incorrect-nested-dir-1/test-incorrect-nested-dir-2/pom.xml create mode 100644 core/src/test/resources/jenkinsci/test-repo/test-nested-dir-1/pom.xml create mode 100644 core/src/test/resources/jenkinsci/test-repo/test-nested-dir-1/test-nested-dir-2/pom.xml diff --git a/core/pom.xml b/core/pom.xml index 024955b15..77f220b4d 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -102,5 +102,9 @@ postgresql test + + org.apache.maven + maven-model + diff --git a/core/src/main/java/io/jenkins/pluginhealth/scoring/probes/HasUnreleasedProductionChangesProbe.java b/core/src/main/java/io/jenkins/pluginhealth/scoring/probes/HasUnreleasedProductionChangesProbe.java index cf904d700..376e90884 100644 --- a/core/src/main/java/io/jenkins/pluginhealth/scoring/probes/HasUnreleasedProductionChangesProbe.java +++ b/core/src/main/java/io/jenkins/pluginhealth/scoring/probes/HasUnreleasedProductionChangesProbe.java @@ -32,6 +32,7 @@ import java.util.Comparator; import java.util.HashSet; import java.util.List; +import java.util.Optional; import java.util.Set; import java.util.regex.Matcher; import java.util.stream.Collectors; @@ -66,15 +67,14 @@ public ProbeResult doApply(Plugin plugin, ProbeContext context) { if (!matcher.find()) { return ProbeResult.error(key(), "SCM link doesn't match GitHub plugin repositories"); } - - final String folder = matcher.group("folder"); + final Optional folder = context.getScmFolderPath(); final Set files = new HashSet<>(); - final List paths = new ArrayList<>(3); paths.add("pom.xml"); - if (folder != null) { - paths.add(folder + "/pom.xml"); - paths.add(folder + "/src/main"); + + if (folder.isPresent()) { + paths.add(folder.get() + "/pom.xml"); + paths.add(folder.get() + "/src/main"); } else { paths.add("src/main"); } @@ -123,6 +123,11 @@ public ProbeResult doApply(Plugin plugin, ProbeContext context) { } } + @Override + public String[] getProbeResultRequirement() { + return new String[]{SCMLinkValidationProbe.KEY, LastCommitDateProbe.KEY}; + } + @Override public String key() { return KEY; @@ -142,9 +147,4 @@ protected boolean isSourceCodeRelated() { */ return false; } - - @Override - public String[] getProbeResultRequirement() { - return new String[]{SCMLinkValidationProbe.KEY, LastCommitDateProbe.KEY}; - } } diff --git a/core/src/main/java/io/jenkins/pluginhealth/scoring/probes/LastCommitDateProbe.java b/core/src/main/java/io/jenkins/pluginhealth/scoring/probes/LastCommitDateProbe.java index be0230ec0..0ed4117c4 100644 --- a/core/src/main/java/io/jenkins/pluginhealth/scoring/probes/LastCommitDateProbe.java +++ b/core/src/main/java/io/jenkins/pluginhealth/scoring/probes/LastCommitDateProbe.java @@ -25,6 +25,7 @@ package io.jenkins.pluginhealth.scoring.probes; import java.time.ZonedDateTime; +import java.util.Optional; import java.util.regex.Matcher; import io.jenkins.pluginhealth.scoring.model.Plugin; @@ -45,10 +46,9 @@ @Component @Order(value = LastCommitDateProbe.ORDER) public class LastCommitDateProbe extends Probe { - private static final Logger LOGGER = LoggerFactory.getLogger(LastCommitDateProbe.class); - public static final int ORDER = SCMLinkValidationProbe.ORDER + 100; public static final String KEY = "last-commit-date"; + private static final Logger LOGGER = LoggerFactory.getLogger(LastCommitDateProbe.class); @Override public ProbeResult doApply(Plugin plugin, ProbeContext context) { @@ -57,12 +57,12 @@ public ProbeResult doApply(Plugin plugin, ProbeContext context) { return ProbeResult.failure(key(), "The SCM link is not valid"); } final String repo = String.format("https://%s/%s", matcher.group("server"), matcher.group("repo")); - final String folder = matcher.group("folder"); + final Optional folder = context.getScmFolderPath(); try (Git git = Git.cloneRepository().setURI(repo).setDirectory(context.getScmRepository().toFile()).call()) { final LogCommand logCommand = git.log().setMaxCount(1); - if (folder != null) { - logCommand.addPath(folder); + if (folder.isPresent()) { + logCommand.addPath(folder.get().toString()); } final RevCommit commit = logCommand.call().iterator().next(); if (commit == null) { @@ -80,6 +80,11 @@ public ProbeResult doApply(Plugin plugin, ProbeContext context) { } } + @Override + public String[] getProbeResultRequirement() { + return new String[]{SCMLinkValidationProbe.KEY}; + } + @Override public String key() { return KEY; @@ -99,9 +104,4 @@ protected boolean isSourceCodeRelated() { */ return false; } - - @Override - public String[] getProbeResultRequirement() { - return new String[]{SCMLinkValidationProbe.KEY}; - } } diff --git a/core/src/main/java/io/jenkins/pluginhealth/scoring/probes/Probe.java b/core/src/main/java/io/jenkins/pluginhealth/scoring/probes/Probe.java index 52abcde6c..305be590b 100644 --- a/core/src/main/java/io/jenkins/pluginhealth/scoring/probes/Probe.java +++ b/core/src/main/java/io/jenkins/pluginhealth/scoring/probes/Probe.java @@ -109,7 +109,7 @@ private boolean shouldBeExecuted(Plugin plugin, ProbeContext context) { /** * List of probe key to be present in the {@link Plugin#details} map and to be {@link ResultStatus#SUCCESS} in * order to consider executing the {@link Probe#doApply(Plugin, ProbeContext)} code. - * By default, the requirement is an empty array. I cannot be null. + * By default, the requirement is an empty array. It cannot be null. * * @return array of {@link Probe#key()} to be present in {@link Plugin#details}. */ diff --git a/core/src/main/java/io/jenkins/pluginhealth/scoring/probes/ProbeContext.java b/core/src/main/java/io/jenkins/pluginhealth/scoring/probes/ProbeContext.java index 2d3e5c2dc..ba5e8694a 100644 --- a/core/src/main/java/io/jenkins/pluginhealth/scoring/probes/ProbeContext.java +++ b/core/src/main/java/io/jenkins/pluginhealth/scoring/probes/ProbeContext.java @@ -45,6 +45,7 @@ public class ProbeContext { private GitHub github; private ZonedDateTime lastCommitDate; private Map pluginDocumentationLinks; + private Optional scmFolderPath; public ProbeContext(String pluginName, UpdateCenter updateCenter) throws IOException { this.updateCenter = updateCenter; @@ -88,6 +89,14 @@ public Optional getRepositoryName(String scm) { return match.find() ? Optional.of(match.group("repo")) : Optional.empty(); } + public Optional getScmFolderPath() { + return scmFolderPath; + } + + public void setScmFolderPath(Optional scmFolderPath) { + this.scmFolderPath = scmFolderPath; + } + /* default */ void cleanUp() throws IOException { try (Stream paths = Files.walk(this.scmRepository)) { paths.sorted(Comparator.reverseOrder()) diff --git a/core/src/main/java/io/jenkins/pluginhealth/scoring/probes/SCMLinkValidationProbe.java b/core/src/main/java/io/jenkins/pluginhealth/scoring/probes/SCMLinkValidationProbe.java index 5e0469b11..d58377eec 100644 --- a/core/src/main/java/io/jenkins/pluginhealth/scoring/probes/SCMLinkValidationProbe.java +++ b/core/src/main/java/io/jenkins/pluginhealth/scoring/probes/SCMLinkValidationProbe.java @@ -24,13 +24,24 @@ package io.jenkins.pluginhealth.scoring.probes; +import java.io.FileInputStream; import java.io.IOException; +import java.io.InputStreamReader; +import java.io.Reader; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Optional; import java.util.regex.Matcher; import java.util.regex.Pattern; +import java.util.stream.Stream; import io.jenkins.pluginhealth.scoring.model.Plugin; import io.jenkins.pluginhealth.scoring.model.ProbeResult; +import org.apache.maven.model.Model; +import org.apache.maven.model.io.xpp3.MavenXpp3Reader; +import org.codehaus.plexus.util.xml.pull.XmlPullParserException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.core.annotation.Order; @@ -42,20 +53,102 @@ @Component @Order(value = SCMLinkValidationProbe.ORDER) public class SCMLinkValidationProbe extends Probe { - private static final Logger LOGGER = LoggerFactory.getLogger(SCMLinkValidationProbe.class); - - private static final String GH_REGEXP = "https://(?[^/]*)/(?jenkinsci/[^/]*)(?:/(?.*))?"; - public static final Pattern GH_PATTERN = Pattern.compile(GH_REGEXP); public static final int ORDER = UpdateCenterPluginPublicationProbe.ORDER + 100; public static final String KEY = "scm"; + private static final Logger LOGGER = LoggerFactory.getLogger(SCMLinkValidationProbe.class); + private static final String GH_REGEXP = "https://(?[^/]*)/(?jenkinsci/[^/]*)"; + public static final Pattern GH_PATTERN = Pattern.compile(GH_REGEXP); @Override public ProbeResult doApply(Plugin plugin, ProbeContext context) { if (plugin.getScm() == null || plugin.getScm().isBlank()) { LOGGER.warn("{} has no SCM link", plugin.getName()); - return ProbeResult.error(key(), "The plugin SCM link is empty"); + return ProbeResult.error(key(), "The plugin SCM link is empty."); + } + return fromSCMLink(context, plugin.getScm(), plugin.getName()); + } + + /** + * Validates the SCM link, and sets {@link ProbeContext#setScmFolderPath(Optional)}. The value is always the path of the POM file. + * + * @param context Refer {@link ProbeContext}. + * @param scm The SCM link {@link Plugin#getScm()}. + * @param pluginName The name of the plugin {@link Plugin#getName()}. + * @return ProbeResult {@link ProbeResult}. + */ + private ProbeResult fromSCMLink(ProbeContext context, String scm, String pluginName) { + Matcher matcher = GH_PATTERN.matcher(scm); + if (!matcher.find()) { + LOGGER.atDebug().log(() -> String.format("%s is not respecting the SCM URL Template.", scm)); + return ProbeResult.failure(key(), "SCM link doesn't match GitHub plugin repositories."); + } + try { + context.getGitHub().getRepository(matcher.group("repo")); // clones the repository, fetches the repo path using the regex Matcher + Optional pluginPathInRepository = findPluginPom(context.getScmRepository(), pluginName); + Optional folderPath = pluginPathInRepository.map(path -> path.getParent()); + if (folderPath.isEmpty()) { + return ProbeResult.error(key(), String.format("No valid POM file found in %s plugin.", pluginName)); + } + context.setScmFolderPath(folderPath.map(path -> path.getFileName().toString())); + return ProbeResult.success(key(), "The plugin SCM link is valid."); + } catch (IOException ex) { + return ProbeResult.failure(key(), "The plugin SCM link is invalid."); + } + } + + /** + * Searches for Pom file in every directory available in the repository. + * + * @param directory path in the scm. + * @param pluginName the name of the plugin. + * @return an Optional path if pom file is found. + */ + private Optional findPluginPom(Path directory, String pluginName) { + if (!Files.isDirectory(directory)) { + LOGGER.error("Directory {} does not exists during {} probe.", directory, pluginName); + return Optional.empty(); + } + /* + * The `maxDepth` is 3 because a lot of plugins aren't located deeper than /plugins/. + * If the `maxDepth` is more than 3, we will be navigating the `src/main/java/io/jenkins/plugins/artifactId/` folder. + * */ + try (Stream paths = Files.find(directory, 3, (path, $) -> + "pom.xml".equals(path.getFileName().toString()))) { + return paths + .filter(pom -> pomFileMatchesPlugin(pom, pluginName)) + .findFirst(); + } catch (IOException e) { + LOGGER.error("Could not browse the folder during probe {}. {}", pluginName, e); + } + return Optional.empty(); + } + + /** + * Checks whether the plugin's pom.xml matches the `packaging` and the `artifactId` of the plugin. + * This helps in finding the correct pom that belongs to the plugin. + * + * @param pluginName The name of the plugin to match. + * @param pomFilePath The path of the pom file to be checked. + * @return a boolean value stating whether the file checked matches the criteria. + */ + private boolean pomFileMatchesPlugin(Path pomFilePath, String pluginName) { + MavenXpp3Reader mavenReader = new MavenXpp3Reader(); + try (Reader reader = new InputStreamReader(new FileInputStream(pomFilePath.toFile()), StandardCharsets.UTF_8)) { + Model model = mavenReader.read(reader); + if ("hpi".equals(model.getPackaging()) && pluginName.equals(model.getArtifactId())) { + return true; + } + } catch (IOException e) { + LOGGER.error("Pom file not found for {}.", pluginName, e); + } catch (XmlPullParserException e) { + LOGGER.error("Could not parse pom file for {}.", pluginName, e); } - return fromSCMLink(context, plugin.getScm()); + return false; + } + + @Override + public String[] getProbeResultRequirement() { + return new String[]{UpdateCenterPluginPublicationProbe.KEY}; } @Override @@ -75,26 +168,4 @@ public String getDescription() { protected boolean requiresRelease() { return true; } - - private ProbeResult fromSCMLink(ProbeContext context, String scm) { - Matcher matcher = GH_PATTERN.matcher(scm); - if (!matcher.find()) { - if (LOGGER.isDebugEnabled()) { - LOGGER.debug("{} is not respecting the SCM URL Template", scm); - } - return ProbeResult.failure(key(), "SCM link doesn't match GitHub plugin repositories"); - } - - try { - context.getGitHub().getRepository(matcher.group("repo")); - return ProbeResult.success(key(), "The plugin SCM link is valid"); - } catch (IOException ex) { - return ProbeResult.failure(key(), "The plugin SCM link is invalid"); - } - } - - @Override - public String[] getProbeResultRequirement() { - return new String[]{UpdateCenterPluginPublicationProbe.KEY}; - } } diff --git a/core/src/test/java/io/jenkins/pluginhealth/scoring/probes/HasUnreleasedProductionChangesProbeTest.java b/core/src/test/java/io/jenkins/pluginhealth/scoring/probes/HasUnreleasedProductionChangesProbeTest.java index 902aaa013..def55cc53 100644 --- a/core/src/test/java/io/jenkins/pluginhealth/scoring/probes/HasUnreleasedProductionChangesProbeTest.java +++ b/core/src/test/java/io/jenkins/pluginhealth/scoring/probes/HasUnreleasedProductionChangesProbeTest.java @@ -38,6 +38,7 @@ import java.time.ZonedDateTime; import java.util.Date; import java.util.Map; +import java.util.Optional; import io.jenkins.pluginhealth.scoring.model.Plugin; import io.jenkins.pluginhealth.scoring.model.ProbeResult; @@ -126,6 +127,8 @@ void shouldFailIfThereIsNotReleasedCommitsInModule() throws IOException, GitAPIE LastCommitDateProbe.KEY, ProbeResult.success(LastCommitDateProbe.KEY, "") )); when(ctx.getScmRepository()).thenReturn(repository); + when(ctx.getScmFolderPath()).thenReturn(Optional.of("test-folder")); + when(plugin.getScm()).thenReturn(scmLink); final PersonIdent defaultCommitter = new PersonIdent( diff --git a/core/src/test/java/io/jenkins/pluginhealth/scoring/probes/SCMLinkValidationProbeTest.java b/core/src/test/java/io/jenkins/pluginhealth/scoring/probes/SCMLinkValidationProbeTest.java index 8bb6de5b8..c1638a68d 100644 --- a/core/src/test/java/io/jenkins/pluginhealth/scoring/probes/SCMLinkValidationProbeTest.java +++ b/core/src/test/java/io/jenkins/pluginhealth/scoring/probes/SCMLinkValidationProbeTest.java @@ -25,6 +25,7 @@ package io.jenkins.pluginhealth.scoring.probes; import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; @@ -32,11 +33,15 @@ import static org.mockito.Mockito.when; import java.io.IOException; +import java.nio.file.Path; +import java.util.List; import java.util.Map; +import java.util.Optional; 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.junit.jupiter.api.Test; import org.kohsuke.github.GHRepository; @@ -90,7 +95,7 @@ void shouldNotAcceptNullNorEmptyScm() { assertThat(r1.status()).isEqualTo(ResultStatus.ERROR); assertThat(r2.status()).isEqualTo(ResultStatus.ERROR); - assertThat(r1.message()).isEqualTo("The plugin SCM link is empty"); + assertThat(r1.message()).isEqualTo("The plugin SCM link is empty."); } @Test @@ -106,28 +111,35 @@ void shouldRecognizeIncorrectSCMUrl() { final ProbeResult r1 = probe.apply(p1, ctx); assertThat(r1.status()).isEqualTo(ResultStatus.FAILURE); - assertThat(r1.message()).isEqualTo("SCM link doesn't match GitHub plugin repositories"); + assertThat(r1.message()).isEqualTo("SCM link doesn't match GitHub plugin repositories."); } @Test void shouldRecognizeCorrectGitHubUrl() throws IOException { final Plugin p1 = mock(Plugin.class); - final ProbeContext ctx = mock(ProbeContext.class); + ProbeContext contextSpy = spy(new ProbeContext(p1.getName(), new UpdateCenter(Map.of(), Map.of(), List.of()))); final GitHub gh = mock(GitHub.class); - final String repositoryName = "jenkinsci/mailer-plugin"; + final String repositoryName = "jenkinsci/test-repo"; when(p1.getScm()).thenReturn("https://github.com/" + repositoryName); when(p1.getDetails()).thenReturn(Map.of( UpdateCenterPluginPublicationProbe.KEY, ProbeResult.success(UpdateCenterPluginPublicationProbe.KEY, "") )); - when(ctx.getGitHub()).thenReturn(gh); - when(gh.getRepository(repositoryName)).thenReturn(new GHRepository()); + + when(contextSpy.getScmRepository()).thenReturn(Path.of("src/test/resources/jenkinsci/test-repo/test-nested-dir-1")); + when(contextSpy.getGitHub()).thenReturn(gh); + GHRepository repository = mock(GHRepository.class); + when(gh.getRepository(repositoryName)).thenReturn(repository); + + when(p1.getName()).thenReturn("test-repo"); + when(contextSpy.getRepositoryName(anyString())).thenReturn(Optional.of(repositoryName)); final SCMLinkValidationProbe probe = getSpy(); - final ProbeResult r1 = probe.apply(p1, ctx); + final ProbeResult r1 = probe.apply(p1, contextSpy); + assertThat(contextSpy.getScmFolderPath()).isEqualTo(Optional.of("test-nested-dir-2")); assertThat(r1.status()).isEqualTo(ResultStatus.SUCCESS); - assertThat(r1.message()).isEqualTo("The plugin SCM link is valid"); + assertThat(r1.message()).isEqualTo("The plugin SCM link is valid."); } @Test @@ -148,6 +160,108 @@ void shouldRecognizeInvalidGitHubUrl() throws Exception { final ProbeResult r1 = probe.apply(p1, ctx); assertThat(r1.status()).isEqualTo(ResultStatus.FAILURE); - assertThat(r1.message()).isEqualTo("The plugin SCM link is invalid"); + assertThat(r1.message()).isEqualTo("The plugin SCM link is invalid."); + } + + @Test + void shouldReturnCorrectScmFolderPath() throws IOException { + final Plugin plugin = mock(Plugin.class); + final GitHub github = mock(GitHub.class); + final String repositoryName = "jenkinsci/test-repo"; + ProbeContext contextSpy = spy(new ProbeContext(plugin.getName(), new UpdateCenter(Map.of(), Map.of(), List.of()))); + + when(plugin.getScm()).thenReturn("https://github.com/" + repositoryName); + when(plugin.getDetails()).thenReturn(Map.of( + UpdateCenterPluginPublicationProbe.KEY, ProbeResult.success(UpdateCenterPluginPublicationProbe.KEY, "") + )); + when(plugin.getName()).thenReturn("test-repo"); + + when(contextSpy.getScmRepository()).thenReturn(Path.of("src/test/resources/jenkinsci/test-repo/test-nested-dir-1")); + when(contextSpy.getGitHub()).thenReturn(github); + GHRepository repository = mock(GHRepository.class); + when(github.getRepository(repositoryName)).thenReturn(repository); + + final SCMLinkValidationProbe probe = getSpy(); + final ProbeResult result = probe.apply(plugin, contextSpy); + + assertThat(contextSpy.getScmFolderPath()).isEqualTo(Optional.of("test-nested-dir-2")); + assertThat(result.status()).isEqualTo(ResultStatus.SUCCESS); + assertThat(result.message()).isEqualTo("The plugin SCM link is valid."); + verify(probe).doApply(plugin, contextSpy); + } + + @Test + void shouldNotReturnInCorrectScmFolderPath() throws IOException { + final Plugin plugin = mock(Plugin.class); + final GitHub github = mock(GitHub.class); + final String repositoryName = "jenkinsci/test-repo"; + ProbeContext contextSpy = spy(new ProbeContext(plugin.getName(), new UpdateCenter(Map.of(), Map.of(), List.of()))); + + when(plugin.getScm()).thenReturn("https://github.com/" + repositoryName); + when(plugin.getDetails()).thenReturn(Map.of( + UpdateCenterPluginPublicationProbe.KEY, ProbeResult.success(UpdateCenterPluginPublicationProbe.KEY, "") + )); + when(plugin.getName()).thenReturn("test-repo"); + + when(contextSpy.getScmRepository()).thenReturn(Path.of("src/test/resources/jenkinsci/test-repo/test-incorrect-nested-dir-1")); + when(contextSpy.getGitHub()).thenReturn(github); + + final SCMLinkValidationProbe probe = getSpy(); + final ProbeResult result = probe.apply(plugin, contextSpy); + + assertThat(contextSpy.getScmFolderPath()).isEqualTo(null); + assertThat(result.status()).isEqualTo(ResultStatus.ERROR); + assertThat(result.message()).isEqualTo("No valid POM file found in test-repo plugin."); + verify(probe).doApply(plugin, contextSpy); + } + + @Test + void shouldFindRootScmFolderPath() throws IOException { + final Plugin plugin = mock(Plugin.class); + final GitHub github = mock(GitHub.class); + final String repositoryName = "jenkinsci/test-repo"; + ProbeContext ctx = new ProbeContext(plugin.getName(), new UpdateCenter(Map.of(), Map.of(), List.of())); + ProbeContext contextSpy = spy(ctx); + + when(plugin.getScm()).thenReturn("https://github.com/" + repositoryName); + when(plugin.getDetails()).thenReturn(Map.of( + UpdateCenterPluginPublicationProbe.KEY, ProbeResult.success(UpdateCenterPluginPublicationProbe.KEY, "") + )); + when(plugin.getName()).thenReturn("test-repo"); + + when(contextSpy.getScmRepository()).thenReturn(Path.of("src/test/resources/jenkinsci/test-repo")); + when(contextSpy.getGitHub()).thenReturn(github); + + final SCMLinkValidationProbe probe = getSpy(); + final ProbeResult result = probe.apply(plugin, contextSpy); + + assertThat(contextSpy.getScmFolderPath()).isEqualTo(Optional.of("test-repo")); + assertThat(result.status()).isEqualTo(ResultStatus.SUCCESS); + assertThat(result.message()).isEqualTo("The plugin SCM link is valid."); + verify(probe).doApply(plugin, contextSpy); + } + + @Test + void shouldFailWhenPomFileDoesNotExistsInTheRepository() throws IOException { + final Plugin plugin = mock(Plugin.class); + final GitHub github = mock(GitHub.class); + final String repositoryName = "jenkinsci/test-no-pom-file-repo"; + ProbeContext contextSpy = spy(new ProbeContext(plugin.getName(), new UpdateCenter(Map.of(), Map.of(), List.of()))); + + when(plugin.getScm()).thenReturn("https://github.com/" + repositoryName); + when(plugin.getDetails()).thenReturn(Map.of( + UpdateCenterPluginPublicationProbe.KEY, ProbeResult.success(UpdateCenterPluginPublicationProbe.KEY, "") + )); + when(plugin.getName()).thenReturn("test-repo"); + + when(contextSpy.getScmRepository()).thenReturn(Path.of("src/test/resources/jenkinsci/test-no-pom-file-repo")); + when(contextSpy.getGitHub()).thenReturn(github); + + final SCMLinkValidationProbe probe = getSpy(); + final ProbeResult result = probe.apply(plugin, contextSpy); + + assertThat(result.status()).isEqualTo(ResultStatus.ERROR); + assertThat(result.message()).isEqualTo("No valid POM file found in test-repo plugin."); + verify(probe).doApply(plugin, contextSpy); } } diff --git a/core/src/test/resources/jenkinsci/test-repo/pom.xml b/core/src/test/resources/jenkinsci/test-repo/pom.xml new file mode 100644 index 000000000..f161e6017 --- /dev/null +++ b/core/src/test/resources/jenkinsci/test-repo/pom.xml @@ -0,0 +1,6 @@ + + 4.0.0 + test-group + test-repo + hpi + diff --git a/core/src/test/resources/jenkinsci/test-repo/test-incorrect-nested-dir-1/pom.xml b/core/src/test/resources/jenkinsci/test-repo/test-incorrect-nested-dir-1/pom.xml new file mode 100644 index 000000000..767ce99de --- /dev/null +++ b/core/src/test/resources/jenkinsci/test-repo/test-incorrect-nested-dir-1/pom.xml @@ -0,0 +1,6 @@ + + 4.0.0 + test-group + test-incorrect-repo + hpi + diff --git a/core/src/test/resources/jenkinsci/test-repo/test-incorrect-nested-dir-1/test-incorrect-nested-dir-2/pom.xml b/core/src/test/resources/jenkinsci/test-repo/test-incorrect-nested-dir-1/test-incorrect-nested-dir-2/pom.xml new file mode 100644 index 000000000..8bb49ae53 --- /dev/null +++ b/core/src/test/resources/jenkinsci/test-repo/test-incorrect-nested-dir-1/test-incorrect-nested-dir-2/pom.xml @@ -0,0 +1,6 @@ + + 4.0.0 + test-group + test-repo + pom + diff --git a/core/src/test/resources/jenkinsci/test-repo/test-nested-dir-1/pom.xml b/core/src/test/resources/jenkinsci/test-repo/test-nested-dir-1/pom.xml new file mode 100644 index 000000000..8bb49ae53 --- /dev/null +++ b/core/src/test/resources/jenkinsci/test-repo/test-nested-dir-1/pom.xml @@ -0,0 +1,6 @@ + + 4.0.0 + test-group + test-repo + pom + diff --git a/core/src/test/resources/jenkinsci/test-repo/test-nested-dir-1/test-nested-dir-2/pom.xml b/core/src/test/resources/jenkinsci/test-repo/test-nested-dir-1/test-nested-dir-2/pom.xml new file mode 100644 index 000000000..f161e6017 --- /dev/null +++ b/core/src/test/resources/jenkinsci/test-repo/test-nested-dir-1/test-nested-dir-2/pom.xml @@ -0,0 +1,6 @@ + + 4.0.0 + test-group + test-repo + hpi + diff --git a/pom.xml b/pom.xml index ccd7f8289..b03a07759 100644 --- a/pom.xml +++ b/pom.xml @@ -154,6 +154,11 @@ pom import + + org.apache.maven + maven-model + 3.9.2 +