From 887583fc43b1ef91fdc8eda1f8710d6db289c66c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robin=20M=C3=BCller?= Date: Fri, 12 Feb 2016 21:53:11 +0100 Subject: [PATCH] Move commit status handling to a Notifier extension --- .../gitlabjenkins/GitLabMergeCause.java | 39 ----- .../gitlabjenkins/GitLabMergeRequest.java | 15 -- .../gitlabjenkins/GitLabPushCause.java | 48 ------- .../gitlabjenkins/GitLabPushRequest.java | 13 -- .../gitlabjenkins/GitLabPushTrigger.java | 124 +--------------- .../gitlabjenkins/GitLabRequest.java | 5 - .../gitlabjenkins/GitLabRunListener.java | 51 ------- .../gitlabjenkins/cause/GitLabMergeCause.java | 50 +++++++ .../gitlabjenkins/cause/GitLabPushCause.java | 60 ++++++++ .../cause/GitLabWebHookCause.java | 29 ++++ .../GitLabBuildDescriptionRunListener.java | 37 +++++ .../GitLabMergeRequestRunListener.java | 88 ++++++++++++ .../GitLabCommitStatusPublisher.java | 133 ++++++++++++++++++ .../GitLabPushTrigger/config.jelly | 5 - .../publisher/Messages.properties | 1 + ...ractGitLabPushTriggerGitlabServerTest.java | 3 +- 16 files changed, 404 insertions(+), 297 deletions(-) delete mode 100644 src/main/java/com/dabsquared/gitlabjenkins/GitLabMergeCause.java delete mode 100644 src/main/java/com/dabsquared/gitlabjenkins/GitLabPushCause.java delete mode 100644 src/main/java/com/dabsquared/gitlabjenkins/GitLabRunListener.java create mode 100644 src/main/java/com/dabsquared/gitlabjenkins/cause/GitLabMergeCause.java create mode 100644 src/main/java/com/dabsquared/gitlabjenkins/cause/GitLabPushCause.java create mode 100644 src/main/java/com/dabsquared/gitlabjenkins/cause/GitLabWebHookCause.java create mode 100644 src/main/java/com/dabsquared/gitlabjenkins/listener/GitLabBuildDescriptionRunListener.java create mode 100644 src/main/java/com/dabsquared/gitlabjenkins/listener/GitLabMergeRequestRunListener.java create mode 100644 src/main/java/com/dabsquared/gitlabjenkins/publisher/GitLabCommitStatusPublisher.java create mode 100644 src/main/resources/com/dabsquared/gitlabjenkins/publisher/Messages.properties diff --git a/src/main/java/com/dabsquared/gitlabjenkins/GitLabMergeCause.java b/src/main/java/com/dabsquared/gitlabjenkins/GitLabMergeCause.java deleted file mode 100644 index 7cb86bd..0000000 --- a/src/main/java/com/dabsquared/gitlabjenkins/GitLabMergeCause.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.dabsquared.gitlabjenkins; - -import hudson.triggers.SCMTrigger; - -import java.io.File; -import java.io.IOException; - -/** - * Created by daniel on 6/8/14. - */ -public class GitLabMergeCause extends SCMTrigger.SCMTriggerCause { - - private GitLabMergeRequest mergeRequest; - - public GitLabMergeCause(GitLabMergeRequest mergeRequest) { - this.mergeRequest = mergeRequest; - } - - public GitLabMergeCause(GitLabMergeRequest mergeRequest, File logFile) throws IOException { - super(logFile); - this.mergeRequest = mergeRequest; - } - - public GitLabMergeCause(GitLabMergeRequest mergeRequest, String pollingLog) { - super(pollingLog); - this.mergeRequest = mergeRequest; - } - - public GitLabMergeRequest getMergeRequest() { - return mergeRequest; - } - - @Override - public String getShortDescription() { - return "GitLab Merge Request #" + this.mergeRequest.getObjectAttribute().getIid() + " : " + this.mergeRequest.getObjectAttribute().getSourceBranch() + - " => " + this.mergeRequest.getObjectAttribute().getTargetBranch(); - } - -} diff --git a/src/main/java/com/dabsquared/gitlabjenkins/GitLabMergeRequest.java b/src/main/java/com/dabsquared/gitlabjenkins/GitLabMergeRequest.java index 000d570..2d96cbf 100644 --- a/src/main/java/com/dabsquared/gitlabjenkins/GitLabMergeRequest.java +++ b/src/main/java/com/dabsquared/gitlabjenkins/GitLabMergeRequest.java @@ -3,8 +3,6 @@ package com.dabsquared.gitlabjenkins; import com.dabsquared.gitlabjenkins.data.ObjectAttributes; import org.apache.commons.lang.builder.ToStringBuilder; import org.apache.commons.lang.builder.ToStringStyle; -import org.gitlab.api.GitlabAPI; -import org.gitlab.api.models.GitlabCommitStatus; import org.gitlab.api.models.GitlabProject; import org.gitlab.api.models.GitlabUser; @@ -62,17 +60,4 @@ public class GitLabMergeRequest extends GitLabRequest { public String toString() { return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE); } - - public GitlabCommitStatus createCommitStatus(GitlabAPI api, String status, String targetUrl) { - try { - if (objectAttributes.getLastCommit() != null) { - return api.createCommitStatus(sourceProject, objectAttributes.getLastCommit().getId(), status, objectAttributes.getLastCommit().getId(), "Jenkins", targetUrl, null); - } - } catch (IOException e) { - e.printStackTrace(); - } - - return null; - } - } diff --git a/src/main/java/com/dabsquared/gitlabjenkins/GitLabPushCause.java b/src/main/java/com/dabsquared/gitlabjenkins/GitLabPushCause.java deleted file mode 100644 index ddd310d..0000000 --- a/src/main/java/com/dabsquared/gitlabjenkins/GitLabPushCause.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.dabsquared.gitlabjenkins; - -import hudson.triggers.SCMTrigger; - -import java.io.File; -import java.io.IOException; - -/** - * Created by daniel on 6/8/14. - */ -public class GitLabPushCause extends SCMTrigger.SCMTriggerCause { - - private final GitLabPushRequest pushRequest; - - public GitLabPushCause(GitLabPushRequest pushRequest) { - this.pushRequest=pushRequest; - } - - public GitLabPushCause(GitLabPushRequest pushRequest, File logFile) throws IOException{ - super(logFile); - this.pushRequest=pushRequest; - } - - public GitLabPushCause(GitLabPushRequest pushRequest, String pollingLog) { - super(pollingLog); - this.pushRequest=pushRequest; - } - - public GitLabPushRequest getPushRequest() { - return pushRequest; - } - - @Override - public String getShortDescription() { - String pushedBy; - if (pushRequest.getCommits().size() > 0){ - pushedBy = pushRequest.getCommits().get(0).getAuthor().getName(); - } else { - pushedBy = pushRequest.getUser_name(); - } - - if (pushedBy == null) { - return "Started by GitLab push"; - } else { - return String.format("Started by GitLab push by %s", pushedBy); - } - } -} diff --git a/src/main/java/com/dabsquared/gitlabjenkins/GitLabPushRequest.java b/src/main/java/com/dabsquared/gitlabjenkins/GitLabPushRequest.java index c9f95cb..ead0e21 100644 --- a/src/main/java/com/dabsquared/gitlabjenkins/GitLabPushRequest.java +++ b/src/main/java/com/dabsquared/gitlabjenkins/GitLabPushRequest.java @@ -4,8 +4,6 @@ import com.dabsquared.gitlabjenkins.data.Commit; import com.dabsquared.gitlabjenkins.data.Repository; import org.apache.commons.lang.builder.ToStringBuilder; import org.apache.commons.lang.builder.ToStringStyle; -import org.gitlab.api.GitlabAPI; -import org.gitlab.api.models.GitlabCommitStatus; import org.gitlab.api.models.GitlabProject; import java.io.IOException; @@ -38,17 +36,6 @@ public class GitLabPushRequest extends GitLabRequest { return sourceProject; } - public GitlabCommitStatus createCommitStatus(GitlabAPI api, String status, String targetUrl) { - try { - if(getLastCommit()!=null) { - return api.createCommitStatus(sourceProject, checkout_sha, status, checkout_sha, "Jenkins", targetUrl, null); - } - } catch (IOException e) { - e.printStackTrace(); - } - return null; - } - private String before; private String after; private String checkout_sha; diff --git a/src/main/java/com/dabsquared/gitlabjenkins/GitLabPushTrigger.java b/src/main/java/com/dabsquared/gitlabjenkins/GitLabPushTrigger.java index 7c6ed42..04f76c3 100644 --- a/src/main/java/com/dabsquared/gitlabjenkins/GitLabPushTrigger.java +++ b/src/main/java/com/dabsquared/gitlabjenkins/GitLabPushTrigger.java @@ -1,12 +1,13 @@ package com.dabsquared.gitlabjenkins; +import com.dabsquared.gitlabjenkins.cause.GitLabMergeCause; +import com.dabsquared.gitlabjenkins.cause.GitLabPushCause; import hudson.Extension; import hudson.Util; import hudson.model.Action; import hudson.model.AutoCompletionCandidates; import hudson.model.Item; import hudson.model.ParameterValue; -import hudson.model.Result; import hudson.model.AbstractProject; import hudson.model.Cause; import hudson.model.CauseAction; @@ -84,7 +85,6 @@ public class GitLabPushTrigger extends Trigger> { private boolean ciSkip = true; private boolean setBuildDescription = true; private boolean addNoteOnMergeRequest = true; - private boolean addCiMessage = false; private boolean addVoteOnMergeRequest = true; private transient boolean allowAllBranches = false; private final String branchFilterName; @@ -93,9 +93,10 @@ public class GitLabPushTrigger extends Trigger> { private final String targetBranchRegex; private boolean acceptMergeRequestOnSuccess = false; + @DataBoundConstructor public GitLabPushTrigger(boolean triggerOnPush, boolean triggerOnMergeRequest, String triggerOpenMergeRequestOnPush, - boolean ciSkip, boolean setBuildDescription, boolean addNoteOnMergeRequest, boolean addCiMessage, + boolean ciSkip, boolean setBuildDescription, boolean addNoteOnMergeRequest, boolean addVoteOnMergeRequest, boolean acceptMergeRequestOnSuccess, String branchFilterName, String includeBranchesSpec, String excludeBranchesSpec, String targetBranchRegex) { this.triggerOnPush = triggerOnPush; @@ -104,7 +105,6 @@ public class GitLabPushTrigger extends Trigger> { this.ciSkip = ciSkip; this.setBuildDescription = setBuildDescription; this.addNoteOnMergeRequest = addNoteOnMergeRequest; - this.addCiMessage = addCiMessage; this.addVoteOnMergeRequest = addVoteOnMergeRequest; this.branchFilterName = branchFilterName; this.includeBranchesSpec = includeBranchesSpec; @@ -141,10 +141,6 @@ public class GitLabPushTrigger extends Trigger> { return acceptMergeRequestOnSuccess; } - public boolean getAddCiMessage() { - return addCiMessage; - } - public boolean getCiSkip() { return ciSkip; } @@ -246,10 +242,6 @@ public class GitLabPushTrigger extends Trigger> { } } - if(addCiMessage) { - req.createCommitStatus(getDescriptor().getGitlab().instance(), "pending", Jenkins.getInstance().getRootUrl() + job.getUrl()); - } - scheduledJob.scheduleBuild2(projectbuildDelay, actions); } } @@ -369,7 +361,7 @@ public class GitLabPushTrigger extends Trigger> { Action action = createAction(req, job); int projectbuildDelay = 0; - + if (job instanceof ParameterizedJobMixIn.ParameterizedJob) { ParameterizedJobMixIn.ParameterizedJob abstractProject = (ParameterizedJobMixIn.ParameterizedJob)job; if (abstractProject.getQuietPeriod() > projectbuildDelay) { @@ -377,10 +369,6 @@ public class GitLabPushTrigger extends Trigger> { } } - if(addCiMessage) { - req.createCommitStatus(getDescriptor().getGitlab().instance(), "pending", Jenkins.getInstance().getRootUrl() + job.getUrl()); - } - scheduledJob.scheduleBuild2(projectbuildDelay, action, new CauseAction(cause)); } else { LOGGER.log(Level.INFO, "trigger on merge request not set"); @@ -465,108 +453,6 @@ public class GitLabPushTrigger extends Trigger> { } } - public void onCompleted(Run run){ - Cause mCause= run.getCause(GitLabMergeCause.class); - if (mCause != null && mCause instanceof GitLabMergeCause) { - onCompleteMergeRequest(run, (GitLabMergeCause) mCause); - } - - Cause pCause= run.getCause(GitLabPushCause.class); - if (pCause != null && pCause instanceof GitLabPushCause) { - onCompletedPushRequest(run, (GitLabPushCause) pCause); - } - - } - - private void onCompletedPushRequest(Run run, GitLabPushCause cause) { - if(addCiMessage) { - String status; - if (run.getResult() == Result.ABORTED) { - status = "canceled"; - }else if (run.getResult() == Result.SUCCESS) { - status = "success"; - }else { - status = "failed"; - } - cause.getPushRequest().createCommitStatus(this.getDescriptor().getGitlab().instance(), status, Jenkins.getInstance().getRootUrl() + run.getUrl()); - } - } - - private void onCompleteMergeRequest(Run run,GitLabMergeCause cause){ - if (acceptMergeRequestOnSuccess && run.getResult() == Result.SUCCESS) { - try { - GitlabProject proj = new GitlabProject(); - proj.setId(cause.getMergeRequest().getObjectAttribute().getTargetProjectId()); - this.getDescriptor().getGitlab().instance().acceptMergeRequest( - proj, - cause.getMergeRequest().getObjectAttribute().getId(), - "Merge Request accepted by jenkins build success"); - } catch (IOException e) { - e.printStackTrace(); - } - } - if(addNoteOnMergeRequest) { - StringBuilder msg = new StringBuilder(); - if (run.getResult() == Result.SUCCESS) { - String icon = addVoteOnMergeRequest ? ":+1:" : ":white_check_mark:"; - msg.append(icon); - } else { - String icon = addVoteOnMergeRequest ? ":-1:" : ":anguished:"; - msg.append(icon); - } - msg.append(" Jenkins Build ").append(run.getResult().color.getDescription()); - String buildUrl = Jenkins.getInstance().getRootUrl() + run.getUrl(); - msg.append("\n\nResults available at: ") - .append("[").append("Jenkins " + buildUrl).append("](").append(buildUrl).append(")"); - try { - GitlabProject proj = new GitlabProject(); - proj.setId(cause.getMergeRequest().getObjectAttribute().getTargetProjectId()); - org.gitlab.api.models.GitlabMergeRequest mr = this.getDescriptor().getGitlab().instance().getMergeRequest(proj,cause.getMergeRequest().getObjectAttribute().getId()); - this.getDescriptor().getGitlab().instance().createNote(mr,msg.toString()); - } catch (IOException e) { - e.printStackTrace(); - } - } - - if(addCiMessage) { - String status; - if (run.getResult() == Result.ABORTED) { - status = "canceled"; - }else if (run.getResult() == Result.SUCCESS) { - status = "success"; - }else { - status = "failed"; - } - cause.getMergeRequest().createCommitStatus(this.getDescriptor().getGitlab().instance(), status, Jenkins.getInstance().getRootUrl() + run.getUrl()); - } - } - - public void onStarted(Run run) { - setBuildCauseInJob(run); - - Cause mCause= run.getCause(GitLabMergeCause.class); - if (mCause != null && mCause instanceof GitLabMergeCause) { - onStartedMergeRequest(run, (GitLabMergeCause) mCause); - } - - Cause pCause= run.getCause(GitLabPushCause.class); - if (pCause != null && pCause instanceof GitLabPushCause) { - onStartedPushRequest(run, (GitLabPushCause) pCause); - } - } - - private void onStartedPushRequest(Run run, GitLabPushCause cause) { - if(addCiMessage) { - cause.getPushRequest().createCommitStatus(this.getDescriptor().getGitlab().instance(), "running", Jenkins.getInstance().getRootUrl() + run.getUrl()); - } - } - - private void onStartedMergeRequest(Run run, GitLabMergeCause cause) { - if(addCiMessage) { - cause.getMergeRequest().createCommitStatus(this.getDescriptor().getGitlab().instance(), "running", Jenkins.getInstance().getRootUrl() + run.getUrl()); - } - } - private String getSourceBranch(GitLabRequest req) { String result = null; if (req instanceof GitLabPushRequest) { diff --git a/src/main/java/com/dabsquared/gitlabjenkins/GitLabRequest.java b/src/main/java/com/dabsquared/gitlabjenkins/GitLabRequest.java index 8621f33..74d99b6 100644 --- a/src/main/java/com/dabsquared/gitlabjenkins/GitLabRequest.java +++ b/src/main/java/com/dabsquared/gitlabjenkins/GitLabRequest.java @@ -14,8 +14,6 @@ import com.google.gson.JsonDeserializationContext; import com.google.gson.JsonDeserializer; import com.google.gson.JsonElement; import com.google.gson.JsonParseException; -import org.gitlab.api.GitlabAPI; -import org.gitlab.api.models.GitlabCommitStatus; public abstract class GitLabRequest { protected enum Builder { @@ -52,7 +50,4 @@ public abstract class GitLabRequest { + Arrays.toString(DATE_FORMATS)); } } - - public abstract GitlabCommitStatus createCommitStatus(GitlabAPI api, String status, String targetUrl); - } diff --git a/src/main/java/com/dabsquared/gitlabjenkins/GitLabRunListener.java b/src/main/java/com/dabsquared/gitlabjenkins/GitLabRunListener.java deleted file mode 100644 index 3c7ac8b..0000000 --- a/src/main/java/com/dabsquared/gitlabjenkins/GitLabRunListener.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.dabsquared.gitlabjenkins; - -import hudson.Extension; -import hudson.model.Run; -import hudson.model.AbstractBuild; -import hudson.model.TaskListener; -import hudson.model.listeners.RunListener; -import hudson.triggers.Trigger; -import jenkins.model.ParameterizedJobMixIn; - -import javax.annotation.Nonnull; - -/** - * RunListener that will be called when a build starts and completes. - * Will lookup GitLabPushTrigger and call onStarted and onCompleted methods - * in order to have access to the build and set properties. - */ -@Extension -public class GitLabRunListener extends RunListener { - - @Override - public void onCompleted(Run run, @Nonnull TaskListener listener) { - GitLabPushTrigger trig = getTrigger(run); - if (trig != null) { - trig.onCompleted(run); - } - super.onCompleted(run, listener); - } - - @Override - public void onStarted(Run run, TaskListener listener) { - GitLabPushTrigger trig = getTrigger(run); - if (trig != null) { - trig.onStarted(run); - } - super.onStarted(run, listener); - } - - - private GitLabPushTrigger getTrigger(Run run) { - if (run instanceof AbstractBuild) { - ParameterizedJobMixIn.ParameterizedJob p = ((AbstractBuild) run).getProject(); - for (Trigger t : p.getTriggers().values()) { - if (t instanceof GitLabPushTrigger) - return (GitLabPushTrigger) t; - } - } - - return null; - } -} diff --git a/src/main/java/com/dabsquared/gitlabjenkins/cause/GitLabMergeCause.java b/src/main/java/com/dabsquared/gitlabjenkins/cause/GitLabMergeCause.java new file mode 100644 index 0000000..c2967b9 --- /dev/null +++ b/src/main/java/com/dabsquared/gitlabjenkins/cause/GitLabMergeCause.java @@ -0,0 +1,50 @@ +package com.dabsquared.gitlabjenkins.cause; + +import com.dabsquared.gitlabjenkins.GitLabMergeRequest; +import com.dabsquared.gitlabjenkins.data.ObjectAttributes; +import hudson.init.InitMilestone; +import hudson.init.Initializer; +import hudson.model.Run; + +import java.io.File; +import java.io.IOException; + +/** + * Created by daniel on 6/8/14. + */ +public class GitLabMergeCause extends GitLabWebHookCause { + + private transient GitLabMergeRequest mergeRequest; + + public GitLabMergeCause(GitLabMergeRequest mergeRequest) { + this(mergeRequest, ""); + } + + public GitLabMergeCause(GitLabMergeRequest mergeRequest, File logFile) throws IOException { + super(mergeRequest, logFile); + } + + public GitLabMergeCause(GitLabMergeRequest mergeRequest, String pollingLog) { + super(mergeRequest, pollingLog); + } + + @Override + public String getShortDescription() { + ObjectAttributes objectAttribute = getRequest().getObjectAttribute(); + return "GitLab Merge Request #" + objectAttribute.getIid() + " : " + objectAttribute.getSourceBranch() + + " => " + objectAttribute.getTargetBranch(); + } + + @Initializer(before = InitMilestone.PLUGINS_STARTED) + public static void addAliases() { + Run.XSTREAM2.addCompatibilityAlias("com.dabsquared.gitlabjenkins.GitLabMergeCause", GitLabMergeCause.class); + } + + protected Object readResolve() { + if (getRequest() == null) { + return new GitLabMergeCause(mergeRequest); + } else { + return this; + } + } +} diff --git a/src/main/java/com/dabsquared/gitlabjenkins/cause/GitLabPushCause.java b/src/main/java/com/dabsquared/gitlabjenkins/cause/GitLabPushCause.java new file mode 100644 index 0000000..62498f9 --- /dev/null +++ b/src/main/java/com/dabsquared/gitlabjenkins/cause/GitLabPushCause.java @@ -0,0 +1,60 @@ +package com.dabsquared.gitlabjenkins.cause; + +import com.dabsquared.gitlabjenkins.GitLabPushRequest; +import hudson.init.InitMilestone; +import hudson.init.Initializer; +import hudson.model.Run; + +import java.io.File; +import java.io.IOException; + +/** + * Created by daniel on 6/8/14. + */ +public class GitLabPushCause extends GitLabWebHookCause { + + private transient GitLabPushRequest pushRequest; + + public GitLabPushCause(GitLabPushRequest pushRequest) { + this(pushRequest, ""); + } + + public GitLabPushCause(GitLabPushRequest pushRequest, File logFile) throws IOException { + super(pushRequest, logFile); + } + + public GitLabPushCause(GitLabPushRequest pushRequest, String pollingLog) { + super(pushRequest, pollingLog); + } + + @Override + public String getShortDescription() { + String pushedBy = retrievePushedBy(); + if (pushedBy == null) { + return "Started by GitLab push"; + } else { + return String.format("Started by GitLab push by %s", pushedBy); + } + } + + private String retrievePushedBy() { + if (getRequest().getCommits().size() > 0) { + return getRequest().getCommits().get(0).getAuthor().getName(); + } else { + return getRequest().getUser_name(); + } + } + + @Initializer(before = InitMilestone.PLUGINS_STARTED) + public static void addAliases() { + Run.XSTREAM2.addCompatibilityAlias("com.dabsquared.gitlabjenkins.GitLabPushCause", GitLabPushCause.class); + } + + protected Object readResolve() { + if (getRequest() == null) { + return new GitLabPushCause(pushRequest); + } else { + return this; + } + } +} diff --git a/src/main/java/com/dabsquared/gitlabjenkins/cause/GitLabWebHookCause.java b/src/main/java/com/dabsquared/gitlabjenkins/cause/GitLabWebHookCause.java new file mode 100644 index 0000000..075ff5b --- /dev/null +++ b/src/main/java/com/dabsquared/gitlabjenkins/cause/GitLabWebHookCause.java @@ -0,0 +1,29 @@ +package com.dabsquared.gitlabjenkins.cause; + +import com.dabsquared.gitlabjenkins.GitLabRequest; +import hudson.triggers.SCMTrigger; + +import java.io.File; +import java.io.IOException; + +/** + * @author Robin Müller + */ +public class GitLabWebHookCause extends SCMTrigger.SCMTriggerCause { + + private final T request; + + public GitLabWebHookCause(T request, String pollingLog) { + super(pollingLog); + this.request = request; + } + + public GitLabWebHookCause(T request, File logFile) throws IOException { + super(logFile); + this.request = request; + } + + public T getRequest() { + return request; + } +} diff --git a/src/main/java/com/dabsquared/gitlabjenkins/listener/GitLabBuildDescriptionRunListener.java b/src/main/java/com/dabsquared/gitlabjenkins/listener/GitLabBuildDescriptionRunListener.java new file mode 100644 index 0000000..0107476 --- /dev/null +++ b/src/main/java/com/dabsquared/gitlabjenkins/listener/GitLabBuildDescriptionRunListener.java @@ -0,0 +1,37 @@ +package com.dabsquared.gitlabjenkins.listener; + +import com.dabsquared.gitlabjenkins.GitLabPushTrigger; +import com.dabsquared.gitlabjenkins.cause.GitLabWebHookCause; +import hudson.Extension; +import hudson.model.AbstractBuild; +import hudson.model.Cause; +import hudson.model.TaskListener; +import hudson.model.listeners.RunListener; + +import java.io.IOException; + +/** + * RunListener that will be called when a build starts and completes. + * Will lookup GitLabPushTrigger and call set the build description if necessary. + * + * @author Robin Müller + */ +@Extension +public class GitLabBuildDescriptionRunListener extends RunListener> { + + @Override + public void onStarted(AbstractBuild build, TaskListener listener) { + GitLabPushTrigger trigger = build.getProject().getTrigger(GitLabPushTrigger.class); + if (trigger != null && trigger.getSetBuildDescription()) { + Cause cause = build.getCause(GitLabWebHookCause.class); + if (cause != null && !cause.getShortDescription().isEmpty()) { + try { + build.setDescription(cause.getShortDescription()); + } catch (IOException e) { + listener.getLogger().println("Failed to set build description"); + } + } + } + } + +} diff --git a/src/main/java/com/dabsquared/gitlabjenkins/listener/GitLabMergeRequestRunListener.java b/src/main/java/com/dabsquared/gitlabjenkins/listener/GitLabMergeRequestRunListener.java new file mode 100644 index 0000000..23e5c53 --- /dev/null +++ b/src/main/java/com/dabsquared/gitlabjenkins/listener/GitLabMergeRequestRunListener.java @@ -0,0 +1,88 @@ +package com.dabsquared.gitlabjenkins.listener; + +import com.dabsquared.gitlabjenkins.GitLabPushTrigger; +import com.dabsquared.gitlabjenkins.cause.GitLabMergeCause; +import hudson.Extension; +import hudson.model.AbstractBuild; +import hudson.model.Result; +import hudson.model.TaskListener; +import hudson.model.listeners.RunListener; +import jenkins.model.Jenkins; +import org.gitlab.api.GitlabAPI; +import org.gitlab.api.models.GitlabMergeRequest; +import org.gitlab.api.models.GitlabProject; + +import javax.annotation.Nonnull; +import java.io.IOException; +import java.text.MessageFormat; + +/** + * @author Robin Müller + */ +@Extension +public class GitLabMergeRequestRunListener extends RunListener> { + + @Override + public void onCompleted(AbstractBuild build, @Nonnull TaskListener listener) { + GitLabPushTrigger trigger = build.getProject().getTrigger(GitLabPushTrigger.class); + GitLabMergeCause gitLabMergeCause = build.getCause(GitLabMergeCause.class); + + if (trigger != null && gitLabMergeCause != null) { + String buildUrl = getBuildUrl(build); + Result buildResult = build.getResult(); + Integer projectId = gitLabMergeCause.getRequest().getObjectAttribute().getSourceProjectId(); + Integer mergeRequestId = gitLabMergeCause.getRequest().getObjectAttribute().getId(); + if (buildResult == Result.SUCCESS) { + acceptMergeRequestIfNecessary(trigger, listener, projectId, mergeRequestId); + } + addNoteOnMergeRequestIfNecessary(trigger, listener, projectId, mergeRequestId, build.getProject().getDisplayName(), build.getNumber(), + buildUrl, getResultIcon(trigger, Result.SUCCESS), buildResult.color.getDescription()); + } + } + + private String getBuildUrl(AbstractBuild build) { + return Jenkins.getInstance().getRootUrl() + build.getUrl(); + } + + private void acceptMergeRequestIfNecessary(GitLabPushTrigger trigger, TaskListener listener, Integer projectId, Integer mergeRequestId) { + if (trigger.getAcceptMergeRequestOnSuccess()) { + try { + GitlabProject project = new GitlabProject(); + project.setId(projectId); + getClient().acceptMergeRequest(project, mergeRequestId, "Merge Request accepted by jenkins build success"); + } catch (Throwable e) { + listener.getLogger().println("Failed to accept merge request."); + } + } + } + + private void addNoteOnMergeRequestIfNecessary(GitLabPushTrigger trigger, TaskListener listener, Integer projectId, Integer mergeRequestId, + String projectName, int buildNumber, String buildUrl, String resultIcon, String statusDescription) { + if (trigger.getAddNoteOnMergeRequest()) { + String message = MessageFormat.format("{0} Jenkins Build {1}\n\nResults available at: [Jenkins [{2} #{3}]]({4})", resultIcon, + statusDescription, projectName, buildNumber, buildUrl); + try { + GitlabMergeRequest mergeRequest = new GitlabMergeRequest(); + mergeRequest.setProjectId(projectId); + mergeRequest.setId(mergeRequestId); + getClient().createNote(mergeRequest, message); + } catch (IOException e) { + listener.getLogger().println("Failed to accept merge request."); + } + } + } + + private String getResultIcon(GitLabPushTrigger trigger, Result result) { + if (result == Result.SUCCESS) { + return trigger.getAddVoteOnMergeRequest() ? ":+1:" : ":white_check_mark:"; + } else { + return trigger.getAddVoteOnMergeRequest() ? ":-1:" : ":anguished:"; + } + } + + private GitlabAPI getClient() { + GitLabPushTrigger.DescriptorImpl descriptor = (GitLabPushTrigger.DescriptorImpl) Jenkins.getInstance().getDescriptor(GitLabPushTrigger.class); + return descriptor.getGitlab().instance(); + } + +} diff --git a/src/main/java/com/dabsquared/gitlabjenkins/publisher/GitLabCommitStatusPublisher.java b/src/main/java/com/dabsquared/gitlabjenkins/publisher/GitLabCommitStatusPublisher.java new file mode 100644 index 0000000..648472b --- /dev/null +++ b/src/main/java/com/dabsquared/gitlabjenkins/publisher/GitLabCommitStatusPublisher.java @@ -0,0 +1,133 @@ +package com.dabsquared.gitlabjenkins.publisher; + +import com.dabsquared.gitlabjenkins.GitLabPushTrigger; +import hudson.Extension; +import hudson.Launcher; +import hudson.model.AbstractBuild; +import hudson.model.AbstractProject; +import hudson.model.BuildListener; +import hudson.model.Result; +import hudson.model.TaskListener; +import hudson.plugins.git.util.BuildData; +import hudson.tasks.BuildStepDescriptor; +import hudson.tasks.BuildStepMonitor; +import hudson.tasks.Notifier; +import hudson.tasks.Publisher; +import jenkins.model.Jenkins; +import org.eclipse.jgit.transport.URIish; +import org.gitlab.api.GitlabAPI; +import org.gitlab.api.models.GitlabProject; +import org.kohsuke.stapler.DataBoundConstructor; + +import java.io.IOException; +import java.net.URISyntaxException; +import java.util.Set; + +/** + * @author Robin Müller + */ +public class GitLabCommitStatusPublisher extends Notifier { + + @DataBoundConstructor + public GitLabCommitStatusPublisher() { } + + public BuildStepMonitor getRequiredMonitorService() { + return BuildStepMonitor.BUILD; + } + + @Override + public boolean prebuild(AbstractBuild build, BuildListener listener) { + GitlabProject buildProject = retrieveGitlabProject(getClient(), build, listener); + if (buildProject != null) { + String commitHash = getBuildRevision(build); + updateCommitStatus(listener, buildProject, commitHash, "running", getBuildUrl(build)); + } + return true; + } + + @Override + public boolean perform(AbstractBuild build, Launcher launcher, BuildListener listener) throws InterruptedException, IOException { + GitlabProject buildProject = retrieveGitlabProject(getClient(), build, listener); + if (buildProject != null) { + String commitHash = getBuildRevision(build); + String buildUrl = getBuildUrl(build); + Result buildResult = build.getResult(); + if (buildResult == Result.SUCCESS) { + updateCommitStatus(listener, buildProject, commitHash, "success", buildUrl); + } else if (buildResult == Result.ABORTED) { + updateCommitStatus(listener, buildProject, commitHash, "canceled", buildUrl); + } else { + updateCommitStatus(listener, buildProject, commitHash, "failed", buildUrl); + } + } + return true; + } + + private String getBuildRevision(AbstractBuild build) { + return build.getAction(BuildData.class).getLastBuiltRevision().getSha1String(); + } + + private void updateCommitStatus(BuildListener listener, GitlabProject buildProject, String commitHash, String state, String buildUrl) { + try { + getClient().createCommitStatus(buildProject, commitHash, state, commitHash, "jenkins", buildUrl, null); + } catch (IOException e) { + listener.getLogger().println("Failed to update Gitlab commit status"); + } + } + + private String getBuildUrl(AbstractBuild build) { + return Jenkins.getInstance().getRootUrl() + build.getUrl(); + } + + private GitlabAPI getClient() { + GitLabPushTrigger.DescriptorImpl descriptor = (GitLabPushTrigger.DescriptorImpl) Jenkins.getInstance().getDescriptor(GitLabPushTrigger.class); + return descriptor.getGitlab().instance(); + } + + private GitlabProject retrieveGitlabProject(GitlabAPI client, AbstractBuild build, TaskListener listener) { + Set remoteUrls = build.getAction(BuildData.class).getRemoteUrls(); + for (String remoteUrl : remoteUrls) { + try { + try { + return client.getProject(retrieveProjectId(remoteUrl)); + } catch (Throwable e) { + listener.getLogger().printf("Failed to retrieve GitLab project for projectId: %s", retrieveProjectId(remoteUrl)); + } + } catch (URISyntaxException e) { + // nothing to do + } + } + + return null; + } + + private String retrieveProjectId(String remoteUrl) throws URISyntaxException { + String projectId = new URIish(remoteUrl).getPath(); + if (projectId.startsWith("/")) { + projectId = projectId.substring(1); + } + if (projectId.endsWith(".git")) { + projectId = projectId.substring(0, projectId.lastIndexOf(".git")); + } + return projectId; + } + + @Extension + public static class DescriptorImpl extends BuildStepDescriptor { + + @Override + public boolean isApplicable(Class aClass) { + return true; + } + + @Override + public String getDisplayName() { + return Messages.GitLabCommitStatusPublisher_DisplayName(); + } + + @Override + public String getHelpFile() { + return "/plugin/gitlab-plugin/help/help-gitlab8.1CI.html"; + } + } +} diff --git a/src/main/resources/com/dabsquared/gitlabjenkins/GitLabPushTrigger/config.jelly b/src/main/resources/com/dabsquared/gitlabjenkins/GitLabPushTrigger/config.jelly index 64e1d50..a5819f2 100644 --- a/src/main/resources/com/dabsquared/gitlabjenkins/GitLabPushTrigger/config.jelly +++ b/src/main/resources/com/dabsquared/gitlabjenkins/GitLabPushTrigger/config.jelly @@ -20,10 +20,6 @@ - - - @@ -59,5 +55,4 @@ - diff --git a/src/main/resources/com/dabsquared/gitlabjenkins/publisher/Messages.properties b/src/main/resources/com/dabsquared/gitlabjenkins/publisher/Messages.properties new file mode 100644 index 0000000..135a852 --- /dev/null +++ b/src/main/resources/com/dabsquared/gitlabjenkins/publisher/Messages.properties @@ -0,0 +1 @@ +GitLabCommitStatusPublisher.DisplayName=Publish build status to GitLab commit (GitLab 8.1+ required) diff --git a/src/test/java/com/dabsquared/gitlabjenkins/AbstractGitLabPushTriggerGitlabServerTest.java b/src/test/java/com/dabsquared/gitlabjenkins/AbstractGitLabPushTriggerGitlabServerTest.java index bc31152..e942def 100644 --- a/src/test/java/com/dabsquared/gitlabjenkins/AbstractGitLabPushTriggerGitlabServerTest.java +++ b/src/test/java/com/dabsquared/gitlabjenkins/AbstractGitLabPushTriggerGitlabServerTest.java @@ -122,7 +122,6 @@ public abstract class AbstractGitLabPushTriggerGitlabServerTest { boolean ciSkip = false; boolean setBuildDescription = true; boolean addNoteOnMergeRequest = true; - boolean addCiMessage = true; boolean addVoteOnMergeRequest = true; boolean acceptMergeRequestOnSuccess = false; String branchFilter = null; @@ -130,7 +129,7 @@ public abstract class AbstractGitLabPushTriggerGitlabServerTest { String excludeBranchesSpec = null; String targetBranchRegex = null; GitLabPushTrigger gitLabPushTrigger = new GitLabPushTrigger(triggerOnPush, triggerOnMergeRequest, - triggerOpenMergeRequestOnPush, ciSkip, setBuildDescription, addNoteOnMergeRequest, addCiMessage, + triggerOpenMergeRequestOnPush, ciSkip, setBuildDescription, addNoteOnMergeRequest, addVoteOnMergeRequest, acceptMergeRequestOnSuccess, branchFilter, includeBranchesSpec, excludeBranchesSpec, targetBranchRegex);