From bd129a715237add3321efa41d99ef809c59c4117 Mon Sep 17 00:00:00 2001 From: Derrick Gibelyou Date: Thu, 20 Jun 2019 09:43:39 -0600 Subject: [PATCH 1/3] Add new pipeline function to return merge request status --- .../GitLabMergeRequestStatusStep.java | 125 ++++++++++++++++++ 1 file changed, 125 insertions(+) create mode 100644 src/main/java/com/dabsquared/gitlabjenkins/workflow/GitLabMergeRequestStatusStep.java diff --git a/src/main/java/com/dabsquared/gitlabjenkins/workflow/GitLabMergeRequestStatusStep.java b/src/main/java/com/dabsquared/gitlabjenkins/workflow/GitLabMergeRequestStatusStep.java new file mode 100644 index 000000000..8d6e62385 --- /dev/null +++ b/src/main/java/com/dabsquared/gitlabjenkins/workflow/GitLabMergeRequestStatusStep.java @@ -0,0 +1,125 @@ +package com.dabsquared.gitlabjenkins.workflow; + +import com.dabsquared.gitlabjenkins.connection.GitLabConnectionProperty; +import com.dabsquared.gitlabjenkins.gitlab.api.GitLabClient; +import com.dabsquared.gitlabjenkins.gitlab.api.model.BuildState; +import com.dabsquared.gitlabjenkins.gitlab.api.model.MergeRequest; +import com.dabsquared.gitlabjenkins.gitlab.hook.model.State; +import com.dabsquared.gitlabjenkins.util.CommitStatusUpdater; +import com.google.common.collect.ImmutableSet; +import hudson.Extension; +import hudson.model.Run; +import hudson.model.TaskListener; +import hudson.util.ListBoxModel; +import org.jenkinsci.plugins.workflow.steps.*; +import org.kohsuke.stapler.DataBoundConstructor; +import org.kohsuke.stapler.DataBoundSetter; +import org.kohsuke.stapler.export.ExportedBean; + +import java.util.EnumSet; +import java.util.List; +import java.util.Set; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * @author Robin Müller + */ +@ExportedBean +public class GitLabMergeRequestStatusStep extends Step { + + private final static Logger LOGGER = Logger.getLogger(GitLabMergeRequestStatusStep.class.getName()); + + private String projectName; + private String branchName; + + @DataBoundConstructor + public GitLabMergeRequestStatusStep(String project_name, String branch_name) { + this.projectName = project_name; + this.branchName = branch_name; + } + + public String getProjectName() { + return projectName; + } + + @DataBoundSetter + public void setProjectName(String project_name) { + this.projectName = project_name; + } + + public String getBranchName() { + return branchName; + } + + @DataBoundSetter + public void setBranchName(String branch_name) { + this.branchName = branch_name; + } + + @Override + public StepExecution start(StepContext context) throws Exception { + return new GitLabMergeRequestStatusStepExecution(context, this); + } + + public static class GitLabMergeRequestStatusStepExecution extends SynchronousNonBlockingStepExecution { + private static final long serialVersionUID = 1; + + private final transient Run run; + + private final transient GitLabMergeRequestStatusStep step; + + GitLabMergeRequestStatusStepExecution(StepContext context, GitLabMergeRequestStatusStep step) throws Exception { + super(context); + this.step = step; + run = context.get(Run.class); + } + + @Override + protected MergeRequest run() throws Exception { + GitLabClient client = GitLabConnectionProperty.getClient(run); + if (client == null) { + LOGGER.log(Level.WARNING, "Failed to find gitlab connection"); + return null; + } + + Integer page = 1; + do { + List mergeRequests = client.getMergeRequests(step.branchName, State.opened, page, 100); + for (MergeRequest mr : mergeRequests) { + if (mr.getSourceBranch().equals(step.branchName)) { + return mr; + } + } + page = mergeRequests.isEmpty() ? null : page + 1; + } while (page != null); + return null; + } + } + + @Extension + public static final class DescriptorImpl extends StepDescriptor { + @Override + public String getDisplayName() { + return "Return the MergeRequest status for the branch, if it exists."; + } + + @Override + public String getFunctionName() { + return "gitlabMergeRequestStatus"; + } + + public ListBoxModel doFillStateItems() { + ListBoxModel options = new ListBoxModel(); + for (BuildState buildState : EnumSet.allOf(BuildState.class)) { + options.add(buildState.name()); + } + return options; + } + + @Override + public Set> getRequiredContext() { + return ImmutableSet.of(TaskListener.class, Run.class); + } + } +} From 5f325c176e2c7b7878091ed879549e7fd869f23d Mon Sep 17 00:00:00 2001 From: Derrick Gibelyou Date: Thu, 20 Jun 2019 09:45:11 -0600 Subject: [PATCH 2/3] Try to add test for MergeRequestStatus --- .../GitLabMergeRequestStatusStepTest.java | 27 +++++++++++++++++++ .../gitlabMergeRequestStatus-pipeline.groovy | 8 ++++++ 2 files changed, 35 insertions(+) create mode 100644 src/test/java/com/dabsquared/gitlabjenkins/workflow/GitLabMergeRequestStatusStepTest.java create mode 100644 src/test/resources/com/dabsquared/gitlabjenkins/workflow/pipeline/gitlabMergeRequestStatus-pipeline.groovy diff --git a/src/test/java/com/dabsquared/gitlabjenkins/workflow/GitLabMergeRequestStatusStepTest.java b/src/test/java/com/dabsquared/gitlabjenkins/workflow/GitLabMergeRequestStatusStepTest.java new file mode 100644 index 000000000..ade3f6cec --- /dev/null +++ b/src/test/java/com/dabsquared/gitlabjenkins/workflow/GitLabMergeRequestStatusStepTest.java @@ -0,0 +1,27 @@ +package com.dabsquared.gitlabjenkins.workflow; + + +import hudson.model.Run; +import org.apache.commons.io.IOUtils; +import org.jenkinsci.plugins.workflow.cps.CpsFlowDefinition; +import org.jenkinsci.plugins.workflow.job.WorkflowJob; +import org.junit.Rule; +import org.junit.Test; +import org.jvnet.hudson.test.JenkinsRule; + +public class GitLabMergeRequestStatusStepTest { + + @Rule + public JenkinsRule j = new JenkinsRule(); + + @Test + public void gitlabCommitStatus() throws Exception { + WorkflowJob project = j.createProject(WorkflowJob.class); + String pipelineText = IOUtils.toString(getClass().getResourceAsStream( + "pipeline/gitlabMergeRequestStatus-pipeline.groovy")); + project.setDefinition(new CpsFlowDefinition(pipelineText, false)); + Run build = j.buildAndAssertSuccess(project); + j.assertLogContains("MR1 target = master", build); + j.assertLogContains("No MR for feature 2", build); + } +} diff --git a/src/test/resources/com/dabsquared/gitlabjenkins/workflow/pipeline/gitlabMergeRequestStatus-pipeline.groovy b/src/test/resources/com/dabsquared/gitlabjenkins/workflow/pipeline/gitlabMergeRequestStatus-pipeline.groovy new file mode 100644 index 000000000..27a81a4d0 --- /dev/null +++ b/src/test/resources/com/dabsquared/gitlabjenkins/workflow/pipeline/gitlabMergeRequestStatus-pipeline.groovy @@ -0,0 +1,8 @@ +package com.dabsquared.gitlabjenkins.workflow.pipeline + +def mr1 = gitlabMergeRequestStatus('project', 'feature1') +echo "MR1 target = ${mr1.targetBranch}" + +def mr2 = gitlabMergeRequestStatus('project', 'feature2') +if (mr2.size() == 0) + echo 'No MR for feature 2' From b429f423785cb680e0036fefee5cd026b57900e9 Mon Sep 17 00:00:00 2001 From: Derrick Gibelyou Date: Thu, 20 Jun 2019 10:00:29 -0600 Subject: [PATCH 3/3] Add mock mr response json --- .../workflow/pipeline/mr-closed.json | 56 +++++++++++++++++ .../workflow/pipeline/mr-open.json | 63 +++++++++++++++++++ 2 files changed, 119 insertions(+) create mode 100644 src/test/resources/com/dabsquared/gitlabjenkins/workflow/pipeline/mr-closed.json create mode 100644 src/test/resources/com/dabsquared/gitlabjenkins/workflow/pipeline/mr-open.json diff --git a/src/test/resources/com/dabsquared/gitlabjenkins/workflow/pipeline/mr-closed.json b/src/test/resources/com/dabsquared/gitlabjenkins/workflow/pipeline/mr-closed.json new file mode 100644 index 000000000..6b10c3b34 --- /dev/null +++ b/src/test/resources/com/dabsquared/gitlabjenkins/workflow/pipeline/mr-closed.json @@ -0,0 +1,56 @@ +[ + { + "id": 10, + "iid": 10, + "project_id": 10, + "title": "MR Feature 2", + "description": "This is an MR for feature 2", + "state": "merged", + "created_at": "2019-06-17T22:54:32.858Z", + "updated_at": "2019-06-20T15:27:10.756Z", + "merged_by": { + "id": 15, + "name": "John Doe", + "username": "jdoe", + "state": "active" + }, + "merged_at": "2019-06-20T15:27:10.828Z", + "closed_by": null, + "closed_at": null, + "target_branch": "master", + "source_branch": "feature2", + "user_notes_count": 2, + "upvotes": 0, + "downvotes": 0, + "assignee": null, + "author": { + "id": 11, + "name": "Jane Doe", + "username": "jdoe", + "state": "active" + }, + "assignees": [], + "source_project_id": 10, + "target_project_id": 10, + "labels": [], + "work_in_progress": false, + "milestone": null, + "merge_when_pipeline_succeeds": false, + "merge_status": "can_be_merged", + "sha": "cf00b438ffa638410dc64b85dac72d49b72e6474", + "merge_commit_sha": "51b9249082908db50efde6cd0219e264bff3ac79", + "discussion_locked": null, + "should_remove_source_branch": null, + "force_remove_source_branch": true, + "reference": "!46", + "web_url": "https://gitlab/project/merge_requests/2", + "time_stats": { + "time_estimate": 0, + "total_time_spent": 0, + "human_time_estimate": null, + "human_total_time_spent": null + }, + "squash": false, + "approvals_before_merge": null + } +] diff --git a/src/test/resources/com/dabsquared/gitlabjenkins/workflow/pipeline/mr-open.json b/src/test/resources/com/dabsquared/gitlabjenkins/workflow/pipeline/mr-open.json new file mode 100644 index 000000000..0eed0fafe --- /dev/null +++ b/src/test/resources/com/dabsquared/gitlabjenkins/workflow/pipeline/mr-open.json @@ -0,0 +1,63 @@ +[ + { + "id": 11, + "iid": 35, + "project_id": 10, + "title": "MR Feature 1", + "description": "Mr for Feature 1", + "state": "opened", + "created_at": "2019-06-11T18:20:14.331Z", + "updated_at": "2019-06-11T18:22:03.181Z", + "merged_by": null, + "merged_at": null, + "closed_by": null, + "closed_at": null, + "target_branch": "master", + "source_branch": "feature1", + "user_notes_count": 2, + "upvotes": 0, + "downvotes": 0, + "assignee": { + "id": 11, + "name": "Jane Doe", + "username": "jdoe", + "state": "active" + }, + "author": { + "id": 15, + "name": "John Doe", + "username": "jdoe", + "state": "active" + }, + "assignees": [ + { + "id": 11, + "name": "Jane Doe", + "username": "jdoe", + "state": "active" + } + ], + "source_project_id": 65, + "target_project_id": 65, + "labels": [], + "work_in_progress": false, + "milestone": null, + "merge_when_pipeline_succeeds": false, + "merge_status": "can_be_merged", + "sha": "6d3e8611f0a452d7c9d343c6fd734fd47fdfabca", + "merge_commit_sha": null, + "discussion_locked": null, + "should_remove_source_branch": null, + "force_remove_source_branch": true, + "reference": "!35", + "web_url": "https://gitlabee/project/merge_requests/1", + "time_stats": { + "time_estimate": 0, + "total_time_spent": 0, + "human_time_estimate": null, + "human_total_time_spent": null + }, + "squash": false, + "approvals_before_merge": null + } +]