From ff1af651aaa89bbe883e0287a5bb66034f6893bc Mon Sep 17 00:00:00 2001 From: AayushSaini101 Date: Sat, 23 Mar 2024 12:47:32 +0530 Subject: [PATCH 1/3] Add test cases --- .../probes/DefaultBranchBuildStatusProbe.java | 94 +++++++++++++++++++ .../DefaultBranchBuildStatusProbeTest.java | 35 +++++++ 2 files changed, 129 insertions(+) create mode 100644 core/src/main/java/io/jenkins/pluginhealth/scoring/probes/DefaultBranchBuildStatusProbe.java create mode 100644 core/src/test/java/io/jenkins/pluginhealth/scoring/probes/DefaultBranchBuildStatusProbeTest.java diff --git a/core/src/main/java/io/jenkins/pluginhealth/scoring/probes/DefaultBranchBuildStatusProbe.java b/core/src/main/java/io/jenkins/pluginhealth/scoring/probes/DefaultBranchBuildStatusProbe.java new file mode 100644 index 000000000..c0f6fd45d --- /dev/null +++ b/core/src/main/java/io/jenkins/pluginhealth/scoring/probes/DefaultBranchBuildStatusProbe.java @@ -0,0 +1,94 @@ +/* + * MIT License + * + * Copyright (c) 2023 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 java.io.IOException; +import java.util.Optional; + +import io.jenkins.pluginhealth.scoring.model.Plugin; +import io.jenkins.pluginhealth.scoring.model.ProbeResult; + +import org.kohsuke.github.GHCheckRun; +import org.kohsuke.github.GHCommit; +import org.kohsuke.github.GHRepository; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; + +/** + * This probe checks whether build failed on Default Branch or not. + */ +@Component +@Order(DefaultBranchBuildStatusProbe.ORDER) +public class DefaultBranchBuildStatusProbe extends Probe { + + public static final int ORDER = JenkinsCoreProbe.ORDER + 100; + public static final String KEY = "default-branch-build-status"; + + @Override + protected ProbeResult doApply(Plugin plugin, ProbeContext context) { + final io.jenkins.pluginhealth.scoring.model.updatecenter.Plugin ucPlugin = + context.getUpdateCenter().plugins().get(plugin.getName()); + if (ucPlugin == null) { + return error("Plugin cannot be found in Update-Center."); + } + final String defaultBranch = ucPlugin.defaultBranch(); + if (defaultBranch == null || defaultBranch.isBlank()) { + return this.error("No default branch configured for the plugin."); + } + try + { + final Optional repositoryName = context.getRepositoryName(); + final GHRepository ghRepository = context.getGitHub().getRepository(repositoryName.get()); + GHCommit commit = ghRepository.getCommit(defaultBranch); + GHCheckRun checkRun = commit.getCheckRuns().iterator().next(); + GHCheckRun.Conclusion conclusion = checkRun.getConclusion(); + + if (conclusion == GHCheckRun.Conclusion.FAILURE) { + return this.success("Build Failed in Default Branch"); + } else { + return this.success("Build is Success in Default Branch"); + } + } catch (IOException ex) { + throw new RuntimeException(ex); + } + + } + + @Override + public String key() { + return KEY; + } + + @Override + public String getDescription() { + return "Return whether the build is failed on default branch or not"; + } + + @Override + public long getVersion() { + return 1; + } + +} diff --git a/core/src/test/java/io/jenkins/pluginhealth/scoring/probes/DefaultBranchBuildStatusProbeTest.java b/core/src/test/java/io/jenkins/pluginhealth/scoring/probes/DefaultBranchBuildStatusProbeTest.java new file mode 100644 index 000000000..c9e51df1d --- /dev/null +++ b/core/src/test/java/io/jenkins/pluginhealth/scoring/probes/DefaultBranchBuildStatusProbeTest.java @@ -0,0 +1,35 @@ +/* + * MIT License + * + * Copyright (c) 2023 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.mockito.Mockito.spy; + +class DefaultBranchBuildStatusProbeTest extends AbstractProbeTest { + + @Override + DefaultBranchBuildStatusProbe getSpy() { + return spy(DefaultBranchBuildStatusProbe.class); + } + +} From 820233f9dcb9f7297d0aa42618469ead6281025a Mon Sep 17 00:00:00 2001 From: AayushSaini101 Date: Sat, 23 Mar 2024 13:00:46 +0530 Subject: [PATCH 2/3] Add test cases --- .DS_Store | Bin 0 -> 8196 bytes .../probes/DefaultBranchBuildStatusProbe.java | 53 ++++--- .../DefaultBranchBuildStatusProbeTest.java | 140 +++++++++++++++++- 3 files changed, 163 insertions(+), 30 deletions(-) create mode 100644 .DS_Store diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..917aee9252e174491c28bfe56c03545b6ec87cd0 GIT binary patch literal 8196 zcmeHLziSjh6#m9r&54K+A_Q!fR6!wl+NfBp;rvnA1Qfgb6)usx>|riS5M+C?@ei=m z#M&l;jbIQ28+*Y*1v_i8@S7iZGjqF_QiPp>*>}wM-hS_Wv$w-r0AhKoQv>D!R5_)c zJ;qDHkhq+=amcJJ(hA0-*R8Fz)BYgm85V*9L4lw^P#`D}6!>2h;F&E)b;`M~(Qpk4 z1O-Z|fP6p1oYE%7X4-T!R8ZfxH5;caN}yF4i%0`*(5a!cQ0Lr}cWP zm$tZ8J#+c=^;diQSAD#5AU;^L-v-1L^@(6+#EUg-q2;mzCvNlZ6CQ33`+M)+ywEx1 zylf`Zz1)0&2FY-k`K+UZRW$uv&Pv!p-8^-Tnh>G>zJ8pP%Nd~5F6uC95E zTE;x;@zvCONY)xgP@rrIRCK}fvj4v}{ri8}WC`^K1xlrWi0Ui#WtMDu>s;}&*N! repositoryName = context.getRepositoryName(); - final GHRepository ghRepository = context.getGitHub().getRepository(repositoryName.get()); - GHCommit commit = ghRepository.getCommit(defaultBranch); - GHCheckRun checkRun = commit.getCheckRuns().iterator().next(); - GHCheckRun.Conclusion conclusion = checkRun.getConclusion(); + try { + final io.jenkins.pluginhealth.scoring.model.updatecenter.Plugin ucPlugin = + context.getUpdateCenter().plugins().get(plugin.getName()); + if (ucPlugin == null) { + return error("Plugin cannot be found in Update-Center."); + } + final String defaultBranch = ucPlugin.defaultBranch(); + if (defaultBranch == null || defaultBranch.isBlank()) { + return this.error("No default branch configured for the plugin."); + } - if (conclusion == GHCheckRun.Conclusion.FAILURE) { - return this.success("Build Failed in Default Branch"); - } else { - return this.success("Build is Success in Default Branch"); - } - } catch (IOException ex) { - throw new RuntimeException(ex); - } + final Optional repositoryName = context.getRepositoryName(); + final GHRepository ghRepository = context.getGitHub().getRepository(repositoryName.get()); + GHCommit commit = ghRepository.getCommit(ucPlugin.defaultBranch()); + GHCheckRun checkRun = commit.getCheckRuns().iterator().next(); + Conclusion conclusion = checkRun.getConclusion(); + if (conclusion == Conclusion.FAILURE) { + return this.success("Build Failed in Default Branch"); + } else { + return this.success("Build is Success in Default Branch"); + } + } catch (Exception ex) { + return this.error("Failed to obtain the status of the default Branch."); + } } @Override @@ -90,5 +88,4 @@ public String getDescription() { public long getVersion() { return 1; } - } diff --git a/core/src/test/java/io/jenkins/pluginhealth/scoring/probes/DefaultBranchBuildStatusProbeTest.java b/core/src/test/java/io/jenkins/pluginhealth/scoring/probes/DefaultBranchBuildStatusProbeTest.java index c9e51df1d..8f6db6eef 100644 --- a/core/src/test/java/io/jenkins/pluginhealth/scoring/probes/DefaultBranchBuildStatusProbeTest.java +++ b/core/src/test/java/io/jenkins/pluginhealth/scoring/probes/DefaultBranchBuildStatusProbeTest.java @@ -1,7 +1,7 @@ /* * MIT License * - * Copyright (c) 2023 Jenkins Infra + * Copyright (c) 2023-2024 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 @@ -23,13 +23,149 @@ */ 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.verify; +import static org.mockito.Mockito.when; -class DefaultBranchBuildStatusProbeTest extends AbstractProbeTest { +import java.io.IOException; +import java.time.ZonedDateTime; +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.updatecenter.UpdateCenter; + +import hudson.util.VersionNumber; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.kohsuke.github.GHCheckRun; +import org.kohsuke.github.GHCommit; +import org.kohsuke.github.GHRepository; +import org.kohsuke.github.GitHub; +import org.kohsuke.github.PagedIterable; +import org.kohsuke.github.PagedIterator; + +class DefaultBranchBuildStatusProbeTest extends AbstractProbeTest { + + private DefaultBranchBuildStatusProbe probe; @Override DefaultBranchBuildStatusProbe getSpy() { return spy(DefaultBranchBuildStatusProbe.class); } + @BeforeEach + public void init() { + + probe = getSpy(); + } + + @Test + public void shouldReturnBuildSucessOntheDefaultBranch() throws IOException { + + final String pluginName = "mailer"; + final String pluginRepo = "jenkinsci/" + pluginName + "-plugin"; + final String scmLink = "https://github.com/" + pluginRepo; + final String defaultBranch = "main"; + final GitHub gitHub = mock(GitHub.class); + final GHRepository ghRepository = mock(GHRepository.class); + final GHCommit ghCommit = mock(GHCommit.class); + final GHCheckRun checkRun = mock(GHCheckRun.class); + final PagedIterable checkrun = mock(PagedIterable.class); + final PagedIterator checkIterator = mock(PagedIterator.class); + final Plugin plugin = mock(Plugin.class); + final ProbeContext ctx = mock(ProbeContext.class); + + final GitHub gh = mock(GitHub.class); + + when(plugin.getName()).thenReturn(pluginName); + when(plugin.getScm()).thenReturn(scmLink); + when(ctx.getUpdateCenter()) + .thenReturn(new UpdateCenter( + Map.of( + pluginName, + new io.jenkins.pluginhealth.scoring.model.updatecenter.Plugin( + pluginName, + new VersionNumber("1.0"), + scmLink, + ZonedDateTime.now(), + List.of(), + 0, + "42", + defaultBranch)), + Map.of(), + List.of())); + when(ctx.getGitHub()).thenReturn(gh); + when(ctx.getRepositoryName()).thenReturn(Optional.of(pluginRepo)); + when(ctx.getGitHub()).thenReturn(gitHub); + when(ctx.getRepositoryName()).thenReturn(Optional.of("org/repo")); + when(gitHub.getRepository("org/repo")).thenReturn(ghRepository); + when(ghRepository.getCommit(defaultBranch)).thenReturn(ghCommit); + when(gh.getRepository(pluginRepo)).thenReturn(ghRepository); + when(ghCommit.getCheckRuns()).thenReturn(checkrun); + when(ghCommit.getCheckRuns().iterator()).thenReturn(checkIterator); + when(ghCommit.getCheckRuns().iterator().hasNext()).thenReturn /**/(true); + when(ghCommit.getCheckRuns().iterator().next()).thenReturn(checkRun); + assertThat(probe.apply(plugin, ctx)) + .usingRecursiveComparison() + .comparingOnlyFields("id", "message", "status") + .isEqualTo(ProbeResult.success( + DefaultBranchBuildStatusProbe.KEY, "Build is Success in Default Branch", probe.getVersion())); + verify(probe).doApply(plugin, ctx); + } + + @Test + public void shouldReturnErrorMessageCommitsNotFound() throws IOException { + + final String pluginName = "mailer"; + final String pluginRepo = "jenkinsci/" + pluginName + "-plugin"; + final String scmLink = "https://github.com/" + pluginRepo; + final String defaultBranch = "main"; + final GitHub gitHub = mock(GitHub.class); + final GHRepository ghRepository = mock(GHRepository.class); + final GHCommit ghCommit = mock(GHCommit.class); + final PagedIterable checkrun = mock(PagedIterable.class); + final Plugin plugin = mock(Plugin.class); + final ProbeContext ctx = mock(ProbeContext.class); + + final GitHub gh = mock(GitHub.class); + + when(plugin.getName()).thenReturn(pluginName); + when(plugin.getScm()).thenReturn(scmLink); + when(ctx.getUpdateCenter()) + .thenReturn(new UpdateCenter( + Map.of( + pluginName, + new io.jenkins.pluginhealth.scoring.model.updatecenter.Plugin( + pluginName, + new VersionNumber("1.0"), + scmLink, + ZonedDateTime.now(), + List.of(), + 0, + "42", + defaultBranch)), + Map.of(), + List.of())); + when(ctx.getGitHub()).thenReturn(gh); + when(ctx.getRepositoryName()).thenReturn(Optional.of(pluginRepo)); + when(ctx.getGitHub()).thenReturn(gitHub); + when(ctx.getRepositoryName()).thenReturn(Optional.of("org/repo")); + when(gitHub.getRepository("org/repo")).thenReturn(ghRepository); + when(ghRepository.getCommit(defaultBranch)).thenReturn(ghCommit); + when(gh.getRepository(pluginRepo)).thenReturn(ghRepository); + when(ghCommit.getCheckRuns()).thenReturn(checkrun); + assertThat(probe.apply(plugin, ctx)) + .usingRecursiveComparison() + .comparingOnlyFields("id", "message", "status") + .isEqualTo(ProbeResult.error( + DefaultBranchBuildStatusProbe.KEY, + "Failed to obtain the status of the default Branch.", + probe.getVersion())); + verify(probe).doApply(plugin, ctx); + } } From 549af83bdf68ccadbd7535234ed5c06737e9461e Mon Sep 17 00:00:00 2001 From: AayushSaini101 Date: Sat, 23 Mar 2024 13:06:19 +0530 Subject: [PATCH 3/3] Remove unwanted file --- .DS_Store | Bin 8196 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 .DS_Store diff --git a/.DS_Store b/.DS_Store deleted file mode 100644 index 917aee9252e174491c28bfe56c03545b6ec87cd0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8196 zcmeHLziSjh6#m9r&54K+A_Q!fR6!wl+NfBp;rvnA1Qfgb6)usx>|riS5M+C?@ei=m z#M&l;jbIQ28+*Y*1v_i8@S7iZGjqF_QiPp>*>}wM-hS_Wv$w-r0AhKoQv>D!R5_)c zJ;qDHkhq+=amcJJ(hA0-*R8Fz)BYgm85V*9L4lw^P#`D}6!>2h;F&E)b;`M~(Qpk4 z1O-Z|fP6p1oYE%7X4-T!R8ZfxH5;caN}yF4i%0`*(5a!cQ0Lr}cWP zm$tZ8J#+c=^;diQSAD#5AU;^L-v-1L^@(6+#EUg-q2;mzCvNlZ6CQ33`+M)+ywEx1 zylf`Zz1)0&2FY-k`K+UZRW$uv&Pv!p-8^-Tnh>G>zJ8pP%Nd~5F6uC95E zTE;x;@zvCONY)xgP@rrIRCK}fvj4v}{ri8}WC`^K1xlrWi0Ui#WtMDu>s;}&*N!