From 45a1ef5eb247ebfa34e450add3f5f9cae0c8a9e7 Mon Sep 17 00:00:00 2001 From: Pierre Baumard Date: Fri, 8 Nov 2024 23:36:13 +0100 Subject: [PATCH] Fix JENKINS-71955 NullPointerException because getMergeRequestsEnabled is null (#456) --- .../gitlabbranchsource/GitLabSCMSource.java | 7 +- .../GitLabSCMSourceTest.java | 70 +++++++++++++++++++ 2 files changed, 74 insertions(+), 3 deletions(-) create mode 100644 src/test/java/io/jenkins/plugins/gitlabbranchsource/GitLabSCMSourceTest.java diff --git a/src/main/java/io/jenkins/plugins/gitlabbranchsource/GitLabSCMSource.java b/src/main/java/io/jenkins/plugins/gitlabbranchsource/GitLabSCMSource.java index 2911022a..295bb51e 100644 --- a/src/main/java/io/jenkins/plugins/gitlabbranchsource/GitLabSCMSource.java +++ b/src/main/java/io/jenkins/plugins/gitlabbranchsource/GitLabSCMSource.java @@ -116,7 +116,7 @@ public class GitLabSCMSource extends AbstractGitSCMSource { private String sshRemote; private String httpRemote; private transient Project gitlabProject; - private long projectId; + private Long projectId; /** * The cache of {@link ObjectMetadataAction} instances for each open MR. @@ -333,7 +333,8 @@ protected void retrieve( if (request.isFetchBranches()) { request.setBranches(gitLabApi.getRepositoryApi().getBranches(gitlabProject)); } - if (request.isFetchMRs() && gitlabProject.getMergeRequestsEnabled()) { + boolean mergeRequestsEnabled = !Boolean.FALSE.equals(gitlabProject.getMergeRequestsEnabled()); + if (request.isFetchMRs() && mergeRequestsEnabled) { final boolean forkedFromProject = (gitlabProject.getForkedFromProject() != null); if (!ctx.buildMRForksNotMirror() && forkedFromProject) { listener.getLogger().format("%nIgnoring merge requests as project is a mirror...%n"); @@ -409,7 +410,7 @@ public SCMSourceCriteria.Probe create( } listener.getLogger().format("%n%d branches were processed%n", count); } - if (request.isFetchMRs() && !request.isComplete() && gitlabProject.getMergeRequestsEnabled()) { + if (request.isFetchMRs() && !request.isComplete() && mergeRequestsEnabled) { int count = 0; listener.getLogger().format("%nChecking merge requests..%n"); HashMap forkMrSources = new HashMap<>(); diff --git a/src/test/java/io/jenkins/plugins/gitlabbranchsource/GitLabSCMSourceTest.java b/src/test/java/io/jenkins/plugins/gitlabbranchsource/GitLabSCMSourceTest.java new file mode 100644 index 00000000..9c261aaf --- /dev/null +++ b/src/test/java/io/jenkins/plugins/gitlabbranchsource/GitLabSCMSourceTest.java @@ -0,0 +1,70 @@ +package io.jenkins.plugins.gitlabbranchsource; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; + +import hudson.model.TaskListener; +import hudson.security.AccessControlled; +import hudson.util.StreamTaskListener; +import io.jenkins.plugins.gitlabbranchsource.helpers.GitLabHelper; +import io.jenkins.plugins.gitlabserverconfig.servers.GitLabServer; +import io.jenkins.plugins.gitlabserverconfig.servers.GitLabServers; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.Arrays; +import java.util.Set; +import jenkins.branch.BranchSource; +import jenkins.scm.api.SCMHead; +import org.gitlab4j.api.GitLabApi; +import org.gitlab4j.api.GitLabApiException; +import org.gitlab4j.api.MergeRequestApi; +import org.gitlab4j.api.ProjectApi; +import org.gitlab4j.api.RepositoryApi; +import org.gitlab4j.api.models.Project; +import org.jenkinsci.plugins.workflow.multibranch.WorkflowMultiBranchProject; +import org.junit.ClassRule; +import org.junit.Test; +import org.jvnet.hudson.test.JenkinsRule; +import org.mockito.MockedStatic; +import org.mockito.Mockito; + +public class GitLabSCMSourceTest { + + private static final String SERVER = "server"; + private static final String PROJECT_NAME = "project"; + private static final String SOURCE_ID = "id"; + + @ClassRule + public static JenkinsRule j = new JenkinsRule(); + + @Test + public void retrieveMRWithEmptyProjectSettings() throws GitLabApiException, IOException, InterruptedException { + GitLabApi gitLabApi = Mockito.mock(GitLabApi.class); + ProjectApi projectApi = Mockito.mock(ProjectApi.class); + RepositoryApi repoApi = Mockito.mock(RepositoryApi.class); + MergeRequestApi mrApi = Mockito.mock(MergeRequestApi.class); + Mockito.when(gitLabApi.getProjectApi()).thenReturn(projectApi); + Mockito.when(gitLabApi.getMergeRequestApi()).thenReturn(mrApi); + Mockito.when(gitLabApi.getRepositoryApi()).thenReturn(repoApi); + Mockito.when(projectApi.getProject(any())).thenReturn(new Project()); + try (MockedStatic utilities = Mockito.mockStatic(GitLabHelper.class)) { + utilities + .when(() -> GitLabHelper.apiBuilder(any(AccessControlled.class), anyString())) + .thenReturn(gitLabApi); + GitLabServers.get().addServer(new GitLabServer("", SERVER, "")); + GitLabSCMSourceBuilder sb = + new GitLabSCMSourceBuilder(SOURCE_ID, SERVER, "creds", "po", "group/project", "project"); + WorkflowMultiBranchProject project = j.createProject(WorkflowMultiBranchProject.class, PROJECT_NAME); + BranchSource source = new BranchSource(sb.build()); + source.getSource() + .setTraits(Arrays.asList(new BranchDiscoveryTrait(0), new OriginMergeRequestDiscoveryTrait(1))); + project.getSourcesList().add(source); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + final TaskListener listener = new StreamTaskListener(out, StandardCharsets.UTF_8); + Set scmHead = source.getSource().fetch(listener); + assertEquals(0, scmHead.size()); + } + } +}