diff --git a/build.gradle b/build.gradle index 67c07bf..ca9215c 100644 --- a/build.gradle +++ b/build.gradle @@ -1,14 +1,14 @@ plugins { id 'java' - id 'org.jenkins-ci.jpi' version '0.39.0' + id 'org.jenkins-ci.jpi' version '0.49.0' } group 'org.jenkins-ci.plugins' -version '0.3.0' +version '0.4.0' description 'Outbound WebHook for Jenkins build events' jenkinsPlugin { - coreVersion = "2.200" + jenkinsVersion = "2.387.3" displayName = "Outbound WebHook for build events" url = "https://github.com/jenkinsci/outbound-webhook-plugin" gitHubUrl = "https://github.com/jenkinsci/outbound-webhook-plugin" @@ -23,13 +23,15 @@ jenkinsPlugin { } repositories { - maven { url 'http://bits.netbeans.org/maven2' } - maven { url 'http://repo.jenkins-ci.org/releases/' } - jcenter() mavenCentral() + maven { url 'https://repo.jenkins-ci.org/releases/' } + maven { url 'https://bits.netbeans.org/maven2' } } dependencies { - compile 'com.alibaba:fastjson:1.2.71' - compile 'com.squareup.okhttp3:okhttp:4.7.2' + api platform('io.jenkins.tools.bom:bom-2.387.x:2102.v854b_fec19c92') + implementation 'org.jenkins-ci.plugins:structs' + implementation 'org.jenkins-ci.plugins.workflow:workflow-basic-steps' + implementation 'com.alibaba:fastjson:2.0.32' + implementation 'com.squareup.okhttp3:okhttp:4.11.0' } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 622ab64..fae0804 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/src/main/java/org/jenkins/plugins/JobListener.java b/src/main/java/org/jenkins/plugins/JobListener.java index 76b4894..72c7ee1 100644 --- a/src/main/java/org/jenkins/plugins/JobListener.java +++ b/src/main/java/org/jenkins/plugins/JobListener.java @@ -1,29 +1,42 @@ package org.jenkins.plugins; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.serializer.SerializerFeature; import hudson.Extension; import hudson.model.AbstractBuild; import hudson.model.Result; import hudson.model.TaskListener; import hudson.model.listeners.RunListener; -import com.alibaba.fastjson.JSON; import okhttp3.*; - -import javax.annotation.Nonnull; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + @Extension public class JobListener extends RunListener { private static final MediaType JSON_MEDIA_TYPE = MediaType.parse("application/json; charset=utf-8"); - private OkHttpClient client; - private static final Logger log = LoggerFactory.getLogger(JobListener.class); + private static final OkHttpClient client = new OkHttpClient(); public JobListener() { super(AbstractBuild.class); - client = new OkHttpClient(); + } + + public static void httpPost(String url, Object object) { + String jsonString = JSON.toJSONString(object, SerializerFeature.WriteEnumUsingToString); + RequestBody body = RequestBody.create(jsonString, JSON_MEDIA_TYPE); + Request request = new Request.Builder().url(url).post(body).build(); + try { + Response response = client.newCall(request).execute(); + log.debug("Invocation of webhook {} successful", url); + if (response.body() != null) log.debug("Response: {}", response.body().string()); + response.close(); + } catch (Exception e) { + log.info("Invocation of webhook {} failed", url, e); + } } @Override @@ -34,10 +47,11 @@ public void onStarted(AbstractBuild build, TaskListener listener) { } String webHookUrl = publisher.webHookUrl; String buildUrl = build.getAbsoluteUrl(); - String projectName = build.getProject().getDisplayName(); + String projectName = build.getProject().getFullName(); String buildName = build.getDisplayName(); + int buildNumber = build.getNumber(); String buildVars = build.getBuildVariables().toString(); - NotificationEvent event = new NotificationEvent(projectName, buildName, buildUrl, buildVars, "start"); + NotificationEvent event = new NotificationEvent(projectName, buildName, buildNumber, buildUrl, buildVars, NotificationEvent.EventType.START); httpPost(webHookUrl, event); } @@ -53,20 +67,21 @@ public void onCompleted(AbstractBuild build, @Nonnull TaskListener listener) { } String webHookUrl = publisher.webHookUrl; String buildUrl = build.getAbsoluteUrl(); - String projectName = build.getProject().getDisplayName(); + String projectName = build.getProject().getFullName(); String buildName = build.getDisplayName(); + int buildNumber = build.getNumber(); String buildVars = build.getBuildVariables().toString(); - NotificationEvent event = new NotificationEvent(projectName, buildName, buildUrl, buildVars, ""); + NotificationEvent event = new NotificationEvent(projectName, buildName, buildNumber, buildUrl, buildVars, null); if (publisher.onSuccess && result.equals(Result.SUCCESS)) { - event.event = "success"; + event.event = NotificationEvent.EventType.SUCCESS; httpPost(webHookUrl, event); } if (publisher.onFailure && result.equals(Result.FAILURE)) { - event.event = "failure"; + event.event = NotificationEvent.EventType.FAILURE; httpPost(webHookUrl, event); } if (publisher.onUnstable && result.equals(Result.UNSTABLE)) { - event.event = "unstable"; + event.event = NotificationEvent.EventType.UNSTABLE; httpPost(webHookUrl, event); } } @@ -79,16 +94,4 @@ private WebHookPublisher GetWebHookPublisher(AbstractBuild build) { } return null; } - - private void httpPost(String url, Object object) { - String jsonString = JSON.toJSONString(object); - RequestBody body = RequestBody.create(JSON_MEDIA_TYPE, jsonString); - Request request = new Request.Builder().url(url).post(body).build(); - try { - Response response = client.newCall(request).execute(); - log.debug("Invocation of webhook {} successful", url); - } catch (Exception e) { - log.info("Invocation of webhook {} failed", url, e); - } - } } diff --git a/src/main/java/org/jenkins/plugins/NotificationEvent.java b/src/main/java/org/jenkins/plugins/NotificationEvent.java index 4d0fe47..3e52836 100644 --- a/src/main/java/org/jenkins/plugins/NotificationEvent.java +++ b/src/main/java/org/jenkins/plugins/NotificationEvent.java @@ -1,9 +1,10 @@ package org.jenkins.plugins; public class NotificationEvent { - public NotificationEvent(String projectName, String buildName, String buildUrl, String buildVars, String event) { + public NotificationEvent(String projectName, String buildName, int buildNumber, String buildUrl, String buildVars, EventType event) { this.projectName = projectName; this.buildName = buildName; + this.buildNumber = buildNumber; this.buildUrl = buildUrl; this.buildVars = buildVars; this.event = event; @@ -11,7 +12,27 @@ public NotificationEvent(String projectName, String buildName, String buildUrl, public String projectName; public String buildName; + public int buildNumber; public String buildUrl; public String buildVars; - public String event; + public EventType event; + + public enum EventType { + START("start"), + SUCCESS("success"), + FAILURE("failure"), + UNSTABLE("unstable"), + PIPELINE("pipeline"); + + private final String value; + + EventType(String value) { + this.value = value; + } + + @Override + public String toString() { + return value; + } + } } diff --git a/src/main/java/org/jenkins/plugins/WebHookPipelineExecution.java b/src/main/java/org/jenkins/plugins/WebHookPipelineExecution.java new file mode 100644 index 0000000..56cc7fc --- /dev/null +++ b/src/main/java/org/jenkins/plugins/WebHookPipelineExecution.java @@ -0,0 +1,32 @@ +package org.jenkins.plugins; + +import hudson.EnvVars; +import hudson.model.Run; +import org.jenkinsci.plugins.workflow.steps.StepContext; +import org.jenkinsci.plugins.workflow.steps.SynchronousNonBlockingStepExecution; + +public class WebHookPipelineExecution extends SynchronousNonBlockingStepExecution { + private final WebHookPipelineStep step; + + public WebHookPipelineExecution(WebHookPipelineStep step, StepContext context) { + super(context); + this.step = step; + } + + @Override + protected Void run() throws Exception { + String webHookUrl = this.step.getWebHookUrl(); + Run run = this.getContext().get(Run.class); + EnvVars envVars = this.getContext().get(EnvVars.class); + if (run == null) throw new Exception("Run is null"); + if (envVars == null) throw new Exception("EnvVars is null"); + String buildUrl = run.getAbsoluteUrl(); + String projectName = run.getParent().getFullName(); + String buildName = run.getDisplayName(); + int buildNumber = run.getNumber(); + String buildVars = envVars.toString(); + NotificationEvent event = new NotificationEvent(projectName, buildName, buildNumber, buildUrl, buildVars, NotificationEvent.EventType.PIPELINE); + JobListener.httpPost(webHookUrl, event); + return null; + } +} diff --git a/src/main/java/org/jenkins/plugins/WebHookPipelineStep.java b/src/main/java/org/jenkins/plugins/WebHookPipelineStep.java new file mode 100644 index 0000000..f9d262f --- /dev/null +++ b/src/main/java/org/jenkins/plugins/WebHookPipelineStep.java @@ -0,0 +1,57 @@ +package org.jenkins.plugins; + +import edu.umd.cs.findbugs.annotations.NonNull; +import hudson.EnvVars; +import hudson.Extension; +import hudson.model.Run; +import org.jenkinsci.plugins.workflow.steps.Step; +import org.jenkinsci.plugins.workflow.steps.StepContext; +import org.jenkinsci.plugins.workflow.steps.StepDescriptor; +import org.jenkinsci.plugins.workflow.steps.StepExecution; +import org.kohsuke.stapler.DataBoundConstructor; + +import java.io.Serializable; +import java.util.Set; + +public class WebHookPipelineStep extends Step implements Serializable { + public static final long serialVersionUID = 1L; + private final String webHookUrl; + + @DataBoundConstructor + public WebHookPipelineStep(String webHookUrl) { + this.webHookUrl = webHookUrl; + } + + public String getWebHookUrl() { + return webHookUrl; + } + + @Override + public StepExecution start(StepContext context) { + return new WebHookPipelineExecution(this, context); + } + + + @Extension(optional = true) + public static class DescriptorImpl extends StepDescriptor { + public DescriptorImpl() { + super(); + } + + @Override + public Set> getRequiredContext() { + return Set.of(Run.class, EnvVars.class); + } + + @Override + public String getFunctionName() { + return "webhookSend"; + } + + @NonNull + @Override + public String getDisplayName() { + return "Send a message to a webhook with current build details"; + } + } +} diff --git a/src/main/resources/org/jenkins/plugins/WebHookPipelineStep/config.jelly b/src/main/resources/org/jenkins/plugins/WebHookPipelineStep/config.jelly new file mode 100644 index 0000000..90b7538 --- /dev/null +++ b/src/main/resources/org/jenkins/plugins/WebHookPipelineStep/config.jelly @@ -0,0 +1,6 @@ + + + + + + diff --git a/src/main/resources/org/jenkins/plugins/WebHookPipelineStep/help-webHookUrl.html b/src/main/resources/org/jenkins/plugins/WebHookPipelineStep/help-webHookUrl.html new file mode 100644 index 0000000..3ddfdd1 --- /dev/null +++ b/src/main/resources/org/jenkins/plugins/WebHookPipelineStep/help-webHookUrl.html @@ -0,0 +1,3 @@ +
+ The URL to send the webhook to. +