From 70eb250bd35e195a914b8023a58888cb4d17d69b Mon Sep 17 00:00:00 2001 From: Mark Berner Date: Sun, 9 Jan 2011 07:22:29 +0200 Subject: [PATCH 001/214] refactoring --- .classpath | 1 + .../hudson/plugins/notification/Endpoint.java | 44 +++++++ .../plugins/notification/HostnamePort.java | 32 +++++ .../HudsonNotificationProperty.java | 124 +++--------------- .../HudsonNotificationPropertyDescriptor.java | 86 ++++++++++++ .../hudson/plugins/notification/Phase.java | 7 +- .../hudson/plugins/notification/Protocol.java | 39 ++---- .../HudsonNotificationProperty/config.jelly | 14 +- .../help-endpoint.html | 5 + .../help-endpoints.html | 5 + .../HudsonNotificationProperty/help-url.html | 5 + .../notification/test/HostnamePortTest.java | 23 ++++ 12 files changed, 236 insertions(+), 149 deletions(-) mode change 100755 => 100644 .classpath create mode 100644 src/main/java/com/tikal/hudson/plugins/notification/Endpoint.java create mode 100644 src/main/java/com/tikal/hudson/plugins/notification/HostnamePort.java mode change 100755 => 100644 src/main/java/com/tikal/hudson/plugins/notification/HudsonNotificationProperty.java create mode 100644 src/main/java/com/tikal/hudson/plugins/notification/HudsonNotificationPropertyDescriptor.java mode change 100755 => 100644 src/main/java/com/tikal/hudson/plugins/notification/Phase.java mode change 100755 => 100644 src/main/java/com/tikal/hudson/plugins/notification/Protocol.java mode change 100755 => 100644 src/main/resources/com/tikal/hudson/plugins/notification/HudsonNotificationProperty/config.jelly create mode 100644 src/main/resources/com/tikal/hudson/plugins/notification/HudsonNotificationProperty/help-endpoint.html create mode 100644 src/main/resources/com/tikal/hudson/plugins/notification/HudsonNotificationProperty/help-endpoints.html create mode 100644 src/main/resources/com/tikal/hudson/plugins/notification/HudsonNotificationProperty/help-url.html create mode 100644 src/test/java/com/tikal/hudson/plugins/notification/test/HostnamePortTest.java diff --git a/.classpath b/.classpath old mode 100755 new mode 100644 index 9c7e003..4a64e59 --- a/.classpath +++ b/.classpath @@ -3,6 +3,7 @@ + diff --git a/src/main/java/com/tikal/hudson/plugins/notification/Endpoint.java b/src/main/java/com/tikal/hudson/plugins/notification/Endpoint.java new file mode 100644 index 0000000..7c47a39 --- /dev/null +++ b/src/main/java/com/tikal/hudson/plugins/notification/Endpoint.java @@ -0,0 +1,44 @@ +package com.tikal.hudson.plugins.notification; + +import hudson.util.FormValidation; + +import org.kohsuke.stapler.DataBoundConstructor; +import org.kohsuke.stapler.QueryParameter; + +public class Endpoint { + + private Protocol protocol; + + private String url; + + @DataBoundConstructor + public Endpoint(Protocol protocol, String url) { + this.protocol = protocol; + this.url = url; + } + + public Protocol getProtocol() { + return protocol; + } + + public void setProtocol(Protocol protocol) { + this.protocol = protocol; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public FormValidation doCheckURL(@QueryParameter(value = "url", fixEmpty = true) String url) { + System.out.println("HudsonNotificationProperty.Endpoint.doCheckURL()"); + if (url.equals("111")) + return FormValidation.ok(); + else + return FormValidation.error("There's a problem here"); + } + +} \ No newline at end of file diff --git a/src/main/java/com/tikal/hudson/plugins/notification/HostnamePort.java b/src/main/java/com/tikal/hudson/plugins/notification/HostnamePort.java new file mode 100644 index 0000000..5f5482a --- /dev/null +++ b/src/main/java/com/tikal/hudson/plugins/notification/HostnamePort.java @@ -0,0 +1,32 @@ +package com.tikal.hudson.plugins.notification; + +import java.util.Scanner; +import java.util.regex.MatchResult; + +public class HostnamePort { + + final public String hostname; + + final public int port; + + public HostnamePort(String hostname, int port) { + this.hostname = hostname; + this.port = port; + } + + static public HostnamePort parseUrl(String url) { + try { + Scanner scanner = new Scanner(url); + scanner.findInLine("(.+):(\\d{1,5})"); + MatchResult result = scanner.match(); + if (result.groupCount() != 2) { + return null; + } + String hostname = result.group(1); + int port = Integer.valueOf(result.group(2)); + return new HostnamePort(hostname, port); + } catch (Exception e) { + return null; + } + } +} \ No newline at end of file diff --git a/src/main/java/com/tikal/hudson/plugins/notification/HudsonNotificationProperty.java b/src/main/java/com/tikal/hudson/plugins/notification/HudsonNotificationProperty.java old mode 100755 new mode 100644 index d105221..0d1b33f --- a/src/main/java/com/tikal/hudson/plugins/notification/HudsonNotificationProperty.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/HudsonNotificationProperty.java @@ -1,131 +1,41 @@ package com.tikal.hudson.plugins.notification; -import hudson.Extension; import hudson.model.JobProperty; -import hudson.model.JobPropertyDescriptor; import hudson.model.AbstractProject; -import hudson.model.Job; +import hudson.util.FormValidation; import java.util.ArrayList; import java.util.List; -import net.sf.json.JSON; -import net.sf.json.JSONArray; -import net.sf.json.JSONObject; - import org.kohsuke.stapler.DataBoundConstructor; -import org.kohsuke.stapler.StaplerRequest; - -import com.thoughtworks.xstream.annotations.XStreamAlias; +import org.kohsuke.stapler.QueryParameter; public class HudsonNotificationProperty extends JobProperty> { - private List targets = new ArrayList(); + private List endpoints = new ArrayList(); @DataBoundConstructor - public HudsonNotificationProperty() { - super(); - } - - public List getTargets() { - return targets; + public HudsonNotificationProperty(List endpoints) { + this.endpoints = endpoints; } - public void setTargets(List targets) { - this.targets = targets; + public List getEndpoints() { + return endpoints; } - @XStreamAlias(value = "target") - public static class Target { - - private Protocol protocol; - - private String url; - - @DataBoundConstructor - public Target(Protocol protocol, String url) { - this.protocol = protocol; - this.url = url; - } - - public Protocol getProtocol() { - return protocol; - } - - public void setProtocol(Protocol protocol) { - this.protocol = protocol; - } - - public String getUrl() { - return url; - } - - public void setUrl(String url) { - this.url = url; - } - + public void setEndpoints(List endpoints) { + this.endpoints = endpoints; } - @Extension - public static final class DescriptorImpl extends JobPropertyDescriptor { - - public DescriptorImpl() { - super(HudsonNotificationProperty.class); - load(); - } - - private List targets = new ArrayList(); - - public boolean isEnabled() { - return !targets.isEmpty(); - } - - public List getTargets() { - return targets; - } - - public void setTargets(List targets) { - this.targets = targets; - } - - @Override - public boolean isApplicable(@SuppressWarnings("rawtypes") Class jobType) { - return true; - } - - public String getDisplayName() { - return "Hudson Job Notification"; - } - - @Override - public HudsonNotificationProperty newInstance(StaplerRequest req, JSONObject formData) throws FormException { - System.out.println(formData.toString(0)); - - HudsonNotificationProperty notificationProperty = new HudsonNotificationProperty(); - if (formData != null && !formData.isNullObject()) { - JSON targetsData = (JSON) formData.get("targets"); - if (targetsData != null && !targetsData.isEmpty()) { - if (targetsData.isArray()) { - JSONArray targetsArrayData = (JSONArray) targetsData; - notificationProperty.setTargets(req.bindJSONToList(Target.class, targetsArrayData)); - } else { - JSONObject targetsObjectData = (JSONObject) targetsData; - notificationProperty.getTargets().add(req.bindJSON(Target.class, targetsObjectData)); - } - } - } - return notificationProperty; - } - - @Override - public boolean configure(StaplerRequest req, JSONObject formData) { - save(); - return true; - } - + public FormValidation doCheckurl(@QueryParameter(value = "url", fixEmpty = true) String url) { + System.out.println("HudsonNotificationProperty.Endpoint.doCheckURL()"); + if (url.equals("111")) + return FormValidation.ok(); + else + return FormValidation.error("There's a problem here"); } - public DescriptorImpl getDescriptor() { - return (DescriptorImpl) super.getDescriptor(); + public HudsonNotificationPropertyDescriptor getDescriptor() { + return (HudsonNotificationPropertyDescriptor) super.getDescriptor(); } } \ No newline at end of file diff --git a/src/main/java/com/tikal/hudson/plugins/notification/HudsonNotificationPropertyDescriptor.java b/src/main/java/com/tikal/hudson/plugins/notification/HudsonNotificationPropertyDescriptor.java new file mode 100644 index 0000000..0501173 --- /dev/null +++ b/src/main/java/com/tikal/hudson/plugins/notification/HudsonNotificationPropertyDescriptor.java @@ -0,0 +1,86 @@ +package com.tikal.hudson.plugins.notification; + +import hudson.Extension; +import hudson.model.JobPropertyDescriptor; +import hudson.model.Job; +import hudson.util.FormValidation; + +import java.util.ArrayList; +import java.util.List; + +import net.sf.json.JSON; +import net.sf.json.JSONArray; +import net.sf.json.JSONObject; + +import org.kohsuke.stapler.QueryParameter; +import org.kohsuke.stapler.StaplerRequest; + +@Extension +public final class HudsonNotificationPropertyDescriptor extends JobPropertyDescriptor { + + public HudsonNotificationPropertyDescriptor() { + super(HudsonNotificationProperty.class); + load(); + } + + private List endpoints = new ArrayList(); + + public boolean isEnabled() { + return !endpoints.isEmpty(); + } + + public List getTargets() { + return endpoints; + } + + public void setEndpoints(List endpoints) { + this.endpoints = endpoints; + } + + @Override + public boolean isApplicable(@SuppressWarnings("rawtypes") Class jobType) { + return true; + } + + public String getDisplayName() { + return "Hudson Job Notification"; + } + + // @Override + // public HudsonNotificationProperty newInstance(StaplerRequest req, + // JSONObject formData) throws FormException { + // System.out.println(formData.toString(0)); + // + // HudsonNotificationProperty notificationProperty = new + // HudsonNotificationProperty(); + // if (formData != null && !formData.isNullObject()) { + // JSON endpointsData = (JSON) formData.get("endpoints"); + // if (endpointsData != null && !endpointsData.isEmpty()) { + // if (endpointsData.isArray()) { + // JSONArray endpointsArrayData = (JSONArray) endpointsData; + // notificationProperty.setEndpoints(req.bindJSONToList(Endpoint.class, + // endpointsArrayData)); + // } else { + // JSONObject endpointsObjectData = (JSONObject) endpointsData; + // notificationProperty.getEndpoints().add(req.bindJSON(Endpoint.class, + // endpointsObjectData)); + // } + // } + // } + // return notificationProperty; + // } + public FormValidation doCheckurl(@QueryParameter(value = "url", fixEmpty = true) String url) { + System.out.println("HudsonNotificationProperty.Endpoint.doCheckURL()"); + if (url.equals("111")) + return FormValidation.ok(); + else + return FormValidation.error("There's a problem here"); + } + + @Override + public boolean configure(StaplerRequest req, JSONObject formData) { + save(); + return true; + } + +} \ No newline at end of file diff --git a/src/main/java/com/tikal/hudson/plugins/notification/Phase.java b/src/main/java/com/tikal/hudson/plugins/notification/Phase.java old mode 100755 new mode 100644 index d4b7f8c..69e2dde --- a/src/main/java/com/tikal/hudson/plugins/notification/Phase.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/Phase.java @@ -4,7 +4,6 @@ import java.util.List; -import com.tikal.hudson.plugins.notification.HudsonNotificationProperty.Target; public enum Phase { STARTED, COMPLETED, FINISHED; @@ -13,9 +12,9 @@ public enum Phase { public void handlePhase(Run run, String status) { HudsonNotificationProperty property = (HudsonNotificationProperty) run.getParent().getProperty(HudsonNotificationProperty.class); if (property != null) { - List targets = property.getTargets(); - for (Target target : targets) { - target.getProtocol().sendNotification(target.getUrl(), run.getParent(), run.getNumber(), this, status); + List targets = property.getEndpoints(); + for (Endpoint target : targets) { + target.getProtocol().sendNotification(target.getUrl(), run.getParent(), run, this, status); } } } diff --git a/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java b/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java old mode 100755 new mode 100644 index 56380f4..ab80ef3 --- a/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java @@ -1,6 +1,8 @@ package com.tikal.hudson.plugins.notification; +import hudson.model.Hudson; import hudson.model.Job; +import hudson.model.Run; import java.io.IOException; import java.io.OutputStream; @@ -13,8 +15,6 @@ import java.net.SocketAddress; import java.net.URL; import java.net.URLConnection; -import java.util.Scanner; -import java.util.regex.MatchResult; import com.google.gson.Gson; import com.google.gson.GsonBuilder; @@ -23,6 +23,7 @@ @SuppressWarnings("rawtypes") public enum Protocol { + UDP { @Override protected void send(String url, byte[] data) { @@ -73,17 +74,17 @@ protected void send(String url, byte[] data) { private Gson gson = new GsonBuilder().create(); - public void sendNotification(String url, Job job, int buildNumber, Phase phase, String status) { - send(url, buildMessage(job, buildNumber, phase, status)); - + public void sendNotification(String url, Job job, Run run, Phase phase, String status) { + send(url, buildMessage(job, run, phase, status)); } - private byte[] buildMessage(Job job, int buildNumber, Phase phase, String status) { + private byte[] buildMessage(Job job, Run run, Phase phase, String status) { JobState jobState = new JobState(); jobState.setName(job.getName()); jobState.setUrl(job.getUrl()); BuildState buildState = new BuildState(); - buildState.setNumber(buildNumber); + buildState.setNumber(run.number); + buildState.setUrl(run.getUrl()); buildState.setPhase(phase); buildState.setStatus(status); jobState.setBuild(buildState); @@ -91,28 +92,4 @@ private byte[] buildMessage(Job job, int buildNumber, Phase phase, String status } abstract protected void send(String url, byte[] data); - - private static class HostnamePort { - - final public String hostname; - - final public int port; - - public HostnamePort(String hostname, int port) { - this.hostname = hostname; - this.port = port; - } - - static public HostnamePort parseUrl(String url) { - Scanner scanner = new Scanner(url); - scanner.findInLine("(.+):(\\d{1,5})"); - MatchResult result = scanner.match(); - if (result.groupCount() != 2) { - return null; - } - String hostname = result.group(1); - int port = Integer.valueOf(result.group(2)); - return new HostnamePort(hostname, port); - } - } } \ No newline at end of file diff --git a/src/main/resources/com/tikal/hudson/plugins/notification/HudsonNotificationProperty/config.jelly b/src/main/resources/com/tikal/hudson/plugins/notification/HudsonNotificationProperty/config.jelly old mode 100755 new mode 100644 index 766d6c9..7a75fe5 --- a/src/main/resources/com/tikal/hudson/plugins/notification/HudsonNotificationProperty/config.jelly +++ b/src/main/resources/com/tikal/hudson/plugins/notification/HudsonNotificationProperty/config.jelly @@ -2,9 +2,9 @@ xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form"> - - + +
@@ -12,9 +12,9 @@ @@ -22,7 +22,7 @@ diff --git a/src/main/resources/com/tikal/hudson/plugins/notification/HudsonNotificationProperty/help-endpoint.html b/src/main/resources/com/tikal/hudson/plugins/notification/HudsonNotificationProperty/help-endpoint.html new file mode 100644 index 0000000..3fe2997 --- /dev/null +++ b/src/main/resources/com/tikal/hudson/plugins/notification/HudsonNotificationProperty/help-endpoint.html @@ -0,0 +1,5 @@ +
+ Help file for fields are discovered through a file name convention. This file is an line help for + the "name" field. You can have arbitrary HTML here. You can write this file as a Jelly script + if you need a dynamic content (but if you do so, change the extension to .jelly) +
\ No newline at end of file diff --git a/src/main/resources/com/tikal/hudson/plugins/notification/HudsonNotificationProperty/help-endpoints.html b/src/main/resources/com/tikal/hudson/plugins/notification/HudsonNotificationProperty/help-endpoints.html new file mode 100644 index 0000000..3fe2997 --- /dev/null +++ b/src/main/resources/com/tikal/hudson/plugins/notification/HudsonNotificationProperty/help-endpoints.html @@ -0,0 +1,5 @@ +
+ Help file for fields are discovered through a file name convention. This file is an line help for + the "name" field. You can have arbitrary HTML here. You can write this file as a Jelly script + if you need a dynamic content (but if you do so, change the extension to .jelly) +
\ No newline at end of file diff --git a/src/main/resources/com/tikal/hudson/plugins/notification/HudsonNotificationProperty/help-url.html b/src/main/resources/com/tikal/hudson/plugins/notification/HudsonNotificationProperty/help-url.html new file mode 100644 index 0000000..3fe2997 --- /dev/null +++ b/src/main/resources/com/tikal/hudson/plugins/notification/HudsonNotificationProperty/help-url.html @@ -0,0 +1,5 @@ +
+ Help file for fields are discovered through a file name convention. This file is an line help for + the "name" field. You can have arbitrary HTML here. You can write this file as a Jelly script + if you need a dynamic content (but if you do so, change the extension to .jelly) +
\ No newline at end of file diff --git a/src/test/java/com/tikal/hudson/plugins/notification/test/HostnamePortTest.java b/src/test/java/com/tikal/hudson/plugins/notification/test/HostnamePortTest.java new file mode 100644 index 0000000..43aa657 --- /dev/null +++ b/src/test/java/com/tikal/hudson/plugins/notification/test/HostnamePortTest.java @@ -0,0 +1,23 @@ +package com.tikal.hudson.plugins.notification.test; + +import junit.framework.Assert; + +import org.junit.Test; + +import com.tikal.hudson.plugins.notification.HostnamePort; + +public class HostnamePortTest { + + @Test + public void parseUrlTest() { + HostnamePort hnp = HostnamePort.parseUrl("111"); + Assert.assertNull(hnp); + hnp = HostnamePort.parseUrl(null); + Assert.assertNull(hnp); + hnp = HostnamePort.parseUrl("localhost:123"); + Assert.assertEquals("localhost", hnp.hostname); + Assert.assertEquals(123, hnp.port); + hnp = HostnamePort.parseUrl("localhost:123456"); + Assert.assertEquals(12345, hnp.port); + } +} From 764a0e897e1143ed32a4bf1efd769fcc3186fde5 Mon Sep 17 00:00:00 2001 From: Mark Berner Date: Sun, 9 Jan 2011 07:26:41 +0200 Subject: [PATCH 002/214] refactoring --- .classpath | 0 .../hudson/plugins/notification/HudsonNotificationProperty.java | 0 src/main/java/com/tikal/hudson/plugins/notification/Phase.java | 0 src/main/java/com/tikal/hudson/plugins/notification/Protocol.java | 0 .../plugins/notification/HudsonNotificationProperty/config.jelly | 0 5 files changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 .classpath mode change 100644 => 100755 src/main/java/com/tikal/hudson/plugins/notification/HudsonNotificationProperty.java mode change 100644 => 100755 src/main/java/com/tikal/hudson/plugins/notification/Phase.java mode change 100644 => 100755 src/main/java/com/tikal/hudson/plugins/notification/Protocol.java mode change 100644 => 100755 src/main/resources/com/tikal/hudson/plugins/notification/HudsonNotificationProperty/config.jelly diff --git a/.classpath b/.classpath old mode 100644 new mode 100755 diff --git a/src/main/java/com/tikal/hudson/plugins/notification/HudsonNotificationProperty.java b/src/main/java/com/tikal/hudson/plugins/notification/HudsonNotificationProperty.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/tikal/hudson/plugins/notification/Phase.java b/src/main/java/com/tikal/hudson/plugins/notification/Phase.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java b/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java old mode 100644 new mode 100755 diff --git a/src/main/resources/com/tikal/hudson/plugins/notification/HudsonNotificationProperty/config.jelly b/src/main/resources/com/tikal/hudson/plugins/notification/HudsonNotificationProperty/config.jelly old mode 100644 new mode 100755 From f40e7425cb81ed768459db19ef2fc73b0ab89cf8 Mon Sep 17 00:00:00 2001 From: Mark Berner Date: Thu, 13 Jan 2011 16:32:57 +0200 Subject: [PATCH 003/214] cosmetic changes --- pom.xml | 2 +- .../HudsonNotificationProperty.java | 17 +----- .../HudsonNotificationPropertyDescriptor.java | 56 +++++++++---------- .../hudson/plugins/notification/Protocol.java | 32 ++++++++++- .../HudsonNotificationProperty/config.jelly | 20 +++---- .../help-endpoint.html | 5 -- .../help-endpoints.html | 7 +-- .../HudsonNotificationProperty/help-name.html | 5 -- .../HudsonNotificationProperty/help-url.html | 11 ++-- src/main/resources/index.jelly | 6 +- src/main/webapp/help-globalConfig.html | 20 ++++--- src/main/webapp/help-projectConfig.html | 14 +++++ 12 files changed, 111 insertions(+), 84 deletions(-) mode change 100755 => 100644 pom.xml mode change 100755 => 100644 src/main/java/com/tikal/hudson/plugins/notification/HudsonNotificationProperty.java mode change 100755 => 100644 src/main/java/com/tikal/hudson/plugins/notification/Protocol.java mode change 100755 => 100644 src/main/resources/com/tikal/hudson/plugins/notification/HudsonNotificationProperty/config.jelly delete mode 100644 src/main/resources/com/tikal/hudson/plugins/notification/HudsonNotificationProperty/help-endpoint.html delete mode 100755 src/main/resources/com/tikal/hudson/plugins/notification/HudsonNotificationProperty/help-name.html mode change 100755 => 100644 src/main/resources/index.jelly mode change 100755 => 100644 src/main/webapp/help-globalConfig.html create mode 100644 src/main/webapp/help-projectConfig.html diff --git a/pom.xml b/pom.xml old mode 100755 new mode 100644 index 2d0f2ec..237edd2 --- a/pom.xml +++ b/pom.xml @@ -13,7 +13,7 @@ 1.0-SNAPSHOT hpi Hudson Notification plugin - Sends notification about jobs phases + Sends notifications about jobs phases and status http://wiki.hudson-ci.org/display/HUDSON/Notification+Plugin diff --git a/src/main/java/com/tikal/hudson/plugins/notification/HudsonNotificationProperty.java b/src/main/java/com/tikal/hudson/plugins/notification/HudsonNotificationProperty.java old mode 100755 new mode 100644 index 0d1b33f..9f816be --- a/src/main/java/com/tikal/hudson/plugins/notification/HudsonNotificationProperty.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/HudsonNotificationProperty.java @@ -2,17 +2,14 @@ import hudson.model.JobProperty; import hudson.model.AbstractProject; -import hudson.util.FormValidation; -import java.util.ArrayList; import java.util.List; import org.kohsuke.stapler.DataBoundConstructor; -import org.kohsuke.stapler.QueryParameter; public class HudsonNotificationProperty extends JobProperty> { - private List endpoints = new ArrayList(); + final public List endpoints; @DataBoundConstructor public HudsonNotificationProperty(List endpoints) { @@ -23,18 +20,6 @@ public List getEndpoints() { return endpoints; } - public void setEndpoints(List endpoints) { - this.endpoints = endpoints; - } - - public FormValidation doCheckurl(@QueryParameter(value = "url", fixEmpty = true) String url) { - System.out.println("HudsonNotificationProperty.Endpoint.doCheckURL()"); - if (url.equals("111")) - return FormValidation.ok(); - else - return FormValidation.error("There's a problem here"); - } - public HudsonNotificationPropertyDescriptor getDescriptor() { return (HudsonNotificationPropertyDescriptor) super.getDescriptor(); } diff --git a/src/main/java/com/tikal/hudson/plugins/notification/HudsonNotificationPropertyDescriptor.java b/src/main/java/com/tikal/hudson/plugins/notification/HudsonNotificationPropertyDescriptor.java index 0501173..78a6c2e 100644 --- a/src/main/java/com/tikal/hudson/plugins/notification/HudsonNotificationPropertyDescriptor.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/HudsonNotificationPropertyDescriptor.java @@ -46,35 +46,35 @@ public String getDisplayName() { return "Hudson Job Notification"; } - // @Override - // public HudsonNotificationProperty newInstance(StaplerRequest req, - // JSONObject formData) throws FormException { - // System.out.println(formData.toString(0)); - // - // HudsonNotificationProperty notificationProperty = new - // HudsonNotificationProperty(); - // if (formData != null && !formData.isNullObject()) { - // JSON endpointsData = (JSON) formData.get("endpoints"); - // if (endpointsData != null && !endpointsData.isEmpty()) { - // if (endpointsData.isArray()) { - // JSONArray endpointsArrayData = (JSONArray) endpointsData; - // notificationProperty.setEndpoints(req.bindJSONToList(Endpoint.class, - // endpointsArrayData)); - // } else { - // JSONObject endpointsObjectData = (JSONObject) endpointsData; - // notificationProperty.getEndpoints().add(req.bindJSON(Endpoint.class, - // endpointsObjectData)); - // } - // } - // } - // return notificationProperty; - // } - public FormValidation doCheckurl(@QueryParameter(value = "url", fixEmpty = true) String url) { - System.out.println("HudsonNotificationProperty.Endpoint.doCheckURL()"); - if (url.equals("111")) + @Override + public HudsonNotificationProperty newInstance(StaplerRequest req, JSONObject formData) throws FormException { + System.out.println(formData.toString(0)); + + List endpoints = new ArrayList(); + if (formData != null && !formData.isNullObject()) { + JSON endpointsData = (JSON) formData.get("endpoints"); + if (endpointsData != null && !endpointsData.isEmpty()) { + if (endpointsData.isArray()) { + JSONArray endpointsArrayData = (JSONArray) endpointsData; + endpoints.addAll(req.bindJSONToList(Endpoint.class, endpointsArrayData)); + } else { + JSONObject endpointsObjectData = (JSONObject) endpointsData; + endpoints.add(req.bindJSON(Endpoint.class, endpointsObjectData)); + } + } + } + HudsonNotificationProperty notificationProperty = new HudsonNotificationProperty(endpoints); + return notificationProperty; + } + + public FormValidation doCheckUrl(@QueryParameter(value = "url", fixEmpty = true) String url, @QueryParameter(value = "protocol") String protocolParameter) { + Protocol protocol = Protocol.valueOf(protocolParameter); + try { + protocol.validateUrl(url); return FormValidation.ok(); - else - return FormValidation.error("There's a problem here"); + } catch (Exception e) { + return FormValidation.error(e.getMessage()); + } } @Override diff --git a/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java b/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java old mode 100755 new mode 100644 index ab80ef3..8cf8ae0 --- a/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java @@ -1,6 +1,5 @@ package com.tikal.hudson.plugins.notification; -import hudson.model.Hudson; import hudson.model.Job; import hudson.model.Run; @@ -36,6 +35,18 @@ protected void send(String url, byte[] data) { e.printStackTrace(); } } + + @Override + public void validateUrl(String url) { + try { + HostnamePort hnp = HostnamePort.parseUrl(url); + if (hnp == null) { + throw new Exception(); + } + } catch (Exception e) { + throw new RuntimeException("Invalid Url: hostname:port"); + } + } }, TCP { @Override @@ -70,6 +81,14 @@ protected void send(String url, byte[] data) { e.printStackTrace(); } } + + public void validateUrl(String url) { + try { + new URL(url); + } catch (MalformedURLException e) { + throw new RuntimeException("Invalid Url: http://hostname:port/path"); + } + } }; private Gson gson = new GsonBuilder().create(); @@ -92,4 +111,15 @@ private byte[] buildMessage(Job job, Run run, Phase phase, String status) { } abstract protected void send(String url, byte[] data); + + public void validateUrl(String url) { + try { + HostnamePort hnp = HostnamePort.parseUrl(url); + if (hnp == null) { + throw new Exception(); + } + } catch (Exception e) { + throw new RuntimeException("Invalid Url: hostname:port"); + } + } } \ No newline at end of file diff --git a/src/main/resources/com/tikal/hudson/plugins/notification/HudsonNotificationProperty/config.jelly b/src/main/resources/com/tikal/hudson/plugins/notification/HudsonNotificationProperty/config.jelly old mode 100755 new mode 100644 index 7a75fe5..65afc39 --- a/src/main/resources/com/tikal/hudson/plugins/notification/HudsonNotificationProperty/config.jelly +++ b/src/main/resources/com/tikal/hudson/plugins/notification/HudsonNotificationProperty/config.jelly @@ -2,15 +2,15 @@ xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form"> - - + +
- +
- +
- - -
- +
- +
- + +
diff --git a/src/main/resources/com/tikal/hudson/plugins/notification/HudsonNotificationProperty/help-endpoint.html b/src/main/resources/com/tikal/hudson/plugins/notification/HudsonNotificationProperty/help-endpoint.html deleted file mode 100644 index 3fe2997..0000000 --- a/src/main/resources/com/tikal/hudson/plugins/notification/HudsonNotificationProperty/help-endpoint.html +++ /dev/null @@ -1,5 +0,0 @@ -
- Help file for fields are discovered through a file name convention. This file is an line help for - the "name" field. You can have arbitrary HTML here. You can write this file as a Jelly script - if you need a dynamic content (but if you do so, change the extension to .jelly) -
\ No newline at end of file diff --git a/src/main/resources/com/tikal/hudson/plugins/notification/HudsonNotificationProperty/help-endpoints.html b/src/main/resources/com/tikal/hudson/plugins/notification/HudsonNotificationProperty/help-endpoints.html index 3fe2997..b6bc8d7 100644 --- a/src/main/resources/com/tikal/hudson/plugins/notification/HudsonNotificationProperty/help-endpoints.html +++ b/src/main/resources/com/tikal/hudson/plugins/notification/HudsonNotificationProperty/help-endpoints.html @@ -1,5 +1,2 @@ -
- Help file for fields are discovered through a file name convention. This file is an line help for - the "name" field. You can have arbitrary HTML here. You can write this file as a Jelly script - if you need a dynamic content (but if you do so, change the extension to .jelly) -
\ No newline at end of file +
Sends notifications about Job status to the defined endpoints +using UDP,TCP or HTTP protocols.
\ No newline at end of file diff --git a/src/main/resources/com/tikal/hudson/plugins/notification/HudsonNotificationProperty/help-name.html b/src/main/resources/com/tikal/hudson/plugins/notification/HudsonNotificationProperty/help-name.html deleted file mode 100755 index 3fe2997..0000000 --- a/src/main/resources/com/tikal/hudson/plugins/notification/HudsonNotificationProperty/help-name.html +++ /dev/null @@ -1,5 +0,0 @@ -
- Help file for fields are discovered through a file name convention. This file is an line help for - the "name" field. You can have arbitrary HTML here. You can write this file as a Jelly script - if you need a dynamic content (but if you do so, change the extension to .jelly) -
\ No newline at end of file diff --git a/src/main/resources/com/tikal/hudson/plugins/notification/HudsonNotificationProperty/help-url.html b/src/main/resources/com/tikal/hudson/plugins/notification/HudsonNotificationProperty/help-url.html index 3fe2997..261993e 100644 --- a/src/main/resources/com/tikal/hudson/plugins/notification/HudsonNotificationProperty/help-url.html +++ b/src/main/resources/com/tikal/hudson/plugins/notification/HudsonNotificationProperty/help-url.html @@ -1,5 +1,8 @@ -
- Help file for fields are discovered through a file name convention. This file is an line help for - the "name" field. You can have arbitrary HTML here. You can write this file as a Jelly script - if you need a dynamic content (but if you do so, change the extension to .jelly) +
+
    +
  • URL format for UDP and TCP protocols is + (hostname|IpAddress):portNumber, e.g. 10.10.10.10:12345
  • +
  • URL format for HTTP protocol is any legal http address, e.g. + http://myhost.com:8080/monitor
  • +
\ No newline at end of file diff --git a/src/main/resources/index.jelly b/src/main/resources/index.jelly old mode 100755 new mode 100644 index 3a17698..655be90 --- a/src/main/resources/index.jelly +++ b/src/main/resources/index.jelly @@ -1 +1,5 @@ -
This plugin allows Hudson to send build notifications.
+
+ This plugin from + Tikal Knowledge + allows sending running Jobs status notifications. +
diff --git a/src/main/webapp/help-globalConfig.html b/src/main/webapp/help-globalConfig.html old mode 100755 new mode 100644 index 7b5ebed..aaf98eb --- a/src/main/webapp/help-globalConfig.html +++ b/src/main/webapp/help-globalConfig.html @@ -1,8 +1,14 @@
-

- This HTML fragment will be injected into the configuration screen - when the user clicks the 'help' icon. See global.jelly for how the - form decides which page to load. - You can have any HTML fragment here. -

-
+

This plugin from Tikal +Knowledge allows sending Job Status notifications.

+
+{
+	"name":"JobName", 
+	"url":"JobUrl", 
+	"build":{
+		"number":1,
+		"phase":"STARTED", 
+		"status":"FAILED"
+	}
+}
+
diff --git a/src/main/webapp/help-projectConfig.html b/src/main/webapp/help-projectConfig.html new file mode 100644 index 0000000..aaf98eb --- /dev/null +++ b/src/main/webapp/help-projectConfig.html @@ -0,0 +1,14 @@ +
+

This plugin from Tikal +Knowledge allows sending Job Status notifications.

+
+{
+	"name":"JobName", 
+	"url":"JobUrl", 
+	"build":{
+		"number":1,
+		"phase":"STARTED", 
+		"status":"FAILED"
+	}
+}
+
From 5b0d7c26000171a28005b7d4aafa8727b57236d3 Mon Sep 17 00:00:00 2001 From: Mark Berner Date: Thu, 13 Jan 2011 16:33:17 +0200 Subject: [PATCH 004/214] cosmetic changes --- pom.xml | 0 .../hudson/plugins/notification/HudsonNotificationProperty.java | 0 src/main/java/com/tikal/hudson/plugins/notification/Protocol.java | 0 .../plugins/notification/HudsonNotificationProperty/config.jelly | 0 src/main/resources/index.jelly | 0 src/main/webapp/help-globalConfig.html | 0 src/main/webapp/help-projectConfig.html | 0 7 files changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 pom.xml mode change 100644 => 100755 src/main/java/com/tikal/hudson/plugins/notification/HudsonNotificationProperty.java mode change 100644 => 100755 src/main/java/com/tikal/hudson/plugins/notification/Protocol.java mode change 100644 => 100755 src/main/resources/com/tikal/hudson/plugins/notification/HudsonNotificationProperty/config.jelly mode change 100644 => 100755 src/main/resources/index.jelly mode change 100644 => 100755 src/main/webapp/help-globalConfig.html mode change 100644 => 100755 src/main/webapp/help-projectConfig.html diff --git a/pom.xml b/pom.xml old mode 100644 new mode 100755 diff --git a/src/main/java/com/tikal/hudson/plugins/notification/HudsonNotificationProperty.java b/src/main/java/com/tikal/hudson/plugins/notification/HudsonNotificationProperty.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java b/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java old mode 100644 new mode 100755 diff --git a/src/main/resources/com/tikal/hudson/plugins/notification/HudsonNotificationProperty/config.jelly b/src/main/resources/com/tikal/hudson/plugins/notification/HudsonNotificationProperty/config.jelly old mode 100644 new mode 100755 diff --git a/src/main/resources/index.jelly b/src/main/resources/index.jelly old mode 100644 new mode 100755 diff --git a/src/main/webapp/help-globalConfig.html b/src/main/webapp/help-globalConfig.html old mode 100644 new mode 100755 diff --git a/src/main/webapp/help-projectConfig.html b/src/main/webapp/help-projectConfig.html old mode 100644 new mode 100755 From 46c2c30a6ae323441b081145c8674bf368d27fd4 Mon Sep 17 00:00:00 2001 From: Mark Berner Date: Thu, 13 Jan 2011 16:56:08 +0200 Subject: [PATCH 005/214] [maven-release-plugin] prepare release notification-1.0 --- pom.xml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index 237edd2..002c362 100755 --- a/pom.xml +++ b/pom.xml @@ -1,5 +1,4 @@ - + 4.0.0 org.jvnet.hudson.plugins @@ -10,7 +9,7 @@ com.tikalk.hudson.plugins notification - 1.0-SNAPSHOT + 1.0 hpi Hudson Notification plugin Sends notifications about jobs phases and status From be9c18246e6b6f3f72c28b5f902afa5141a9ddf3 Mon Sep 17 00:00:00 2001 From: Mark Berner Date: Thu, 13 Jan 2011 16:56:33 +0200 Subject: [PATCH 006/214] [maven-release-plugin] prepare for next development iteration --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 002c362..0f2cf31 100755 --- a/pom.xml +++ b/pom.xml @@ -9,7 +9,7 @@ com.tikalk.hudson.plugins notification - 1.0 + 1.1-SNAPSHOT hpi Hudson Notification plugin Sends notifications about jobs phases and status From adc13a0d925f475916e9c7f9bb62f16f5573c7f0 Mon Sep 17 00:00:00 2001 From: Mark Berner Date: Mon, 17 Jan 2011 10:52:43 +0200 Subject: [PATCH 007/214] distribution management fixed --- pom.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) mode change 100755 => 100644 pom.xml diff --git a/pom.xml b/pom.xml old mode 100755 new mode 100644 index 0f2cf31..697c355 --- a/pom.xml +++ b/pom.xml @@ -1,4 +1,5 @@ - + 4.0.0 org.jvnet.hudson.plugins @@ -15,11 +16,10 @@ Sends notifications about jobs phases and status http://wiki.hudson-ci.org/display/HUDSON/Notification+Plugin - java.net-m2-repository - http://maven.hudson-labs.org/content/repositories/releases/ + http://maven.hudson-labs.org:8081/content/repositories/releases/ From 341aa8c7bad1a1ab6b392507a7e1a4d8f7544cca Mon Sep 17 00:00:00 2001 From: Mark Berner Date: Mon, 17 Jan 2011 10:52:58 +0200 Subject: [PATCH 008/214] distribution management fixed --- pom.xml | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 pom.xml diff --git a/pom.xml b/pom.xml old mode 100644 new mode 100755 From 5b4c58a2988c8f3313bad1ce4427b46a7e86fe3a Mon Sep 17 00:00:00 2001 From: Mark Berner Date: Mon, 17 Jan 2011 10:54:26 +0200 Subject: [PATCH 009/214] [maven-release-plugin] prepare release notification-1.1 --- pom.xml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index 697c355..7d09317 100755 --- a/pom.xml +++ b/pom.xml @@ -1,5 +1,4 @@ - + 4.0.0 org.jvnet.hudson.plugins @@ -10,7 +9,7 @@ com.tikalk.hudson.plugins notification - 1.1-SNAPSHOT + 1.1 hpi Hudson Notification plugin Sends notifications about jobs phases and status From 3690973967a1acda237e7af23d64b647dad984c3 Mon Sep 17 00:00:00 2001 From: Mark Berner Date: Mon, 17 Jan 2011 10:54:58 +0200 Subject: [PATCH 010/214] [maven-release-plugin] prepare for next development iteration --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 7d09317..b3d8551 100755 --- a/pom.xml +++ b/pom.xml @@ -9,7 +9,7 @@ com.tikalk.hudson.plugins notification - 1.1 + 1.2-SNAPSHOT hpi Hudson Notification plugin Sends notifications about jobs phases and status From 01e5cdd108c010b8597240776fba9ed16a5e9958 Mon Sep 17 00:00:00 2001 From: Mark Berner Date: Thu, 20 Jan 2011 10:47:11 +0200 Subject: [PATCH 011/214] parent pom changed --- pom.xml | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/pom.xml b/pom.xml index b3d8551..3d58389 100755 --- a/pom.xml +++ b/pom.xml @@ -1,10 +1,10 @@ - + 4.0.0 org.jvnet.hudson.plugins plugin - 1.391 - ../pom.xml + 1.394 com.tikalk.hudson.plugins @@ -15,13 +15,6 @@ Sends notifications about jobs phases and status http://wiki.hudson-ci.org/display/HUDSON/Notification+Plugin - - - java.net-m2-repository - http://maven.hudson-labs.org:8081/content/repositories/releases/ - - - m.g.o-public From a8ebfb4b361b12cb829b5fd5384230407b00c255 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Sat, 25 Jun 2011 07:24:49 -0700 Subject: [PATCH 012/214] In relation to https://github.com/jenkinsci/notification-plugin/pull/1, fixed a bug that HTTP POST was just not working at all. Plus added a test. --- .../hudson/plugins/notification/Protocol.java | 236 +++++++++--------- .../plugins/notification/ProtocolTest.java | 37 +++ 2 files changed, 149 insertions(+), 124 deletions(-) create mode 100644 src/test/java/com/tikal/hudson/plugins/notification/ProtocolTest.java diff --git a/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java b/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java index 8cf8ae0..0792a13 100755 --- a/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java @@ -1,125 +1,113 @@ -package com.tikal.hudson.plugins.notification; - -import hudson.model.Job; -import hudson.model.Run; - -import java.io.IOException; -import java.io.OutputStream; -import java.net.DatagramPacket; -import java.net.DatagramSocket; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.MalformedURLException; -import java.net.Socket; -import java.net.SocketAddress; -import java.net.URL; -import java.net.URLConnection; - -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; -import com.tikal.hudson.plugins.notification.model.BuildState; -import com.tikal.hudson.plugins.notification.model.JobState; - -@SuppressWarnings("rawtypes") -public enum Protocol { - - UDP { - @Override - protected void send(String url, byte[] data) { - try { - HostnamePort hostnamePort = HostnamePort.parseUrl(url); - DatagramSocket socket = new DatagramSocket(); - DatagramPacket packet = new DatagramPacket(data, data.length, InetAddress.getByName(hostnamePort.hostname), hostnamePort.port); - socket.send(packet); - } catch (Exception e) { - e.printStackTrace(); - } - } - - @Override - public void validateUrl(String url) { - try { - HostnamePort hnp = HostnamePort.parseUrl(url); - if (hnp == null) { - throw new Exception(); - } - } catch (Exception e) { - throw new RuntimeException("Invalid Url: hostname:port"); - } - } - }, - TCP { - @Override - protected void send(String url, byte[] data) { - try { - HostnamePort hostnamePort = HostnamePort.parseUrl(url); - SocketAddress endpoint = new InetSocketAddress(InetAddress.getByName(hostnamePort.hostname), hostnamePort.port); - Socket socket = new Socket(); - socket.connect(endpoint); - OutputStream output = socket.getOutputStream(); - output.write(data); - output.flush(); - output.close(); - } catch (Exception e) { - e.printStackTrace(); - } - } - }, - HTTP { - @Override - protected void send(String url, byte[] data) { - try { - URL targetUrl = new URL(url); - URLConnection connection = targetUrl.openConnection(); - OutputStream output = connection.getOutputStream(); - output.write(data); - output.flush(); - output.close(); - } catch (MalformedURLException e) { - e.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); - } - } - - public void validateUrl(String url) { - try { - new URL(url); - } catch (MalformedURLException e) { - throw new RuntimeException("Invalid Url: http://hostname:port/path"); - } - } - }; - - private Gson gson = new GsonBuilder().create(); - - public void sendNotification(String url, Job job, Run run, Phase phase, String status) { - send(url, buildMessage(job, run, phase, status)); - } - - private byte[] buildMessage(Job job, Run run, Phase phase, String status) { - JobState jobState = new JobState(); - jobState.setName(job.getName()); - jobState.setUrl(job.getUrl()); - BuildState buildState = new BuildState(); - buildState.setNumber(run.number); - buildState.setUrl(run.getUrl()); - buildState.setPhase(phase); - buildState.setStatus(status); - jobState.setBuild(buildState); - return gson.toJson(jobState).getBytes(); - } - - abstract protected void send(String url, byte[] data); - - public void validateUrl(String url) { - try { - HostnamePort hnp = HostnamePort.parseUrl(url); - if (hnp == null) { - throw new Exception(); - } - } catch (Exception e) { - throw new RuntimeException("Invalid Url: hostname:port"); - } - } +package com.tikal.hudson.plugins.notification; + +import hudson.model.Job; +import hudson.model.Run; + +import java.io.IOException; +import java.io.OutputStream; +import java.net.DatagramPacket; +import java.net.DatagramSocket; +import java.net.HttpURLConnection; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.MalformedURLException; +import java.net.Socket; +import java.net.SocketAddress; +import java.net.URL; +import java.net.URLConnection; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.tikal.hudson.plugins.notification.model.BuildState; +import com.tikal.hudson.plugins.notification.model.JobState; + +@SuppressWarnings("rawtypes") +public enum Protocol { + + UDP { + @Override + protected void send(String url, byte[] data) throws IOException { + HostnamePort hostnamePort = HostnamePort.parseUrl(url); + DatagramSocket socket = new DatagramSocket(); + DatagramPacket packet = new DatagramPacket(data, data.length, InetAddress.getByName(hostnamePort.hostname), hostnamePort.port); + socket.send(packet); + } + + @Override + public void validateUrl(String url) { + try { + HostnamePort hnp = HostnamePort.parseUrl(url); + if (hnp == null) { + throw new Exception(); + } + } catch (Exception e) { + throw new RuntimeException("Invalid Url: hostname:port"); + } + } + }, + TCP { + @Override + protected void send(String url, byte[] data) throws IOException { + HostnamePort hostnamePort = HostnamePort.parseUrl(url); + SocketAddress endpoint = new InetSocketAddress(InetAddress.getByName(hostnamePort.hostname), hostnamePort.port); + Socket socket = new Socket(); + socket.connect(endpoint); + OutputStream output = socket.getOutputStream(); + output.write(data); + output.flush(); + output.close(); + } + }, + HTTP { + @Override + protected void send(String url, byte[] data) throws IOException { + URL targetUrl = new URL(url); + URLConnection connection = targetUrl.openConnection(); + connection.setDoOutput(true); + OutputStream output = connection.getOutputStream(); + output.write(data); + output.flush(); + output.close(); + } + + public void validateUrl(String url) { + try { + new URL(url); + } catch (MalformedURLException e) { + throw new RuntimeException("Invalid Url: http://hostname:port/path"); + } + } + }; + + private Gson gson = new GsonBuilder().create(); + + public void sendNotification(String url, Job job, Run run, Phase phase, String status) throws IOException { + send(url, buildMessage(job, run, phase, status)); + } + + private byte[] buildMessage(Job job, Run run, Phase phase, String status) { + JobState jobState = new JobState(); + jobState.setName(job.getName()); + jobState.setUrl(job.getUrl()); + BuildState buildState = new BuildState(); + buildState.setNumber(run.number); + buildState.setUrl(run.getUrl()); + buildState.setPhase(phase); + buildState.setStatus(status); + jobState.setBuild(buildState); + return gson.toJson(jobState).getBytes(); + } + + abstract protected void send(String url, byte[] data) throws IOException; + + public void validateUrl(String url) { + try { + HostnamePort hnp = HostnamePort.parseUrl(url); + if (hnp == null) { + throw new Exception(); + } + } catch (Exception e) { + throw new RuntimeException("Invalid Url: hostname:port"); + } + } } \ No newline at end of file diff --git a/src/test/java/com/tikal/hudson/plugins/notification/ProtocolTest.java b/src/test/java/com/tikal/hudson/plugins/notification/ProtocolTest.java new file mode 100644 index 0000000..366b986 --- /dev/null +++ b/src/test/java/com/tikal/hudson/plugins/notification/ProtocolTest.java @@ -0,0 +1,37 @@ +/* + * The MIT License + * + * Copyright (c) 2011, CloudBees, Inc. + * + * 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 com.tikal.hudson.plugins.notification; + +import junit.framework.TestCase; + +import java.io.IOException; + +/** + * @author Kohsuke Kawaguchi + */ +public class ProtocolTest extends TestCase { + public void testHttpPost() throws IOException { + Protocol.HTTP.send("http://www.google.com/","Hello".getBytes()); + } +} From df4325ad8909bff1e6df8f4f453efc18e6648cf5 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Sat, 25 Jun 2011 07:25:52 -0700 Subject: [PATCH 013/214] Improved the error handling so that the failure is reported to the build, not to the console of the server. --- .../hudson/plugins/notification/Endpoint.java | 4 + .../plugins/notification/JobListener.java | 78 +++++++++---------- .../hudson/plugins/notification/Phase.java | 46 ++++++----- 3 files changed, 69 insertions(+), 59 deletions(-) diff --git a/src/main/java/com/tikal/hudson/plugins/notification/Endpoint.java b/src/main/java/com/tikal/hudson/plugins/notification/Endpoint.java index 7c47a39..7209feb 100644 --- a/src/main/java/com/tikal/hudson/plugins/notification/Endpoint.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/Endpoint.java @@ -41,4 +41,8 @@ public FormValidation doCheckURL(@QueryParameter(value = "url", fixEmpty = true) return FormValidation.error("There's a problem here"); } + @Override + public String toString() { + return protocol+":"+url; + } } \ No newline at end of file diff --git a/src/main/java/com/tikal/hudson/plugins/notification/JobListener.java b/src/main/java/com/tikal/hudson/plugins/notification/JobListener.java index 17626f4..a057a53 100755 --- a/src/main/java/com/tikal/hudson/plugins/notification/JobListener.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/JobListener.java @@ -1,40 +1,40 @@ -package com.tikal.hudson.plugins.notification; - -import hudson.Extension; -import hudson.model.Result; -import hudson.model.TaskListener; -import hudson.model.Run; -import hudson.model.listeners.RunListener; - -@Extension -@SuppressWarnings("rawtypes") -public class JobListener extends RunListener { - - public JobListener() { - super(Run.class); - } - - @Override - public void onStarted(Run r, TaskListener listener) { - Phase.STARTED.handlePhase(r, getStatus(r)); - } - - @Override - public void onCompleted(Run r, TaskListener listener) { - Phase.COMPLETED.handlePhase(r, getStatus(r)); - } - - @Override - public void onFinalized(Run r) { - Phase.FINISHED.handlePhase(r, getStatus(r)); - } - - private String getStatus(Run r) { - Result result = r.getResult(); - String status = null; - if (result != null) { - status = result.toString(); - } - return status; - } +package com.tikal.hudson.plugins.notification; + +import hudson.Extension; +import hudson.model.Result; +import hudson.model.TaskListener; +import hudson.model.Run; +import hudson.model.listeners.RunListener; + +@Extension +@SuppressWarnings("rawtypes") +public class JobListener extends RunListener { + + public JobListener() { + super(Run.class); + } + + @Override + public void onStarted(Run r, TaskListener listener) { + Phase.STARTED.handlePhase(r, getStatus(r), listener); + } + + @Override + public void onCompleted(Run r, TaskListener listener) { + Phase.COMPLETED.handlePhase(r, getStatus(r), listener); + } + + @Override + public void onFinalized(Run r) { + Phase.FINISHED.handlePhase(r, getStatus(r), TaskListener.NULL); + } + + private String getStatus(Run r) { + Result result = r.getResult(); + String status = null; + if (result != null) { + status = result.toString(); + } + return status; + } } \ No newline at end of file diff --git a/src/main/java/com/tikal/hudson/plugins/notification/Phase.java b/src/main/java/com/tikal/hudson/plugins/notification/Phase.java index 69e2dde..c10b120 100755 --- a/src/main/java/com/tikal/hudson/plugins/notification/Phase.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/Phase.java @@ -1,21 +1,27 @@ -package com.tikal.hudson.plugins.notification; - -import hudson.model.Run; - -import java.util.List; - - -public enum Phase { - STARTED, COMPLETED, FINISHED; - - @SuppressWarnings({ "unchecked", "rawtypes" }) - public void handlePhase(Run run, String status) { - HudsonNotificationProperty property = (HudsonNotificationProperty) run.getParent().getProperty(HudsonNotificationProperty.class); - if (property != null) { - List targets = property.getEndpoints(); - for (Endpoint target : targets) { - target.getProtocol().sendNotification(target.getUrl(), run.getParent(), run, this, status); - } - } - } +package com.tikal.hudson.plugins.notification; + +import hudson.model.Run; +import hudson.model.TaskListener; + +import java.io.IOException; +import java.util.List; + + +public enum Phase { + STARTED, COMPLETED, FINISHED; + + @SuppressWarnings({ "unchecked", "rawtypes" }) + public void handlePhase(Run run, String status, TaskListener listener) { + HudsonNotificationProperty property = (HudsonNotificationProperty) run.getParent().getProperty(HudsonNotificationProperty.class); + if (property != null) { + List targets = property.getEndpoints(); + for (Endpoint target : targets) { + try { + target.getProtocol().sendNotification(target.getUrl(), run.getParent(), run, this, status); + } catch (IOException e) { + e.printStackTrace(listener.error("Failed to notify "+target)); + } + } + } + } } \ No newline at end of file From 5af2bc2d2f800dfe45492d16a91a6fb68499c2cb Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Sat, 25 Jun 2011 07:28:32 -0700 Subject: [PATCH 014/214] Removing redundant bits from POM. --- pom.xml | 30 +++++------------------------- 1 file changed, 5 insertions(+), 25 deletions(-) diff --git a/pom.xml b/pom.xml index 3d58389..afc80ff 100755 --- a/pom.xml +++ b/pom.xml @@ -11,9 +11,9 @@ notification 1.2-SNAPSHOT hpi - Hudson Notification plugin + Jenkins Notification plugin Sends notifications about jobs phases and status - http://wiki.hudson-ci.org/display/HUDSON/Notification+Plugin + https://wiki.jenkins-ci.org/display/JENKINS/Notification+Plugin @@ -47,29 +47,9 @@ - - - - org.apache.maven.plugins - maven-compiler-plugin - 2.0.2 - - 1.5 - 1.5 - - - - - - org.jvnet.wagon-svn - wagon-svn - 1.9 - - - - scm:git:git://github.com/hudson/notification-plugin.git - scm:git:git@github.com:hudson/notification-plugin.git - http://github.com/hudson/notification-plugin + scm:git:git://github.com/jenkinsci/notification-plugin.git + scm:git:git@github.com:jenkinsci/notification-plugin.git + http://github.com/jenkinsci/notification-plugin From 41793725397c9358d8a219bce13d18d1fb336f3d Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Sat, 25 Jun 2011 07:29:41 -0700 Subject: [PATCH 015/214] [maven-release-plugin] prepare release notification-1.2 --- pom.xml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index afc80ff..71527f4 100755 --- a/pom.xml +++ b/pom.xml @@ -1,5 +1,4 @@ - + 4.0.0 org.jvnet.hudson.plugins @@ -9,7 +8,7 @@ com.tikalk.hudson.plugins notification - 1.2-SNAPSHOT + 1.2 hpi Jenkins Notification plugin Sends notifications about jobs phases and status From eee13b75205ec002546aebeec45b25682f64b830 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Sat, 25 Jun 2011 07:29:51 -0700 Subject: [PATCH 016/214] [maven-release-plugin] prepare for next development iteration --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 71527f4..b7ea6eb 100755 --- a/pom.xml +++ b/pom.xml @@ -8,7 +8,7 @@ com.tikalk.hudson.plugins notification - 1.2 + 1.3-SNAPSHOT hpi Jenkins Notification plugin Sends notifications about jobs phases and status From e2d45ebdaad3754000d1ecae4dadbc55b3aed4fb Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Fri, 8 Jul 2011 09:45:13 -0700 Subject: [PATCH 017/214] Add full_url to BuildState with the value of Run.getAbsolutePath This allows endpoints to have the full url of the run, not just the path. --- .../tikal/hudson/plugins/notification/Protocol.java | 5 ++++- .../hudson/plugins/notification/model/BuildState.java | 10 ++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java b/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java index 0792a13..6fca57a 100755 --- a/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java @@ -16,6 +16,7 @@ import java.net.URL; import java.net.URLConnection; +import com.google.gson.FieldNamingPolicy; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.tikal.hudson.plugins.notification.model.BuildState; @@ -79,7 +80,8 @@ public void validateUrl(String url) { } }; - private Gson gson = new GsonBuilder().create(); + private Gson gson = new GsonBuilder().setFieldNamingPolicy( + FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES).create(); public void sendNotification(String url, Job job, Run run, Phase phase, String status) throws IOException { send(url, buildMessage(job, run, phase, status)); @@ -94,6 +96,7 @@ private byte[] buildMessage(Job job, Run run, Phase phase, String status) { buildState.setUrl(run.getUrl()); buildState.setPhase(phase); buildState.setStatus(status); + buildState.setFullUrl(run.getAbsoluteUrl()); jobState.setBuild(buildState); return gson.toJson(jobState).getBytes(); } diff --git a/src/main/java/com/tikal/hudson/plugins/notification/model/BuildState.java b/src/main/java/com/tikal/hudson/plugins/notification/model/BuildState.java index 25f1f68..110cfc9 100755 --- a/src/main/java/com/tikal/hudson/plugins/notification/model/BuildState.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/model/BuildState.java @@ -4,6 +4,8 @@ public class BuildState { + private String fullUrl; + private int number; private Phase phase; @@ -43,4 +45,12 @@ public String getUrl() { public void setUrl(String url) { this.url = url; } + + public String getFullUrl() { + return fullUrl; + } + + public void setFullUrl(String fullUrl) { + this.fullUrl = fullUrl; + } } From c982aaf982219c7f4deb2caa6f9c0458b3708ff6 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Fri, 8 Jul 2011 10:41:48 -0700 Subject: [PATCH 018/214] Change wording on description for url. "Whether" => "Where" --- .../notification/HudsonNotificationProperty/config.jelly | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/com/tikal/hudson/plugins/notification/HudsonNotificationProperty/config.jelly b/src/main/resources/com/tikal/hudson/plugins/notification/HudsonNotificationProperty/config.jelly index 65afc39..f4f9127 100755 --- a/src/main/resources/com/tikal/hudson/plugins/notification/HudsonNotificationProperty/config.jelly +++ b/src/main/resources/com/tikal/hudson/plugins/notification/HudsonNotificationProperty/config.jelly @@ -21,7 +21,7 @@ - From cb5e8e433763951c6094e69f9a417a43c7358aab Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Sat, 20 Aug 2011 13:58:25 -0700 Subject: [PATCH 019/214] Handle illegal state exception when getting absolute url. --- .../com/tikal/hudson/plugins/notification/Protocol.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java b/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java index 6fca57a..1f98717 100755 --- a/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java @@ -96,7 +96,11 @@ private byte[] buildMessage(Job job, Run run, Phase phase, String status) { buildState.setUrl(run.getUrl()); buildState.setPhase(phase); buildState.setStatus(status); - buildState.setFullUrl(run.getAbsoluteUrl()); + try { + buildState.setFullUrl(run.getAbsoluteUrl()); + } catch (IllegalStateException ignored) { + // Ignored + } jobState.setBuild(buildState); return gson.toJson(jobState).getBytes(); } From f89ed9cf327e23ae1684efe47c2bbe96a03b0db9 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Sun, 21 Aug 2011 19:51:49 -0700 Subject: [PATCH 020/214] Set fixed length streaming mode and do input values on connection. Fixed length streaming mode is possible since the entire POST data block is known when the method is called and the value is set to the length of the data array. setDoInput(false) is called on the connection since it is only written to and never read from. --- .../java/com/tikal/hudson/plugins/notification/Protocol.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java b/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java index 1f98717..b302719 100755 --- a/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java @@ -64,6 +64,10 @@ protected void send(String url, byte[] data) throws IOException { protected void send(String url, byte[] data) throws IOException { URL targetUrl = new URL(url); URLConnection connection = targetUrl.openConnection(); + if (connection instanceof HttpURLConnection) + ((HttpURLConnection) connection) + .setFixedLengthStreamingMode(data.length); + connection.setDoInput(false); connection.setDoOutput(true); OutputStream output = connection.getOutputStream(); output.write(data); From 12c5461245d814c2248cc6bc9f3d3562d0eaefc6 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Fri, 26 Aug 2011 16:58:05 -0700 Subject: [PATCH 021/214] [maven-release-plugin] prepare release notification-1.3 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index b7ea6eb..3f28efa 100755 --- a/pom.xml +++ b/pom.xml @@ -8,7 +8,7 @@ com.tikalk.hudson.plugins notification - 1.3-SNAPSHOT + 1.3 hpi Jenkins Notification plugin Sends notifications about jobs phases and status From 3926f405c7054cffbc815437144edb60c04662c4 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Fri, 26 Aug 2011 16:58:09 -0700 Subject: [PATCH 022/214] [maven-release-plugin] prepare for next development iteration --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 3f28efa..4f6c000 100755 --- a/pom.xml +++ b/pom.xml @@ -8,7 +8,7 @@ com.tikalk.hudson.plugins notification - 1.3 + 1.4-SNAPSHOT hpi Jenkins Notification plugin Sends notifications about jobs phases and status From bc24e4a8fe1380d169581df677d4ea0de51b743a Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Mon, 28 Nov 2011 12:50:42 -0800 Subject: [PATCH 023/214] Remove System.out calls --- .../java/com/tikal/hudson/plugins/notification/Endpoint.java | 1 - .../notification/HudsonNotificationPropertyDescriptor.java | 1 - 2 files changed, 2 deletions(-) diff --git a/src/main/java/com/tikal/hudson/plugins/notification/Endpoint.java b/src/main/java/com/tikal/hudson/plugins/notification/Endpoint.java index 7209feb..d3730f0 100644 --- a/src/main/java/com/tikal/hudson/plugins/notification/Endpoint.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/Endpoint.java @@ -34,7 +34,6 @@ public void setUrl(String url) { } public FormValidation doCheckURL(@QueryParameter(value = "url", fixEmpty = true) String url) { - System.out.println("HudsonNotificationProperty.Endpoint.doCheckURL()"); if (url.equals("111")) return FormValidation.ok(); else diff --git a/src/main/java/com/tikal/hudson/plugins/notification/HudsonNotificationPropertyDescriptor.java b/src/main/java/com/tikal/hudson/plugins/notification/HudsonNotificationPropertyDescriptor.java index 78a6c2e..cb9170d 100644 --- a/src/main/java/com/tikal/hudson/plugins/notification/HudsonNotificationPropertyDescriptor.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/HudsonNotificationPropertyDescriptor.java @@ -48,7 +48,6 @@ public String getDisplayName() { @Override public HudsonNotificationProperty newInstance(StaplerRequest req, JSONObject formData) throws FormException { - System.out.println(formData.toString(0)); List endpoints = new ArrayList(); if (formData != null && !formData.isNullObject()) { From bf0d8509ea9c1dbbad16e85f98b5a600afb022d0 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Mon, 28 Nov 2011 12:58:03 -0800 Subject: [PATCH 024/214] Add non-sensitive parameters to BuildState. This allows clients being notified to have access to the params that were part of the build. --- .../hudson/plugins/notification/Protocol.java | 18 ++++++++++++++++++ .../plugins/notification/model/BuildState.java | 12 ++++++++++++ 2 files changed, 30 insertions(+) diff --git a/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java b/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java index b302719..01a1dd2 100755 --- a/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java @@ -1,6 +1,11 @@ package com.tikal.hudson.plugins.notification; +import hudson.EnvVars; +import hudson.model.AbstractBuild; import hudson.model.Job; +import hudson.model.ParameterValue; +import hudson.model.ParametersAction; +import hudson.model.PasswordParameterValue; import hudson.model.Run; import java.io.IOException; @@ -15,6 +20,8 @@ import java.net.SocketAddress; import java.net.URL; import java.net.URLConnection; +import java.util.HashMap; +import java.util.Map; import com.google.gson.FieldNamingPolicy; import com.google.gson.Gson; @@ -106,6 +113,17 @@ private byte[] buildMessage(Job job, Run run, Phase phase, String status) { // Ignored } jobState.setBuild(buildState); + + ParametersAction paramsAction = run.getAction(ParametersAction.class); + if (paramsAction != null && run instanceof AbstractBuild) { + AbstractBuild build = (AbstractBuild) run; + EnvVars env = new EnvVars(); + for (ParameterValue value : paramsAction.getParameters()) + if (!value.isSensitive()) + value.buildEnvVars(build, env); + buildState.setParameters(env); + } + return gson.toJson(jobState).getBytes(); } diff --git a/src/main/java/com/tikal/hudson/plugins/notification/model/BuildState.java b/src/main/java/com/tikal/hudson/plugins/notification/model/BuildState.java index 110cfc9..90ff971 100755 --- a/src/main/java/com/tikal/hudson/plugins/notification/model/BuildState.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/model/BuildState.java @@ -2,6 +2,8 @@ import com.tikal.hudson.plugins.notification.Phase; +import java.util.Map; + public class BuildState { private String fullUrl; @@ -13,6 +15,8 @@ public class BuildState { private String status; private String url; + + private Map parameters; public int getNumber() { return number; @@ -53,4 +57,12 @@ public String getFullUrl() { public void setFullUrl(String fullUrl) { this.fullUrl = fullUrl; } + + public Map getParameters() { + return parameters; + } + + public void setParameters(Map params) { + this.parameters = params; + } } From 0793b77f92b014963e73dc1d69aef2c75cac6162 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Mon, 28 Nov 2011 13:05:25 -0800 Subject: [PATCH 025/214] [maven-release-plugin] prepare release notification-1.4 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 4f6c000..136c9e8 100755 --- a/pom.xml +++ b/pom.xml @@ -8,7 +8,7 @@ com.tikalk.hudson.plugins notification - 1.4-SNAPSHOT + 1.4 hpi Jenkins Notification plugin Sends notifications about jobs phases and status From 221aeb71473ce02448cceb77fbccf939b21f642f Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Mon, 28 Nov 2011 13:05:32 -0800 Subject: [PATCH 026/214] [maven-release-plugin] prepare for next development iteration --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 136c9e8..c1c9e75 100755 --- a/pom.xml +++ b/pom.xml @@ -8,7 +8,7 @@ com.tikalk.hudson.plugins notification - 1.4 + 1.5-SNAPSHOT hpi Jenkins Notification plugin Sends notifications about jobs phases and status From 09aafb8b0dad9f94819cebe095e126cb48cac818 Mon Sep 17 00:00:00 2001 From: ikasam_a Date: Sun, 29 Jan 2012 01:01:12 +0900 Subject: [PATCH 027/214] set fullUrl --- .../tikal/hudson/plugins/notification/Protocol.java | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java b/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java index 01a1dd2..5d8f000 100755 --- a/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java @@ -2,6 +2,7 @@ import hudson.EnvVars; import hudson.model.AbstractBuild; +import hudson.model.Hudson; import hudson.model.Job; import hudson.model.ParameterValue; import hudson.model.ParametersAction; @@ -107,11 +108,12 @@ private byte[] buildMessage(Job job, Run run, Phase phase, String status) { buildState.setUrl(run.getUrl()); buildState.setPhase(phase); buildState.setStatus(status); - try { - buildState.setFullUrl(run.getAbsoluteUrl()); - } catch (IllegalStateException ignored) { - // Ignored + + String rootUrl = Hudson.getInstance().getRootUrl(); + if (rootUrl != null) { + buildState.setFullUrl(rootUrl + run.getUrl()); } + jobState.setBuild(buildState); ParametersAction paramsAction = run.getAction(ParametersAction.class); @@ -139,4 +141,4 @@ public void validateUrl(String url) { throw new RuntimeException("Invalid Url: hostname:port"); } } -} \ No newline at end of file +} From 848ae67d80ee8ffa220bf070ac0a5d98178949ba Mon Sep 17 00:00:00 2001 From: Nicolas De Loof Date: Fri, 6 Apr 2012 18:07:46 +0200 Subject: [PATCH 028/214] updated maven pom to use repo.jenkins-ci.org repository --- pom.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index c1c9e75..18ee455 100755 --- a/pom.xml +++ b/pom.xml @@ -16,15 +16,15 @@ - m.g.o-public - http://maven.glassfish.org/content/groups/public/ + repo.jenkins-ci.org + http://repo.jenkins-ci.org/public/ - m.g.o-public - http://maven.glassfish.org/content/groups/public/ + repo.jenkins-ci.org + http://repo.jenkins-ci.org/public/ From 2e8648a22488201f7298a97dee4ccda1200503b1 Mon Sep 17 00:00:00 2001 From: hagzag Date: Sun, 19 Aug 2012 21:58:10 +0300 Subject: [PATCH 029/214] Updating License information --- pom.xml | 19 +++++++++++++++---- .../hudson/plugins/notification/Endpoint.java | 14 ++++++++++++++ .../plugins/notification/HostnamePort.java | 13 +++++++++++++ .../HudsonNotificationProperty.java | 16 +++++++++++++++- .../HudsonNotificationPropertyDescriptor.java | 13 +++++++++++++ .../plugins/notification/JobListener.java | 13 +++++++++++++ .../hudson/plugins/notification/Phase.java | 13 +++++++++++++ .../hudson/plugins/notification/Protocol.java | 13 +++++++++++++ .../notification/model/BuildState.java | 13 +++++++++++++ .../plugins/notification/model/JobState.java | 13 +++++++++++++ .../plugins/notification/ProtocolTest.java | 2 +- .../notification/test/HostnamePortTest.java | 13 +++++++++++++ 12 files changed, 149 insertions(+), 6 deletions(-) diff --git a/pom.xml b/pom.xml index 18ee455..dd728bd 100755 --- a/pom.xml +++ b/pom.xml @@ -1,9 +1,10 @@ - + 4.0.0 - org.jvnet.hudson.plugins + org.jenkins-ci.plugins plugin - 1.394 + 1.465 com.tikalk.hudson.plugins @@ -12,7 +13,7 @@ hpi Jenkins Notification plugin Sends notifications about jobs phases and status - https://wiki.jenkins-ci.org/display/JENKINS/Notification+Plugin + https://wiki.jenkins-ci.org/display/JENKINS/Notification+Plugin @@ -51,4 +52,14 @@ scm:git:git@github.com:jenkinsci/notification-plugin.git http://github.com/jenkinsci/notification-plugin + + + + The Apache Software License, Version 2.0 + http://www.apache.org/licenses/LICENSE-2.0.txt + repo + A business-friendly OSS license + + + diff --git a/src/main/java/com/tikal/hudson/plugins/notification/Endpoint.java b/src/main/java/com/tikal/hudson/plugins/notification/Endpoint.java index d3730f0..a2abce6 100644 --- a/src/main/java/com/tikal/hudson/plugins/notification/Endpoint.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/Endpoint.java @@ -1,3 +1,17 @@ +/** + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package com.tikal.hudson.plugins.notification; import hudson.util.FormValidation; diff --git a/src/main/java/com/tikal/hudson/plugins/notification/HostnamePort.java b/src/main/java/com/tikal/hudson/plugins/notification/HostnamePort.java index 5f5482a..6dee2a5 100644 --- a/src/main/java/com/tikal/hudson/plugins/notification/HostnamePort.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/HostnamePort.java @@ -1,3 +1,16 @@ +/** + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package com.tikal.hudson.plugins.notification; import java.util.Scanner; diff --git a/src/main/java/com/tikal/hudson/plugins/notification/HudsonNotificationProperty.java b/src/main/java/com/tikal/hudson/plugins/notification/HudsonNotificationProperty.java index 9f816be..b685e49 100755 --- a/src/main/java/com/tikal/hudson/plugins/notification/HudsonNotificationProperty.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/HudsonNotificationProperty.java @@ -1,3 +1,16 @@ +/** + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package com.tikal.hudson.plugins.notification; import hudson.model.JobProperty; @@ -7,7 +20,8 @@ import org.kohsuke.stapler.DataBoundConstructor; -public class HudsonNotificationProperty extends JobProperty> { +public class HudsonNotificationProperty extends + JobProperty> { final public List endpoints; diff --git a/src/main/java/com/tikal/hudson/plugins/notification/HudsonNotificationPropertyDescriptor.java b/src/main/java/com/tikal/hudson/plugins/notification/HudsonNotificationPropertyDescriptor.java index cb9170d..b083c08 100644 --- a/src/main/java/com/tikal/hudson/plugins/notification/HudsonNotificationPropertyDescriptor.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/HudsonNotificationPropertyDescriptor.java @@ -1,3 +1,16 @@ +/** + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package com.tikal.hudson.plugins.notification; import hudson.Extension; diff --git a/src/main/java/com/tikal/hudson/plugins/notification/JobListener.java b/src/main/java/com/tikal/hudson/plugins/notification/JobListener.java index a057a53..d85807b 100755 --- a/src/main/java/com/tikal/hudson/plugins/notification/JobListener.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/JobListener.java @@ -1,3 +1,16 @@ +/** + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package com.tikal.hudson.plugins.notification; import hudson.Extension; diff --git a/src/main/java/com/tikal/hudson/plugins/notification/Phase.java b/src/main/java/com/tikal/hudson/plugins/notification/Phase.java index c10b120..b7cf4d4 100755 --- a/src/main/java/com/tikal/hudson/plugins/notification/Phase.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/Phase.java @@ -1,3 +1,16 @@ +/** + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package com.tikal.hudson.plugins.notification; import hudson.model.Run; diff --git a/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java b/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java index 01a1dd2..07c8be9 100755 --- a/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java @@ -1,3 +1,16 @@ +/** + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package com.tikal.hudson.plugins.notification; import hudson.EnvVars; diff --git a/src/main/java/com/tikal/hudson/plugins/notification/model/BuildState.java b/src/main/java/com/tikal/hudson/plugins/notification/model/BuildState.java index 90ff971..253444e 100755 --- a/src/main/java/com/tikal/hudson/plugins/notification/model/BuildState.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/model/BuildState.java @@ -1,3 +1,16 @@ +/** + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package com.tikal.hudson.plugins.notification.model; import com.tikal.hudson.plugins.notification.Phase; diff --git a/src/main/java/com/tikal/hudson/plugins/notification/model/JobState.java b/src/main/java/com/tikal/hudson/plugins/notification/model/JobState.java index 7540161..a2328a4 100755 --- a/src/main/java/com/tikal/hudson/plugins/notification/model/JobState.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/model/JobState.java @@ -1,3 +1,16 @@ +/** + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package com.tikal.hudson.plugins.notification.model; public class JobState { diff --git a/src/test/java/com/tikal/hudson/plugins/notification/ProtocolTest.java b/src/test/java/com/tikal/hudson/plugins/notification/ProtocolTest.java index 366b986..ef61857 100644 --- a/src/test/java/com/tikal/hudson/plugins/notification/ProtocolTest.java +++ b/src/test/java/com/tikal/hudson/plugins/notification/ProtocolTest.java @@ -1,5 +1,5 @@ /* - * The MIT License ++ * The MIT License * * Copyright (c) 2011, CloudBees, Inc. * diff --git a/src/test/java/com/tikal/hudson/plugins/notification/test/HostnamePortTest.java b/src/test/java/com/tikal/hudson/plugins/notification/test/HostnamePortTest.java index 43aa657..196383b 100644 --- a/src/test/java/com/tikal/hudson/plugins/notification/test/HostnamePortTest.java +++ b/src/test/java/com/tikal/hudson/plugins/notification/test/HostnamePortTest.java @@ -1,3 +1,16 @@ +/** + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package com.tikal.hudson.plugins.notification.test; import junit.framework.Assert; From 84035ef6f7c189acd1eb7abf5cb8db060bb31058 Mon Sep 17 00:00:00 2001 From: jsirois Date: Thu, 25 Oct 2012 09:08:16 -0600 Subject: [PATCH 030/214] Support following HTTP redirects encountered during notification POSTS Add a more robust set of tests. --- .../hudson/plugins/notification/Protocol.java | 47 +++-- .../plugins/notification/ProtocolTest.java | 185 +++++++++++++++++- 2 files changed, 214 insertions(+), 18 deletions(-) diff --git a/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java b/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java index 07c8be9..466e1ef 100755 --- a/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java @@ -18,7 +18,6 @@ import hudson.model.Job; import hudson.model.ParameterValue; import hudson.model.ParametersAction; -import hudson.model.PasswordParameterValue; import hudson.model.Run; import java.io.IOException; @@ -32,9 +31,6 @@ import java.net.Socket; import java.net.SocketAddress; import java.net.URL; -import java.net.URLConnection; -import java.util.HashMap; -import java.util.Map; import com.google.gson.FieldNamingPolicy; import com.google.gson.Gson; @@ -83,16 +79,39 @@ protected void send(String url, byte[] data) throws IOException { @Override protected void send(String url, byte[] data) throws IOException { URL targetUrl = new URL(url); - URLConnection connection = targetUrl.openConnection(); - if (connection instanceof HttpURLConnection) - ((HttpURLConnection) connection) - .setFixedLengthStreamingMode(data.length); - connection.setDoInput(false); + if (!targetUrl.getProtocol().startsWith("http")) { + throw new IllegalArgumentException("Not an http(s) url: " + url); + } + + HttpURLConnection connection = (HttpURLConnection) targetUrl.openConnection(); + connection.setFixedLengthStreamingMode(data.length); + connection.setDoInput(true); connection.setDoOutput(true); - OutputStream output = connection.getOutputStream(); - output.write(data); - output.flush(); - output.close(); + + connection.connect(); + try { + OutputStream output = connection.getOutputStream(); + try { + output.write(data); + output.flush(); + } finally { + output.close(); + } + } finally { + // Follow an HTTP Temporary Redirect if we get one, + // + // NB: Normally using the HttpURLConnection interface, we'd call + // connection.setInstanceFollowRedirects(true) to enable 307 redirect following but + // since we have the connection in streaming mode this does not work and we instead + // re-direct manually. + if (307 == connection.getResponseCode()) { + String location = connection.getHeaderField("Location"); + connection.disconnect(); + send(location, data); + } else { + connection.disconnect(); + } + } } public void validateUrl(String url) { @@ -152,4 +171,4 @@ public void validateUrl(String url) { throw new RuntimeException("Invalid Url: hostname:port"); } } -} \ No newline at end of file +} diff --git a/src/test/java/com/tikal/hudson/plugins/notification/ProtocolTest.java b/src/test/java/com/tikal/hudson/plugins/notification/ProtocolTest.java index ef61857..9b44fa5 100644 --- a/src/test/java/com/tikal/hudson/plugins/notification/ProtocolTest.java +++ b/src/test/java/com/tikal/hudson/plugins/notification/ProtocolTest.java @@ -23,15 +23,192 @@ */ package com.tikal.hudson.plugins.notification; -import junit.framework.TestCase; - import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.LinkedList; +import java.util.List; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingQueue; + +import javax.servlet.Servlet; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import com.google.common.base.Objects; +import com.google.common.io.CharStreams; + +import org.mortbay.jetty.HttpHeaders; +import org.mortbay.jetty.Server; +import org.mortbay.jetty.bio.SocketConnector; +import org.mortbay.jetty.servlet.ServletHandler; +import org.mortbay.jetty.servlet.ServletHolder; + +import junit.framework.TestCase; /** * @author Kohsuke Kawaguchi */ public class ProtocolTest extends TestCase { - public void testHttpPost() throws IOException { - Protocol.HTTP.send("http://www.google.com/","Hello".getBytes()); + + static class Request { + private final String url; + private final String method; + private final String body; + + Request(HttpServletRequest request) throws IOException { + this(request.getRequestURL().toString(), request.getMethod(), CharStreams.toString(request.getReader())); + } + + Request(String url, String method, String body) { + this.url = url; + this.method = method; + this.body = body; + } + + @Override + public int hashCode() { + return Objects.hashCode(url, method, body); + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof Request)) { + return false; + } + Request other = (Request) obj; + return Objects.equal(url, other.url) + && Objects.equal(method, other.method) + && Objects.equal(body, other.body); + } + + @Override + public String toString() { + return Objects.toStringHelper(this) + .add("url", url) + .add("method", method) + .add("body", body) + .toString(); + } + } + + static class RecordingServlet extends HttpServlet { + private final BlockingQueue requests; + + public RecordingServlet(BlockingQueue requests) { + this.requests = requests; + } + + @Override + protected void doPost(HttpServletRequest httpRequest, HttpServletResponse httpResponse) + throws ServletException, IOException { + + Request request = new Request(httpRequest); + try { + requests.put(request); + } catch (InterruptedException e) { + throw new ServletException(e); + } + + doPost(request, httpResponse); + } + + protected void doPost(Request request, HttpServletResponse httpResponse) throws IOException { + // noop } + } + + static class RedirectHandler extends RecordingServlet { + private final String redirectURI; + + RedirectHandler(BlockingQueue requests, String redirectURI) { + super(requests); + this.redirectURI = redirectURI; + } + + @Override + protected void doPost(Request request, HttpServletResponse httpResponse) throws IOException { + httpResponse.setStatus(HttpServletResponse.SC_TEMPORARY_REDIRECT); + httpResponse.setHeader(HttpHeaders.LOCATION, redirectURI); + } + } + + private List servers; + + interface UrlFactory { + String getUrl(String path); + } + + private UrlFactory startServer(Servlet servlet, String path) throws Exception { + SocketConnector connector = new SocketConnector(); + connector.setPort(0); + connector.open(); + + Server server = new Server(); + server.addConnector(connector); + + ServletHandler servletHandler = new ServletHandler(); + servletHandler.addServletWithMapping(new ServletHolder(servlet), path); + server.addHandler(servletHandler); + + server.start(); + servers.add(server); + + final URL serverUrl = new URL(String.format("http://localhost:%d", connector.getLocalPort())); + return new UrlFactory() { + public String getUrl(String path) { + try { + return new URL(serverUrl, path).toExternalForm(); + } catch (MalformedURLException e) { + throw new IllegalArgumentException(e); + } + } + }; + } + + @Override + public void setUp() throws Exception { + servers = new LinkedList(); + } + + @Override + public void tearDown() throws Exception { + for (Server server : servers) { + server.stop(); + } + } + + public void testHttpPost() throws Exception { + BlockingQueue requests = new LinkedBlockingQueue(); + + UrlFactory urlFactory = startServer(new RecordingServlet(requests), "/realpath"); + + assertTrue(requests.isEmpty()); + + String uri = urlFactory.getUrl("/realpath"); + Protocol.HTTP.send(uri, "Hello".getBytes()); + + assertEquals(new Request(uri, "POST", "Hello"), requests.take()); + assertTrue(requests.isEmpty()); + } + + public void testHttpPostWithRedirects() throws Exception { + BlockingQueue requests = new LinkedBlockingQueue(); + + UrlFactory urlFactory = startServer(new RecordingServlet(requests), "/realpath"); + + String redirectUri = urlFactory.getUrl("/realpath"); + UrlFactory redirectorUrlFactory = startServer(new RedirectHandler(requests, redirectUri), "/path"); + + assertTrue(requests.isEmpty()); + + String uri = redirectorUrlFactory.getUrl("/path"); + Protocol.HTTP.send(uri, "RedirectMe".getBytes()); + + assertEquals(new Request(uri, "POST", "RedirectMe"), requests.take()); + assertEquals(new Request(redirectUri, "POST", "RedirectMe"), requests.take()); + assertTrue(requests.isEmpty()); + } } From 86371979bdefd5228cfb9fb10640c1337462d290 Mon Sep 17 00:00:00 2001 From: Jonathan Edwards Date: Mon, 19 Nov 2012 12:34:47 +0100 Subject: [PATCH 031/214] Set the HTTP request property to appplication/json to facilitate proper handling of the JSON notification. --- .../java/com/tikal/hudson/plugins/notification/Protocol.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java b/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java index 466e1ef..8872895 100755 --- a/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java @@ -84,6 +84,7 @@ protected void send(String url, byte[] data) throws IOException { } HttpURLConnection connection = (HttpURLConnection) targetUrl.openConnection(); + connection.setRequestProperty("Content-Type", "application/json;charset=UTF-8"); connection.setFixedLengthStreamingMode(data.length); connection.setDoInput(true); connection.setDoOutput(true); From f032d46c1858e05a9c7a117f208e5e5e8ebccbcd Mon Sep 17 00:00:00 2001 From: Jack Repenning Date: Fri, 30 Nov 2012 18:06:02 -0800 Subject: [PATCH 032/214] Do BasicAuth, if provided in URL --- .../com/tikal/hudson/plugins/notification/Protocol.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java b/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java index 338ad49..6bf6bde 100755 --- a/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java @@ -33,6 +33,8 @@ import java.net.SocketAddress; import java.net.URL; +import javax.xml.bind.DatatypeConverter; + import com.google.gson.FieldNamingPolicy; import com.google.gson.Gson; import com.google.gson.GsonBuilder; @@ -86,6 +88,12 @@ protected void send(String url, byte[] data) throws IOException { HttpURLConnection connection = (HttpURLConnection) targetUrl.openConnection(); connection.setRequestProperty("Content-Type", "application/json;charset=UTF-8"); + String userInfo = targetUrl.getUserInfo(); + if (null != userInfo) { + String b64UserInfo = DatatypeConverter.printBase64Binary(userInfo.getBytes()); + String authorizationHeader = "Basic " + b64UserInfo; + connection.setRequestProperty("Authorization", authorizationHeader); + } connection.setFixedLengthStreamingMode(data.length); connection.setDoInput(true); connection.setDoOutput(true); From bcc692845fa9c41efef3f00dc1a04b198fecd968 Mon Sep 17 00:00:00 2001 From: Jack Repenning Date: Mon, 3 Dec 2012 13:55:18 -0800 Subject: [PATCH 033/214] Provide help p anel hint to this capability --- .../notification/HudsonNotificationProperty/help-url.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/resources/com/tikal/hudson/plugins/notification/HudsonNotificationProperty/help-url.html b/src/main/resources/com/tikal/hudson/plugins/notification/HudsonNotificationProperty/help-url.html index 261993e..1050173 100644 --- a/src/main/resources/com/tikal/hudson/plugins/notification/HudsonNotificationProperty/help-url.html +++ b/src/main/resources/com/tikal/hudson/plugins/notification/HudsonNotificationProperty/help-url.html @@ -3,6 +3,6 @@
  • URL format for UDP and TCP protocols is (hostname|IpAddress):portNumber, e.g. 10.10.10.10:12345
  • URL format for HTTP protocol is any legal http address, e.g. - http://myhost.com:8080/monitor
  • + http://[user:password@]myhost.com:8080/monitor - \ No newline at end of file + From a82ba4133effbda047719da7f1fbc95cf15ad5ba Mon Sep 17 00:00:00 2001 From: Jack Repenning Date: Fri, 7 Dec 2012 14:14:48 -0800 Subject: [PATCH 034/214] Provide test case testHttpPostWithBasicAuth --- .../plugins/notification/ProtocolTest.java | 43 +++++++++++++++++-- 1 file changed, 39 insertions(+), 4 deletions(-) diff --git a/src/test/java/com/tikal/hudson/plugins/notification/ProtocolTest.java b/src/test/java/com/tikal/hudson/plugins/notification/ProtocolTest.java index 9b44fa5..5230b20 100644 --- a/src/test/java/com/tikal/hudson/plugins/notification/ProtocolTest.java +++ b/src/test/java/com/tikal/hudson/plugins/notification/ProtocolTest.java @@ -36,6 +36,7 @@ import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import javax.xml.bind.DatatypeConverter; import com.google.common.base.Objects; import com.google.common.io.CharStreams; @@ -59,7 +60,17 @@ static class Request { private final String body; Request(HttpServletRequest request) throws IOException { - this(request.getRequestURL().toString(), request.getMethod(), CharStreams.toString(request.getReader())); + if (null == request.getHeader("Authorization")) { + this.url = request.getRequestURL().toString(); + } + else { + String auth = request.getHeader("Authorization").split(" ")[1]; + String b64UserInfo = auth; + String userInfo = new String(DatatypeConverter.parseBase64Binary(auth)) + "@"; + this.url = request.getRequestURL().toString().replaceFirst("^http://", "http://" + userInfo); + } + this.method = request.getMethod(); + this.body = CharStreams.toString(request.getReader()); } Request(String url, String method, String body) { @@ -142,6 +153,10 @@ interface UrlFactory { } private UrlFactory startServer(Servlet servlet, String path) throws Exception { + return startSecureServer(servlet, path, ""); + } + + private UrlFactory startSecureServer(Servlet servlet, String path, String authority) throws Exception { SocketConnector connector = new SocketConnector(); connector.setPort(0); connector.open(); @@ -156,8 +171,12 @@ private UrlFactory startServer(Servlet servlet, String path) throws Exception { server.start(); servers.add(server); - final URL serverUrl = new URL(String.format("http://localhost:%d", connector.getLocalPort())); - return new UrlFactory() { + if (!authority.isEmpty()) { + authority += "@"; + } + + final URL serverUrl = new URL(String.format("http://" + authority + "localhost:%d", connector.getLocalPort())); + return new UrlFactory() { public String getUrl(String path) { try { return new URL(serverUrl, path).toExternalForm(); @@ -194,7 +213,23 @@ public void testHttpPost() throws Exception { assertTrue(requests.isEmpty()); } - public void testHttpPostWithRedirects() throws Exception { + public void testHttpPostWithBasicAuth() throws Exception { + BlockingQueue requests = new LinkedBlockingQueue(); + + UrlFactory urlFactory = startSecureServer(new RecordingServlet(requests), "/realpath", "fred:foo"); + + assertTrue(requests.isEmpty()); + + String uri = urlFactory.getUrl("/realpath"); + Protocol.HTTP.send(uri, "Hello".getBytes()); + + // HttpServletRequests extract userInfo into Authorization header, + // so Request(HttpServletRequest) has reassembled it into uri + assertEquals(new Request(uri, "POST", "Hello"), requests.take()); + assertTrue(requests.isEmpty()); + } + + public void testHttpPostWithRedirects() throws Exception { BlockingQueue requests = new LinkedBlockingQueue(); UrlFactory urlFactory = startServer(new RecordingServlet(requests), "/realpath"); From 3d11ad6803b4ce80e7ca4424dbf0dd8bb56a4997 Mon Sep 17 00:00:00 2001 From: Jack Repenning Date: Fri, 7 Dec 2012 17:11:54 -0800 Subject: [PATCH 035/214] Enhanced BasicAuth verification Formatting: * Fix up some whitespace * Don't concatenate strings as input to String.format --- .../hudson/plugins/notification/Protocol.java | 6 +++--- .../plugins/notification/ProtocolTest.java | 16 +++++++++++----- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java b/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java index 6bf6bde..cd47697 100755 --- a/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java @@ -90,9 +90,9 @@ protected void send(String url, byte[] data) throws IOException { connection.setRequestProperty("Content-Type", "application/json;charset=UTF-8"); String userInfo = targetUrl.getUserInfo(); if (null != userInfo) { - String b64UserInfo = DatatypeConverter.printBase64Binary(userInfo.getBytes()); - String authorizationHeader = "Basic " + b64UserInfo; - connection.setRequestProperty("Authorization", authorizationHeader); + String b64UserInfo = DatatypeConverter.printBase64Binary(userInfo.getBytes()); + String authorizationHeader = "Basic " + b64UserInfo; + connection.setRequestProperty("Authorization", authorizationHeader); } connection.setFixedLengthStreamingMode(data.length); connection.setDoInput(true); diff --git a/src/test/java/com/tikal/hudson/plugins/notification/ProtocolTest.java b/src/test/java/com/tikal/hudson/plugins/notification/ProtocolTest.java index 5230b20..12af338 100644 --- a/src/test/java/com/tikal/hudson/plugins/notification/ProtocolTest.java +++ b/src/test/java/com/tikal/hudson/plugins/notification/ProtocolTest.java @@ -58,16 +58,19 @@ static class Request { private final String url; private final String method; private final String body; + private final String userInfo; Request(HttpServletRequest request) throws IOException { if (null == request.getHeader("Authorization")) { this.url = request.getRequestURL().toString(); + this.userInfo = null; } else { String auth = request.getHeader("Authorization").split(" ")[1]; String b64UserInfo = auth; String userInfo = new String(DatatypeConverter.parseBase64Binary(auth)) + "@"; this.url = request.getRequestURL().toString().replaceFirst("^http://", "http://" + userInfo); + this.userInfo = userInfo; } this.method = request.getMethod(); this.body = CharStreams.toString(request.getReader()); @@ -77,6 +80,7 @@ static class Request { this.url = url; this.method = method; this.body = body; + this.userInfo = null; } @Override @@ -153,7 +157,7 @@ interface UrlFactory { } private UrlFactory startServer(Servlet servlet, String path) throws Exception { - return startSecureServer(servlet, path, ""); + return startSecureServer(servlet, path, ""); } private UrlFactory startSecureServer(Servlet servlet, String path, String authority) throws Exception { @@ -172,11 +176,11 @@ private UrlFactory startSecureServer(Servlet servlet, String path, String author servers.add(server); if (!authority.isEmpty()) { - authority += "@"; + authority += "@"; } - final URL serverUrl = new URL(String.format("http://" + authority + "localhost:%d", connector.getLocalPort())); - return new UrlFactory() { + final URL serverUrl = new URL(String.format("http://%slocalhost:%d", authority, connector.getLocalPort())); + return new UrlFactory() { public String getUrl(String path) { try { return new URL(serverUrl, path).toExternalForm(); @@ -225,8 +229,10 @@ public void testHttpPostWithBasicAuth() throws Exception { // HttpServletRequests extract userInfo into Authorization header, // so Request(HttpServletRequest) has reassembled it into uri - assertEquals(new Request(uri, "POST", "Hello"), requests.take()); + Request theRequest = requests.take(); assertTrue(requests.isEmpty()); + assertEquals(new Request(uri, "POST", "Hello"), theRequest); + assertNotNull(theRequest); } public void testHttpPostWithRedirects() throws Exception { From 8a5acd433cec9075ed4390606d7ee2561bc01f99 Mon Sep 17 00:00:00 2001 From: Jack Repenning Date: Thu, 13 Dec 2012 19:18:11 -0800 Subject: [PATCH 036/214] Correctly test migration of user info from URI to header Also, remove some unused variables. --- .../plugins/notification/ProtocolTest.java | 23 ++++++++++++++----- 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/src/test/java/com/tikal/hudson/plugins/notification/ProtocolTest.java b/src/test/java/com/tikal/hudson/plugins/notification/ProtocolTest.java index 12af338..ada6d92 100644 --- a/src/test/java/com/tikal/hudson/plugins/notification/ProtocolTest.java +++ b/src/test/java/com/tikal/hudson/plugins/notification/ProtocolTest.java @@ -67,10 +67,8 @@ static class Request { } else { String auth = request.getHeader("Authorization").split(" ")[1]; - String b64UserInfo = auth; - String userInfo = new String(DatatypeConverter.parseBase64Binary(auth)) + "@"; - this.url = request.getRequestURL().toString().replaceFirst("^http://", "http://" + userInfo); - this.userInfo = userInfo; + this.userInfo = new String(DatatypeConverter.parseBase64Binary(auth)) + "@"; + this.url = request.getRequestURL().toString(); } this.method = request.getMethod(); this.body = CharStreams.toString(request.getReader()); @@ -107,6 +105,20 @@ public String toString() { .add("body", body) .toString(); } + + public String getUrl() { + return url; + } + + public String getUrlWithAuthority() { + if (null == userInfo) { + // Detect possible bug: userInfo never moved from URI to Authorization header + return null; + } + else { + return url.replaceFirst("^http://", "http://" + userInfo); + } + } } static class RecordingServlet extends HttpServlet { @@ -231,8 +243,7 @@ public void testHttpPostWithBasicAuth() throws Exception { // so Request(HttpServletRequest) has reassembled it into uri Request theRequest = requests.take(); assertTrue(requests.isEmpty()); - assertEquals(new Request(uri, "POST", "Hello"), theRequest); - assertNotNull(theRequest); + assertEquals(new Request(uri, "POST", "Hello").getUrl(), theRequest.getUrlWithAuthority()); } public void testHttpPostWithRedirects() throws Exception { From d0d08f75ea57c56dc29098446d3283a99090af0e Mon Sep 17 00:00:00 2001 From: Jack Repenning Date: Thu, 13 Dec 2012 19:44:35 -0800 Subject: [PATCH 037/214] Format and comment cleanup --- .../plugins/notification/ProtocolTest.java | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/src/test/java/com/tikal/hudson/plugins/notification/ProtocolTest.java b/src/test/java/com/tikal/hudson/plugins/notification/ProtocolTest.java index ada6d92..cb84621 100644 --- a/src/test/java/com/tikal/hudson/plugins/notification/ProtocolTest.java +++ b/src/test/java/com/tikal/hudson/plugins/notification/ProtocolTest.java @@ -61,17 +61,13 @@ static class Request { private final String userInfo; Request(HttpServletRequest request) throws IOException { - if (null == request.getHeader("Authorization")) { - this.url = request.getRequestURL().toString(); - this.userInfo = null; - } - else { - String auth = request.getHeader("Authorization").split(" ")[1]; - this.userInfo = new String(DatatypeConverter.parseBase64Binary(auth)) + "@"; - this.url = request.getRequestURL().toString(); - } + this.url = request.getRequestURL().toString(); this.method = request.getMethod(); this.body = CharStreams.toString(request.getReader()); + String auth = request.getHeader("Authorization"); + this.userInfo = (null == auth) + ? null + : new String(DatatypeConverter.parseBase64Binary(auth.split(" ")[1])) + "@"; } Request(String url, String method, String body) { @@ -239,8 +235,6 @@ public void testHttpPostWithBasicAuth() throws Exception { String uri = urlFactory.getUrl("/realpath"); Protocol.HTTP.send(uri, "Hello".getBytes()); - // HttpServletRequests extract userInfo into Authorization header, - // so Request(HttpServletRequest) has reassembled it into uri Request theRequest = requests.take(); assertTrue(requests.isEmpty()); assertEquals(new Request(uri, "POST", "Hello").getUrl(), theRequest.getUrlWithAuthority()); From f2bf86ecb669aa54a2a08667729ea73cf87fc3b2 Mon Sep 17 00:00:00 2001 From: Tomas Varaneckas Date: Wed, 20 Feb 2013 20:32:44 +0200 Subject: [PATCH 038/214] Added displayName parameter --- .../tikal/hudson/plugins/notification/Protocol.java | 1 + .../plugins/notification/model/BuildState.java | 12 +++++++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java b/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java index 338ad49..96c7bc2 100755 --- a/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java @@ -141,6 +141,7 @@ private byte[] buildMessage(Job job, Run run, Phase phase, String status) { buildState.setUrl(run.getUrl()); buildState.setPhase(phase); buildState.setStatus(status); + buildState.setDisplayName(run.getDisplayName()); String rootUrl = Hudson.getInstance().getRootUrl(); if (rootUrl != null) { diff --git a/src/main/java/com/tikal/hudson/plugins/notification/model/BuildState.java b/src/main/java/com/tikal/hudson/plugins/notification/model/BuildState.java index 253444e..d01406f 100755 --- a/src/main/java/com/tikal/hudson/plugins/notification/model/BuildState.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/model/BuildState.java @@ -28,7 +28,9 @@ public class BuildState { private String status; private String url; - + + private String displayName; + private Map parameters; public int getNumber() { @@ -78,4 +80,12 @@ public Map getParameters() { public void setParameters(Map params) { this.parameters = params; } + + public void setDisplayName(String displayName) { + this.displayName = displayName; + } + + public String getDisplayName() { + return displayName; + } } From db3862a2376e000b9e0aa2c613d80e64a152a710 Mon Sep 17 00:00:00 2001 From: Tomas Varaneckas Date: Wed, 20 Feb 2013 21:18:02 +0200 Subject: [PATCH 039/214] Indent fix --- .../plugins/notification/model/BuildState.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/tikal/hudson/plugins/notification/model/BuildState.java b/src/main/java/com/tikal/hudson/plugins/notification/model/BuildState.java index d01406f..db4df84 100755 --- a/src/main/java/com/tikal/hudson/plugins/notification/model/BuildState.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/model/BuildState.java @@ -81,11 +81,11 @@ public void setParameters(Map params) { this.parameters = params; } - public void setDisplayName(String displayName) { - this.displayName = displayName; - } + public void setDisplayName(String displayName) { + this.displayName = displayName; + } - public String getDisplayName() { - return displayName; - } + public String getDisplayName() { + return displayName; + } } From d30a3fe2dfeeb6229eedcfad54fc7d748a91957b Mon Sep 17 00:00:00 2001 From: Olivier Lamy Date: Tue, 25 Jun 2013 19:49:07 +1000 Subject: [PATCH 040/214] remove and ignore ide files --- .classpath | 10 ---------- .gitignore | 5 +++++ .project | 24 ------------------------ .settings/org.eclipse.jdt.core.prefs | 6 ------ .settings/org.maven.ide.eclipse.prefs | 9 --------- 5 files changed, 5 insertions(+), 49 deletions(-) delete mode 100755 .classpath delete mode 100755 .project delete mode 100755 .settings/org.eclipse.jdt.core.prefs delete mode 100755 .settings/org.maven.ide.eclipse.prefs diff --git a/.classpath b/.classpath deleted file mode 100755 index 4a64e59..0000000 --- a/.classpath +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.gitignore b/.gitignore index c35a4ed..d694a09 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,7 @@ /target /work +.settings/ +.project +.classpath +.idea +*.iml diff --git a/.project b/.project deleted file mode 100755 index b581bda..0000000 --- a/.project +++ /dev/null @@ -1,24 +0,0 @@ - - - hudson-notification-plugin - - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.maven.ide.eclipse.maven2Builder - - - - - - org.eclipse.jdt.groovy.core.groovyNature - org.eclipse.jdt.core.javanature - org.maven.ide.eclipse.maven2Nature - - diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs deleted file mode 100755 index d094481..0000000 --- a/.settings/org.eclipse.jdt.core.prefs +++ /dev/null @@ -1,6 +0,0 @@ -#Tue Oct 05 17:22:06 IST 2010 -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5 -org.eclipse.jdt.core.compiler.compliance=1.5 -org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning -org.eclipse.jdt.core.compiler.source=1.5 diff --git a/.settings/org.maven.ide.eclipse.prefs b/.settings/org.maven.ide.eclipse.prefs deleted file mode 100755 index 86a59f7..0000000 --- a/.settings/org.maven.ide.eclipse.prefs +++ /dev/null @@ -1,9 +0,0 @@ -#Tue Oct 05 17:21:50 IST 2010 -activeProfiles= -eclipse.preferences.version=1 -fullBuildGoals=process-test-resources -includeModules=false -resolveWorkspaceProjects=true -resourceFilterGoals=process-resources resources\:testResources -skipCompilerPlugin=true -version=1 From b71a3f121c1f144e38b46d43852ea038dec8722b Mon Sep 17 00:00:00 2001 From: Olivier Lamy Date: Tue, 25 Jun 2013 19:53:28 +1000 Subject: [PATCH 041/214] upgrade parent --- pom.xml | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/pom.xml b/pom.xml index dd728bd..c76a624 100755 --- a/pom.xml +++ b/pom.xml @@ -1,11 +1,12 @@ 4.0.0 - - org.jenkins-ci.plugins - plugin - 1.465 - + + + org.jenkins-ci.plugins + plugin + 1.480 + com.tikalk.hudson.plugins notification From 2828714e488a982b6f58320cb08c692999573e65 Mon Sep 17 00:00:00 2001 From: Olivier Lamy Date: Tue, 25 Jun 2013 19:54:06 +1000 Subject: [PATCH 042/214] fix repositories declaration --- pom.xml | 38 +++++++++++++++++++++++++------------- 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/pom.xml b/pom.xml index c76a624..2252376 100755 --- a/pom.xml +++ b/pom.xml @@ -16,21 +16,33 @@ Sends notifications about jobs phases and status https://wiki.jenkins-ci.org/display/JENKINS/Notification+Plugin - - - repo.jenkins-ci.org - http://repo.jenkins-ci.org/public/ - - + + + repo.jenkins-ci.org + http://repo.jenkins-ci.org/public/ + + true + + + false + + + - - - repo.jenkins-ci.org - http://repo.jenkins-ci.org/public/ - - + + + repo.jenkins-ci.org + http://repo.jenkins-ci.org/public/ + + true + + + false + + + - + com.google.code.gson gson From feb72429cf1ac8fd6b49166735472321e2935966 Mon Sep 17 00:00:00 2001 From: Olivier Lamy Date: Tue, 25 Jun 2013 20:11:08 +1000 Subject: [PATCH 043/214] merge from git@github.com:guillaumerose/notification-plugin.git master --- .../hudson/plugins/notification/Endpoint.java | 12 +++- .../hudson/plugins/notification/Format.java | 44 +++++++++++++++ .../plugins/notification/JobListener.java | 15 +---- .../hudson/plugins/notification/Phase.java | 55 ++++++++++++++++++- .../hudson/plugins/notification/Protocol.java | 15 ++--- .../plugins/notification/model/JobState.java | 3 + .../HudsonNotificationProperty/config.jelly | 10 ++++ 7 files changed, 131 insertions(+), 23 deletions(-) create mode 100644 src/main/java/com/tikal/hudson/plugins/notification/Format.java diff --git a/src/main/java/com/tikal/hudson/plugins/notification/Endpoint.java b/src/main/java/com/tikal/hudson/plugins/notification/Endpoint.java index a2abce6..2f79d97 100644 --- a/src/main/java/com/tikal/hudson/plugins/notification/Endpoint.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/Endpoint.java @@ -22,13 +22,15 @@ public class Endpoint { private Protocol protocol; + private Format format; private String url; @DataBoundConstructor - public Endpoint(Protocol protocol, String url) { + public Endpoint(Protocol protocol, String url, Format format) { this.protocol = protocol; this.url = url; + this.format = format; } public Protocol getProtocol() { @@ -46,6 +48,14 @@ public String getUrl() { public void setUrl(String url) { this.url = url; } + + public Format getFormat() { + return format; + } + + public void setFormat(Format format) { + this.format = format; + } public FormValidation doCheckURL(@QueryParameter(value = "url", fixEmpty = true) String url) { if (url.equals("111")) diff --git a/src/main/java/com/tikal/hudson/plugins/notification/Format.java b/src/main/java/com/tikal/hudson/plugins/notification/Format.java new file mode 100644 index 0000000..776985f --- /dev/null +++ b/src/main/java/com/tikal/hudson/plugins/notification/Format.java @@ -0,0 +1,44 @@ +/** + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.tikal.hudson.plugins.notification; + +import java.io.IOException; + +import com.google.gson.FieldNamingPolicy; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.thoughtworks.xstream.XStream; +import com.tikal.hudson.plugins.notification.model.JobState; + +public enum Format { + XML { + private XStream xstream = new XStream(); + + @Override + protected byte[] serialize(JobState jobState) throws IOException { + xstream.processAnnotations(JobState.class); + return xstream.toXML(jobState).getBytes(); + } + }, + JSON { + private Gson gson = new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES).create(); + + @Override + protected byte[] serialize(JobState jobState) throws IOException { + return gson.toJson(jobState).getBytes(); + } + }; + + abstract protected byte[] serialize(JobState jobState) throws IOException; +} diff --git a/src/main/java/com/tikal/hudson/plugins/notification/JobListener.java b/src/main/java/com/tikal/hudson/plugins/notification/JobListener.java index d85807b..46a6a0c 100755 --- a/src/main/java/com/tikal/hudson/plugins/notification/JobListener.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/JobListener.java @@ -14,7 +14,6 @@ package com.tikal.hudson.plugins.notification; import hudson.Extension; -import hudson.model.Result; import hudson.model.TaskListener; import hudson.model.Run; import hudson.model.listeners.RunListener; @@ -29,25 +28,17 @@ public JobListener() { @Override public void onStarted(Run r, TaskListener listener) { - Phase.STARTED.handlePhase(r, getStatus(r), listener); + Phase.STARTED.handle(r, listener); } @Override public void onCompleted(Run r, TaskListener listener) { - Phase.COMPLETED.handlePhase(r, getStatus(r), listener); + Phase.COMPLETED.handle(r, listener); } @Override public void onFinalized(Run r) { - Phase.FINISHED.handlePhase(r, getStatus(r), TaskListener.NULL); + Phase.FINISHED.handle(r, TaskListener.NULL); } - private String getStatus(Run r) { - Result result = r.getResult(); - String status = null; - if (result != null) { - status = result.toString(); - } - return status; - } } \ No newline at end of file diff --git a/src/main/java/com/tikal/hudson/plugins/notification/Phase.java b/src/main/java/com/tikal/hudson/plugins/notification/Phase.java index b7cf4d4..91e4663 100755 --- a/src/main/java/com/tikal/hudson/plugins/notification/Phase.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/Phase.java @@ -13,28 +13,77 @@ */ package com.tikal.hudson.plugins.notification; +import hudson.EnvVars; +import hudson.model.AbstractBuild; +import hudson.model.Hudson; +import hudson.model.Job; +import hudson.model.ParameterValue; +import hudson.model.ParametersAction; +import hudson.model.Result; import hudson.model.Run; import hudson.model.TaskListener; import java.io.IOException; import java.util.List; +import com.tikal.hudson.plugins.notification.model.BuildState; +import com.tikal.hudson.plugins.notification.model.JobState; +@SuppressWarnings({ "unchecked", "rawtypes" }) public enum Phase { STARTED, COMPLETED, FINISHED; - @SuppressWarnings({ "unchecked", "rawtypes" }) - public void handlePhase(Run run, String status, TaskListener listener) { + public void handle(Run run, TaskListener listener) { HudsonNotificationProperty property = (HudsonNotificationProperty) run.getParent().getProperty(HudsonNotificationProperty.class); if (property != null) { List targets = property.getEndpoints(); for (Endpoint target : targets) { try { - target.getProtocol().sendNotification(target.getUrl(), run.getParent(), run, this, status); + JobState jobState = buildJobState(run.getParent(), run); + target.getProtocol().send(target.getUrl(), target.getFormat().serialize(jobState)); } catch (IOException e) { e.printStackTrace(listener.error("Failed to notify "+target)); } } } } + + private JobState buildJobState(Job job, Run run) { + JobState jobState = new JobState(); + jobState.setName(job.getName()); + jobState.setUrl(job.getUrl()); + BuildState buildState = new BuildState(); + buildState.setNumber(run.number); + buildState.setUrl(run.getUrl()); + buildState.setPhase(this); + buildState.setStatus(getStatus(run)); + + String rootUrl = Hudson.getInstance().getRootUrl(); + if (rootUrl != null) { + buildState.setFullUrl(rootUrl + run.getUrl()); + } + + jobState.setBuild(buildState); + + ParametersAction paramsAction = run.getAction(ParametersAction.class); + if (paramsAction != null && run instanceof AbstractBuild) { + AbstractBuild build = (AbstractBuild) run; + EnvVars env = new EnvVars(); + for (ParameterValue value : paramsAction.getParameters()) + if (!value.isSensitive()) + value.buildEnvVars(build, env); + buildState.setParameters(env); + } + + return jobState; + } + + private String getStatus(Run r) { + Result result = r.getResult(); + String status = null; + if (result != null) { + status = result.toString(); + } + return status; + } } \ No newline at end of file diff --git a/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java b/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java index 22dae6f..67fb9bb 100755 --- a/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java @@ -13,13 +13,6 @@ */ package com.tikal.hudson.plugins.notification; -import hudson.EnvVars; -import hudson.model.AbstractBuild; -import hudson.model.Hudson; -import hudson.model.Job; -import hudson.model.ParameterValue; -import hudson.model.ParametersAction; -import hudson.model.Run; import java.io.IOException; import java.io.OutputStream; @@ -40,6 +33,13 @@ import com.google.gson.GsonBuilder; import com.tikal.hudson.plugins.notification.model.BuildState; import com.tikal.hudson.plugins.notification.model.JobState; +import hudson.EnvVars; +import hudson.model.AbstractBuild; +import hudson.model.Hudson; +import hudson.model.Job; +import hudson.model.ParameterValue; +import hudson.model.ParametersAction; +import hudson.model.Run; @SuppressWarnings("rawtypes") public enum Protocol { @@ -133,6 +133,7 @@ public void validateUrl(String url) { } }; + private Gson gson = new GsonBuilder().setFieldNamingPolicy( FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES).create(); diff --git a/src/main/java/com/tikal/hudson/plugins/notification/model/JobState.java b/src/main/java/com/tikal/hudson/plugins/notification/model/JobState.java index a2328a4..9920d0e 100755 --- a/src/main/java/com/tikal/hudson/plugins/notification/model/JobState.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/model/JobState.java @@ -13,6 +13,9 @@ */ package com.tikal.hudson.plugins.notification.model; +import com.thoughtworks.xstream.annotations.XStreamAlias; + +@XStreamAlias("job") public class JobState { private String name; diff --git a/src/main/resources/com/tikal/hudson/plugins/notification/HudsonNotificationProperty/config.jelly b/src/main/resources/com/tikal/hudson/plugins/notification/HudsonNotificationProperty/config.jelly index f4f9127..8f5a1b2 100755 --- a/src/main/resources/com/tikal/hudson/plugins/notification/HudsonNotificationProperty/config.jelly +++ b/src/main/resources/com/tikal/hudson/plugins/notification/HudsonNotificationProperty/config.jelly @@ -8,6 +8,16 @@
    + + + + +
    + + + +
    From 7ceaf08d1355ef073beba7a46bdcf91f01150872 Mon Sep 17 00:00:00 2001 From: Olivier Lamy Date: Sat, 29 Jun 2013 09:58:52 +1000 Subject: [PATCH 044/214] make json as default if none --- .../com/tikal/hudson/plugins/notification/Endpoint.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/tikal/hudson/plugins/notification/Endpoint.java b/src/main/java/com/tikal/hudson/plugins/notification/Endpoint.java index 2f79d97..8f5e760 100644 --- a/src/main/java/com/tikal/hudson/plugins/notification/Endpoint.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/Endpoint.java @@ -22,7 +22,11 @@ public class Endpoint { private Protocol protocol; - private Format format; + + /** + * json as default + */ + private Format format = Format.JSON; private String url; @@ -50,6 +54,9 @@ public void setUrl(String url) { } public Format getFormat() { + if (this.format==null){ + this.format = Format.JSON; + } return format; } From c03e4dce5af0ce3b950ae22535f5bb7a51868b19 Mon Sep 17 00:00:00 2001 From: Olivier Lamy Date: Sat, 29 Jun 2013 17:30:37 +1000 Subject: [PATCH 045/214] [maven-release-plugin] prepare release notification-1.5 --- pom.xml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index 2252376..45b6468 100755 --- a/pom.xml +++ b/pom.xml @@ -1,5 +1,4 @@ - + 4.0.0 @@ -10,7 +9,7 @@ com.tikalk.hudson.plugins notification - 1.5-SNAPSHOT + 1.5 hpi Jenkins Notification plugin Sends notifications about jobs phases and status From f74d872afe092ee706342039f0a544b3c9bbf561 Mon Sep 17 00:00:00 2001 From: Olivier Lamy Date: Sat, 29 Jun 2013 17:30:50 +1000 Subject: [PATCH 046/214] [maven-release-plugin] prepare for next development iteration --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 45b6468..eb43655 100755 --- a/pom.xml +++ b/pom.xml @@ -9,7 +9,7 @@ com.tikalk.hudson.plugins notification - 1.5 + 1.6-SNAPSHOT hpi Jenkins Notification plugin Sends notifications about jobs phases and status From 3bb5a3139250fe7893f33e594ab18840c3fcc580 Mon Sep 17 00:00:00 2001 From: Wannes Sels Date: Mon, 3 Mar 2014 11:21:57 +0100 Subject: [PATCH 047/214] removed dead code --- .../hudson/plugins/notification/Protocol.java | 51 ------------------- 1 file changed, 51 deletions(-) diff --git a/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java b/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java index 67fb9bb..8ce99b6 100755 --- a/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java @@ -28,20 +28,7 @@ import javax.xml.bind.DatatypeConverter; -import com.google.gson.FieldNamingPolicy; -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; -import com.tikal.hudson.plugins.notification.model.BuildState; -import com.tikal.hudson.plugins.notification.model.JobState; -import hudson.EnvVars; -import hudson.model.AbstractBuild; -import hudson.model.Hudson; -import hudson.model.Job; -import hudson.model.ParameterValue; -import hudson.model.ParametersAction; -import hudson.model.Run; -@SuppressWarnings("rawtypes") public enum Protocol { UDP { @@ -134,44 +121,6 @@ public void validateUrl(String url) { }; - private Gson gson = new GsonBuilder().setFieldNamingPolicy( - FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES).create(); - - public void sendNotification(String url, Job job, Run run, Phase phase, String status) throws IOException { - send(url, buildMessage(job, run, phase, status)); - } - - private byte[] buildMessage(Job job, Run run, Phase phase, String status) { - JobState jobState = new JobState(); - jobState.setName(job.getName()); - jobState.setUrl(job.getUrl()); - BuildState buildState = new BuildState(); - buildState.setNumber(run.number); - buildState.setUrl(run.getUrl()); - buildState.setPhase(phase); - buildState.setStatus(status); - buildState.setDisplayName(run.getDisplayName()); - - String rootUrl = Hudson.getInstance().getRootUrl(); - if (rootUrl != null) { - buildState.setFullUrl(rootUrl + run.getUrl()); - } - - jobState.setBuild(buildState); - - ParametersAction paramsAction = run.getAction(ParametersAction.class); - if (paramsAction != null && run instanceof AbstractBuild) { - AbstractBuild build = (AbstractBuild) run; - EnvVars env = new EnvVars(); - for (ParameterValue value : paramsAction.getParameters()) - if (!value.isSensitive()) - value.buildEnvVars(build, env); - buildState.setParameters(env); - } - - return gson.toJson(jobState).getBytes(); - } - abstract protected void send(String url, byte[] data) throws IOException; public void validateUrl(String url) { From ed88bd744181f5c9d3b3311411638702832505cf Mon Sep 17 00:00:00 2001 From: Wannes Sels Date: Mon, 3 Mar 2014 12:00:54 +0100 Subject: [PATCH 048/214] added optional timeout, defaults to 30 seconds [FIXED JENKINS-22014] --- .../hudson/plugins/notification/Endpoint.java | 15 ++++++++++++++- .../tikal/hudson/plugins/notification/Phase.java | 2 +- .../hudson/plugins/notification/Protocol.java | 16 +++++++++------- .../HudsonNotificationProperty/config.jelly | 8 +++++++- .../HudsonNotificationProperty/help-timeout.html | 1 + .../plugins/notification/ProtocolTest.java | 6 +++--- 6 files changed, 35 insertions(+), 13 deletions(-) create mode 100644 src/main/resources/com/tikal/hudson/plugins/notification/HudsonNotificationProperty/help-timeout.html diff --git a/src/main/java/com/tikal/hudson/plugins/notification/Endpoint.java b/src/main/java/com/tikal/hudson/plugins/notification/Endpoint.java index 8f5e760..872af9e 100644 --- a/src/main/java/com/tikal/hudson/plugins/notification/Endpoint.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/Endpoint.java @@ -21,6 +21,8 @@ public class Endpoint { + public static final Integer DEFAULT_TIMEOUT = 30000; + private Protocol protocol; /** @@ -29,12 +31,23 @@ public class Endpoint { private Format format = Format.JSON; private String url; + + private Integer timeout = DEFAULT_TIMEOUT; @DataBoundConstructor - public Endpoint(Protocol protocol, String url, Format format) { + public Endpoint(Protocol protocol, String url, Format format, Integer timeout) { this.protocol = protocol; this.url = url; this.format = format; + this.setTimeout(timeout); + } + + public int getTimeout() { + return timeout == null ? DEFAULT_TIMEOUT : timeout; + } + + public void setTimeout(Integer timeout) { + this.timeout = timeout; } public Protocol getProtocol() { diff --git a/src/main/java/com/tikal/hudson/plugins/notification/Phase.java b/src/main/java/com/tikal/hudson/plugins/notification/Phase.java index 91e4663..a82155b 100755 --- a/src/main/java/com/tikal/hudson/plugins/notification/Phase.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/Phase.java @@ -40,7 +40,7 @@ public void handle(Run run, TaskListener listener) { for (Endpoint target : targets) { try { JobState jobState = buildJobState(run.getParent(), run); - target.getProtocol().send(target.getUrl(), target.getFormat().serialize(jobState)); + target.getProtocol().send(target.getUrl(), target.getFormat().serialize(jobState), target.getTimeout()); } catch (IOException e) { e.printStackTrace(listener.error("Failed to notify "+target)); } diff --git a/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java b/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java index 8ce99b6..592255b 100755 --- a/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java @@ -33,7 +33,7 @@ public enum Protocol { UDP { @Override - protected void send(String url, byte[] data) throws IOException { + protected void send(String url, byte[] data, int timeout) throws IOException { HostnamePort hostnamePort = HostnamePort.parseUrl(url); DatagramSocket socket = new DatagramSocket(); DatagramPacket packet = new DatagramPacket(data, data.length, InetAddress.getByName(hostnamePort.hostname), hostnamePort.port); @@ -54,11 +54,12 @@ public void validateUrl(String url) { }, TCP { @Override - protected void send(String url, byte[] data) throws IOException { + protected void send(String url, byte[] data, int timeout) throws IOException { HostnamePort hostnamePort = HostnamePort.parseUrl(url); SocketAddress endpoint = new InetSocketAddress(InetAddress.getByName(hostnamePort.hostname), hostnamePort.port); Socket socket = new Socket(); - socket.connect(endpoint); + socket.setSoTimeout(timeout); + socket.connect(endpoint, timeout); OutputStream output = socket.getOutputStream(); output.write(data); output.flush(); @@ -67,7 +68,7 @@ protected void send(String url, byte[] data) throws IOException { }, HTTP { @Override - protected void send(String url, byte[] data) throws IOException { + protected void send(String url, byte[] data, int timeout) throws IOException { URL targetUrl = new URL(url); if (!targetUrl.getProtocol().startsWith("http")) { throw new IllegalArgumentException("Not an http(s) url: " + url); @@ -84,7 +85,8 @@ protected void send(String url, byte[] data) throws IOException { connection.setFixedLengthStreamingMode(data.length); connection.setDoInput(true); connection.setDoOutput(true); - + connection.setConnectTimeout(timeout); + connection.setReadTimeout(timeout); connection.connect(); try { OutputStream output = connection.getOutputStream(); @@ -104,7 +106,7 @@ protected void send(String url, byte[] data) throws IOException { if (307 == connection.getResponseCode()) { String location = connection.getHeaderField("Location"); connection.disconnect(); - send(location, data); + send(location, data,timeout); } else { connection.disconnect(); } @@ -121,7 +123,7 @@ public void validateUrl(String url) { }; - abstract protected void send(String url, byte[] data) throws IOException; + abstract protected void send(String url, byte[] data, int timeout) throws IOException; public void validateUrl(String url) { try { diff --git a/src/main/resources/com/tikal/hudson/plugins/notification/HudsonNotificationProperty/config.jelly b/src/main/resources/com/tikal/hudson/plugins/notification/HudsonNotificationProperty/config.jelly index 8f5a1b2..2563ffc 100755 --- a/src/main/resources/com/tikal/hudson/plugins/notification/HudsonNotificationProperty/config.jelly +++ b/src/main/resources/com/tikal/hudson/plugins/notification/HudsonNotificationProperty/config.jelly @@ -36,12 +36,18 @@
    - + + +
    +
    diff --git a/src/main/resources/com/tikal/hudson/plugins/notification/HudsonNotificationProperty/help-timeout.html b/src/main/resources/com/tikal/hudson/plugins/notification/HudsonNotificationProperty/help-timeout.html new file mode 100644 index 0000000..5e8902f --- /dev/null +++ b/src/main/resources/com/tikal/hudson/plugins/notification/HudsonNotificationProperty/help-timeout.html @@ -0,0 +1 @@ +
    Sets connection timeout (in milliseconds) for TCP and HTTP. Default timeout is 30 seconds (30,000 ms)
    \ No newline at end of file diff --git a/src/test/java/com/tikal/hudson/plugins/notification/ProtocolTest.java b/src/test/java/com/tikal/hudson/plugins/notification/ProtocolTest.java index cb84621..c032ccd 100644 --- a/src/test/java/com/tikal/hudson/plugins/notification/ProtocolTest.java +++ b/src/test/java/com/tikal/hudson/plugins/notification/ProtocolTest.java @@ -219,7 +219,7 @@ public void testHttpPost() throws Exception { assertTrue(requests.isEmpty()); String uri = urlFactory.getUrl("/realpath"); - Protocol.HTTP.send(uri, "Hello".getBytes()); + Protocol.HTTP.send(uri, "Hello".getBytes(),30000); assertEquals(new Request(uri, "POST", "Hello"), requests.take()); assertTrue(requests.isEmpty()); @@ -233,7 +233,7 @@ public void testHttpPostWithBasicAuth() throws Exception { assertTrue(requests.isEmpty()); String uri = urlFactory.getUrl("/realpath"); - Protocol.HTTP.send(uri, "Hello".getBytes()); + Protocol.HTTP.send(uri, "Hello".getBytes(),30000); Request theRequest = requests.take(); assertTrue(requests.isEmpty()); @@ -251,7 +251,7 @@ public void testHttpPostWithRedirects() throws Exception { assertTrue(requests.isEmpty()); String uri = redirectorUrlFactory.getUrl("/path"); - Protocol.HTTP.send(uri, "RedirectMe".getBytes()); + Protocol.HTTP.send(uri, "RedirectMe".getBytes(),30000); assertEquals(new Request(uri, "POST", "RedirectMe"), requests.take()); assertEquals(new Request(redirectUri, "POST", "RedirectMe"), requests.take()); From 2af09e3002ff887a5eaa7577b190f1cbb9c123e3 Mon Sep 17 00:00:00 2001 From: Evgeny Goldin Date: Mon, 9 Jun 2014 14:18:59 +0200 Subject: [PATCH 049/214] Added features: * It is now possible to select job lifecycle event to trigger notification - job started, completed, finalized or all of them (the default behavior). * Scm information is reported - url, branch, commit. Only Git is supported so far. * Artifacts information is reported - Jenkins (if archived) and S3 (if uploaded to S3) URLs. Improvements: * When defining an endpoint - default endpoint timeout (30000) is pre-filled in a form. * When defining an endpoint - protocols order in a dropdown is changed to HTTP, TCP, UDP. * Endpoint URL validation error now includes the faulty URL if it's not empty. * Correct "Content-Type" header is sent, according to XML or JSON payload submitted. * POM dependencies updated. * Various IDEA warning were eliminated, like proper sorting of access modifiers. * Tabs are replaced by 4 spaces. --- pom.xml | 177 ++++++++++------- .../hudson/plugins/notification/Endpoint.java | 124 ++++++------ .../hudson/plugins/notification/Format.java | 40 ++-- .../plugins/notification/HostnamePort.java | 42 ++-- .../HudsonNotificationProperty.java | 32 +-- .../HudsonNotificationPropertyDescriptor.java | 141 ++++++------- .../plugins/notification/JobListener.java | 30 +-- .../hudson/plugins/notification/Phase.java | 167 ++++++++++------ .../hudson/plugins/notification/Protocol.java | 105 +++++----- .../notification/model/BuildState.java | 185 +++++++++++++----- .../plugins/notification/model/JobState.java | 42 ++-- .../plugins/notification/model/ScmState.java | 54 +++++ .../HudsonNotificationProperty/config.jelly | 115 ++++++----- .../HudsonNotificationProperty/help-url.html | 8 +- src/main/resources/index.jelly | 6 +- src/main/webapp/help-globalConfig.html | 14 +- src/main/webapp/help-projectConfig.html | 14 +- .../plugins/notification/ProtocolTest.java | 39 ++-- .../notification/test/HostnamePortTest.java | 26 +-- 19 files changed, 799 insertions(+), 562 deletions(-) create mode 100644 src/main/java/com/tikal/hudson/plugins/notification/model/ScmState.java diff --git a/pom.xml b/pom.xml index eb43655..98477d8 100755 --- a/pom.xml +++ b/pom.xml @@ -1,77 +1,120 @@ - - 4.0.0 + - - org.jenkins-ci.plugins - plugin - 1.480 - + 4.0.0 + com.tikalk.hudson.plugins + notification + 1.6-SNAPSHOT + hpi + Jenkins Notification plugin + Sends notifications about jobs phases and status + https://wiki.jenkins-ci.org/display/JENKINS/Notification+Plugin - com.tikalk.hudson.plugins - notification - 1.6-SNAPSHOT - hpi - Jenkins Notification plugin - Sends notifications about jobs phases and status - https://wiki.jenkins-ci.org/display/JENKINS/Notification+Plugin + + org.jenkins-ci.plugins + plugin + 1.566 + - - - repo.jenkins-ci.org - http://repo.jenkins-ci.org/public/ - - true - - - false - - - + + + repo.jenkins-ci.org + http://repo.jenkins-ci.org/public/ + + true + + + false + + + - - - repo.jenkins-ci.org - http://repo.jenkins-ci.org/public/ - - true - - - false - - - + + + repo.jenkins-ci.org + http://repo.jenkins-ci.org/public/ + + true + + + false + + + - - - com.google.code.gson - gson - 1.4 - - + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.1 + + + + org.jenkins-ci.tools + maven-hpi-plugin + 1.109 + + + + - - - markb - Mark Berner - markb@tikalk.com - Tikal Knowledge - http://tikalk.com - - + + + + com.google.code.gson + gson + 2.2.4 + + + + org.jenkins-ci.plugins + s3 + 0.6 + true + + - - scm:git:git://github.com/jenkinsci/notification-plugin.git - scm:git:git@github.com:jenkinsci/notification-plugin.git - http://github.com/jenkinsci/notification-plugin - + + + markb + Mark Berner + markb@tikalk.com + Tikal Knowledge + http://tikalk.com + + + hagzag + Haggai Philip Zagury + hagzag@tikalk.com + Tikal Knowledge + http://tikalk.com + + + evgenyg + Evgeny Goldin + evgenyg@gmail.com + AKQA + http://akqa.com + + - - - The Apache Software License, Version 2.0 - http://www.apache.org/licenses/LICENSE-2.0.txt - repo - A business-friendly OSS license - - + + scm:git:git://github.com/jenkinsci/notification-plugin.git + scm:git:git@github.com:jenkinsci/notification-plugin.git + http://github.com/jenkinsci/notification-plugin + + + + The Apache Software License, Version 2.0 + http://www.apache.org/licenses/LICENSE-2.0.txt + repo + A business-friendly OSS license + + + diff --git a/src/main/java/com/tikal/hudson/plugins/notification/Endpoint.java b/src/main/java/com/tikal/hudson/plugins/notification/Endpoint.java index 872af9e..b177f33 100644 --- a/src/main/java/com/tikal/hudson/plugins/notification/Endpoint.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/Endpoint.java @@ -15,74 +15,88 @@ package com.tikal.hudson.plugins.notification; import hudson.util.FormValidation; - import org.kohsuke.stapler.DataBoundConstructor; import org.kohsuke.stapler.QueryParameter; public class Endpoint { - public static final Integer DEFAULT_TIMEOUT = 30000; + public static final Integer DEFAULT_TIMEOUT = 30000; - private Protocol protocol; + private Protocol protocol; /** * json as default */ - private Format format = Format.JSON; - - private String url; - - private Integer timeout = DEFAULT_TIMEOUT; - - @DataBoundConstructor - public Endpoint(Protocol protocol, String url, Format format, Integer timeout) { - this.protocol = protocol; - this.url = url; - this.format = format; - this.setTimeout(timeout); - } - - public int getTimeout() { - return timeout == null ? DEFAULT_TIMEOUT : timeout; - } - - public void setTimeout(Integer timeout) { - this.timeout = timeout; - } - - public Protocol getProtocol() { - return protocol; - } - - public void setProtocol(Protocol protocol) { - this.protocol = protocol; - } - - public String getUrl() { - return url; - } - - public void setUrl(String url) { - this.url = url; - } - - public Format getFormat() { + private Format format = Format.JSON; + + private String url; + + private String event = "all"; + + private Integer timeout = DEFAULT_TIMEOUT; + + @DataBoundConstructor + public Endpoint(Protocol protocol, String url, String event, Format format, Integer timeout) { + setProtocol( protocol ); + setUrl( url ); + setEvent( event ); + setFormat( format ); + setTimeout( timeout ); + } + + public int getTimeout() { + return timeout == null ? DEFAULT_TIMEOUT : timeout; + } + + public void setTimeout(Integer timeout) { + this.timeout = timeout; + } + + public Protocol getProtocol() { + return protocol; + } + + public void setProtocol(Protocol protocol) { + this.protocol = protocol; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public String getEvent (){ + return event; + } + + public void setEvent ( String event ){ + this.event = event; + } + + public Format getFormat() { if (this.format==null){ this.format = Format.JSON; } - return format; - } - - public void setFormat(Format format) { - this.format = format; - } - - public FormValidation doCheckURL(@QueryParameter(value = "url", fixEmpty = true) String url) { - if (url.equals("111")) - return FormValidation.ok(); - else - return FormValidation.error("There's a problem here"); - } + return format; + } + + public void setFormat(Format format) { + this.format = format; + } + + public FormValidation doCheckURL(@QueryParameter(value = "url", fixEmpty = true) String url) { + if (url.equals("111")) + return FormValidation.ok(); + else + return FormValidation.error("There's a problem here"); + } + + public boolean isJson() { + return getFormat() == Format.JSON; + } @Override public String toString() { diff --git a/src/main/java/com/tikal/hudson/plugins/notification/Format.java b/src/main/java/com/tikal/hudson/plugins/notification/Format.java index 776985f..fa0e777 100644 --- a/src/main/java/com/tikal/hudson/plugins/notification/Format.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/Format.java @@ -13,32 +13,32 @@ */ package com.tikal.hudson.plugins.notification; -import java.io.IOException; - import com.google.gson.FieldNamingPolicy; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.thoughtworks.xstream.XStream; import com.tikal.hudson.plugins.notification.model.JobState; +import java.io.IOException; + public enum Format { - XML { - private XStream xstream = new XStream(); + XML { + private final XStream xstream = new XStream(); + + @Override + protected byte[] serialize(JobState jobState) throws IOException { + xstream.processAnnotations(JobState.class); + return xstream.toXML(jobState).getBytes( "UTF-8" ); + } + }, + JSON { + private final Gson gson = new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES).create(); + + @Override + protected byte[] serialize(JobState jobState) throws IOException { + return gson.toJson(jobState).getBytes( "UTF-8" ); + } + }; - @Override - protected byte[] serialize(JobState jobState) throws IOException { - xstream.processAnnotations(JobState.class); - return xstream.toXML(jobState).getBytes(); - } - }, - JSON { - private Gson gson = new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES).create(); - - @Override - protected byte[] serialize(JobState jobState) throws IOException { - return gson.toJson(jobState).getBytes(); - } - }; - - abstract protected byte[] serialize(JobState jobState) throws IOException; + protected abstract byte[] serialize(JobState jobState) throws IOException; } diff --git a/src/main/java/com/tikal/hudson/plugins/notification/HostnamePort.java b/src/main/java/com/tikal/hudson/plugins/notification/HostnamePort.java index 6dee2a5..d460945 100644 --- a/src/main/java/com/tikal/hudson/plugins/notification/HostnamePort.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/HostnamePort.java @@ -18,28 +18,28 @@ public class HostnamePort { - final public String hostname; + public final String hostname; - final public int port; + public final int port; - public HostnamePort(String hostname, int port) { - this.hostname = hostname; - this.port = port; - } + public HostnamePort(String hostname, int port) { + this.hostname = hostname; + this.port = port; + } - static public HostnamePort parseUrl(String url) { - try { - Scanner scanner = new Scanner(url); - scanner.findInLine("(.+):(\\d{1,5})"); - MatchResult result = scanner.match(); - if (result.groupCount() != 2) { - return null; - } - String hostname = result.group(1); - int port = Integer.valueOf(result.group(2)); - return new HostnamePort(hostname, port); - } catch (Exception e) { - return null; - } - } + public static HostnamePort parseUrl(String url) { + try { + Scanner scanner = new Scanner(url); + scanner.findInLine("(.+):(\\d{1,5})"); + MatchResult result = scanner.match(); + if (result.groupCount() != 2) { + return null; + } + String hostname = result.group(1); + int port = Integer.valueOf(result.group(2)); + return new HostnamePort(hostname, port); + } catch (Exception e) { + return null; + } + } } \ No newline at end of file diff --git a/src/main/java/com/tikal/hudson/plugins/notification/HudsonNotificationProperty.java b/src/main/java/com/tikal/hudson/plugins/notification/HudsonNotificationProperty.java index b685e49..c15be16 100755 --- a/src/main/java/com/tikal/hudson/plugins/notification/HudsonNotificationProperty.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/HudsonNotificationProperty.java @@ -13,28 +13,30 @@ */ package com.tikal.hudson.plugins.notification; -import hudson.model.JobProperty; import hudson.model.AbstractProject; +import hudson.model.JobProperty; +import org.kohsuke.stapler.DataBoundConstructor; +import java.util.ArrayList; import java.util.List; -import org.kohsuke.stapler.DataBoundConstructor; - public class HudsonNotificationProperty extends - JobProperty> { + JobProperty> { - final public List endpoints; + public final List endpoints; - @DataBoundConstructor - public HudsonNotificationProperty(List endpoints) { - this.endpoints = endpoints; - } + @DataBoundConstructor + public HudsonNotificationProperty(List endpoints) { + this.endpoints = new ArrayList( endpoints ); + } - public List getEndpoints() { - return endpoints; - } + public List getEndpoints() { + return endpoints; + } - public HudsonNotificationPropertyDescriptor getDescriptor() { - return (HudsonNotificationPropertyDescriptor) super.getDescriptor(); - } + @SuppressWarnings( "CastToConcreteClass" ) + @Override + public HudsonNotificationPropertyDescriptor getDescriptor() { + return (HudsonNotificationPropertyDescriptor) super.getDescriptor(); + } } \ No newline at end of file diff --git a/src/main/java/com/tikal/hudson/plugins/notification/HudsonNotificationPropertyDescriptor.java b/src/main/java/com/tikal/hudson/plugins/notification/HudsonNotificationPropertyDescriptor.java index b083c08..1503c29 100644 --- a/src/main/java/com/tikal/hudson/plugins/notification/HudsonNotificationPropertyDescriptor.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/HudsonNotificationPropertyDescriptor.java @@ -14,85 +14,88 @@ package com.tikal.hudson.plugins.notification; import hudson.Extension; -import hudson.model.JobPropertyDescriptor; import hudson.model.Job; +import hudson.model.JobPropertyDescriptor; import hudson.util.FormValidation; - -import java.util.ArrayList; -import java.util.List; - import net.sf.json.JSON; import net.sf.json.JSONArray; import net.sf.json.JSONObject; - import org.kohsuke.stapler.QueryParameter; import org.kohsuke.stapler.StaplerRequest; +import java.util.ArrayList; +import java.util.List; + @Extension public final class HudsonNotificationPropertyDescriptor extends JobPropertyDescriptor { - public HudsonNotificationPropertyDescriptor() { - super(HudsonNotificationProperty.class); - load(); - } - - private List endpoints = new ArrayList(); - - public boolean isEnabled() { - return !endpoints.isEmpty(); - } - - public List getTargets() { - return endpoints; - } - - public void setEndpoints(List endpoints) { - this.endpoints = endpoints; - } - - @Override - public boolean isApplicable(@SuppressWarnings("rawtypes") Class jobType) { - return true; - } - - public String getDisplayName() { - return "Hudson Job Notification"; - } - - @Override - public HudsonNotificationProperty newInstance(StaplerRequest req, JSONObject formData) throws FormException { - - List endpoints = new ArrayList(); - if (formData != null && !formData.isNullObject()) { - JSON endpointsData = (JSON) formData.get("endpoints"); - if (endpointsData != null && !endpointsData.isEmpty()) { - if (endpointsData.isArray()) { - JSONArray endpointsArrayData = (JSONArray) endpointsData; - endpoints.addAll(req.bindJSONToList(Endpoint.class, endpointsArrayData)); - } else { - JSONObject endpointsObjectData = (JSONObject) endpointsData; - endpoints.add(req.bindJSON(Endpoint.class, endpointsObjectData)); - } - } - } - HudsonNotificationProperty notificationProperty = new HudsonNotificationProperty(endpoints); - return notificationProperty; - } - - public FormValidation doCheckUrl(@QueryParameter(value = "url", fixEmpty = true) String url, @QueryParameter(value = "protocol") String protocolParameter) { - Protocol protocol = Protocol.valueOf(protocolParameter); - try { - protocol.validateUrl(url); - return FormValidation.ok(); - } catch (Exception e) { - return FormValidation.error(e.getMessage()); - } - } - - @Override - public boolean configure(StaplerRequest req, JSONObject formData) { - save(); - return true; - } + public HudsonNotificationPropertyDescriptor() { + super(HudsonNotificationProperty.class); + load(); + } + + private List endpoints = new ArrayList(); + + public boolean isEnabled() { + return !endpoints.isEmpty(); + } + + public List getTargets() { + return endpoints; + } + + public void setEndpoints(List endpoints) { + this.endpoints = new ArrayList( endpoints ); + } + + @Override + public boolean isApplicable(@SuppressWarnings("rawtypes") Class jobType) { + return true; + } + + @Override + public String getDisplayName() { + return "Hudson Job Notification"; + } + + public int getDefaultTimeout(){ + return Endpoint.DEFAULT_TIMEOUT; + } + + @Override + public HudsonNotificationProperty newInstance(StaplerRequest req, JSONObject formData) throws FormException { + + List endpoints = new ArrayList(); + if (formData != null && !formData.isNullObject()) { + JSON endpointsData = (JSON) formData.get("endpoints"); + if (endpointsData != null && !endpointsData.isEmpty()) { + if (endpointsData.isArray()) { + JSONArray endpointsArrayData = (JSONArray) endpointsData; + endpoints.addAll(req.bindJSONToList(Endpoint.class, endpointsArrayData)); + } else { + JSONObject endpointsObjectData = (JSONObject) endpointsData; + endpoints.add(req.bindJSON(Endpoint.class, endpointsObjectData)); + } + } + } + HudsonNotificationProperty notificationProperty = new HudsonNotificationProperty(endpoints); + return notificationProperty; + } + + public FormValidation doCheckUrl(@QueryParameter(value = "url", fixEmpty = true) String url, @QueryParameter(value = "protocol") String protocolParameter) { + Protocol protocol = Protocol.valueOf(protocolParameter); + try { + protocol.validateUrl(url); + return FormValidation.ok(); + } catch (Exception e) { + return FormValidation.error(e.getMessage()); + } + } + + @Override + public boolean configure(StaplerRequest req, JSONObject formData) { + save(); + return true; + } } \ No newline at end of file diff --git a/src/main/java/com/tikal/hudson/plugins/notification/JobListener.java b/src/main/java/com/tikal/hudson/plugins/notification/JobListener.java index 46a6a0c..c000af1 100755 --- a/src/main/java/com/tikal/hudson/plugins/notification/JobListener.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/JobListener.java @@ -22,23 +22,23 @@ @SuppressWarnings("rawtypes") public class JobListener extends RunListener { - public JobListener() { - super(Run.class); - } + public JobListener() { + super(Run.class); + } - @Override - public void onStarted(Run r, TaskListener listener) { - Phase.STARTED.handle(r, listener); - } + @Override + public void onStarted(Run r, TaskListener listener) { + Phase.STARTED.handle(r, listener); + } - @Override - public void onCompleted(Run r, TaskListener listener) { - Phase.COMPLETED.handle(r, listener); - } + @Override + public void onCompleted(Run r, TaskListener listener) { + Phase.COMPLETED.handle(r, listener); + } - @Override - public void onFinalized(Run r) { - Phase.FINISHED.handle(r, TaskListener.NULL); - } + @Override + public void onFinalized(Run r) { + Phase.FINALIZED.handle(r, TaskListener.NULL); + } } \ No newline at end of file diff --git a/src/main/java/com/tikal/hudson/plugins/notification/Phase.java b/src/main/java/com/tikal/hudson/plugins/notification/Phase.java index a82155b..69e62bd 100755 --- a/src/main/java/com/tikal/hudson/plugins/notification/Phase.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/Phase.java @@ -13,77 +13,118 @@ */ package com.tikal.hudson.plugins.notification; +import com.tikal.hudson.plugins.notification.model.BuildState; +import com.tikal.hudson.plugins.notification.model.JobState; +import com.tikal.hudson.plugins.notification.model.ScmState; import hudson.EnvVars; -import hudson.model.AbstractBuild; -import hudson.model.Hudson; -import hudson.model.Job; -import hudson.model.ParameterValue; -import hudson.model.ParametersAction; -import hudson.model.Result; -import hudson.model.Run; -import hudson.model.TaskListener; +import hudson.model.*; +import jenkins.model.Jenkins; import java.io.IOException; -import java.util.List; - -import com.tikal.hudson.plugins.notification.model.BuildState; -import com.tikal.hudson.plugins.notification.model.JobState; +import java.util.*; @SuppressWarnings({ "unchecked", "rawtypes" }) public enum Phase { - STARTED, COMPLETED, FINISHED; + STARTED, COMPLETED, FINALIZED; + + @SuppressWarnings( "CastToConcreteClass" ) + public void handle(Run run, TaskListener listener) { + + HudsonNotificationProperty property = (HudsonNotificationProperty) run.getParent().getProperty(HudsonNotificationProperty.class); + if ( property == null ){ return; } + + for ( Endpoint target : property.getEndpoints()) { + if ( isRun( target )) { + listener.getLogger().println( String.format( "Notifying endpoint '%s'", target )); - public void handle(Run run, TaskListener listener) { - HudsonNotificationProperty property = (HudsonNotificationProperty) run.getParent().getProperty(HudsonNotificationProperty.class); - if (property != null) { - List targets = property.getEndpoints(); - for (Endpoint target : targets) { try { - JobState jobState = buildJobState(run.getParent(), run); - target.getProtocol().send(target.getUrl(), target.getFormat().serialize(jobState), target.getTimeout()); - } catch (IOException e) { - e.printStackTrace(listener.error("Failed to notify "+target)); + JobState jobState = buildJobState(run.getParent(), run, listener); + target.getProtocol().send(target.getUrl(), + target.getFormat().serialize(jobState), + target.getTimeout(), + target.isJson()); + } catch (Throwable error) { + error.printStackTrace( listener.error( String.format( "Failed to notify endpoint '%s'", target ))); + listener.getLogger().println( String.format( "Failed to notify endpoint '%s' - %s: %s", + target, error.getClass().getName(), error.getMessage())); + } + } + } + } + + + /** + * Determines if the endpoint specified should be notified at the current job phase. + */ + private boolean isRun( Endpoint endpoint ) { + String event = endpoint.getEvent(); + return (( event == null ) || event.equals( "all" ) || event.equals( this.toString().toLowerCase())); + } + + private JobState buildJobState(Job job, Run run, TaskListener listener) + throws IOException, InterruptedException + { + + Jenkins jenkins = Jenkins.getInstance(); + String rootUrl = jenkins.getRootUrl(); + JobState jobState = new JobState(); + BuildState buildState = new BuildState(); + ScmState scmState = new ScmState(); + Result result = run.getResult(); + ParametersAction paramsAction = run.getAction(ParametersAction.class); + List artifacts = run.getArtifacts(); + EnvVars environment = run.getEnvironment( listener ); + + jobState.setName( job.getName()); + jobState.setUrl( job.getUrl()); + jobState.setBuild( buildState ); + + buildState.setNumber( run.number ); + buildState.setUrl( run.getUrl()); + buildState.setPhase( this ); + buildState.setScm( scmState ); + + if ( result != null ) { + buildState.setStatus(result.toString()); + } + + if ( rootUrl != null ) { + buildState.setFullUrl(rootUrl + run.getUrl()); + } + + if ( artifacts != null ) { + Map> urls = new HashMap>( artifacts.size()); + for ( Run.Artifact a : artifacts ) { + final String artifactUrl = jenkins.getRootUrl() + run.getUrl() + "artifact/" + a.getHref(); + urls.put( a.getFileName(), new ArrayList(){{ add( artifactUrl ); }}); + } + buildState.setArtifacts( urls ); + } + + buildState.updateArtifacts( job, run ); + + if ( paramsAction != null ) { + EnvVars env = new EnvVars(); + for (ParameterValue value : paramsAction.getParameters()){ + if ( ! value.isSensitive()) { + value.buildEnvironment( run, env ); } } - } - } - - private JobState buildJobState(Job job, Run run) { - JobState jobState = new JobState(); - jobState.setName(job.getName()); - jobState.setUrl(job.getUrl()); - BuildState buildState = new BuildState(); - buildState.setNumber(run.number); - buildState.setUrl(run.getUrl()); - buildState.setPhase(this); - buildState.setStatus(getStatus(run)); - - String rootUrl = Hudson.getInstance().getRootUrl(); - if (rootUrl != null) { - buildState.setFullUrl(rootUrl + run.getUrl()); - } - - jobState.setBuild(buildState); - - ParametersAction paramsAction = run.getAction(ParametersAction.class); - if (paramsAction != null && run instanceof AbstractBuild) { - AbstractBuild build = (AbstractBuild) run; - EnvVars env = new EnvVars(); - for (ParameterValue value : paramsAction.getParameters()) - if (!value.isSensitive()) - value.buildEnvVars(build, env); - buildState.setParameters(env); - } - - return jobState; - } - - private String getStatus(Run r) { - Result result = r.getResult(); - String status = null; - if (result != null) { - status = result.toString(); - } - return status; - } + buildState.setParameters(env); + } + + if ( environment.get( "GIT_URL" ) != null ) { + scmState.setUrl( environment.get( "GIT_URL" )); + } + + if ( environment.get( "GIT_BRANCH" ) != null ) { + scmState.setBranch( environment.get( "GIT_BRANCH" )); + } + + if ( environment.get( "GIT_COMMIT" ) != null ) { + scmState.setCommit( environment.get( "GIT_COMMIT" )); + } + + return jobState; + } } \ No newline at end of file diff --git a/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java b/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java index 592255b..e536f5a 100755 --- a/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java @@ -14,68 +14,47 @@ package com.tikal.hudson.plugins.notification; +import javax.xml.bind.DatatypeConverter; import java.io.IOException; import java.io.OutputStream; -import java.net.DatagramPacket; -import java.net.DatagramSocket; -import java.net.HttpURLConnection; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.MalformedURLException; -import java.net.Socket; -import java.net.SocketAddress; -import java.net.URL; - -import javax.xml.bind.DatatypeConverter; +import java.net.*; public enum Protocol { - UDP { - @Override - protected void send(String url, byte[] data, int timeout) throws IOException { + UDP { + @Override + protected void send(String url, byte[] data, int timeout, boolean isJson) throws IOException { HostnamePort hostnamePort = HostnamePort.parseUrl(url); DatagramSocket socket = new DatagramSocket(); DatagramPacket packet = new DatagramPacket(data, data.length, InetAddress.getByName(hostnamePort.hostname), hostnamePort.port); socket.send(packet); - } - - @Override - public void validateUrl(String url) { - try { - HostnamePort hnp = HostnamePort.parseUrl(url); - if (hnp == null) { - throw new Exception(); - } - } catch (Exception e) { - throw new RuntimeException("Invalid Url: hostname:port"); - } - } - }, - TCP { - @Override - protected void send(String url, byte[] data, int timeout) throws IOException { + } + }, + TCP { + @Override + protected void send(String url, byte[] data, int timeout, boolean isJson) throws IOException { HostnamePort hostnamePort = HostnamePort.parseUrl(url); SocketAddress endpoint = new InetSocketAddress(InetAddress.getByName(hostnamePort.hostname), hostnamePort.port); Socket socket = new Socket(); - socket.setSoTimeout(timeout); + socket.setSoTimeout(timeout); socket.connect(endpoint, timeout); OutputStream output = socket.getOutputStream(); output.write(data); output.flush(); output.close(); - } - }, - HTTP { - @Override - protected void send(String url, byte[] data, int timeout) throws IOException { + } + }, + HTTP { + @Override + protected void send(String url, byte[] data, int timeout, boolean isJson) throws IOException { URL targetUrl = new URL(url); if (!targetUrl.getProtocol().startsWith("http")) { throw new IllegalArgumentException("Not an http(s) url: " + url); } HttpURLConnection connection = (HttpURLConnection) targetUrl.openConnection(); - connection.setRequestProperty("Content-Type", "application/json;charset=UTF-8"); + connection.setRequestProperty("Content-Type", String.format( "application/%s;charset=UTF-8", isJson ? "json" : "xml" )); String userInfo = targetUrl.getUserInfo(); if (null != userInfo) { String b64UserInfo = DatatypeConverter.printBase64Binary(userInfo.getBytes()); @@ -106,33 +85,41 @@ protected void send(String url, byte[] data, int timeout) throws IOException { if (307 == connection.getResponseCode()) { String location = connection.getHeaderField("Location"); connection.disconnect(); - send(location, data,timeout); + send(location, data,timeout, isJson); } else { connection.disconnect(); } } - } + } - public void validateUrl(String url) { - try { - new URL(url); - } catch (MalformedURLException e) { - throw new RuntimeException("Invalid Url: http://hostname:port/path"); - } - } - }; + @Override + public void validateUrl( String url ) { + try { + // noinspection ResultOfObjectAllocationIgnored + new URL( url ); + } catch ( MalformedURLException e ) { + throw new RuntimeException( String.format( "%sUse http://hostname:port/path for endpoint URL", + isEmpty ( url ) ? "" : "Invalid URL '" + url + "'. " )); + } + } + }; - abstract protected void send(String url, byte[] data, int timeout) throws IOException; + protected abstract void send(String url, byte[] data, int timeout, boolean isJson) throws IOException; + + public void validateUrl(String url) { + try { + HostnamePort hnp = HostnamePort.parseUrl(url); + if (hnp == null) { + throw new Exception(); + } + } catch (Exception e) { + throw new RuntimeException( String.format( "%sUse hostname:port for endpoint URL", + isEmpty ( url ) ? "" : "Invalid URL '" + url + "'. " )); + } + } - public void validateUrl(String url) { - try { - HostnamePort hnp = HostnamePort.parseUrl(url); - if (hnp == null) { - throw new Exception(); - } - } catch (Exception e) { - throw new RuntimeException("Invalid Url: hostname:port"); - } - } + private static boolean isEmpty( String s ) { + return (( s == null ) || ( s.trim().length() < 1 )); + } } diff --git a/src/main/java/com/tikal/hudson/plugins/notification/model/BuildState.java b/src/main/java/com/tikal/hudson/plugins/notification/model/BuildState.java index db4df84..2b87836 100755 --- a/src/main/java/com/tikal/hudson/plugins/notification/model/BuildState.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/model/BuildState.java @@ -14,78 +14,163 @@ package com.tikal.hudson.plugins.notification.model; import com.tikal.hudson.plugins.notification.Phase; - +import hudson.model.AbstractBuild; +import hudson.model.Job; +import hudson.model.Run; +import hudson.plugins.s3.Entry; +import hudson.plugins.s3.S3BucketPublisher; +import hudson.util.DescribableList; +import jenkins.model.Jenkins; + +import java.io.File; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; import java.util.Map; public class BuildState { - private String fullUrl; + private String fullUrl; + + private int number; + + private Phase phase; + + private String status; + + private String url; + + private String displayName; + + private ScmState scm; + + private Map parameters; + + private Map> artifacts; + + public int getNumber() { + return number; + } + + public void setNumber(int number) { + this.number = number; + } + + public Phase getPhase() { + return phase; + } + + public void setPhase(Phase phase) { + this.phase = phase; + } + + public String getStatus() { + return status; + } - private int number; + public void setStatus(String status) { + this.status = status; + } - private Phase phase; + public String getUrl() { + return url; + } - private String status; + public void setUrl(String url) { + this.url = url; + } - private String url; + public String getFullUrl() { + return fullUrl; + } - private String displayName; + public void setFullUrl(String fullUrl) { + this.fullUrl = fullUrl; + } - private Map parameters; + public Map getParameters() { + return parameters; + } - public int getNumber() { - return number; - } + public void setParameters(Map params) { + this.parameters = new HashMap( params ); + } - public void setNumber(int number) { - this.number = number; - } + public Map> getArtifacts () { + return artifacts; + } - public Phase getPhase() { - return phase; - } + public void setArtifacts ( Map> artifacts ) + { + this.artifacts = new HashMap>( artifacts ); + } - public void setPhase(Phase phase) { - this.phase = phase; - } + public void setDisplayName(String displayName) { + this.displayName = displayName; + } - public String getStatus() { - return status; - } + public String getDisplayName() { + return displayName; + } - public void setStatus(String status) { - this.status = status; - } + public ScmState getScm () + { + return scm; + } - public String getUrl() { - return url; - } + public void setScm ( ScmState scmState ) + { + this.scm = scmState; + } - public void setUrl(String url) { - this.url = url; - } - public String getFullUrl() { - return fullUrl; - } + /** + * Updates artifacts Map with S3 links, if corresponding publisher is available. + */ + public void updateArtifacts ( Job job, Run run ) + { + if ( ! ( run instanceof AbstractBuild )){ return; } + if ( Jenkins.getInstance().getPlugin( "s3" ) == null ) { return; } - public void setFullUrl(String fullUrl) { - this.fullUrl = fullUrl; - } + DescribableList publishers = (( AbstractBuild ) run ).getProject().getPublishersList(); + S3BucketPublisher s3Publisher = ( S3BucketPublisher ) publishers.get( S3BucketPublisher.class ); - public Map getParameters() { - return parameters; - } + if ( s3Publisher == null ){ return; } - public void setParameters(Map params) { - this.parameters = params; - } + for ( Entry entry : s3Publisher.getEntries()) { - public void setDisplayName(String displayName) { - this.displayName = displayName; - } + if ( isEmpty( entry.sourceFile, entry.selectedRegion, entry.bucket )){ continue; } + String fileName = new File( entry.sourceFile ).getName(); + if ( isEmpty( fileName )){ continue; } - public String getDisplayName() { - return displayName; - } + // https://s3-eu-west-1.amazonaws.com/evgenyg-temp/ + String bucketUrl = String.format( "https://s3-%s.amazonaws.com/%s", + entry.selectedRegion.toLowerCase().replace( '_', '-' ), + entry.bucket ); + + String fileUrl = entry.managedArtifacts ? + // https://s3-eu-west-1.amazonaws.com/evgenyg-temp/jobs/notification-plugin/21/notification.hpi + String.format( "%s/jobs/%s/%s/%s", bucketUrl, job.getName(), run.getNumber(), fileName ) : + // https://s3-eu-west-1.amazonaws.com/evgenyg-temp/notification.hpi + String.format( "%s/%s", bucketUrl, fileName ); + + if ( artifacts.get( fileName ) == null ) { + artifacts.put( fileName, Arrays.asList( fileUrl )); + } + else { + artifacts.get( fileName ).add( fileUrl ); + } + } + } + + private static boolean isEmpty( String ... strings ) { + + for ( String s : strings ) { + if (( s == null ) || ( s.trim().length() < 1 )){ + return true; + } + } + + return false; + } } diff --git a/src/main/java/com/tikal/hudson/plugins/notification/model/JobState.java b/src/main/java/com/tikal/hudson/plugins/notification/model/JobState.java index 9920d0e..bee2168 100755 --- a/src/main/java/com/tikal/hudson/plugins/notification/model/JobState.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/model/JobState.java @@ -18,33 +18,33 @@ @XStreamAlias("job") public class JobState { - private String name; + private String name; - private String url; + private String url; - private BuildState build; + private BuildState build; - public String getName() { - return name; - } + public String getName() { + return name; + } - public void setName(String name) { - this.name = name; - } + public void setName(String name) { + this.name = name; + } - public String getUrl() { - return url; - } + public String getUrl() { + return url; + } - public void setUrl(String url) { - this.url = url; - } + public void setUrl(String url) { + this.url = url; + } - public BuildState getBuild() { - return build; - } + public BuildState getBuild() { + return build; + } - public void setBuild(BuildState build) { - this.build = build; - } + public void setBuild(BuildState build) { + this.build = build; + } } diff --git a/src/main/java/com/tikal/hudson/plugins/notification/model/ScmState.java b/src/main/java/com/tikal/hudson/plugins/notification/model/ScmState.java new file mode 100644 index 0000000..304f387 --- /dev/null +++ b/src/main/java/com/tikal/hudson/plugins/notification/model/ScmState.java @@ -0,0 +1,54 @@ +/** + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.tikal.hudson.plugins.notification.model; + + +public class ScmState +{ + private String url; + + private String branch; + + private String commit; + + public String getUrl () + { + return url; + } + + public void setUrl ( String url ) + { + this.url = url; + } + + public String getBranch () + { + return branch; + } + + public void setBranch ( String branch ) + { + this.branch = branch; + } + + public String getCommit () + { + return commit; + } + + public void setCommit ( String commit ) + { + this.commit = commit; + } +} diff --git a/src/main/resources/com/tikal/hudson/plugins/notification/HudsonNotificationProperty/config.jelly b/src/main/resources/com/tikal/hudson/plugins/notification/HudsonNotificationProperty/config.jelly index 2563ffc..d97c0fd 100755 --- a/src/main/resources/com/tikal/hudson/plugins/notification/HudsonNotificationProperty/config.jelly +++ b/src/main/resources/com/tikal/hudson/plugins/notification/HudsonNotificationProperty/config.jelly @@ -1,55 +1,66 @@ + xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form"> - - - - - -
    - - - - - - - - - - - - -
    - - - -
    - - - -
    - - - -
    - - - -
    -
    - - - - -
    + + + + + +
    + + + + + + + + + + + + + + + +
    + + + +
    + + + +
    + + + +
    + + + +
    + + + +
    +
    + + + + +
    diff --git a/src/main/resources/com/tikal/hudson/plugins/notification/HudsonNotificationProperty/help-url.html b/src/main/resources/com/tikal/hudson/plugins/notification/HudsonNotificationProperty/help-url.html index 1050173..c8b0c19 100644 --- a/src/main/resources/com/tikal/hudson/plugins/notification/HudsonNotificationProperty/help-url.html +++ b/src/main/resources/com/tikal/hudson/plugins/notification/HudsonNotificationProperty/help-url.html @@ -1,8 +1,8 @@
      -
    • URL format for UDP and TCP protocols is - (hostname|IpAddress):portNumber, e.g. 10.10.10.10:12345
    • -
    • URL format for HTTP protocol is any legal http address, e.g. - http://[user:password@]myhost.com:8080/monitor
    • +
    • URL format for UDP and TCP protocols is + (hostname|IpAddress):portNumber, e.g. 10.10.10.10:12345
    • +
    • URL format for HTTP protocol is any legal http address, e.g. + http://[user:password@]myhost.com:8080/monitor
    diff --git a/src/main/resources/index.jelly b/src/main/resources/index.jelly index 655be90..a349a15 100755 --- a/src/main/resources/index.jelly +++ b/src/main/resources/index.jelly @@ -1,5 +1,5 @@
    - This plugin from - Tikal Knowledge - allows sending running Jobs status notifications. + This plugin from + Tikal Knowledge + allows sending running Jobs status notifications.
    diff --git a/src/main/webapp/help-globalConfig.html b/src/main/webapp/help-globalConfig.html index aaf98eb..f6b7a1f 100755 --- a/src/main/webapp/help-globalConfig.html +++ b/src/main/webapp/help-globalConfig.html @@ -3,12 +3,12 @@ Knowledge allows sending Job Status notifications.

     {
    -	"name":"JobName", 
    -	"url":"JobUrl", 
    -	"build":{
    -		"number":1,
    -		"phase":"STARTED", 
    -		"status":"FAILED"
    -	}
    +    "name":"JobName",
    +    "url":"JobUrl",
    +    "build":{
    +        "number":1,
    +        "phase":"STARTED",
    +        "status":"FAILED"
    +    }
     }
     
    diff --git a/src/main/webapp/help-projectConfig.html b/src/main/webapp/help-projectConfig.html index aaf98eb..f6b7a1f 100755 --- a/src/main/webapp/help-projectConfig.html +++ b/src/main/webapp/help-projectConfig.html @@ -3,12 +3,12 @@ Knowledge allows sending Job Status notifications.

     {
    -	"name":"JobName", 
    -	"url":"JobUrl", 
    -	"build":{
    -		"number":1,
    -		"phase":"STARTED", 
    -		"status":"FAILED"
    -	}
    +    "name":"JobName",
    +    "url":"JobUrl",
    +    "build":{
    +        "number":1,
    +        "phase":"STARTED",
    +        "status":"FAILED"
    +    }
     }
     
    diff --git a/src/test/java/com/tikal/hudson/plugins/notification/ProtocolTest.java b/src/test/java/com/tikal/hudson/plugins/notification/ProtocolTest.java index c032ccd..68f0a35 100644 --- a/src/test/java/com/tikal/hudson/plugins/notification/ProtocolTest.java +++ b/src/test/java/com/tikal/hudson/plugins/notification/ProtocolTest.java @@ -23,31 +23,28 @@ */ package com.tikal.hudson.plugins.notification; -import java.io.IOException; -import java.net.MalformedURLException; -import java.net.URL; -import java.util.LinkedList; -import java.util.List; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.LinkedBlockingQueue; - -import javax.servlet.Servlet; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import javax.xml.bind.DatatypeConverter; - import com.google.common.base.Objects; import com.google.common.io.CharStreams; - +import junit.framework.TestCase; import org.mortbay.jetty.HttpHeaders; import org.mortbay.jetty.Server; import org.mortbay.jetty.bio.SocketConnector; import org.mortbay.jetty.servlet.ServletHandler; import org.mortbay.jetty.servlet.ServletHolder; -import junit.framework.TestCase; +import javax.servlet.Servlet; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.xml.bind.DatatypeConverter; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.LinkedList; +import java.util.List; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingQueue; /** * @author Kohsuke Kawaguchi @@ -65,7 +62,7 @@ static class Request { this.method = request.getMethod(); this.body = CharStreams.toString(request.getReader()); String auth = request.getHeader("Authorization"); - this.userInfo = (null == auth) + this.userInfo = (null == auth) ? null : new String(DatatypeConverter.parseBase64Binary(auth.split(" ")[1])) + "@"; } @@ -219,7 +216,7 @@ public void testHttpPost() throws Exception { assertTrue(requests.isEmpty()); String uri = urlFactory.getUrl("/realpath"); - Protocol.HTTP.send(uri, "Hello".getBytes(),30000); + Protocol.HTTP.send(uri, "Hello".getBytes(),30000, true); assertEquals(new Request(uri, "POST", "Hello"), requests.take()); assertTrue(requests.isEmpty()); @@ -233,7 +230,7 @@ public void testHttpPostWithBasicAuth() throws Exception { assertTrue(requests.isEmpty()); String uri = urlFactory.getUrl("/realpath"); - Protocol.HTTP.send(uri, "Hello".getBytes(),30000); + Protocol.HTTP.send(uri, "Hello".getBytes(),30000, true); Request theRequest = requests.take(); assertTrue(requests.isEmpty()); @@ -251,7 +248,7 @@ public void testHttpPostWithRedirects() throws Exception { assertTrue(requests.isEmpty()); String uri = redirectorUrlFactory.getUrl("/path"); - Protocol.HTTP.send(uri, "RedirectMe".getBytes(),30000); + Protocol.HTTP.send(uri, "RedirectMe".getBytes(),30000, true); assertEquals(new Request(uri, "POST", "RedirectMe"), requests.take()); assertEquals(new Request(redirectUri, "POST", "RedirectMe"), requests.take()); diff --git a/src/test/java/com/tikal/hudson/plugins/notification/test/HostnamePortTest.java b/src/test/java/com/tikal/hudson/plugins/notification/test/HostnamePortTest.java index 196383b..8f80020 100644 --- a/src/test/java/com/tikal/hudson/plugins/notification/test/HostnamePortTest.java +++ b/src/test/java/com/tikal/hudson/plugins/notification/test/HostnamePortTest.java @@ -20,17 +20,17 @@ import com.tikal.hudson.plugins.notification.HostnamePort; public class HostnamePortTest { - - @Test - public void parseUrlTest() { - HostnamePort hnp = HostnamePort.parseUrl("111"); - Assert.assertNull(hnp); - hnp = HostnamePort.parseUrl(null); - Assert.assertNull(hnp); - hnp = HostnamePort.parseUrl("localhost:123"); - Assert.assertEquals("localhost", hnp.hostname); - Assert.assertEquals(123, hnp.port); - hnp = HostnamePort.parseUrl("localhost:123456"); - Assert.assertEquals(12345, hnp.port); - } + + @Test + public void parseUrlTest() { + HostnamePort hnp = HostnamePort.parseUrl("111"); + Assert.assertNull(hnp); + hnp = HostnamePort.parseUrl(null); + Assert.assertNull(hnp); + hnp = HostnamePort.parseUrl("localhost:123"); + Assert.assertEquals("localhost", hnp.hostname); + Assert.assertEquals(123, hnp.port); + hnp = HostnamePort.parseUrl("localhost:123456"); + Assert.assertEquals(12345, hnp.port); + } } From 91b08fe35941d8e0a6f417f7ab6528123f318c63 Mon Sep 17 00:00:00 2001 From: Haggai Philip Zagury Date: Wed, 11 Jun 2014 10:30:33 +0300 Subject: [PATCH 050/214] [maven-release-plugin] prepare release notification-1.6 --- pom.xml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index 98477d8..1eeba9a 100755 --- a/pom.xml +++ b/pom.xml @@ -1,11 +1,9 @@ - + 4.0.0 com.tikalk.hudson.plugins notification - 1.6-SNAPSHOT + 1.6 hpi Jenkins Notification plugin Sends notifications about jobs phases and status From 4886d1ff4821879410f4f4a93168e6cc179a8eb3 Mon Sep 17 00:00:00 2001 From: Haggai Philip Zagury Date: Wed, 11 Jun 2014 10:30:39 +0300 Subject: [PATCH 051/214] [maven-release-plugin] prepare for next development iteration --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 1eeba9a..76f8d01 100755 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ 4.0.0 com.tikalk.hudson.plugins notification - 1.6 + 1.7-SNAPSHOT hpi Jenkins Notification plugin Sends notifications about jobs phases and status From 0ef9f66d0eb73a46123c705ec52bc9b26b92a75b Mon Sep 17 00:00:00 2001 From: Evgeny Goldin Date: Sun, 22 Jun 2014 13:05:52 +0200 Subject: [PATCH 052/214] Artifacts map has changed to Map> --- .../hudson/plugins/notification/Phase.java | 12 +--- .../hudson/plugins/notification/Utils.java | 54 ++++++++++++++ .../notification/model/BuildState.java | 71 +++++++++++++------ 3 files changed, 105 insertions(+), 32 deletions(-) create mode 100644 src/main/java/com/tikal/hudson/plugins/notification/Utils.java diff --git a/src/main/java/com/tikal/hudson/plugins/notification/Phase.java b/src/main/java/com/tikal/hudson/plugins/notification/Phase.java index 69e62bd..b11d8e2 100755 --- a/src/main/java/com/tikal/hudson/plugins/notification/Phase.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/Phase.java @@ -21,7 +21,7 @@ import jenkins.model.Jenkins; import java.io.IOException; -import java.util.*; + @SuppressWarnings({ "unchecked", "rawtypes" }) public enum Phase { @@ -72,7 +72,6 @@ private JobState buildJobState(Job job, Run run, TaskListener listener) ScmState scmState = new ScmState(); Result result = run.getResult(); ParametersAction paramsAction = run.getAction(ParametersAction.class); - List artifacts = run.getArtifacts(); EnvVars environment = run.getEnvironment( listener ); jobState.setName( job.getName()); @@ -92,15 +91,6 @@ private JobState buildJobState(Job job, Run run, TaskListener listener) buildState.setFullUrl(rootUrl + run.getUrl()); } - if ( artifacts != null ) { - Map> urls = new HashMap>( artifacts.size()); - for ( Run.Artifact a : artifacts ) { - final String artifactUrl = jenkins.getRootUrl() + run.getUrl() + "artifact/" + a.getHref(); - urls.put( a.getFileName(), new ArrayList(){{ add( artifactUrl ); }}); - } - buildState.setArtifacts( urls ); - } - buildState.updateArtifacts( job, run ); if ( paramsAction != null ) { diff --git a/src/main/java/com/tikal/hudson/plugins/notification/Utils.java b/src/main/java/com/tikal/hudson/plugins/notification/Utils.java new file mode 100644 index 0000000..af2a70a --- /dev/null +++ b/src/main/java/com/tikal/hudson/plugins/notification/Utils.java @@ -0,0 +1,54 @@ +package com.tikal.hudson.plugins.notification; + +import java.util.Arrays; + + +/** + * Helper utilities + */ +public final class Utils +{ + private Utils () + { + } + + + /** + * Determines if any of Strings specified is either null or empty. + */ + @SuppressWarnings( "MethodWithMultipleReturnPoints" ) + public static boolean isEmpty( String ... strings ) + { + if (( strings == null ) || ( strings.length < 1 )) { + return true; + } + + for ( String s : strings ) + { + if (( s == null ) || ( s.trim().length() < 1 )) + { + return true; + } + } + + return false; + } + + + /** + * Verifies neither of Strings specified is null or empty. + * @return first String provided + * @throws java.lang.IllegalArgumentException + */ + @SuppressWarnings( "ReturnOfNull" ) + public static String verifyNotEmpty( String ... strings ) + { + if ( isEmpty( strings )) + { + throw new IllegalArgumentException( String.format( + "Some String arguments are null or empty: %s", Arrays.toString( strings ))); + } + + return strings[ 0 ]; + } +} diff --git a/src/main/java/com/tikal/hudson/plugins/notification/model/BuildState.java b/src/main/java/com/tikal/hudson/plugins/notification/model/BuildState.java index 2b87836..75557d3 100755 --- a/src/main/java/com/tikal/hudson/plugins/notification/model/BuildState.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/model/BuildState.java @@ -13,6 +13,7 @@ */ package com.tikal.hudson.plugins.notification.model; +import static com.tikal.hudson.plugins.notification.Utils.*; import com.tikal.hudson.plugins.notification.Phase; import hudson.model.AbstractBuild; import hudson.model.Job; @@ -23,7 +24,6 @@ import jenkins.model.Jenkins; import java.io.File; -import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -46,7 +46,19 @@ public class BuildState { private Map parameters; - private Map> artifacts; + /** + * Map of artifacts: file name => Map of artifact locations ( location name => artifact URL ) + * "artifacts": { + "notification.jar": { + "archive": "http://localhost:8080/job/notification-plugin/54/artifact/target/notification.jar" + }, + "notification.hpi": { + "s3": "https://s3-eu-west-1.amazonaws.com/notification-plugin/jobs/notification-plugin/54/notification.hpi", + "archive": "http://localhost:8080/job/notification-plugin/54/artifact/target/notification.hpi" + } + } + */ + private Map> artifacts = new HashMap>(); public int getNumber() { return number; @@ -96,15 +108,10 @@ public void setParameters(Map params) { this.parameters = new HashMap( params ); } - public Map> getArtifacts () { + public Map> getArtifacts () { return artifacts; } - public void setArtifacts ( Map> artifacts ) - { - this.artifacts = new HashMap>( artifacts ); - } - public void setDisplayName(String displayName) { this.displayName = displayName; } @@ -128,6 +135,27 @@ public void setScm ( ScmState scmState ) * Updates artifacts Map with S3 links, if corresponding publisher is available. */ public void updateArtifacts ( Job job, Run run ) + { + updateArchivedArtifacts( run ); + updateS3Artifacts( job, run ); + } + + + private void updateArchivedArtifacts ( Run run ) + { + @SuppressWarnings( "unchecked" ) + List buildArtifacts = run.getArtifacts(); + + if (( buildArtifacts == null ) || buildArtifacts.isEmpty()) { return; } + + for ( Run.Artifact a : buildArtifacts ) { + String artifactUrl = Jenkins.getInstance().getRootUrl() + run.getUrl() + "artifact/" + a.getHref(); + updateArtifact( a.getFileName(), "archive", artifactUrl ); + } + } + + + private void updateS3Artifacts ( Job job, Run run ) { if ( ! ( run instanceof AbstractBuild )){ return; } if ( Jenkins.getInstance().getPlugin( "s3" ) == null ) { return; } @@ -139,7 +167,7 @@ public void updateArtifacts ( Job job, Run run ) for ( Entry entry : s3Publisher.getEntries()) { - if ( isEmpty( entry.sourceFile, entry.selectedRegion, entry.bucket )){ continue; } + if ( isEmpty( job.getName(), entry.sourceFile, entry.selectedRegion, entry.bucket )){ continue; } String fileName = new File( entry.sourceFile ).getName(); if ( isEmpty( fileName )){ continue; } @@ -154,23 +182,24 @@ public void updateArtifacts ( Job job, Run run ) // https://s3-eu-west-1.amazonaws.com/evgenyg-temp/notification.hpi String.format( "%s/%s", bucketUrl, fileName ); - if ( artifacts.get( fileName ) == null ) { - artifacts.put( fileName, Arrays.asList( fileUrl )); - } - else { - artifacts.get( fileName ).add( fileUrl ); - } + updateArtifact( fileName, "s3", fileUrl ); } } - private static boolean isEmpty( String ... strings ) { - for ( String s : strings ) { - if (( s == null ) || ( s.trim().length() < 1 )){ - return true; - } + private void updateArtifact( String fileName, String locationName, String locationUrl ) + { + verifyNotEmpty( fileName, locationName, locationUrl ); + + if ( ! artifacts.containsKey( fileName )) { + artifacts.put( fileName, new HashMap()); + } + + if ( artifacts.get( fileName ).containsKey( locationName )) { + throw new RuntimeException( String.format( + "Artifacts Map already contains location '%s': %s", locationName, artifacts )); } - return false; + artifacts.get( fileName ).put( locationName, locationUrl ); } } From 68c7e46fc3ee4f4ca21d034f4ee38941b17926ee Mon Sep 17 00:00:00 2001 From: Evgeny Goldin Date: Sun, 22 Jun 2014 23:23:04 +0200 Subject: [PATCH 053/214] Cosmetics --- .../plugins/notification/model/BuildState.java | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/tikal/hudson/plugins/notification/model/BuildState.java b/src/main/java/com/tikal/hudson/plugins/notification/model/BuildState.java index 75557d3..9f97304 100755 --- a/src/main/java/com/tikal/hudson/plugins/notification/model/BuildState.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/model/BuildState.java @@ -146,7 +146,7 @@ private void updateArchivedArtifacts ( Run run ) @SuppressWarnings( "unchecked" ) List buildArtifacts = run.getArtifacts(); - if (( buildArtifacts == null ) || buildArtifacts.isEmpty()) { return; } + if ( buildArtifacts == null ) { return; } for ( Run.Artifact a : buildArtifacts ) { String artifactUrl = Jenkins.getInstance().getRootUrl() + run.getUrl() + "artifact/" + a.getHref(); @@ -157,8 +157,9 @@ private void updateArchivedArtifacts ( Run run ) private void updateS3Artifacts ( Job job, Run run ) { - if ( ! ( run instanceof AbstractBuild )){ return; } if ( Jenkins.getInstance().getPlugin( "s3" ) == null ) { return; } + if ( ! ( run instanceof AbstractBuild )){ return; } + if ( isEmpty( job.getName())){ return; } DescribableList publishers = (( AbstractBuild ) run ).getProject().getPublishersList(); S3BucketPublisher s3Publisher = ( S3BucketPublisher ) publishers.get( S3BucketPublisher.class ); @@ -167,7 +168,7 @@ private void updateS3Artifacts ( Job job, Run run ) for ( Entry entry : s3Publisher.getEntries()) { - if ( isEmpty( job.getName(), entry.sourceFile, entry.selectedRegion, entry.bucket )){ continue; } + if ( isEmpty( entry.sourceFile, entry.selectedRegion, entry.bucket )){ continue; } String fileName = new File( entry.sourceFile ).getName(); if ( isEmpty( fileName )){ continue; } @@ -187,6 +188,13 @@ private void updateS3Artifacts ( Job job, Run run ) } + /** + * Updates an artifact URL. + * + * @param fileName artifact file name + * @param locationName artifact location name, like "s3" or "archive" + * @param locationUrl artifact URL at the location specified + */ private void updateArtifact( String fileName, String locationName, String locationUrl ) { verifyNotEmpty( fileName, locationName, locationUrl ); @@ -197,7 +205,8 @@ private void updateArtifact( String fileName, String locationName, String locati if ( artifacts.get( fileName ).containsKey( locationName )) { throw new RuntimeException( String.format( - "Artifacts Map already contains location '%s': %s", locationName, artifacts )); + "Adding artifacts mapping '%s/%s/%s' - artifacts Map already contains mapping of location '%s': %s", + fileName, locationName, locationUrl, locationName, artifacts )); } artifacts.get( fileName ).put( locationName, locationUrl ); From 62ef84f4de8600b06dc3b0572adbbdafabc29ff3 Mon Sep 17 00:00:00 2001 From: Evgeny Goldin Date: Sat, 28 Jun 2014 19:31:34 +0200 Subject: [PATCH 054/214] BuildState cosmetics --- .../plugins/notification/model/BuildState.java | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/src/main/java/com/tikal/hudson/plugins/notification/model/BuildState.java b/src/main/java/com/tikal/hudson/plugins/notification/model/BuildState.java index 9f97304..d1404b9 100755 --- a/src/main/java/com/tikal/hudson/plugins/notification/model/BuildState.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/model/BuildState.java @@ -48,17 +48,15 @@ public class BuildState { /** * Map of artifacts: file name => Map of artifact locations ( location name => artifact URL ) - * "artifacts": { - "notification.jar": { - "archive": "http://localhost:8080/job/notification-plugin/54/artifact/target/notification.jar" - }, - "notification.hpi": { - "s3": "https://s3-eu-west-1.amazonaws.com/notification-plugin/jobs/notification-plugin/54/notification.hpi", - "archive": "http://localhost:8080/job/notification-plugin/54/artifact/target/notification.hpi" - } - } + * --- + * artifacts: + * notification.hpi: + * s3: https://s3-eu-west-1.amazonaws.com/evgenyg-bakery-artifacts/jobs/notification-plugin/78/notification.hpi + * archive: http://localhost:8080/job/notification-plugin/78/artifact/target/notification.hpi + * notification.jar: + * archive: http://localhost:8080/job/notification-plugin/78/artifact/target/notification.jar */ - private Map> artifacts = new HashMap>(); + private final Map> artifacts = new HashMap>(); public int getNumber() { return number; From a8baad5cb9b400372a9298ce59f46827e44a1d99 Mon Sep 17 00:00:00 2001 From: Evgeny Goldin Date: Sat, 28 Jun 2014 19:31:34 +0200 Subject: [PATCH 055/214] BuildState cosmetics --- pom.xml | 6 +++--- .../plugins/notification/model/BuildState.java | 18 ++++++++---------- 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/pom.xml b/pom.xml index 76f8d01..e0f6944 100755 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ 4.0.0 com.tikalk.hudson.plugins notification - 1.7-SNAPSHOT + 1.8-SNAPSHOT hpi Jenkins Notification plugin Sends notifications about jobs phases and status @@ -101,8 +101,8 @@ - scm:git:git://github.com/jenkinsci/notification-plugin.git - scm:git:git@github.com:jenkinsci/notification-plugin.git + scm:git:ssh://github.com/jenkinsci/notification-plugin.git + scm:git:ssh@github.com:jenkinsci/notification-plugin.git http://github.com/jenkinsci/notification-plugin diff --git a/src/main/java/com/tikal/hudson/plugins/notification/model/BuildState.java b/src/main/java/com/tikal/hudson/plugins/notification/model/BuildState.java index 9f97304..d1404b9 100755 --- a/src/main/java/com/tikal/hudson/plugins/notification/model/BuildState.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/model/BuildState.java @@ -48,17 +48,15 @@ public class BuildState { /** * Map of artifacts: file name => Map of artifact locations ( location name => artifact URL ) - * "artifacts": { - "notification.jar": { - "archive": "http://localhost:8080/job/notification-plugin/54/artifact/target/notification.jar" - }, - "notification.hpi": { - "s3": "https://s3-eu-west-1.amazonaws.com/notification-plugin/jobs/notification-plugin/54/notification.hpi", - "archive": "http://localhost:8080/job/notification-plugin/54/artifact/target/notification.hpi" - } - } + * --- + * artifacts: + * notification.hpi: + * s3: https://s3-eu-west-1.amazonaws.com/evgenyg-bakery-artifacts/jobs/notification-plugin/78/notification.hpi + * archive: http://localhost:8080/job/notification-plugin/78/artifact/target/notification.hpi + * notification.jar: + * archive: http://localhost:8080/job/notification-plugin/78/artifact/target/notification.jar */ - private Map> artifacts = new HashMap>(); + private final Map> artifacts = new HashMap>(); public int getNumber() { return number; From 219508e6d83e9c0fb1615796cfb1d6d6d2d7dc7c Mon Sep 17 00:00:00 2001 From: Haggai Philip Zagury Date: Sun, 14 Sep 2014 08:03:00 +0300 Subject: [PATCH 056/214] Fix pom + SCM url --- pom.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index e0f6944..76f8d01 100755 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ 4.0.0 com.tikalk.hudson.plugins notification - 1.8-SNAPSHOT + 1.7-SNAPSHOT hpi Jenkins Notification plugin Sends notifications about jobs phases and status @@ -101,8 +101,8 @@ - scm:git:ssh://github.com/jenkinsci/notification-plugin.git - scm:git:ssh@github.com:jenkinsci/notification-plugin.git + scm:git:git://github.com/jenkinsci/notification-plugin.git + scm:git:git@github.com:jenkinsci/notification-plugin.git http://github.com/jenkinsci/notification-plugin From 63e23ffd4ca0360a6308d3b0e849a61f50f414fe Mon Sep 17 00:00:00 2001 From: Evgeny Goldin Date: Sun, 14 Sep 2014 14:07:47 +0200 Subject: [PATCH 057/214] circle.yml and settings.xml added --- circle.yml | 17 +++++++++++++++++ settings.xml | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+) create mode 100644 circle.yml create mode 100644 settings.xml diff --git a/circle.yml b/circle.yml new file mode 100644 index 0000000..0019dd9 --- /dev/null +++ b/circle.yml @@ -0,0 +1,17 @@ +# https://circleci.com/docs/configuration +# https://circleci.com/docs/environment + +machine: + java: + version: oraclejdk7 +dependencies: + override: + - mvn -s settings.xml clean + cache_directories: + - ~/.m2 +test: + override: + - mvn -s settings.xml clean package +general: + artifacts: + - target/notification.hpi diff --git a/settings.xml b/settings.xml new file mode 100644 index 0000000..542aa34 --- /dev/null +++ b/settings.xml @@ -0,0 +1,40 @@ + + + + + * + remote-repos + http://jcenter.bintray.com/ + remote-repos + + + + + jcenter + + + + false + + central + libs-releases + http://jcenter.bintray.com + + + + + + false + + central + plugins-releases + http://jcenter.bintray.com + + + + + + jcenter + + From cda7fbf69b1c7349036030672b83f60ee378ce90 Mon Sep 17 00:00:00 2001 From: Evgeny Goldin Date: Sun, 14 Sep 2014 14:14:18 +0200 Subject: [PATCH 058/214] .gitignore update --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index d694a09..c502c4b 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ .classpath .idea *.iml +go.sh From e9b146a3d1907772114ee0b0a79c662772438486 Mon Sep 17 00:00:00 2001 From: Evgeny Goldin Date: Sun, 14 Sep 2014 14:19:28 +0200 Subject: [PATCH 059/214] circle.yml - cache_directories update --- circle.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/circle.yml b/circle.yml index 0019dd9..6b2400d 100644 --- a/circle.yml +++ b/circle.yml @@ -1,5 +1,7 @@ +# ----------------------------------------- # https://circleci.com/docs/configuration # https://circleci.com/docs/environment +# ----------------------------------------- machine: java: @@ -7,11 +9,11 @@ machine: dependencies: override: - mvn -s settings.xml clean - cache_directories: - - ~/.m2 test: override: - mvn -s settings.xml clean package + cache_directories: + - ~/.m2 general: artifacts: - target/notification.hpi From d41c2f8985f3fb896d067c8ceb39ef2403d8dd57 Mon Sep 17 00:00:00 2001 From: Evgeny Goldin Date: Sun, 14 Sep 2014 14:21:37 +0200 Subject: [PATCH 060/214] circle.yml - cache_directories update --- circle.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/circle.yml b/circle.yml index 6b2400d..4e30fc6 100644 --- a/circle.yml +++ b/circle.yml @@ -8,12 +8,12 @@ machine: version: oraclejdk7 dependencies: override: - - mvn -s settings.xml clean -test: - override: - - mvn -s settings.xml clean package + - mvn -s settings.xml package cache_directories: - ~/.m2 +test: + override: + - mvn -s settings.xml clean install general: artifacts: - target/notification.hpi From 11f9a8cff0ccba7642e98e84d498f4938ef81cfc Mon Sep 17 00:00:00 2001 From: Evgeny Goldin Date: Sun, 14 Sep 2014 14:26:38 +0200 Subject: [PATCH 061/214] circle.yml: -Dmaven.test.skip=true --- circle.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/circle.yml b/circle.yml index 4e30fc6..c6c4a8d 100644 --- a/circle.yml +++ b/circle.yml @@ -8,7 +8,7 @@ machine: version: oraclejdk7 dependencies: override: - - mvn -s settings.xml package + - mvn -s settings.xml package -Dmaven.test.skip=true cache_directories: - ~/.m2 test: From b43315a728bb58bd4c60965797690592b616f6b5 Mon Sep 17 00:00:00 2001 From: Evgeny Goldin Date: Sun, 14 Sep 2014 14:29:36 +0200 Subject: [PATCH 062/214] circle.yml - Maven updates --- circle.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/circle.yml b/circle.yml index c6c4a8d..b89aa19 100644 --- a/circle.yml +++ b/circle.yml @@ -8,12 +8,12 @@ machine: version: oraclejdk7 dependencies: override: - - mvn -s settings.xml package -Dmaven.test.skip=true + - mvn -s settings.xml dependency:go-offline cache_directories: - ~/.m2 test: override: - - mvn -s settings.xml clean install + - mvn -s settings.xml clean package general: artifacts: - target/notification.hpi From cd4e4c4abb3eb1a5b5b066bff4b70f8c0aa7bbc1 Mon Sep 17 00:00:00 2001 From: Evgeny Goldin Date: Sun, 14 Sep 2014 14:41:25 +0200 Subject: [PATCH 063/214] circle.yml cleanup --- circle.yml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/circle.yml b/circle.yml index b89aa19..9152059 100644 --- a/circle.yml +++ b/circle.yml @@ -8,12 +8,9 @@ machine: version: oraclejdk7 dependencies: override: - - mvn -s settings.xml dependency:go-offline + - mvn -s settings.xml clean package cache_directories: - ~/.m2 -test: - override: - - mvn -s settings.xml clean package general: artifacts: - target/notification.hpi From c229ca1affbeef0aa03a168293d9eea0f64f0913 Mon Sep 17 00:00:00 2001 From: Evgeny Goldin Date: Sun, 14 Sep 2014 14:43:42 +0200 Subject: [PATCH 064/214] circle.yml - override test --- circle.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/circle.yml b/circle.yml index 9152059..ed21173 100644 --- a/circle.yml +++ b/circle.yml @@ -11,6 +11,8 @@ dependencies: - mvn -s settings.xml clean package cache_directories: - ~/.m2 +test: + override: general: artifacts: - target/notification.hpi From b0cef56bf083b436afe718e19b79e20f2895edee Mon Sep 17 00:00:00 2001 From: Evgeny Goldin Date: Sun, 14 Sep 2014 14:45:25 +0200 Subject: [PATCH 065/214] circle.yml - override test --- circle.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/circle.yml b/circle.yml index ed21173..8e5db56 100644 --- a/circle.yml +++ b/circle.yml @@ -13,6 +13,7 @@ dependencies: - ~/.m2 test: override: + - general: artifacts: - target/notification.hpi From 097189426fae9fe570828d58e28061bd87a20ee8 Mon Sep 17 00:00:00 2001 From: Evgeny Goldin Date: Sun, 14 Sep 2014 14:45:47 +0200 Subject: [PATCH 066/214] circle.yml - override test --- circle.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/circle.yml b/circle.yml index 8e5db56..ca33bd4 100644 --- a/circle.yml +++ b/circle.yml @@ -13,7 +13,7 @@ dependencies: - ~/.m2 test: override: - - + - id general: artifacts: - target/notification.hpi From 7d6c7b6de8a7420975f69697163567b5332bda96 Mon Sep 17 00:00:00 2001 From: Haggai Philip Zagury Date: Tue, 16 Sep 2014 14:20:39 +0300 Subject: [PATCH 067/214] Try fix release plugin issue (releases snapshot version) --- pom.xml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/pom.xml b/pom.xml index 76f8d01..4b9a8b4 100755 --- a/pom.xml +++ b/pom.xml @@ -56,6 +56,17 @@ maven-hpi-plugin 1.109 + + maven-release-plugin + 2.4.2 + + + org.apache.maven.scm + maven-scm-provider-gitexe + 1.8.1 + + + From 2e7fb5208ffea92ebdefde212212cdbeef8cdebd Mon Sep 17 00:00:00 2001 From: Haggai Philip Zagury Date: Tue, 16 Sep 2014 14:21:53 +0300 Subject: [PATCH 068/214] [maven-release-plugin] prepare release notification-1.7 --- pom.xml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 4b9a8b4..7c5676e 100755 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ 4.0.0 com.tikalk.hudson.plugins notification - 1.7-SNAPSHOT + 1.7 hpi Jenkins Notification plugin Sends notifications about jobs phases and status @@ -115,7 +115,8 @@ scm:git:git://github.com/jenkinsci/notification-plugin.git scm:git:git@github.com:jenkinsci/notification-plugin.git http://github.com/jenkinsci/notification-plugin - + notification-1.7 + From 9ea99ac1900c937116a401bfbd38adcf80b9db08 Mon Sep 17 00:00:00 2001 From: Haggai Philip Zagury Date: Tue, 16 Sep 2014 14:21:58 +0300 Subject: [PATCH 069/214] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 7c5676e..22cd36f 100755 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ 4.0.0 com.tikalk.hudson.plugins notification - 1.7 + 1.8-SNAPSHOT hpi Jenkins Notification plugin Sends notifications about jobs phases and status @@ -115,7 +115,7 @@ scm:git:git://github.com/jenkinsci/notification-plugin.git scm:git:git@github.com:jenkinsci/notification-plugin.git http://github.com/jenkinsci/notification-plugin - notification-1.7 + HEAD From 17c72ecd3f5040b74d86179ba3299e9d96a9b12b Mon Sep 17 00:00:00 2001 From: Dave Hall Date: Sat, 11 Oct 2014 11:34:26 +1100 Subject: [PATCH 070/214] Add build log to payload --- .../com/tikal/hudson/plugins/notification/Phase.java | 2 ++ .../hudson/plugins/notification/model/BuildState.java | 9 +++++++++ 2 files changed, 11 insertions(+) diff --git a/src/main/java/com/tikal/hudson/plugins/notification/Phase.java b/src/main/java/com/tikal/hudson/plugins/notification/Phase.java index b11d8e2..dd6fb85 100755 --- a/src/main/java/com/tikal/hudson/plugins/notification/Phase.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/Phase.java @@ -73,6 +73,7 @@ private JobState buildJobState(Job job, Run run, TaskListener listener) Result result = run.getResult(); ParametersAction paramsAction = run.getAction(ParametersAction.class); EnvVars environment = run.getEnvironment( listener ); + String log = run.getLog(); jobState.setName( job.getName()); jobState.setUrl( job.getUrl()); @@ -82,6 +83,7 @@ private JobState buildJobState(Job job, Run run, TaskListener listener) buildState.setUrl( run.getUrl()); buildState.setPhase( this ); buildState.setScm( scmState ); + buildState.setLog( log ); if ( result != null ) { buildState.setStatus(result.toString()); diff --git a/src/main/java/com/tikal/hudson/plugins/notification/model/BuildState.java b/src/main/java/com/tikal/hudson/plugins/notification/model/BuildState.java index d1404b9..79d2d8b 100755 --- a/src/main/java/com/tikal/hudson/plugins/notification/model/BuildState.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/model/BuildState.java @@ -46,6 +46,8 @@ public class BuildState { private Map parameters; + private String log; + /** * Map of artifacts: file name => Map of artifact locations ( location name => artifact URL ) * --- @@ -128,6 +130,13 @@ public void setScm ( ScmState scmState ) this.scm = scmState; } + public String getLog() { + return log; + } + + public void setLog(String log) { + this.log = log; + } /** * Updates artifacts Map with S3 links, if corresponding publisher is available. From da26771d3d37fa77c26345ac7ab35529a9eef31a Mon Sep 17 00:00:00 2001 From: Marcello de Sales Date: Tue, 11 Nov 2014 20:44:25 -0800 Subject: [PATCH 071/214] JENKINS-25558: Notifications Plugin does not honor the "http_proxy" environment variable: Fix This commit partially fixes the problem by using an HTTP Proxy without authentication. In addition, it does not provide test cases, but it does work properly. The message after using a new build of this plugin was as follows: Started by user mdesales Notifying endpoint 'HTTP:https://zapier.com/hooks/catch/o54xyk/' Building in workspace /app/installs/jenkins/jobs/Status Notification/workspace Notifying endpoint 'HTTP:https://zapier.com/hooks/catch/o54xyk/' Finished: SUCCESS (Sorry, in a rush to get things done and I can try providing a test with an internal http proxy server). * modified: src/main/java/com/tikal/hudson/plugins/notification/Protocol.java - Verifying if the environment variable "http_proxy" is set. If so, decorate the connection with the proxy information before making the HTTP request. --- .../hudson/plugins/notification/Protocol.java | 36 +++++++++++++++++-- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java b/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java index e536f5a..5e489df 100755 --- a/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java @@ -14,10 +14,20 @@ package com.tikal.hudson.plugins.notification; -import javax.xml.bind.DatatypeConverter; import java.io.IOException; import java.io.OutputStream; -import java.net.*; +import java.net.DatagramPacket; +import java.net.DatagramSocket; +import java.net.HttpURLConnection; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.MalformedURLException; +import java.net.Proxy; +import java.net.Socket; +import java.net.SocketAddress; +import java.net.URL; + +import javax.xml.bind.DatatypeConverter; public enum Protocol { @@ -53,7 +63,27 @@ protected void send(String url, byte[] data, int timeout, boolean isJson) throws throw new IllegalArgumentException("Not an http(s) url: " + url); } - HttpURLConnection connection = (HttpURLConnection) targetUrl.openConnection(); + // Verifying if the HTTP_PROXY is available + final String httpProxyUrl = System.getenv().get("http_proxy"); + URL proxyUrl = null; + if (httpProxyUrl != null && httpProxyUrl.length() > 0) { + proxyUrl = new URL(httpProxyUrl); + if (!proxyUrl.getProtocol().startsWith("http")) { + throw new IllegalArgumentException("Not an http(s) url: " + httpProxyUrl); + } + } + + HttpURLConnection connection = null; + if (proxyUrl == null) { + connection = (HttpURLConnection) targetUrl.openConnection(); + + } else { + // Proxy connection to the address provided + final int proxyPort = proxyUrl.getPort() > 0 ? proxyUrl.getPort() : 80; + Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyUrl.getHost(), proxyPort)); + connection = (HttpURLConnection) targetUrl.openConnection(proxy); + } + connection.setRequestProperty("Content-Type", String.format( "application/%s;charset=UTF-8", isJson ? "json" : "xml" )); String userInfo = targetUrl.getUserInfo(); if (null != userInfo) { From 2491933009d52d8b739ea7e4d379c285bdd4b576 Mon Sep 17 00:00:00 2001 From: Dave Hall Date: Sat, 22 Nov 2014 01:22:56 +1100 Subject: [PATCH 072/214] Make number of log lines configurable --- .../hudson/plugins/notification/Endpoint.java | 15 ++++++-- .../hudson/plugins/notification/Phase.java | 34 ++++++++++++++++--- .../HudsonNotificationProperty/config.jelly | 8 +++++ 3 files changed, 51 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/tikal/hudson/plugins/notification/Endpoint.java b/src/main/java/com/tikal/hudson/plugins/notification/Endpoint.java index b177f33..ccfbd93 100644 --- a/src/main/java/com/tikal/hudson/plugins/notification/Endpoint.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/Endpoint.java @@ -35,13 +35,16 @@ public class Endpoint { private Integer timeout = DEFAULT_TIMEOUT; + private Integer loglines = 0; + @DataBoundConstructor - public Endpoint(Protocol protocol, String url, String event, Format format, Integer timeout) { + public Endpoint(Protocol protocol, String url, String event, Format format, Integer timeout, Integer loglines) { setProtocol( protocol ); setUrl( url ); setEvent( event ); setFormat( format ); setTimeout( timeout ); + setLoglines( loglines ); } public int getTimeout() { @@ -87,6 +90,14 @@ public void setFormat(Format format) { this.format = format; } + public Integer getLoglines() { + return this.loglines; + } + + public void setLoglines(Integer loglines) { + this.loglines = loglines; + } + public FormValidation doCheckURL(@QueryParameter(value = "url", fixEmpty = true) String url) { if (url.equals("111")) return FormValidation.ok(); @@ -102,4 +113,4 @@ public boolean isJson() { public String toString() { return protocol+":"+url; } -} \ No newline at end of file +} diff --git a/src/main/java/com/tikal/hudson/plugins/notification/Phase.java b/src/main/java/com/tikal/hudson/plugins/notification/Phase.java index dd6fb85..962f8f8 100755 --- a/src/main/java/com/tikal/hudson/plugins/notification/Phase.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/Phase.java @@ -21,6 +21,7 @@ import jenkins.model.Jenkins; import java.io.IOException; +import java.util.List; @SuppressWarnings({ "unchecked", "rawtypes" }) @@ -38,7 +39,7 @@ public void handle(Run run, TaskListener listener) { listener.getLogger().println( String.format( "Notifying endpoint '%s'", target )); try { - JobState jobState = buildJobState(run.getParent(), run, listener); + JobState jobState = buildJobState(run.getParent(), run, listener, target); target.getProtocol().send(target.getUrl(), target.getFormat().serialize(jobState), target.getTimeout(), @@ -61,7 +62,7 @@ private boolean isRun( Endpoint endpoint ) { return (( event == null ) || event.equals( "all" ) || event.equals( this.toString().toLowerCase())); } - private JobState buildJobState(Job job, Run run, TaskListener listener) + private JobState buildJobState(Job job, Run run, TaskListener listener, Endpoint target) throws IOException, InterruptedException { @@ -73,7 +74,7 @@ private JobState buildJobState(Job job, Run run, TaskListener listener) Result result = run.getResult(); ParametersAction paramsAction = run.getAction(ParametersAction.class); EnvVars environment = run.getEnvironment( listener ); - String log = run.getLog(); + String log = this.getLog(run, target); jobState.setName( job.getName()); jobState.setUrl( job.getUrl()); @@ -119,4 +120,29 @@ private JobState buildJobState(Job job, Run run, TaskListener listener) return jobState; } -} \ No newline at end of file + + private String getLog(Run run, Endpoint target) { + String log = ""; + Integer loglines = target.getLoglines(); + try { + switch (loglines) { + // The full log + case -1: + log = run.getLog(); + break; + // No log + case 0: + log = ""; + break; + default: + List logEntries = run.getLog(loglines); + for (String entry: logEntries) { + log += entry + "\n"; + } + } + } catch (IOException e) { + log = "Unable to retrieve log"; + } + return log; + } +} diff --git a/src/main/resources/com/tikal/hudson/plugins/notification/HudsonNotificationProperty/config.jelly b/src/main/resources/com/tikal/hudson/plugins/notification/HudsonNotificationProperty/config.jelly index d97c0fd..ce95168 100755 --- a/src/main/resources/com/tikal/hudson/plugins/notification/HudsonNotificationProperty/config.jelly +++ b/src/main/resources/com/tikal/hudson/plugins/notification/HudsonNotificationProperty/config.jelly @@ -56,6 +56,14 @@ + + + + + + + From d003019437910164301846a0166d6d82d3b3ad14 Mon Sep 17 00:00:00 2001 From: Dave Hall Date: Tue, 25 Nov 2014 01:27:50 +1100 Subject: [PATCH 073/214] Switch to StringBuilder --- .../tikal/hudson/plugins/notification/Phase.java | 13 ++++++------- .../plugins/notification/model/BuildState.java | 9 +++++---- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/main/java/com/tikal/hudson/plugins/notification/Phase.java b/src/main/java/com/tikal/hudson/plugins/notification/Phase.java index 962f8f8..6ec2a3d 100755 --- a/src/main/java/com/tikal/hudson/plugins/notification/Phase.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/Phase.java @@ -74,7 +74,7 @@ private JobState buildJobState(Job job, Run run, TaskListener listener, Endpoint Result result = run.getResult(); ParametersAction paramsAction = run.getAction(ParametersAction.class); EnvVars environment = run.getEnvironment( listener ); - String log = this.getLog(run, target); + StringBuilder log = this.getLog(run, target); jobState.setName( job.getName()); jobState.setUrl( job.getUrl()); @@ -121,27 +121,26 @@ private JobState buildJobState(Job job, Run run, TaskListener listener, Endpoint return jobState; } - private String getLog(Run run, Endpoint target) { - String log = ""; + private StringBuilder getLog(Run run, Endpoint target) { + StringBuilder log = new StringBuilder(""); Integer loglines = target.getLoglines(); try { switch (loglines) { // The full log case -1: - log = run.getLog(); + log = log.append(run.getLog()); break; // No log case 0: - log = ""; break; default: List logEntries = run.getLog(loglines); for (String entry: logEntries) { - log += entry + "\n"; + log.append(entry + "\n"); } } } catch (IOException e) { - log = "Unable to retrieve log"; + log.append("Unable to retrieve log"); } return log; } diff --git a/src/main/java/com/tikal/hudson/plugins/notification/model/BuildState.java b/src/main/java/com/tikal/hudson/plugins/notification/model/BuildState.java index 79d2d8b..bf69792 100755 --- a/src/main/java/com/tikal/hudson/plugins/notification/model/BuildState.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/model/BuildState.java @@ -24,6 +24,7 @@ import jenkins.model.Jenkins; import java.io.File; +import java.lang.StringBuilder; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -46,7 +47,7 @@ public class BuildState { private Map parameters; - private String log; + private StringBuilder log; /** * Map of artifacts: file name => Map of artifact locations ( location name => artifact URL ) @@ -130,11 +131,11 @@ public void setScm ( ScmState scmState ) this.scm = scmState; } - public String getLog() { - return log; + public StringBuilder getLog() { + return this.log; } - public void setLog(String log) { + public void setLog(StringBuilder log) { this.log = log; } From 9229e4c5ed49cebc615feec4c42f3ba3cd574a8b Mon Sep 17 00:00:00 2001 From: Dave Hall Date: Thu, 27 Nov 2014 02:49:46 +1100 Subject: [PATCH 074/214] Fix NullPointerException --- .../java/com/tikal/hudson/plugins/notification/Phase.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/com/tikal/hudson/plugins/notification/Phase.java b/src/main/java/com/tikal/hudson/plugins/notification/Phase.java index 6ec2a3d..626a1cc 100755 --- a/src/main/java/com/tikal/hudson/plugins/notification/Phase.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/Phase.java @@ -124,6 +124,11 @@ private JobState buildJobState(Job job, Run run, TaskListener listener, Endpoint private StringBuilder getLog(Run run, Endpoint target) { StringBuilder log = new StringBuilder(""); Integer loglines = target.getLoglines(); + + if (null == loglines) { + loglines = 0; + } + try { switch (loglines) { // The full log From 14d6446e99be98353cda342adb384aee6fe77a02 Mon Sep 17 00:00:00 2001 From: Dave Hall Date: Thu, 4 Dec 2014 14:34:53 +1100 Subject: [PATCH 075/214] Don't concatenate strings, use append() instead --- src/main/java/com/tikal/hudson/plugins/notification/Phase.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/tikal/hudson/plugins/notification/Phase.java b/src/main/java/com/tikal/hudson/plugins/notification/Phase.java index 626a1cc..044a8b7 100755 --- a/src/main/java/com/tikal/hudson/plugins/notification/Phase.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/Phase.java @@ -141,7 +141,8 @@ private StringBuilder getLog(Run run, Endpoint target) { default: List logEntries = run.getLog(loglines); for (String entry: logEntries) { - log.append(entry + "\n"); + log.append(entry); + log.append("\n"); } } } catch (IOException e) { From 4d7b2604c1a4503d49b8bc1f61ca904fb213ee72 Mon Sep 17 00:00:00 2001 From: Dave Hall Date: Thu, 4 Dec 2014 20:33:41 +1100 Subject: [PATCH 076/214] Clean up switch/case logic --- .../java/com/tikal/hudson/plugins/notification/Phase.java | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/tikal/hudson/plugins/notification/Phase.java b/src/main/java/com/tikal/hudson/plugins/notification/Phase.java index 044a8b7..c5ffc12 100755 --- a/src/main/java/com/tikal/hudson/plugins/notification/Phase.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/Phase.java @@ -126,17 +126,14 @@ private StringBuilder getLog(Run run, Endpoint target) { Integer loglines = target.getLoglines(); if (null == loglines) { - loglines = 0; + return log; } try { switch (loglines) { // The full log case -1: - log = log.append(run.getLog()); - break; - // No log - case 0: + log.append(run.getLog()); break; default: List logEntries = run.getLog(loglines); From 36ef67fcd31d32dca3908a57e8107d6afa886591 Mon Sep 17 00:00:00 2001 From: vb-linetco Date: Wed, 25 Feb 2015 15:48:04 +0100 Subject: [PATCH 077/214] added support for parameters in url --- .../java/com/tikal/hudson/plugins/notification/Phase.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/tikal/hudson/plugins/notification/Phase.java b/src/main/java/com/tikal/hudson/plugins/notification/Phase.java index c5ffc12..4491cb9 100755 --- a/src/main/java/com/tikal/hudson/plugins/notification/Phase.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/Phase.java @@ -33,6 +33,8 @@ public void handle(Run run, TaskListener listener) { HudsonNotificationProperty property = (HudsonNotificationProperty) run.getParent().getProperty(HudsonNotificationProperty.class); if ( property == null ){ return; } + + EnvVar environment = run.getEnvironment(listener); for ( Endpoint target : property.getEndpoints()) { if ( isRun( target )) { @@ -40,7 +42,8 @@ public void handle(Run run, TaskListener listener) { try { JobState jobState = buildJobState(run.getParent(), run, listener, target); - target.getProtocol().send(target.getUrl(), + String expandedUrl = environment.expand(target.getUrl()); + target.getProtocol().send(expandedUrl, target.getFormat().serialize(jobState), target.getTimeout(), target.isJson()); From eaca65ec4fb41d37b544deac8c11221f179d428b Mon Sep 17 00:00:00 2001 From: vb-linetco Date: Wed, 25 Feb 2015 16:01:28 +0100 Subject: [PATCH 078/214] fixed typo --- src/main/java/com/tikal/hudson/plugins/notification/Phase.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/tikal/hudson/plugins/notification/Phase.java b/src/main/java/com/tikal/hudson/plugins/notification/Phase.java index 4491cb9..c7a23e9 100755 --- a/src/main/java/com/tikal/hudson/plugins/notification/Phase.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/Phase.java @@ -34,7 +34,7 @@ public void handle(Run run, TaskListener listener) { HudsonNotificationProperty property = (HudsonNotificationProperty) run.getParent().getProperty(HudsonNotificationProperty.class); if ( property == null ){ return; } - EnvVar environment = run.getEnvironment(listener); + EnvVars environment = run.getEnvironment(listener); for ( Endpoint target : property.getEndpoints()) { if ( isRun( target )) { From fbe94f53cec52e684da87e4496e3209b63d0c2b2 Mon Sep 17 00:00:00 2001 From: vb-linetco Date: Wed, 25 Feb 2015 16:11:24 +0100 Subject: [PATCH 079/214] expand the envvar inside the try --- src/main/java/com/tikal/hudson/plugins/notification/Phase.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/com/tikal/hudson/plugins/notification/Phase.java b/src/main/java/com/tikal/hudson/plugins/notification/Phase.java index c7a23e9..04aee2a 100755 --- a/src/main/java/com/tikal/hudson/plugins/notification/Phase.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/Phase.java @@ -34,14 +34,13 @@ public void handle(Run run, TaskListener listener) { HudsonNotificationProperty property = (HudsonNotificationProperty) run.getParent().getProperty(HudsonNotificationProperty.class); if ( property == null ){ return; } - EnvVars environment = run.getEnvironment(listener); - for ( Endpoint target : property.getEndpoints()) { if ( isRun( target )) { listener.getLogger().println( String.format( "Notifying endpoint '%s'", target )); try { JobState jobState = buildJobState(run.getParent(), run, listener, target); + EnvVars environment = run.getEnvironment(listener); String expandedUrl = environment.expand(target.getUrl()); target.getProtocol().send(expandedUrl, target.getFormat().serialize(jobState), From 219d5ca6e8510c11da6a952ecc496d37c08bad70 Mon Sep 17 00:00:00 2001 From: Haggai Philip Zagury Date: Thu, 26 Feb 2015 14:30:43 +0200 Subject: [PATCH 080/214] [maven-release-plugin] prepare release notification-1.8 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 22cd36f..9e30cbc 100755 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ 4.0.0 com.tikalk.hudson.plugins notification - 1.8-SNAPSHOT + 1.8 hpi Jenkins Notification plugin Sends notifications about jobs phases and status @@ -115,7 +115,7 @@ scm:git:git://github.com/jenkinsci/notification-plugin.git scm:git:git@github.com:jenkinsci/notification-plugin.git http://github.com/jenkinsci/notification-plugin - HEAD + notification-1.8 From 207ebf63815e307c896859c74cfa8acaef510156 Mon Sep 17 00:00:00 2001 From: Haggai Philip Zagury Date: Thu, 26 Feb 2015 14:30:47 +0200 Subject: [PATCH 081/214] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 9e30cbc..2f809b4 100755 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ 4.0.0 com.tikalk.hudson.plugins notification - 1.8 + 1.9-SNAPSHOT hpi Jenkins Notification plugin Sends notifications about jobs phases and status @@ -115,7 +115,7 @@ scm:git:git://github.com/jenkinsci/notification-plugin.git scm:git:git@github.com:jenkinsci/notification-plugin.git http://github.com/jenkinsci/notification-plugin - notification-1.8 + HEAD From 0983d1a251246c27f07d331d0f124ea2978fd674 Mon Sep 17 00:00:00 2001 From: Haggai Philip Zagury Date: Thu, 26 Feb 2015 15:04:02 +0200 Subject: [PATCH 082/214] [maven-release-plugin] prepare release notification-1.9 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 2f809b4..c38861c 100755 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ 4.0.0 com.tikalk.hudson.plugins notification - 1.9-SNAPSHOT + 1.9 hpi Jenkins Notification plugin Sends notifications about jobs phases and status @@ -115,7 +115,7 @@ scm:git:git://github.com/jenkinsci/notification-plugin.git scm:git:git@github.com:jenkinsci/notification-plugin.git http://github.com/jenkinsci/notification-plugin - HEAD + notification-1.9 From 44058edaebd457c433a568fc0117ffd7d26639fb Mon Sep 17 00:00:00 2001 From: Haggai Philip Zagury Date: Thu, 26 Feb 2015 15:04:08 +0200 Subject: [PATCH 083/214] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index c38861c..419dabb 100755 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ 4.0.0 com.tikalk.hudson.plugins notification - 1.9 + 1.10-SNAPSHOT hpi Jenkins Notification plugin Sends notifications about jobs phases and status @@ -115,7 +115,7 @@ scm:git:git://github.com/jenkinsci/notification-plugin.git scm:git:git@github.com:jenkinsci/notification-plugin.git http://github.com/jenkinsci/notification-plugin - notification-1.9 + HEAD From 3b5b149abb23e224b395bbb0fa4f189a8708fe03 Mon Sep 17 00:00:00 2001 From: Ryan Plauche Date: Tue, 19 May 2015 14:38:25 -0500 Subject: [PATCH 084/214] Added attribute queueId to BuildState model, pulling from hudson.models.Run. --- pom.xml | 2 +- .../com/tikal/hudson/plugins/notification/Phase.java | 1 + .../hudson/plugins/notification/model/BuildState.java | 10 ++++++++++ 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 419dabb..82ac2b0 100755 --- a/pom.xml +++ b/pom.xml @@ -12,7 +12,7 @@ org.jenkins-ci.plugins plugin - 1.566 + 1.605 diff --git a/src/main/java/com/tikal/hudson/plugins/notification/Phase.java b/src/main/java/com/tikal/hudson/plugins/notification/Phase.java index 04aee2a..43f32d7 100755 --- a/src/main/java/com/tikal/hudson/plugins/notification/Phase.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/Phase.java @@ -83,6 +83,7 @@ private JobState buildJobState(Job job, Run run, TaskListener listener, Endpoint jobState.setBuild( buildState ); buildState.setNumber( run.number ); + buildState.setQueueId( run.getQueueId() ); buildState.setUrl( run.getUrl()); buildState.setPhase( this ); buildState.setScm( scmState ); diff --git a/src/main/java/com/tikal/hudson/plugins/notification/model/BuildState.java b/src/main/java/com/tikal/hudson/plugins/notification/model/BuildState.java index bf69792..434b3d9 100755 --- a/src/main/java/com/tikal/hudson/plugins/notification/model/BuildState.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/model/BuildState.java @@ -35,6 +35,8 @@ public class BuildState { private int number; + private long queueId; + private Phase phase; private String status; @@ -69,6 +71,14 @@ public void setNumber(int number) { this.number = number; } + public long getQueueId() { + return queueId; + } + + public void setQueueId(long queue) { + this.queueId = queue; + } + public Phase getPhase() { return phase; } From 407a5d64441eab2ecd64103d3993c565195f596d Mon Sep 17 00:00:00 2001 From: Rich Kang Date: Mon, 29 Jun 2015 11:09:07 +0100 Subject: [PATCH 085/214] Use artifact relativePath, not filename This allows multiple files of the same name in different folders as the array keys no longer collide. --- .../com/tikal/hudson/plugins/notification/model/BuildState.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/tikal/hudson/plugins/notification/model/BuildState.java b/src/main/java/com/tikal/hudson/plugins/notification/model/BuildState.java index bf69792..7598ab7 100755 --- a/src/main/java/com/tikal/hudson/plugins/notification/model/BuildState.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/model/BuildState.java @@ -158,7 +158,7 @@ private void updateArchivedArtifacts ( Run run ) for ( Run.Artifact a : buildArtifacts ) { String artifactUrl = Jenkins.getInstance().getRootUrl() + run.getUrl() + "artifact/" + a.getHref(); - updateArtifact( a.getFileName(), "archive", artifactUrl ); + updateArtifact( a.relativePath, "archive", artifactUrl ); } } From 5b8efbb0bc64855edec3643f9747dde86fa0332a Mon Sep 17 00:00:00 2001 From: Kristen Oliphant Date: Fri, 30 Oct 2015 16:09:26 -0400 Subject: [PATCH 086/214] Add Failure Notification Added a notification only on failure --- .../tikal/hudson/plugins/notification/Phase.java | 14 +++++++++++--- .../HudsonNotificationProperty/config.jelly | 1 + 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/tikal/hudson/plugins/notification/Phase.java b/src/main/java/com/tikal/hudson/plugins/notification/Phase.java index 43f32d7..31ef4bd 100755 --- a/src/main/java/com/tikal/hudson/plugins/notification/Phase.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/Phase.java @@ -35,7 +35,7 @@ public void handle(Run run, TaskListener listener) { if ( property == null ){ return; } for ( Endpoint target : property.getEndpoints()) { - if ( isRun( target )) { + if ( isRun( target, run.getResult() )) { listener.getLogger().println( String.format( "Notifying endpoint '%s'", target )); try { @@ -59,9 +59,17 @@ public void handle(Run run, TaskListener listener) { /** * Determines if the endpoint specified should be notified at the current job phase. */ - private boolean isRun( Endpoint endpoint ) { + private boolean isRun( Endpoint endpoint, Result result ) { String event = endpoint.getEvent(); - return (( event == null ) || event.equals( "all" ) || event.equals( this.toString().toLowerCase())); + + String status = ""; + if ( result != null ) { + status = result.toString(); + } + + boolean buildFailed = event.equals("failed") && this.toString().toLowerCase().equals("finalized") && status.toLowerCase().equals("failure"); + + return (( event == null ) || event.equals( "all" ) || event.equals( this.toString().toLowerCase()) || buildFailed); } private JobState buildJobState(Job job, Run run, TaskListener listener, Endpoint target) diff --git a/src/main/resources/com/tikal/hudson/plugins/notification/HudsonNotificationProperty/config.jelly b/src/main/resources/com/tikal/hudson/plugins/notification/HudsonNotificationProperty/config.jelly index ce95168..ced4069 100755 --- a/src/main/resources/com/tikal/hudson/plugins/notification/HudsonNotificationProperty/config.jelly +++ b/src/main/resources/com/tikal/hudson/plugins/notification/HudsonNotificationProperty/config.jelly @@ -37,6 +37,7 @@ Job Started Job Completed Job Finalized + Job Failed From 055a89b13564d72d7b3d34323113546555e959e5 Mon Sep 17 00:00:00 2001 From: Haggai Philip Zagury Date: Thu, 12 Nov 2015 16:38:59 +0200 Subject: [PATCH 087/214] [maven-release-plugin] prepare release notification-1.10 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 82ac2b0..cb17139 100755 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ 4.0.0 com.tikalk.hudson.plugins notification - 1.10-SNAPSHOT + 1.10 hpi Jenkins Notification plugin Sends notifications about jobs phases and status @@ -115,7 +115,7 @@ scm:git:git://github.com/jenkinsci/notification-plugin.git scm:git:git@github.com:jenkinsci/notification-plugin.git http://github.com/jenkinsci/notification-plugin - HEAD + notification-1.10 From 67a9ebb16b81c68955480e1e99638ba3886af6aa Mon Sep 17 00:00:00 2001 From: Haggai Philip Zagury Date: Thu, 12 Nov 2015 16:39:05 +0200 Subject: [PATCH 088/214] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index cb17139..762ef85 100755 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ 4.0.0 com.tikalk.hudson.plugins notification - 1.10 + 1.11-SNAPSHOT hpi Jenkins Notification plugin Sends notifications about jobs phases and status @@ -115,7 +115,7 @@ scm:git:git://github.com/jenkinsci/notification-plugin.git scm:git:git@github.com:jenkinsci/notification-plugin.git http://github.com/jenkinsci/notification-plugin - notification-1.10 + HEAD From bd5709d93a032865bcc79d5d135d51b7d1618783 Mon Sep 17 00:00:00 2001 From: Steven Aerts Date: Mon, 4 Jan 2016 14:53:53 +0100 Subject: [PATCH 089/214] JENKINS-32270: use jenkins proxy configuration if no http_proxy environment variable is defined, use the jenkins proxy configuration if it is defined. --- .../hudson/plugins/notification/Protocol.java | 29 +++++++------------ 1 file changed, 10 insertions(+), 19 deletions(-) diff --git a/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java b/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java index 5e489df..231a048 100755 --- a/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java @@ -14,20 +14,12 @@ package com.tikal.hudson.plugins.notification; -import java.io.IOException; -import java.io.OutputStream; -import java.net.DatagramPacket; -import java.net.DatagramSocket; -import java.net.HttpURLConnection; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.MalformedURLException; -import java.net.Proxy; -import java.net.Socket; -import java.net.SocketAddress; -import java.net.URL; +import jenkins.model.Jenkins; import javax.xml.bind.DatatypeConverter; +import java.io.IOException; +import java.io.OutputStream; +import java.net.*; public enum Protocol { @@ -73,17 +65,16 @@ protected void send(String url, byte[] data, int timeout, boolean isJson) throws } } - HttpURLConnection connection = null; - if (proxyUrl == null) { - connection = (HttpURLConnection) targetUrl.openConnection(); - - } else { + Proxy proxy = Proxy.NO_PROXY; + if (proxyUrl != null) { // Proxy connection to the address provided final int proxyPort = proxyUrl.getPort() > 0 ? proxyUrl.getPort() : 80; - Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyUrl.getHost(), proxyPort)); - connection = (HttpURLConnection) targetUrl.openConnection(proxy); + proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyUrl.getHost(), proxyPort)); + } else if (Jenkins.getInstance() != null && Jenkins.getInstance().proxy != null) { + proxy = Jenkins.getInstance().proxy.createProxy(targetUrl.getHost()); } + HttpURLConnection connection = (HttpURLConnection) targetUrl.openConnection(proxy); connection.setRequestProperty("Content-Type", String.format( "application/%s;charset=UTF-8", isJson ? "json" : "xml" )); String userInfo = targetUrl.getUserInfo(); if (null != userInfo) { From b431780f6ee46bb773e8a7d47c1fe5406915adf2 Mon Sep 17 00:00:00 2001 From: Jon Date: Thu, 21 Apr 2016 12:35:28 +0100 Subject: [PATCH 090/214] Update JobState.java Add displayName property --- .../hudson/plugins/notification/model/JobState.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/main/java/com/tikal/hudson/plugins/notification/model/JobState.java b/src/main/java/com/tikal/hudson/plugins/notification/model/JobState.java index bee2168..a8bd06c 100755 --- a/src/main/java/com/tikal/hudson/plugins/notification/model/JobState.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/model/JobState.java @@ -20,6 +20,8 @@ public class JobState { private String name; + private String displayName; + private String url; private BuildState build; @@ -32,6 +34,14 @@ public void setName(String name) { this.name = name; } + public String getDisplayName() { + return displayName; + } + + public void setDisplayName(String displayName) { + this.displayName = displayName; + } + public String getUrl() { return url; } From 1b4a9e6de26ff0f7d056946208bb09e6c20d3bb3 Mon Sep 17 00:00:00 2001 From: Jon Date: Thu, 21 Apr 2016 12:44:21 +0100 Subject: [PATCH 091/214] Update Phase.java set displayName --- src/main/java/com/tikal/hudson/plugins/notification/Phase.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/com/tikal/hudson/plugins/notification/Phase.java b/src/main/java/com/tikal/hudson/plugins/notification/Phase.java index 43f32d7..76e6ecc 100755 --- a/src/main/java/com/tikal/hudson/plugins/notification/Phase.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/Phase.java @@ -79,6 +79,7 @@ private JobState buildJobState(Job job, Run run, TaskListener listener, Endpoint StringBuilder log = this.getLog(run, target); jobState.setName( job.getName()); + jobState.setDisplayName(job.getDisplayName()); jobState.setUrl( job.getUrl()); jobState.setBuild( buildState ); From 32871c8afa23aa9d94d2b62e885cf6f6f1967cb2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anders=20Bj=C3=B6rklund?= Date: Mon, 25 Apr 2016 18:21:00 +0200 Subject: [PATCH 092/214] Add timestamp to the build state (as millis) --- .../tikal/hudson/plugins/notification/JobListener.java | 8 ++++---- .../com/tikal/hudson/plugins/notification/Phase.java | 7 ++++--- .../hudson/plugins/notification/model/BuildState.java | 10 ++++++++++ 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/tikal/hudson/plugins/notification/JobListener.java b/src/main/java/com/tikal/hudson/plugins/notification/JobListener.java index c000af1..95cf44a 100755 --- a/src/main/java/com/tikal/hudson/plugins/notification/JobListener.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/JobListener.java @@ -28,17 +28,17 @@ public JobListener() { @Override public void onStarted(Run r, TaskListener listener) { - Phase.STARTED.handle(r, listener); + Phase.STARTED.handle(r, listener, r.getTimeInMillis()); } @Override public void onCompleted(Run r, TaskListener listener) { - Phase.COMPLETED.handle(r, listener); + Phase.COMPLETED.handle(r, listener, r.getTimeInMillis() + r.getDuration()); } @Override public void onFinalized(Run r) { - Phase.FINALIZED.handle(r, TaskListener.NULL); + Phase.FINALIZED.handle(r, TaskListener.NULL, System.currentTimeMillis()); } -} \ No newline at end of file +} diff --git a/src/main/java/com/tikal/hudson/plugins/notification/Phase.java b/src/main/java/com/tikal/hudson/plugins/notification/Phase.java index 43f32d7..c9f09af 100755 --- a/src/main/java/com/tikal/hudson/plugins/notification/Phase.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/Phase.java @@ -29,7 +29,7 @@ public enum Phase { STARTED, COMPLETED, FINALIZED; @SuppressWarnings( "CastToConcreteClass" ) - public void handle(Run run, TaskListener listener) { + public void handle(Run run, TaskListener listener, long timestamp) { HudsonNotificationProperty property = (HudsonNotificationProperty) run.getParent().getProperty(HudsonNotificationProperty.class); if ( property == null ){ return; } @@ -39,7 +39,7 @@ public void handle(Run run, TaskListener listener) { listener.getLogger().println( String.format( "Notifying endpoint '%s'", target )); try { - JobState jobState = buildJobState(run.getParent(), run, listener, target); + JobState jobState = buildJobState(run.getParent(), run, listener, timestamp, target); EnvVars environment = run.getEnvironment(listener); String expandedUrl = environment.expand(target.getUrl()); target.getProtocol().send(expandedUrl, @@ -64,7 +64,7 @@ private boolean isRun( Endpoint endpoint ) { return (( event == null ) || event.equals( "all" ) || event.equals( this.toString().toLowerCase())); } - private JobState buildJobState(Job job, Run run, TaskListener listener, Endpoint target) + private JobState buildJobState(Job job, Run run, TaskListener listener, long timestamp, Endpoint target) throws IOException, InterruptedException { @@ -86,6 +86,7 @@ private JobState buildJobState(Job job, Run run, TaskListener listener, Endpoint buildState.setQueueId( run.getQueueId() ); buildState.setUrl( run.getUrl()); buildState.setPhase( this ); + buildState.setTimestamp( timestamp ); buildState.setScm( scmState ); buildState.setLog( log ); diff --git a/src/main/java/com/tikal/hudson/plugins/notification/model/BuildState.java b/src/main/java/com/tikal/hudson/plugins/notification/model/BuildState.java index dcdd0ae..5ee634a 100755 --- a/src/main/java/com/tikal/hudson/plugins/notification/model/BuildState.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/model/BuildState.java @@ -37,6 +37,8 @@ public class BuildState { private long queueId; + private long timestamp; + private Phase phase; private String status; @@ -79,6 +81,14 @@ public void setQueueId(long queue) { this.queueId = queue; } + public long getTimestamp() { + return timestamp; + } + + public void setTimestamp(long timestamp) { + this.timestamp = timestamp; + } + public Phase getPhase() { return phase; } From b151c50f4a83909df68f412a086a3035bad9f399 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anders=20Bj=C3=B6rklund?= Date: Thu, 12 May 2016 08:08:06 +0200 Subject: [PATCH 093/214] Add queued phase, to log the time spent in queue This queue time does not include the "quiet period". The event is not logged until the build is started. --- .../com/tikal/hudson/plugins/notification/JobListener.java | 3 +++ src/main/java/com/tikal/hudson/plugins/notification/Phase.java | 2 +- .../notification/HudsonNotificationProperty/config.jelly | 1 + 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/tikal/hudson/plugins/notification/JobListener.java b/src/main/java/com/tikal/hudson/plugins/notification/JobListener.java index 95cf44a..c59cfb2 100755 --- a/src/main/java/com/tikal/hudson/plugins/notification/JobListener.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/JobListener.java @@ -16,6 +16,7 @@ import hudson.Extension; import hudson.model.TaskListener; import hudson.model.Run; +import hudson.model.Executor; import hudson.model.listeners.RunListener; @Extension @@ -28,6 +29,8 @@ public JobListener() { @Override public void onStarted(Run r, TaskListener listener) { + Executor e = r.getExecutor(); + Phase.QUEUED.handle(r, TaskListener.NULL, e != null ? System.currentTimeMillis() - e.getTimeSpentInQueue() : 0L); Phase.STARTED.handle(r, listener, r.getTimeInMillis()); } diff --git a/src/main/java/com/tikal/hudson/plugins/notification/Phase.java b/src/main/java/com/tikal/hudson/plugins/notification/Phase.java index c9f09af..f611d33 100755 --- a/src/main/java/com/tikal/hudson/plugins/notification/Phase.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/Phase.java @@ -26,7 +26,7 @@ @SuppressWarnings({ "unchecked", "rawtypes" }) public enum Phase { - STARTED, COMPLETED, FINALIZED; + QUEUED, STARTED, COMPLETED, FINALIZED; @SuppressWarnings( "CastToConcreteClass" ) public void handle(Run run, TaskListener listener, long timestamp) { diff --git a/src/main/resources/com/tikal/hudson/plugins/notification/HudsonNotificationProperty/config.jelly b/src/main/resources/com/tikal/hudson/plugins/notification/HudsonNotificationProperty/config.jelly index ce95168..3c39ab6 100755 --- a/src/main/resources/com/tikal/hudson/plugins/notification/HudsonNotificationProperty/config.jelly +++ b/src/main/resources/com/tikal/hudson/plugins/notification/HudsonNotificationProperty/config.jelly @@ -34,6 +34,7 @@ From a9c58908077ac2d1d54333e0d401a69ea902b3db Mon Sep 17 00:00:00 2001 From: mwinston Date: Mon, 22 Jan 2018 15:03:50 -0800 Subject: [PATCH 122/214] Added unit test for the isRun method --- .../hudson/plugins/notification/Phase.java | 4 +- .../plugins/notification/PhaseTest.java | 101 ++++++++++++++++++ 2 files changed, 104 insertions(+), 1 deletion(-) create mode 100644 src/test/java/com/tikal/hudson/plugins/notification/PhaseTest.java diff --git a/src/main/java/com/tikal/hudson/plugins/notification/Phase.java b/src/main/java/com/tikal/hudson/plugins/notification/Phase.java index 84bb8ae..bcc2590 100755 --- a/src/main/java/com/tikal/hudson/plugins/notification/Phase.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/Phase.java @@ -109,7 +109,9 @@ private boolean isRun( Endpoint endpoint, Result result, Result previousRunResul } boolean firstSuccessAfterFailureNotification = event.equals("failedAndFirstSuccess") - && this.toString().toLowerCase().equals("finalized") && result.equals(Result.SUCCESS) + && this.toString().toLowerCase().equals("finalized") && result != null + && result.equals(Result.SUCCESS) + && previousRunResult != null && previousRunResult.equals(Result.FAILURE); boolean buildFailed = (event.equals("failed") || event.equals("failedAndFirstSuccess")) && this.toString().toLowerCase().equals("finalized") && status.toLowerCase().equals("failure"); diff --git a/src/test/java/com/tikal/hudson/plugins/notification/PhaseTest.java b/src/test/java/com/tikal/hudson/plugins/notification/PhaseTest.java new file mode 100644 index 0000000..e84697a --- /dev/null +++ b/src/test/java/com/tikal/hudson/plugins/notification/PhaseTest.java @@ -0,0 +1,101 @@ +package com.tikal.hudson.plugins.notification; + +import static org.junit.Assert.assertEquals; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +import org.junit.Test; + +import hudson.model.Result; + +public class PhaseTest { + + @Test + public void testIsRun() { + try { + Endpoint endPoint = new Endpoint(null); + Method isRunMethod = Phase.class.getDeclaredMethod("isRun", Endpoint.class, Result.class, Result.class); + isRunMethod.setAccessible(true); + + assertEquals("returns true for null endpoint event", + isRunMethod.invoke(Phase.QUEUED, endPoint, null, null), Boolean.TRUE); + + endPoint.setEvent("all"); + for (Phase phaseValue : Phase.values()) { + assertEquals("all Event returns true for Phase " + phaseValue.toString(), + isRunMethod.invoke(phaseValue, endPoint, null, null), Boolean.TRUE); + } + + endPoint.setEvent("queued"); + assertEquals("queued Event returns true for Phase Queued", + isRunMethod.invoke(Phase.QUEUED, endPoint, null, null), Boolean.TRUE); + assertEquals("queued Event returns false for Phase Started", + isRunMethod.invoke(Phase.STARTED, endPoint, null, null), Boolean.FALSE); + + endPoint.setEvent("started"); + assertEquals("started Event returns true for Phase Started", + isRunMethod.invoke(Phase.STARTED, endPoint, null, null), Boolean.TRUE); + assertEquals("started Event returns false for Phase Completed", + isRunMethod.invoke(Phase.COMPLETED, endPoint, null, null), Boolean.FALSE); + + + endPoint.setEvent("completed"); + assertEquals("completed Event returns true for Phase Completed", + isRunMethod.invoke(Phase.COMPLETED, endPoint, null, null), Boolean.TRUE); + assertEquals("completed Event returns false for Phase Finalized", + isRunMethod.invoke(Phase.FINALIZED, endPoint, null, null), Boolean.FALSE); + + + endPoint.setEvent("finalized"); + assertEquals("finalized Event returns true for Phase Finalized", + isRunMethod.invoke(Phase.FINALIZED, endPoint, null, null), Boolean.TRUE); + assertEquals("finalized Event returns true for Phase Queued", + isRunMethod.invoke(Phase.QUEUED, endPoint, null, null), Boolean.FALSE); + + + endPoint.setEvent("failed"); + assertEquals("failed Event returns false for Phase Finalized and no status", + isRunMethod.invoke(Phase.FINALIZED, endPoint, null, null), Boolean.FALSE); + assertEquals("failed Event returns false for Phase Finalized and success status", + isRunMethod.invoke(Phase.FINALIZED, endPoint, Result.SUCCESS, null), Boolean.FALSE); + assertEquals("failed Event returns true for Phase Finalized and success failure", + isRunMethod.invoke(Phase.FINALIZED, endPoint, Result.FAILURE, null), Boolean.TRUE); + assertEquals("failed Event returns false for Phase not Finalized and success failure", + isRunMethod.invoke(Phase.COMPLETED, endPoint, Result.FAILURE, null), Boolean.FALSE); + + endPoint.setEvent("failedAndFirstSuccess"); + assertEquals("failedAndFirstSuccess Event returns false for Phase Finalized and no status", + isRunMethod.invoke(Phase.FINALIZED, endPoint, null, null), Boolean.FALSE); + assertEquals("failedAndFirstSuccess Event returns false for Phase Finalized and no previous status", + isRunMethod.invoke(Phase.FINALIZED, endPoint, Result.SUCCESS, null), Boolean.FALSE); + assertEquals("failedAndFirstSuccess Event returns true for Phase Finalized and no previous status and failed status", + isRunMethod.invoke(Phase.FINALIZED, endPoint, Result.FAILURE, null), Boolean.TRUE); + assertEquals("failedAndFirstSuccess Event returns true for Phase Finalized and failed status", + isRunMethod.invoke(Phase.FINALIZED, endPoint, Result.FAILURE, Result.FAILURE), Boolean.TRUE); + assertEquals("failedAndFirstSuccess Event returns true for Phase Finalized and success status with previous status of failure", + isRunMethod.invoke(Phase.FINALIZED, endPoint, Result.SUCCESS, Result.FAILURE), Boolean.TRUE); + assertEquals("failedAndFirstSuccess Event returns false for Phase Finalized and success status with previous status of success", + isRunMethod.invoke(Phase.FINALIZED, endPoint, Result.SUCCESS, Result.SUCCESS), Boolean.FALSE); + assertEquals("failedAndFirstSuccess Event returns false for Phase not Finalized", + isRunMethod.invoke(Phase.COMPLETED, endPoint, Result.SUCCESS, Result.FAILURE), Boolean.FALSE); + + + + + } catch (NoSuchMethodException | SecurityException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (IllegalAccessException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (IllegalArgumentException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (InvocationTargetException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + +} From dd898c328e1511c0a8a8a53dedf5ada3fe3d14d2 Mon Sep 17 00:00:00 2001 From: mwinston Date: Mon, 22 Jan 2018 15:24:07 -0800 Subject: [PATCH 123/214] Refactor Phase::isRun to handle additional cases gracefully. --- .../hudson/plugins/notification/Phase.java | 32 ++++++++++++------- 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/src/main/java/com/tikal/hudson/plugins/notification/Phase.java b/src/main/java/com/tikal/hudson/plugins/notification/Phase.java index bcc2590..188d086 100755 --- a/src/main/java/com/tikal/hudson/plugins/notification/Phase.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/Phase.java @@ -102,21 +102,29 @@ public void handle(Run run, TaskListener listener, long timestamp) { */ private boolean isRun( Endpoint endpoint, Result result, Result previousRunResult ) { String event = endpoint.getEvent(); + + if(event == null) + return true; - String status = ""; - if ( result != null ) { - status = result.toString(); + switch(event){ + case "all": + return true; + case "queued": + case "started": + case "completed": + case "finalized": + return event.equals(this.toString().toLowerCase()); + case "failed": + if (result == null) {return false;} + return this.equals(FINALIZED) && result.equals(Result.FAILURE); + case "failedAndFirstSuccess": + if (result == null || !this.equals(FINALIZED)) {return false;} + if (result.equals(Result.FAILURE)) {return true;} + if (previousRunResult != null && result.equals(Result.SUCCESS) && previousRunResult.equals(Result.FAILURE)) {return true;} + return false; } - boolean firstSuccessAfterFailureNotification = event.equals("failedAndFirstSuccess") - && this.toString().toLowerCase().equals("finalized") && result != null - && result.equals(Result.SUCCESS) - && previousRunResult != null - && previousRunResult.equals(Result.FAILURE); - - boolean buildFailed = (event.equals("failed") || event.equals("failedAndFirstSuccess")) && this.toString().toLowerCase().equals("finalized") && status.toLowerCase().equals("failure"); - - return (( event == null ) || event.equals( "all" ) || event.equals( this.toString().toLowerCase()) || buildFailed || firstSuccessAfterFailureNotification); + return false; } private JobState buildJobState(Job job, Run run, TaskListener listener, long timestamp, Endpoint target) From 51f81be2b18e66407e496783049b8b5d0e39f297 Mon Sep 17 00:00:00 2001 From: mwinston Date: Mon, 22 Jan 2018 15:26:19 -0800 Subject: [PATCH 124/214] Added default value to case statement. --- .../com/tikal/hudson/plugins/notification/Phase.java | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/tikal/hudson/plugins/notification/Phase.java b/src/main/java/com/tikal/hudson/plugins/notification/Phase.java index 188d086..10a379a 100755 --- a/src/main/java/com/tikal/hudson/plugins/notification/Phase.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/Phase.java @@ -109,11 +109,6 @@ private boolean isRun( Endpoint endpoint, Result result, Result previousRunResul switch(event){ case "all": return true; - case "queued": - case "started": - case "completed": - case "finalized": - return event.equals(this.toString().toLowerCase()); case "failed": if (result == null) {return false;} return this.equals(FINALIZED) && result.equals(Result.FAILURE); @@ -122,9 +117,9 @@ private boolean isRun( Endpoint endpoint, Result result, Result previousRunResul if (result.equals(Result.FAILURE)) {return true;} if (previousRunResult != null && result.equals(Result.SUCCESS) && previousRunResult.equals(Result.FAILURE)) {return true;} return false; + default: + return event.equals(this.toString().toLowerCase()); } - - return false; } private JobState buildJobState(Job job, Run run, TaskListener listener, long timestamp, Endpoint target) From 050ed9c6579767987e3219c4cd8fefdd7ce12cb4 Mon Sep 17 00:00:00 2001 From: Chen Cohen Date: Mon, 2 Apr 2018 15:46:24 +0300 Subject: [PATCH 125/214] [maven-release-plugin] prepare release notification-1.13 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index d7525ba..4dec17a 100755 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ 4.0.0 com.tikalk.hudson.plugins notification - 1.13-SNAPSHOT + 1.13 hpi Jenkins Notification plugin Sends notifications about jobs phases and status @@ -169,7 +169,7 @@ scm:git:git://github.com/jenkinsci/notification-plugin.git scm:git:git@github.com:jenkinsci/notification-plugin.git http://github.com/jenkinsci/notification-plugin - HEAD + notification-1.13 From c10a4d5ee661fe033903c60e94a47e22e0c6ec32 Mon Sep 17 00:00:00 2001 From: Chen Cohen Date: Mon, 2 Apr 2018 15:46:32 +0300 Subject: [PATCH 126/214] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 4dec17a..809803b 100755 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ 4.0.0 com.tikalk.hudson.plugins notification - 1.13 + 1.14-SNAPSHOT hpi Jenkins Notification plugin Sends notifications about jobs phases and status @@ -169,7 +169,7 @@ scm:git:git://github.com/jenkinsci/notification-plugin.git scm:git:git@github.com:jenkinsci/notification-plugin.git http://github.com/jenkinsci/notification-plugin - notification-1.13 + HEAD From 38518dadd67f9eb447b62913d3c6031cd943faec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20Gond=C5=BEa?= Date: Fri, 15 Jun 2018 14:19:56 +0200 Subject: [PATCH 127/214] Add Jenkinsfile --- Jenkinsfile | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 Jenkinsfile diff --git a/Jenkinsfile b/Jenkinsfile new file mode 100644 index 0000000..77c9ed7 --- /dev/null +++ b/Jenkinsfile @@ -0,0 +1,4 @@ +#!/usr/bin/env groovy + +/* `buildPlugin` step provided by: https://github.com/jenkins-infra/pipeline-library */ +buildPlugin() From 64172adcb47f22c62b96ef83d447c08797c6ced9 Mon Sep 17 00:00:00 2001 From: Daniel Beck Date: Tue, 8 Oct 2019 11:53:37 +0200 Subject: [PATCH 128/214] Use HTTPS URLs in pom.xml --- pom.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index 809803b..79ca86d 100755 --- a/pom.xml +++ b/pom.xml @@ -22,7 +22,7 @@ repo.jenkins-ci.org - http://repo.jenkins-ci.org/public/ + https://repo.jenkins-ci.org/public/ true @@ -35,7 +35,7 @@ repo.jenkins-ci.org - http://repo.jenkins-ci.org/public/ + https://repo.jenkins-ci.org/public/ true @@ -54,7 +54,7 @@ maven-compiler-plugin 3.1 - + org.jenkins-ci.tools maven-hpi-plugin From 065165c4368faab8b2ac738a668eceeea8711867 Mon Sep 17 00:00:00 2001 From: Stephen Ball Date: Thu, 19 Nov 2020 20:54:17 +0000 Subject: [PATCH 129/214] Remove from config screen for version 2.266 of Jenkins --- pom.xml | 2 +- .../HudsonNotificationProperty/config.jelly | 75 +++++++++---------- .../lib/notification/blockWrapper.jelly | 16 ++++ .../notification/blockWrapperCentered.jelly | 16 ++++ .../lib/notification/cellWrapper.jelly | 16 ++++ .../lib/notification/rowWrapper.jelly | 16 ++++ 6 files changed, 102 insertions(+), 39 deletions(-) create mode 100644 src/main/resources/lib/notification/blockWrapper.jelly create mode 100644 src/main/resources/lib/notification/blockWrapperCentered.jelly create mode 100644 src/main/resources/lib/notification/cellWrapper.jelly create mode 100644 src/main/resources/lib/notification/rowWrapper.jelly diff --git a/pom.xml b/pom.xml index 79ca86d..27ad460 100755 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ 4.0.0com.tikalk.hudson.pluginsnotification - 1.14-SNAPSHOT + 1.16-SNAPSHOThpiJenkins Notification pluginSends notifications about jobs phases and status diff --git a/src/main/resources/com/tikal/hudson/plugins/notification/HudsonNotificationProperty/config.jelly b/src/main/resources/com/tikal/hudson/plugins/notification/HudsonNotificationProperty/config.jelly index a7c1335..fa37508 100755 --- a/src/main/resources/com/tikal/hudson/plugins/notification/HudsonNotificationProperty/config.jelly +++ b/src/main/resources/com/tikal/hudson/plugins/notification/HudsonNotificationProperty/config.jelly @@ -1,26 +1,26 @@ + xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form" xmlns:c="/lib/credentials" xmlns:p="/lib/notification"> -
    + -
    - - - - - - - - - - - - - - - - - - - - - - - - - -
    + + + -
    + + + + -
    + + + + -
    + + + + @@ -59,43 +59,42 @@ -
    + + + + -
    + + + + -
    + + + + -
    + + + + -
    + + + - +
    diff --git a/src/main/resources/lib/notification/blockWrapper.jelly b/src/main/resources/lib/notification/blockWrapper.jelly new file mode 100644 index 0000000..d43a2fe --- /dev/null +++ b/src/main/resources/lib/notification/blockWrapper.jelly @@ -0,0 +1,16 @@ + + + + + +
    + +
    +
    + + + +
    +
    +
    +
    diff --git a/src/main/resources/lib/notification/blockWrapperCentered.jelly b/src/main/resources/lib/notification/blockWrapperCentered.jelly new file mode 100644 index 0000000..0e9d7ed --- /dev/null +++ b/src/main/resources/lib/notification/blockWrapperCentered.jelly @@ -0,0 +1,16 @@ + + + + + +
    + +
    +
    + + + +
    +
    +
    +
    diff --git a/src/main/resources/lib/notification/cellWrapper.jelly b/src/main/resources/lib/notification/cellWrapper.jelly new file mode 100644 index 0000000..0a30187 --- /dev/null +++ b/src/main/resources/lib/notification/cellWrapper.jelly @@ -0,0 +1,16 @@ + + + + + +
    + +
    +
    + + + + + +
    +
    diff --git a/src/main/resources/lib/notification/rowWrapper.jelly b/src/main/resources/lib/notification/rowWrapper.jelly new file mode 100644 index 0000000..710190d --- /dev/null +++ b/src/main/resources/lib/notification/rowWrapper.jelly @@ -0,0 +1,16 @@ + + + + + +
    + +
    +
    + + + + + +
    +
    From 18702e6b34d91c43d84739854ec1f6054e253859 Mon Sep 17 00:00:00 2001 From: Stephen Ball Date: Thu, 19 Nov 2020 21:13:44 +0000 Subject: [PATCH 130/214] Add missing file --- src/main/resources/lib/notification/taglib | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 src/main/resources/lib/notification/taglib diff --git a/src/main/resources/lib/notification/taglib b/src/main/resources/lib/notification/taglib new file mode 100644 index 0000000..e69de29 From 873800c1669ad81249bb49f16bacc7a69aaab835 Mon Sep 17 00:00:00 2001 From: Stephen Ball Date: Thu, 19 Nov 2020 22:04:02 +0000 Subject: [PATCH 131/214] Update pom.xml Reverted version as I misunderstood (and also some how managed to increase it by 2) --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 27ad460..79ca86d 100755 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ 4.0.0 com.tikalk.hudson.plugins notification - 1.16-SNAPSHOT + 1.14-SNAPSHOT hpi Jenkins Notification plugin Sends notifications about jobs phases and status From 3219ce87e8fe49ddbb7e125e75e3e5a91b0fa63e Mon Sep 17 00:00:00 2001 From: Stephen Ball Date: Fri, 20 Nov 2020 08:53:10 +0000 Subject: [PATCH 132/214] Trying to figure out failing build --- Jenkinsfile | 5 +++-- pom.xml | 8 ++++++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 77c9ed7..2defed2 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -1,4 +1,5 @@ #!/usr/bin/env groovy -/* `buildPlugin` step provided by: https://github.com/jenkins-infra/pipeline-library */ -buildPlugin() +// Use recommended configuration, run all tests to completion (don't fail fast) +buildPlugin(configurations: buildPlugin.recommendedConfigurations(), + failFast: false) diff --git a/pom.xml b/pom.xml index 79ca86d..1f7b8c3 100755 --- a/pom.xml +++ b/pom.xml @@ -71,6 +71,14 @@ + + org.codehaus.mojo + findbugs-maven-plugin + 3.0.4 + + ${maven.findbugs.failure.strict} + + From 7435e3ef4e53b968110a137933ea10d8635a7183 Mon Sep 17 00:00:00 2001 From: Stephen Ball Date: Mon, 23 Nov 2020 18:43:18 +0000 Subject: [PATCH 133/214] test --- Jenkinsfile | 5 ++--- pom.xml | 41 ++++++++++++++++++++++------------------- 2 files changed, 24 insertions(+), 22 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 2defed2..77c9ed7 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -1,5 +1,4 @@ #!/usr/bin/env groovy -// Use recommended configuration, run all tests to completion (don't fail fast) -buildPlugin(configurations: buildPlugin.recommendedConfigurations(), - failFast: false) +/* `buildPlugin` step provided by: https://github.com/jenkins-infra/pipeline-library */ +buildPlugin() diff --git a/pom.xml b/pom.xml index 1f7b8c3..983c588 100755 --- a/pom.xml +++ b/pom.xml @@ -1,6 +1,14 @@ 4.0.0 + + + org.jenkins-ci.plugins + plugin + 4.13 + + + com.tikalk.hudson.plugins notification 1.14-SNAPSHOT @@ -9,15 +17,11 @@ Sends notifications about jobs phases and status https://wiki.jenkins-ci.org/display/JENKINS/Notification+Plugin - - org.jenkins-ci.plugins - plugin - 2.9 - - - - false - + + 2.235.1 + 8 + false + @@ -71,19 +75,18 @@ - - org.codehaus.mojo - findbugs-maven-plugin - 3.0.4 - - ${maven.findbugs.failure.strict} - - + + io.jenkins.tools.bom + bom-2.235.x + 18 + import + pom + com.google.code.gson @@ -173,14 +176,14 @@ - + scm:git:git://github.com/jenkinsci/notification-plugin.git scm:git:git@github.com:jenkinsci/notification-plugin.git http://github.com/jenkinsci/notification-plugin HEAD - + The Apache Software License, Version 2.0 http://www.apache.org/licenses/LICENSE-2.0.txt From b22c2406f9f9ec239969dd207cdb83d4a50e7803 Mon Sep 17 00:00:00 2001 From: Stephen Ball Date: Mon, 23 Nov 2020 18:45:26 +0000 Subject: [PATCH 134/214] Fix indenting --- pom.xml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/pom.xml b/pom.xml index 983c588..b4ec467 100755 --- a/pom.xml +++ b/pom.xml @@ -80,13 +80,13 @@ - - io.jenkins.tools.bom - bom-2.235.x - 18 - import - pom - + + io.jenkins.tools.bom + bom-2.235.x + 18 + import + pom + com.google.code.gson From 42966d6e7dad9ec88b948ebb97db0d865de35bde Mon Sep 17 00:00:00 2001 From: Stephen Ball Date: Wed, 25 Nov 2020 14:20:52 +0000 Subject: [PATCH 135/214] Move bom to dependencyManagement --- pom.xml | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/pom.xml b/pom.xml index b4ec467..6c8b3a6 100755 --- a/pom.xml +++ b/pom.xml @@ -79,14 +79,19 @@ + + + + io.jenkins.tools.bom + bom-2.235.x + 18 + import + pom + + + + - - io.jenkins.tools.bom - bom-2.235.x - 18 - import - pom - com.google.code.gson From 396ae48981c12f0f6caaeaa0a9c5b88750deebdc Mon Sep 17 00:00:00 2001 From: Stephen Ball Date: Sat, 19 Dec 2020 14:27:11 +0000 Subject: [PATCH 136/214] Apply changes from #41 --- pom.xml | 52 +- .../hudson/plugins/notification/Format.java | 4 +- .../plugins/notification/HostnamePort.java | 4 +- .../hudson/plugins/notification/Phase.java | 13 +- .../hudson/plugins/notification/Protocol.java | 3 +- .../hudson/plugins/notification/Utils.java | 8 +- .../notification/model/BuildState.java | 530 +++++++++--------- .../plugins/notification/ProtocolTest.java | 23 +- 8 files changed, 298 insertions(+), 339 deletions(-) diff --git a/pom.xml b/pom.xml index 6c8b3a6..2ff6cc5 100755 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.jenkins-ci.plugins plugin - 4.13 + 4.14 @@ -49,42 +49,12 @@ - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.1 - - - - org.jenkins-ci.tools - maven-hpi-plugin - 1.109 - - - maven-release-plugin - 2.4.2 - - - org.apache.maven.scm - maven-scm-provider-gitexe - 1.8.1 - - - - - - - io.jenkins.tools.bom bom-2.235.x - 18 + 19 import pom @@ -102,7 +72,7 @@ org.jenkins-ci.plugins s3 - 0.10.9 + 0.11.5 true @@ -113,26 +83,22 @@ org.apache.httpcomponents httpcore + + org.apache.commons + commons-lang3 + org.jenkins-ci.plugins token-macro - 2.3 true org.jenkins-ci.plugins junit - 1.20 true - - org.mortbay.jetty - jetty - 6.1.26 - test - net.sf.ezmorph ezmorph @@ -142,12 +108,10 @@ org.jenkins-ci.plugins credentials - 1.21 org.jenkins-ci.plugins plain-credentials - 1.3 @@ -184,7 +148,7 @@ scm:git:git://github.com/jenkinsci/notification-plugin.git scm:git:git@github.com:jenkinsci/notification-plugin.git - http://github.com/jenkinsci/notification-plugin + https://github.com/jenkinsci/notification-plugin HEAD diff --git a/src/main/java/com/tikal/hudson/plugins/notification/Format.java b/src/main/java/com/tikal/hudson/plugins/notification/Format.java index fa0e777..702910b 100644 --- a/src/main/java/com/tikal/hudson/plugins/notification/Format.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/Format.java @@ -23,7 +23,7 @@ public enum Format { XML { - private final XStream xstream = new XStream(); + private transient final XStream xstream = new XStream(); @Override protected byte[] serialize(JobState jobState) throws IOException { @@ -32,7 +32,7 @@ protected byte[] serialize(JobState jobState) throws IOException { } }, JSON { - private final Gson gson = new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES).create(); + private transient final Gson gson = new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES).create(); @Override protected byte[] serialize(JobState jobState) throws IOException { diff --git a/src/main/java/com/tikal/hudson/plugins/notification/HostnamePort.java b/src/main/java/com/tikal/hudson/plugins/notification/HostnamePort.java index d460945..0be8426 100644 --- a/src/main/java/com/tikal/hudson/plugins/notification/HostnamePort.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/HostnamePort.java @@ -36,10 +36,10 @@ public static HostnamePort parseUrl(String url) { return null; } String hostname = result.group(1); - int port = Integer.valueOf(result.group(2)); + int port = Integer.parseInt(result.group(2)); return new HostnamePort(hostname, port); } catch (Exception e) { return null; } } -} \ No newline at end of file +} diff --git a/src/main/java/com/tikal/hudson/plugins/notification/Phase.java b/src/main/java/com/tikal/hudson/plugins/notification/Phase.java index 8e758fa..afd63f4 100755 --- a/src/main/java/com/tikal/hudson/plugins/notification/Phase.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/Phase.java @@ -50,6 +50,9 @@ private Result findLastBuildThatFinished(Run run){ Run previousRun = run.getPreviousCompletedBuild(); while(previousRun != null){ Result previousResults = previousRun.getResult(); + if (previousResults == null) { + throw new IllegalStateException("Previous result can't be null here"); + } if (previousResults.equals(Result.SUCCESS) || previousResults.equals(Result.FAILURE) || previousResults.equals(Result.UNSTABLE)){ return previousResults; } @@ -57,15 +60,15 @@ private Result findLastBuildThatFinished(Run run){ } return null; } - + @SuppressWarnings( "CastToConcreteClass" ) public void handle(Run run, TaskListener listener, long timestamp) { HudsonNotificationProperty property = (HudsonNotificationProperty) run.getParent().getProperty(HudsonNotificationProperty.class); if ( property == null ){ return; } - + Result previousCompletedRunResults = findLastBuildThatFinished(run); - + for ( Endpoint target : property.getEndpoints()) { if (isRun(target, run.getResult(), previousCompletedRunResults) && !Utils.isEmpty(target.getUrlInfo().getUrlOrId())) { int triesRemaining = target.getRetries(); @@ -150,7 +153,7 @@ private boolean isRun( Endpoint endpoint, Result result, Result previousRunResul if(event == null) return true; - + switch(event){ case "all": return true; @@ -163,7 +166,7 @@ private boolean isRun( Endpoint endpoint, Result result, Result previousRunResul if (previousRunResult != null && result.equals(Result.SUCCESS) && previousRunResult.equals(Result.FAILURE)) {return true;} return false; default: - return event.equals(this.toString().toLowerCase()); + return event.equals(this.toString().toLowerCase()); } } diff --git a/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java b/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java index 5d37263..1157a7e 100755 --- a/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java @@ -20,6 +20,7 @@ import java.io.IOException; import java.io.OutputStream; import java.net.*; +import java.nio.charset.Charset; public enum Protocol { @@ -78,7 +79,7 @@ protected void send(String url, byte[] data, int timeout, boolean isJson) throws connection.setRequestProperty("Content-Type", String.format( "application/%s;charset=UTF-8", isJson ? "json" : "xml" )); String userInfo = targetUrl.getUserInfo(); if (null != userInfo) { - String b64UserInfo = DatatypeConverter.printBase64Binary(userInfo.getBytes()); + String b64UserInfo = DatatypeConverter.printBase64Binary(userInfo.getBytes(Charset.defaultCharset())); // TODO see if UTF-8 can be used instead of platform default encoding String authorizationHeader = "Basic " + b64UserInfo; connection.setRequestProperty("Authorization", authorizationHeader); } diff --git a/src/main/java/com/tikal/hudson/plugins/notification/Utils.java b/src/main/java/com/tikal/hudson/plugins/notification/Utils.java index d341c92..6c347f5 100644 --- a/src/main/java/com/tikal/hudson/plugins/notification/Utils.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/Utils.java @@ -59,7 +59,7 @@ public static void verifyNotEmpty( String ... strings ) "Some String arguments are null or empty: %s", Arrays.toString( strings ))); } } - + /** * Get the actual URL from the credential id * @param credentialId Credential id to lookup @@ -75,10 +75,6 @@ public static String getSecretUrl(String credentialId) { return null; } Secret secretUrl = creds.getSecret(); - if (secretUrl != null) { - return secretUrl.getPlainText(); - } - - return ""; + return secretUrl.getPlainText(); } } diff --git a/src/main/java/com/tikal/hudson/plugins/notification/model/BuildState.java b/src/main/java/com/tikal/hudson/plugins/notification/model/BuildState.java index 0f8999f..e26117a 100755 --- a/src/main/java/com/tikal/hudson/plugins/notification/model/BuildState.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/model/BuildState.java @@ -1,266 +1,264 @@ -/** - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.tikal.hudson.plugins.notification.model; - -import static com.tikal.hudson.plugins.notification.Utils.*; -import com.tikal.hudson.plugins.notification.Phase; -import hudson.model.AbstractBuild; -import hudson.model.Job; -import hudson.model.Run; -import hudson.plugins.s3.Entry; -import hudson.plugins.s3.S3BucketPublisher; -import hudson.util.DescribableList; -import jenkins.model.Jenkins; - -import java.io.File; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -public class BuildState { - - private String fullUrl; - - private int number; - - private long queueId; - - private long timestamp; - - private Phase phase; - - private String status; - - private String url; - - private String displayName; - - private ScmState scm; - - private Map parameters; - - private StringBuilder log; - - private String notes; - - private TestState testSummary; - - - - - /** - * Map of artifacts: file name => Map of artifact locations ( location name => artifact URL ) - * --- - * artifacts: - * notification.hpi: - * s3: https://s3-eu-west-1.amazonaws.com/evgenyg-bakery-artifacts/jobs/notification-plugin/78/notification.hpi - * archive: http://localhost:8080/job/notification-plugin/78/artifact/target/notification.hpi - * notification.jar: - * archive: http://localhost:8080/job/notification-plugin/78/artifact/target/notification.jar - */ - private final Map> artifacts = new HashMap>(); - - public int getNumber() { - return number; - } - - public void setNumber(int number) { - this.number = number; - } - - public long getQueueId() { - return queueId; - } - - public void setQueueId(long queue) { - this.queueId = queue; - } - - public long getTimestamp() { - return timestamp; - } - - public void setTimestamp(long timestamp) { - this.timestamp = timestamp; - } - - public Phase getPhase() { - return phase; - } - - public void setPhase(Phase phase) { - this.phase = phase; - } - - public String getStatus() { - return status; - } - - public void setStatus(String status) { - this.status = status; - } - - public String getUrl() { - return url; - } - - public void setUrl(String url) { - this.url = url; - } - - public String getFullUrl() { - return fullUrl; - } - - public void setFullUrl(String fullUrl) { - this.fullUrl = fullUrl; - } - - public Map getParameters() { - return parameters; - } - - public void setParameters(Map params) { - this.parameters = new HashMap( params ); - } - - public Map> getArtifacts () { - return artifacts; - } - - public void setDisplayName(String displayName) { - this.displayName = displayName; - } - - public String getDisplayName() { - return displayName; - } - - public ScmState getScm () - { - return scm; - } - - public void setScm ( ScmState scmState ) - { - this.scm = scmState; - } - - public StringBuilder getLog() { - return this.log; - } - - public void setLog(StringBuilder log) { - this.log = log; - } - - public String getNotes() { - return notes; - } - - public void setNotes(String buildNotes) { - this.notes = buildNotes; - } - - public TestState getTestSummary() { - return testSummary; - } - - public void setTestSummary(TestState testSummary) { - this.testSummary = testSummary; - } - - /** - * Updates artifacts Map with S3 links, if corresponding publisher is available. - * @param job Job to update - * @param run Run to update - */ - public void updateArtifacts ( Job job, Run run ) - { - updateArchivedArtifacts( run ); - updateS3Artifacts( job, run ); - } - - - private void updateArchivedArtifacts ( Run run ) - { - @SuppressWarnings( "unchecked" ) - List buildArtifacts = run.getArtifacts(); - - if ( buildArtifacts == null ) { return; } - - for ( Run.Artifact a : buildArtifacts ) { - String artifactUrl = Jenkins.getInstance().getRootUrl() + run.getUrl() + "artifact/" + a.getHref(); - updateArtifact( a.relativePath, "archive", artifactUrl ); - } - } - - - private void updateS3Artifacts ( Job job, Run run ) - { - if ( Jenkins.getInstance().getPlugin( "s3" ) == null ) { return; } - if ( ! ( run instanceof AbstractBuild )){ return; } - if ( isEmpty( job.getName())){ return; } - - DescribableList publishers = (( AbstractBuild ) run ).getProject().getPublishersList(); - S3BucketPublisher s3Publisher = ( S3BucketPublisher ) publishers.get( S3BucketPublisher.class ); - - if ( s3Publisher == null ){ return; } - - for ( Entry entry : s3Publisher.getEntries()) { - - if ( isEmpty( entry.sourceFile, entry.selectedRegion, entry.bucket )){ continue; } - String fileName = new File( entry.sourceFile ).getName(); - if ( isEmpty( fileName )){ continue; } - - // https://s3-eu-west-1.amazonaws.com/evgenyg-temp/ - String bucketUrl = String.format( "https://s3-%s.amazonaws.com/%s", - entry.selectedRegion.toLowerCase().replace( '_', '-' ), - entry.bucket ); - - String fileUrl = entry.managedArtifacts ? - // https://s3-eu-west-1.amazonaws.com/evgenyg-temp/jobs/notification-plugin/21/notification.hpi - String.format( "%s/jobs/%s/%s/%s", bucketUrl, job.getName(), run.getNumber(), fileName ) : - // https://s3-eu-west-1.amazonaws.com/evgenyg-temp/notification.hpi - String.format( "%s/%s", bucketUrl, fileName ); - - updateArtifact( fileName, "s3", fileUrl ); - } - } - - - /** - * Updates an artifact URL. - * - * @param fileName artifact file name - * @param locationName artifact location name, like "s3" or "archive" - * @param locationUrl artifact URL at the location specified - */ - private void updateArtifact( String fileName, String locationName, String locationUrl ) - { - verifyNotEmpty( fileName, locationName, locationUrl ); - - if ( ! artifacts.containsKey( fileName )) { - artifacts.put( fileName, new HashMap()); - } - - if ( artifacts.get( fileName ).containsKey( locationName )) { - throw new RuntimeException( String.format( - "Adding artifacts mapping '%s/%s/%s' - artifacts Map already contains mapping of location '%s': %s", - fileName, locationName, locationUrl, locationName, artifacts )); - } - - artifacts.get( fileName ).put( locationName, locationUrl ); - } -} +/** + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.tikal.hudson.plugins.notification.model; + +import static com.tikal.hudson.plugins.notification.Utils.*; +import com.tikal.hudson.plugins.notification.Phase; +import hudson.model.AbstractBuild; +import hudson.model.Job; +import hudson.model.Run; +import hudson.plugins.s3.Entry; +import hudson.plugins.s3.S3BucketPublisher; +import hudson.util.DescribableList; +import jenkins.model.Jenkins; + +import java.io.File; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class BuildState { + + private String fullUrl; + + private int number; + + private long queueId; + + private long timestamp; + + private Phase phase; + + private String status; + + private String url; + + private String displayName; + + private ScmState scm; + + private Map parameters; + + private StringBuilder log; + + private String notes; + + private TestState testSummary; + + + + + /** + * Map of artifacts: file name => Map of artifact locations ( location name => artifact URL ) + * --- + * artifacts: + * notification.hpi: + * s3: https://s3-eu-west-1.amazonaws.com/evgenyg-bakery-artifacts/jobs/notification-plugin/78/notification.hpi + * archive: http://localhost:8080/job/notification-plugin/78/artifact/target/notification.hpi + * notification.jar: + * archive: http://localhost:8080/job/notification-plugin/78/artifact/target/notification.jar + */ + private final Map> artifacts = new HashMap>(); + + public int getNumber() { + return number; + } + + public void setNumber(int number) { + this.number = number; + } + + public long getQueueId() { + return queueId; + } + + public void setQueueId(long queue) { + this.queueId = queue; + } + + public long getTimestamp() { + return timestamp; + } + + public void setTimestamp(long timestamp) { + this.timestamp = timestamp; + } + + public Phase getPhase() { + return phase; + } + + public void setPhase(Phase phase) { + this.phase = phase; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public String getFullUrl() { + return fullUrl; + } + + public void setFullUrl(String fullUrl) { + this.fullUrl = fullUrl; + } + + public Map getParameters() { + return parameters; + } + + public void setParameters(Map params) { + this.parameters = new HashMap( params ); + } + + public Map> getArtifacts () { + return artifacts; + } + + public void setDisplayName(String displayName) { + this.displayName = displayName; + } + + public String getDisplayName() { + return displayName; + } + + public ScmState getScm () + { + return scm; + } + + public void setScm ( ScmState scmState ) + { + this.scm = scmState; + } + + public StringBuilder getLog() { + return this.log; + } + + public void setLog(StringBuilder log) { + this.log = log; + } + + public String getNotes() { + return notes; + } + + public void setNotes(String buildNotes) { + this.notes = buildNotes; + } + + public TestState getTestSummary() { + return testSummary; + } + + public void setTestSummary(TestState testSummary) { + this.testSummary = testSummary; + } + + /** + * Updates artifacts Map with S3 links, if corresponding publisher is available. + * @param job Job to update + * @param run Run to update + */ + public void updateArtifacts ( Job job, Run run ) + { + updateArchivedArtifacts( run ); + updateS3Artifacts( job, run ); + } + + + private void updateArchivedArtifacts ( Run run ) + { + @SuppressWarnings( "unchecked" ) + List buildArtifacts = run.getArtifacts(); + + for ( Run.Artifact a : buildArtifacts ) { + String artifactUrl = Jenkins.getInstance().getRootUrl() + run.getUrl() + "artifact/" + a.getHref(); + updateArtifact( a.relativePath, "archive", artifactUrl ); + } + } + + + private void updateS3Artifacts ( Job job, Run run ) + { + if ( Jenkins.getInstance().getPlugin( "s3" ) == null ) { return; } + if ( ! ( run instanceof AbstractBuild )){ return; } + if ( isEmpty( job.getName())){ return; } + + DescribableList publishers = (( AbstractBuild ) run ).getProject().getPublishersList(); + S3BucketPublisher s3Publisher = ( S3BucketPublisher ) publishers.get( S3BucketPublisher.class ); + + if ( s3Publisher == null ){ return; } + + for ( Entry entry : s3Publisher.getEntries()) { + + if ( isEmpty( entry.sourceFile, entry.selectedRegion, entry.bucket )){ continue; } + String fileName = new File( entry.sourceFile ).getName(); + if ( isEmpty( fileName )){ continue; } + + // https://s3-eu-west-1.amazonaws.com/evgenyg-temp/ + String bucketUrl = String.format( "https://s3-%s.amazonaws.com/%s", + entry.selectedRegion.toLowerCase().replace( '_', '-' ), + entry.bucket ); + + String fileUrl = entry.managedArtifacts ? + // https://s3-eu-west-1.amazonaws.com/evgenyg-temp/jobs/notification-plugin/21/notification.hpi + String.format( "%s/jobs/%s/%s/%s", bucketUrl, job.getName(), run.getNumber(), fileName ) : + // https://s3-eu-west-1.amazonaws.com/evgenyg-temp/notification.hpi + String.format( "%s/%s", bucketUrl, fileName ); + + updateArtifact( fileName, "s3", fileUrl ); + } + } + + + /** + * Updates an artifact URL. + * + * @param fileName artifact file name + * @param locationName artifact location name, like "s3" or "archive" + * @param locationUrl artifact URL at the location specified + */ + private void updateArtifact( String fileName, String locationName, String locationUrl ) + { + verifyNotEmpty( fileName, locationName, locationUrl ); + + if ( ! artifacts.containsKey( fileName )) { + artifacts.put( fileName, new HashMap()); + } + + if ( artifacts.get( fileName ).containsKey( locationName )) { + throw new RuntimeException( String.format( + "Adding artifacts mapping '%s/%s/%s' - artifacts Map already contains mapping of location '%s': %s", + fileName, locationName, locationUrl, locationName, artifacts )); + } + + artifacts.get( fileName ).put( locationName, locationUrl ); + } +} diff --git a/src/test/java/com/tikal/hudson/plugins/notification/ProtocolTest.java b/src/test/java/com/tikal/hudson/plugins/notification/ProtocolTest.java index 68f0a35..2eb3aea 100644 --- a/src/test/java/com/tikal/hudson/plugins/notification/ProtocolTest.java +++ b/src/test/java/com/tikal/hudson/plugins/notification/ProtocolTest.java @@ -26,11 +26,11 @@ import com.google.common.base.Objects; import com.google.common.io.CharStreams; import junit.framework.TestCase; -import org.mortbay.jetty.HttpHeaders; -import org.mortbay.jetty.Server; -import org.mortbay.jetty.bio.SocketConnector; -import org.mortbay.jetty.servlet.ServletHandler; -import org.mortbay.jetty.servlet.ServletHolder; +import org.eclipse.jetty.server.Connector; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.server.ServerConnector; +import org.eclipse.jetty.servlet.ServletHandler; +import org.eclipse.jetty.servlet.ServletHolder; import javax.servlet.Servlet; import javax.servlet.ServletException; @@ -151,7 +151,7 @@ static class RedirectHandler extends RecordingServlet { @Override protected void doPost(Request request, HttpServletResponse httpResponse) throws IOException { httpResponse.setStatus(HttpServletResponse.SC_TEMPORARY_REDIRECT); - httpResponse.setHeader(HttpHeaders.LOCATION, redirectURI); + httpResponse.setHeader("Location", redirectURI); } } @@ -166,16 +166,13 @@ private UrlFactory startServer(Servlet servlet, String path) throws Exception { } private UrlFactory startSecureServer(Servlet servlet, String path, String authority) throws Exception { - SocketConnector connector = new SocketConnector(); - connector.setPort(0); - connector.open(); - Server server = new Server(); - server.addConnector(connector); + ServerConnector connector = new ServerConnector(server); + server.setConnectors(new Connector[] {connector}); ServletHandler servletHandler = new ServletHandler(); + server.setHandler(servletHandler); servletHandler.addServletWithMapping(new ServletHolder(servlet), path); - server.addHandler(servletHandler); server.start(); servers.add(server); @@ -198,7 +195,7 @@ public String getUrl(String path) { @Override public void setUp() throws Exception { - servers = new LinkedList(); + servers = new LinkedList<>(); } @Override From bdfbd337f1ceb3363e02f0f5db5db330e0104efb Mon Sep 17 00:00:00 2001 From: Haggai Philip Zagury Date: Wed, 23 Dec 2020 16:17:40 +0200 Subject: [PATCH 137/214] [maven-release-plugin] prepare release notification-1.14 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 2ff6cc5..33b4652 100755 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ com.tikalk.hudson.plugins notification - 1.14-SNAPSHOT + 1.14 hpi Jenkins Notification plugin Sends notifications about jobs phases and status @@ -149,7 +149,7 @@ scm:git:git://github.com/jenkinsci/notification-plugin.git scm:git:git@github.com:jenkinsci/notification-plugin.git https://github.com/jenkinsci/notification-plugin - HEAD + notification-1.14 From c02235083d6ba8efb9b73ad8897b3015ccd209f2 Mon Sep 17 00:00:00 2001 From: Haggai Philip Zagury Date: Wed, 23 Dec 2020 16:17:50 +0200 Subject: [PATCH 138/214] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 33b4652..735b604 100755 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ com.tikalk.hudson.plugins notification - 1.14 + 1.15-SNAPSHOT hpi Jenkins Notification plugin Sends notifications about jobs phases and status @@ -149,7 +149,7 @@ scm:git:git://github.com/jenkinsci/notification-plugin.git scm:git:git@github.com:jenkinsci/notification-plugin.git https://github.com/jenkinsci/notification-plugin - notification-1.14 + HEAD From 55ed5fdcae5fa17a565d7107070040f5eac4e0a8 Mon Sep 17 00:00:00 2001 From: Arda Kuyumcu Date: Wed, 5 May 2021 13:41:33 -0700 Subject: [PATCH 139/214] Add build duration to job notification (#39) --- .../com/tikal/hudson/plugins/notification/Phase.java | 1 + .../hudson/plugins/notification/model/BuildState.java | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/src/main/java/com/tikal/hudson/plugins/notification/Phase.java b/src/main/java/com/tikal/hudson/plugins/notification/Phase.java index afd63f4..227f506 100755 --- a/src/main/java/com/tikal/hudson/plugins/notification/Phase.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/Phase.java @@ -194,6 +194,7 @@ private JobState buildJobState(Job job, Run run, TaskListener listener, long tim buildState.setUrl( run.getUrl()); buildState.setPhase( this ); buildState.setTimestamp( timestamp ); + buildState.setDuration( run.getDuration() ); buildState.setScm( scmState ); buildState.setLog( log ); buildState.setNotes(resolveMacros(run, listener, target.getBuildNotes())); diff --git a/src/main/java/com/tikal/hudson/plugins/notification/model/BuildState.java b/src/main/java/com/tikal/hudson/plugins/notification/model/BuildState.java index e26117a..5cd7b42 100755 --- a/src/main/java/com/tikal/hudson/plugins/notification/model/BuildState.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/model/BuildState.java @@ -38,6 +38,8 @@ public class BuildState { private long timestamp; + private long duration; + private Phase phase; private String status; @@ -95,6 +97,14 @@ public void setTimestamp(long timestamp) { this.timestamp = timestamp; } + public long getDuration() { + return duration; + } + + public void setDuration(long duration) { + this.duration = duration; + } + public Phase getPhase() { return phase; } From 1e3ea7624af56ed536c9fe3158b1abc242865d0c Mon Sep 17 00:00:00 2001 From: sxcoll2 <36202445+sxcoll2@users.noreply.github.com> Date: Sat, 15 May 2021 10:03:52 -0600 Subject: [PATCH 140/214] if a proxy is set, the no_proxy available via Jenkins.getInstance().proxy.createProxy is not honored (#34) Co-authored-by: Steve Collins --- .../tikal/hudson/plugins/notification/Protocol.java | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java b/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java index 1157a7e..fab4fd6 100755 --- a/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java @@ -51,6 +51,7 @@ protected void send(String url, byte[] data, int timeout, boolean isJson) throws HTTP { @Override protected void send(String url, byte[] data, int timeout, boolean isJson) throws IOException { + URL targetUrl = new URL(url); if (!targetUrl.getProtocol().startsWith("http")) { throw new IllegalArgumentException("Not an http(s) url: " + url); @@ -67,12 +68,12 @@ protected void send(String url, byte[] data, int timeout, boolean isJson) throws } Proxy proxy = Proxy.NO_PROXY; - if (proxyUrl != null) { - // Proxy connection to the address provided - final int proxyPort = proxyUrl.getPort() > 0 ? proxyUrl.getPort() : 80; - proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyUrl.getHost(), proxyPort)); - } else if (Jenkins.getInstance() != null && Jenkins.getInstance().proxy != null) { - proxy = Jenkins.getInstance().proxy.createProxy(targetUrl.getHost()); + if (Jenkins.getInstance() != null && Jenkins.getInstance().proxy != null) { + proxy = Jenkins.getInstance().proxy.createProxy(targetUrl.getHost()); + } else if (proxyUrl != null) { + // Proxy connection to the address provided + final int proxyPort = proxyUrl.getPort() > 0 ? proxyUrl.getPort() : 80; + proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyUrl.getHost(), proxyPort)); } HttpURLConnection connection = (HttpURLConnection) targetUrl.openConnection(proxy); From 8a67d5f8351f03534d5c03287630857dc09a7abe Mon Sep 17 00:00:00 2001 From: yuezhuangshi Date: Tue, 13 Jul 2021 04:47:54 +0800 Subject: [PATCH 141/214] JENKINS-59908: Fix expandAll call so it works with a Run parameter. (#43) * Fix 'expandAll' call so it works with a 'Run' parameter * Fix findbugs issue --- .../com/tikal/hudson/plugins/notification/Phase.java | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/tikal/hudson/plugins/notification/Phase.java b/src/main/java/com/tikal/hudson/plugins/notification/Phase.java index 227f506..f52f22f 100755 --- a/src/main/java/com/tikal/hudson/plugins/notification/Phase.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/Phase.java @@ -19,6 +19,7 @@ import com.tikal.hudson.plugins.notification.model.TestState; import hudson.EnvVars; +import hudson.FilePath; import hudson.model.AbstractBuild; import hudson.model.Job; import hudson.model.ParameterValue; @@ -32,13 +33,13 @@ import hudson.tasks.test.TestResult; import jenkins.model.Jenkins; import org.apache.commons.lang.StringUtils; - import org.jenkinsci.plugins.tokenmacro.TokenMacro; import java.io.IOException; import java.io.PrintStream; import java.util.ArrayList; import java.util.List; +import java.util.Optional; import java.util.Set; @@ -242,11 +243,17 @@ private String resolveMacros(Run build, TaskListener listener, String text) { String result = text; try { - result = TokenMacro.expandAll((AbstractBuild) build, listener, text); + FilePath workspace = Optional.ofNullable(build.getExecutor()) + .orElseThrow(() -> new IllegalStateException("Failed to obtained executor of this run")) + .getCurrentWorkspace(); + if ( workspace != null ) { + result = TokenMacro.expandAll(build, workspace, listener, text); + } } catch (Throwable e) { // Catching Throwable here because the TokenMacro plugin is optional // so will throw a ClassDefNotFoundError if the plugin is not installed or disabled. listener.getLogger().println("Failed to evaluate macro '" + text + "'"); + listener.getLogger().println(e); } return result; From 906b3834bc22b96b806d988947b79e628cb760a0 Mon Sep 17 00:00:00 2001 From: hagzag Date: Tue, 13 Jul 2021 00:05:24 +0300 Subject: [PATCH 142/214] [maven-release-plugin] prepare release notification-1.15 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 735b604..96195c1 100755 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ com.tikalk.hudson.plugins notification - 1.15-SNAPSHOT + 1.15 hpi Jenkins Notification plugin Sends notifications about jobs phases and status @@ -149,7 +149,7 @@ scm:git:git://github.com/jenkinsci/notification-plugin.git scm:git:git@github.com:jenkinsci/notification-plugin.git https://github.com/jenkinsci/notification-plugin - HEAD + notification-1.15 From f5688091343a5bfe0edcc129c18544c137fc319c Mon Sep 17 00:00:00 2001 From: hagzag Date: Tue, 13 Jul 2021 00:06:34 +0300 Subject: [PATCH 143/214] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 96195c1..1214fe6 100755 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ com.tikalk.hudson.plugins notification - 1.15 + 1.16-SNAPSHOT hpi Jenkins Notification plugin Sends notifications about jobs phases and status @@ -149,7 +149,7 @@ scm:git:git://github.com/jenkinsci/notification-plugin.git scm:git:git@github.com:jenkinsci/notification-plugin.git https://github.com/jenkinsci/notification-plugin - notification-1.15 + HEAD From ec80e6f7df4881e699c346e179e0edcc0c891ac7 Mon Sep 17 00:00:00 2001 From: hagzag Date: Tue, 13 Jul 2021 00:08:12 +0300 Subject: [PATCH 144/214] [maven-release-plugin] rollback the release of notification-1.15 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 1214fe6..735b604 100755 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ com.tikalk.hudson.plugins notification - 1.16-SNAPSHOT + 1.15-SNAPSHOT hpi Jenkins Notification plugin Sends notifications about jobs phases and status From db5721e462e2850757c68b2322a1d56b2a1dd99d Mon Sep 17 00:00:00 2001 From: robinverduijn Date: Wed, 14 Jul 2021 13:18:25 -0700 Subject: [PATCH 145/214] JENKINS-59908: Fix expandAll call so it works with a Run parameter. (#44) * Revert "JENKINS-59908: Fix expandAll call so it works with a Run parameter. (#43)" This reverts commit 8a67d5f8351f03534d5c03287630857dc09a7abe. * Improve logging when a blanket Throwable is swallowed. * Fix `expandAll` call so it works with a `Run` parameter. Previously, due to the blanket catch of a `Throwable` here, the code was masking the fact that `TokenMacro.expandAll` was never invoked, failing like this: ``` Failed to evaluate macro '' java.lang.ClassCastException: org.jenkinsci.plugins.workflow.job.WorkflowRun cannot be cast to hudson.model.AbstractBuild ``` --- .../hudson/plugins/notification/Phase.java | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/tikal/hudson/plugins/notification/Phase.java b/src/main/java/com/tikal/hudson/plugins/notification/Phase.java index f52f22f..606d885 100755 --- a/src/main/java/com/tikal/hudson/plugins/notification/Phase.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/Phase.java @@ -21,6 +21,7 @@ import hudson.EnvVars; import hudson.FilePath; import hudson.model.AbstractBuild; +import hudson.model.Executor; import hudson.model.Job; import hudson.model.ParameterValue; import hudson.model.ParametersAction; @@ -33,13 +34,13 @@ import hudson.tasks.test.TestResult; import jenkins.model.Jenkins; import org.apache.commons.lang.StringUtils; + import org.jenkinsci.plugins.tokenmacro.TokenMacro; import java.io.IOException; import java.io.PrintStream; import java.util.ArrayList; import java.util.List; -import java.util.Optional; import java.util.Set; @@ -243,17 +244,17 @@ private String resolveMacros(Run build, TaskListener listener, String text) { String result = text; try { - FilePath workspace = Optional.ofNullable(build.getExecutor()) - .orElseThrow(() -> new IllegalStateException("Failed to obtained executor of this run")) - .getCurrentWorkspace(); - if ( workspace != null ) { - result = TokenMacro.expandAll(build, workspace, listener, text); + Executor executor = build.getExecutor(); + if(executor != null) { + FilePath workspace = executor.getCurrentWorkspace(); + if(workspace != null) { + result = TokenMacro.expandAll(build, workspace, listener, text); + } } } catch (Throwable e) { // Catching Throwable here because the TokenMacro plugin is optional // so will throw a ClassDefNotFoundError if the plugin is not installed or disabled. - listener.getLogger().println("Failed to evaluate macro '" + text + "'"); - listener.getLogger().println(e); + e.printStackTrace(listener.error(String.format("Failed to evaluate macro '%s'", text))); } return result; From 562813f9baceee79c4cc70e9675d1e4c7e1caca4 Mon Sep 17 00:00:00 2001 From: hagzag Date: Wed, 14 Jul 2021 23:44:49 +0300 Subject: [PATCH 146/214] [maven-release-plugin] prepare release notification-1.15 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 735b604..96195c1 100755 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ com.tikalk.hudson.plugins notification - 1.15-SNAPSHOT + 1.15 hpi Jenkins Notification plugin Sends notifications about jobs phases and status @@ -149,7 +149,7 @@ scm:git:git://github.com/jenkinsci/notification-plugin.git scm:git:git@github.com:jenkinsci/notification-plugin.git https://github.com/jenkinsci/notification-plugin - HEAD + notification-1.15 From abe045e7cb23303ffe85c79160efa99060479ae9 Mon Sep 17 00:00:00 2001 From: hagzag Date: Wed, 14 Jul 2021 23:48:32 +0300 Subject: [PATCH 147/214] [maven-release-plugin] rollback the release of notification-1.15 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 96195c1..735b604 100755 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ com.tikalk.hudson.plugins notification - 1.15 + 1.15-SNAPSHOT hpi Jenkins Notification plugin Sends notifications about jobs phases and status @@ -149,7 +149,7 @@ scm:git:git://github.com/jenkinsci/notification-plugin.git scm:git:git@github.com:jenkinsci/notification-plugin.git https://github.com/jenkinsci/notification-plugin - notification-1.15 + HEAD From b4e443314284625eaeadc6a273e315b385452821 Mon Sep 17 00:00:00 2001 From: hagzag Date: Wed, 14 Jul 2021 23:52:37 +0300 Subject: [PATCH 148/214] [maven-release-plugin] prepare release notification-1.15 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 735b604..96195c1 100755 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ com.tikalk.hudson.plugins notification - 1.15-SNAPSHOT + 1.15 hpi Jenkins Notification plugin Sends notifications about jobs phases and status @@ -149,7 +149,7 @@ scm:git:git://github.com/jenkinsci/notification-plugin.git scm:git:git@github.com:jenkinsci/notification-plugin.git https://github.com/jenkinsci/notification-plugin - HEAD + notification-1.15 From d7aa89e123d33541decf974c3eee95f9aebe26f9 Mon Sep 17 00:00:00 2001 From: hagzag Date: Wed, 14 Jul 2021 23:52:50 +0300 Subject: [PATCH 149/214] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 96195c1..1214fe6 100755 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ com.tikalk.hudson.plugins notification - 1.15 + 1.16-SNAPSHOT hpi Jenkins Notification plugin Sends notifications about jobs phases and status @@ -149,7 +149,7 @@ scm:git:git://github.com/jenkinsci/notification-plugin.git scm:git:git@github.com:jenkinsci/notification-plugin.git https://github.com/jenkinsci/notification-plugin - notification-1.15 + HEAD From e3338f8ca4ab62afa2a4c0f92d40e144d1eb36ad Mon Sep 17 00:00:00 2001 From: Haggai Philip Zagury Date: Thu, 15 Jul 2021 07:42:38 +0300 Subject: [PATCH 150/214] Create codeql-analysis.yml (#45) --- .github/workflows/codeql-analysis.yml | 71 +++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 .github/workflows/codeql-analysis.yml diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml new file mode 100644 index 0000000..626c2db --- /dev/null +++ b/.github/workflows/codeql-analysis.yml @@ -0,0 +1,71 @@ +# For most projects, this workflow file will not need changing; you simply need +# to commit it to your repository. +# +# You may wish to alter this file to override the set of languages analyzed, +# or to provide custom queries or build logic. +# +# ******** NOTE ******** +# We have attempted to detect the languages in your repository. Please check +# the `language` matrix defined below to confirm you have the correct set of +# supported CodeQL languages. +# +name: "CodeQL" + +on: + push: + branches: [ master ] + pull_request: + # The branches below must be a subset of the branches above + branches: [ master ] + schedule: + - cron: '31 8 * * 0' + +jobs: + analyze: + name: Analyze + runs-on: ubuntu-latest + permissions: + actions: read + contents: read + security-events: write + + strategy: + fail-fast: false + matrix: + language: [ 'java' ] + # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ] + # Learn more: + # https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed + + steps: + - name: Checkout repository + uses: actions/checkout@v2 + + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v1 + with: + languages: ${{ matrix.language }} + # If you wish to specify custom queries, you can do so here or in a config file. + # By default, queries listed here will override any specified in a config file. + # Prefix the list here with "+" to use these queries and those in the config file. + # queries: ./path/to/local/query, your-org/your-repo/queries@main + + # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). + # If this step fails, then you should remove it and run the build manually (see below) + - name: Autobuild + uses: github/codeql-action/autobuild@v1 + + # ℹ️ Command-line programs to run using the OS shell. + # 📚 https://git.io/JvXDl + + # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines + # and modify them (or add more) to build your code if your project + # uses a compiled language + + #- run: | + # make bootstrap + # make release + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v1 From 7e4da20db29c11f3d52dded14392e3d25c815a95 Mon Sep 17 00:00:00 2001 From: Basil Crow Date: Sat, 7 May 2022 22:55:28 -0700 Subject: [PATCH 151/214] [JENKINS-55955] Remove JAXB dependency from Notification (#46) * Refresh build * Remove JAXB dependency --- .mvn/extensions.xml | 7 + .mvn/maven.config | 2 + pom.xml | 140 +++++++++--------- .../hudson/plugins/notification/Protocol.java | 5 +- .../plugins/notification/ProtocolTest.java | 4 +- 5 files changed, 86 insertions(+), 72 deletions(-) create mode 100644 .mvn/extensions.xml create mode 100644 .mvn/maven.config diff --git a/.mvn/extensions.xml b/.mvn/extensions.xml new file mode 100644 index 0000000..a65d82e --- /dev/null +++ b/.mvn/extensions.xml @@ -0,0 +1,7 @@ + + + io.jenkins.tools.incrementals + git-changelist-maven-extension + 1.3 + + diff --git a/.mvn/maven.config b/.mvn/maven.config new file mode 100644 index 0000000..2a0299c --- /dev/null +++ b/.mvn/maven.config @@ -0,0 +1,2 @@ +-Pconsume-incrementals +-Pmight-produce-incrementals diff --git a/pom.xml b/pom.xml index 1214fe6..ae6fc02 100755 --- a/pom.xml +++ b/pom.xml @@ -1,3 +1,4 @@ + 4.0.0 @@ -5,22 +6,23 @@ org.jenkins-ci.plugins plugin - 4.14 + 4.40 - com.tikalk.hudson.plugins - notification - 1.16-SNAPSHOT - hpi - Jenkins Notification plugin - Sends notifications about jobs phases and status - https://wiki.jenkins-ci.org/display/JENKINS/Notification+Plugin + com.tikalk.hudson.plugins + notification + ${revision}${changelist} + hpi + Jenkins Notification plugin + Sends notifications about jobs phases and status + https://github.com/jenkinsci/${project.artifactId}-plugin - 2.235.1 - 8 - false + 1.16 + -SNAPSHOT + 2.289.3 + jenkinsci/${project.artifactId}-plugin @@ -53,67 +55,71 @@ io.jenkins.tools.bom - bom-2.235.x - 19 + bom-2.289.x + 1362.v59f2f3db_80ee import pom - - - - com.google.code.gson - gson - 2.2.4 - - - - org.jenkins-ci.plugins - s3 - 0.11.5 - true - - - org.apache.httpcomponents - httpclient - - - org.apache.httpcomponents - httpcore - + + + + com.google.code.gson + gson + 2.9.0 + + + org.jenkins-ci.plugins + credentials + + + org.jenkins-ci.plugins + junit + true + + + org.jenkins-ci.plugins + plain-credentials + + + + org.jenkins-ci.plugins + s3 + 0.12.1 + true + + + org.apache.httpcomponents + httpclient + + + org.apache.httpcomponents + httpcore + org.apache.commons commons-lang3 - - - - org.jenkins-ci.plugins - token-macro - true - - - org.jenkins-ci.plugins - junit - true - - - net.sf.ezmorph - ezmorph - 1.0.6 - test - - - org.jenkins-ci.plugins - credentials - - - org.jenkins-ci.plugins - plain-credentials - - + + org.jenkins-ci + symbol-annotation + + + + + org.jenkins-ci.plugins + token-macro + true + + + net.sf.ezmorph + ezmorph + 1.0.6 + test + + @@ -146,11 +152,11 @@ - scm:git:git://github.com/jenkinsci/notification-plugin.git - scm:git:git@github.com:jenkinsci/notification-plugin.git - https://github.com/jenkinsci/notification-plugin - HEAD - + scm:git:https://github.com/${gitHubRepo}.git + scm:git:git@github.com:${gitHubRepo}.git + ${scmTag} + https://github.com/${gitHubRepo} + diff --git a/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java b/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java index fab4fd6..dbda148 100755 --- a/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java @@ -16,12 +16,11 @@ import jenkins.model.Jenkins; -import javax.xml.bind.DatatypeConverter; import java.io.IOException; import java.io.OutputStream; import java.net.*; import java.nio.charset.Charset; - +import java.util.Base64; public enum Protocol { @@ -80,7 +79,7 @@ protected void send(String url, byte[] data, int timeout, boolean isJson) throws connection.setRequestProperty("Content-Type", String.format( "application/%s;charset=UTF-8", isJson ? "json" : "xml" )); String userInfo = targetUrl.getUserInfo(); if (null != userInfo) { - String b64UserInfo = DatatypeConverter.printBase64Binary(userInfo.getBytes(Charset.defaultCharset())); // TODO see if UTF-8 can be used instead of platform default encoding + String b64UserInfo = Base64.getEncoder().encodeToString(userInfo.getBytes(Charset.defaultCharset())); // TODO see if UTF-8 can be used instead of platform default encoding String authorizationHeader = "Basic " + b64UserInfo; connection.setRequestProperty("Authorization", authorizationHeader); } diff --git a/src/test/java/com/tikal/hudson/plugins/notification/ProtocolTest.java b/src/test/java/com/tikal/hudson/plugins/notification/ProtocolTest.java index 2eb3aea..0d5805b 100644 --- a/src/test/java/com/tikal/hudson/plugins/notification/ProtocolTest.java +++ b/src/test/java/com/tikal/hudson/plugins/notification/ProtocolTest.java @@ -37,10 +37,10 @@ import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import javax.xml.bind.DatatypeConverter; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; +import java.util.Base64; import java.util.LinkedList; import java.util.List; import java.util.concurrent.BlockingQueue; @@ -64,7 +64,7 @@ static class Request { String auth = request.getHeader("Authorization"); this.userInfo = (null == auth) ? null - : new String(DatatypeConverter.parseBase64Binary(auth.split(" ")[1])) + "@"; + : new String(Base64.getDecoder().decode(auth.split(" ")[1])) + "@"; } Request(String url, String method, String body) { From 81f0fb240e54285c79c6a54b2a9edbe53233e7b6 Mon Sep 17 00:00:00 2001 From: Haggai Philip Zagury Date: Sun, 8 May 2022 19:15:20 +0300 Subject: [PATCH 152/214] [maven-release-plugin] prepare release notification-1.16 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index ae6fc02..b94dce5 100755 --- a/pom.xml +++ b/pom.xml @@ -12,7 +12,7 @@ com.tikalk.hudson.plugins notification - ${revision}${changelist} + 1.16 hpi Jenkins Notification plugin Sends notifications about jobs phases and status @@ -154,7 +154,7 @@ scm:git:https://github.com/${gitHubRepo}.git scm:git:git@github.com:${gitHubRepo}.git - ${scmTag} + notification-1.16 https://github.com/${gitHubRepo} From 837ae894a1d97f856ee050de370a8c3daa92dfea Mon Sep 17 00:00:00 2001 From: Haggai Philip Zagury Date: Sun, 8 May 2022 19:16:44 +0300 Subject: [PATCH 153/214] [maven-release-plugin] prepare for next development iteration --- pom.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index b94dce5..c3574ff 100755 --- a/pom.xml +++ b/pom.xml @@ -12,14 +12,14 @@ com.tikalk.hudson.plugins notification - 1.16 + ${revision}${changelist} hpi Jenkins Notification plugin Sends notifications about jobs phases and status https://github.com/jenkinsci/${project.artifactId}-plugin - 1.16 + 1.17 -SNAPSHOT 2.289.3 jenkinsci/${project.artifactId}-plugin @@ -154,7 +154,7 @@ scm:git:https://github.com/${gitHubRepo}.git scm:git:git@github.com:${gitHubRepo}.git - notification-1.16 + ${scmTag} https://github.com/${gitHubRepo} From 9251012a7c8c740cbdc3dc59e1c0eae03f4883fa Mon Sep 17 00:00:00 2001 From: Haggai Philip Zagury Date: Sun, 8 May 2022 19:26:14 +0300 Subject: [PATCH 154/214] [maven-release-plugin] rollback the release of notification-1.16 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index c3574ff..ae6fc02 100755 --- a/pom.xml +++ b/pom.xml @@ -19,7 +19,7 @@ https://github.com/jenkinsci/${project.artifactId}-plugin - 1.17 + 1.16 -SNAPSHOT 2.289.3 jenkinsci/${project.artifactId}-plugin From a5f79054b60b4b4b350051e5bc7a9ec83c11a3ed Mon Sep 17 00:00:00 2001 From: Jakob Berlin Date: Mon, 21 Nov 2022 16:38:52 +0100 Subject: [PATCH 155/214] Add branch option to only notify when building specific branch (#42) * Add branch option to only notify when building specific branch (e.g. non-PR branch) Add notifyEndpoints pipeline function to manually call notification Some minor refactorings to e.g. reduce calls of deprecated functions * Fix/invert branch filter logic --- .../hudson/plugins/notification/Endpoint.java | 17 ++ .../HudsonNotificationPropertyDescriptor.java | 34 ++-- .../plugins/notification/NotifyStep.java | 130 +++++++++++++ .../hudson/plugins/notification/Phase.java | 177 ++++++++++-------- .../HudsonNotificationProperty/config.jelly | 9 + .../help-branch.html | 6 + .../plugins/notification/Messages.properties | 1 + 7 files changed, 285 insertions(+), 89 deletions(-) create mode 100644 src/main/java/com/tikal/hudson/plugins/notification/NotifyStep.java create mode 100644 src/main/resources/com/tikal/hudson/plugins/notification/HudsonNotificationProperty/help-branch.html create mode 100644 src/main/resources/com/tikal/hudson/plugins/notification/Messages.properties diff --git a/src/main/java/com/tikal/hudson/plugins/notification/Endpoint.java b/src/main/java/com/tikal/hudson/plugins/notification/Endpoint.java index 47133f6..2886dd2 100644 --- a/src/main/java/com/tikal/hudson/plugins/notification/Endpoint.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/Endpoint.java @@ -23,6 +23,8 @@ public class Endpoint { public static final Integer DEFAULT_RETRIES = 0; + public static final String DEFAULT_BRANCH = ".*"; + private Protocol protocol = Protocol.HTTP; /** @@ -46,6 +48,8 @@ public class Endpoint { private Integer retries = DEFAULT_RETRIES; + private String branch = ".*"; + /** * Adds a new endpoint for notifications * @param protocol - Protocol to use @@ -192,6 +196,19 @@ protected Object readResolve() { return this; } + public String getBranch() { + return branch; + } + + /** + * Sets branch filter + * @param branch - regex + */ + @DataBoundSetter + public void setBranch(final String branch) { + this.branch = branch; + } + @Override public String toString() { return protocol+":"+urlInfo.getUrlOrId(); diff --git a/src/main/java/com/tikal/hudson/plugins/notification/HudsonNotificationPropertyDescriptor.java b/src/main/java/com/tikal/hudson/plugins/notification/HudsonNotificationPropertyDescriptor.java index d688f13..a67529b 100644 --- a/src/main/java/com/tikal/hudson/plugins/notification/HudsonNotificationPropertyDescriptor.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/HudsonNotificationPropertyDescriptor.java @@ -17,7 +17,6 @@ import com.cloudbees.plugins.credentials.common.AbstractIdCredentialsListBoxModel; import com.cloudbees.plugins.credentials.common.StandardCredentials; import com.cloudbees.plugins.credentials.common.StandardListBoxModel; -import com.cloudbees.plugins.credentials.domains.DomainRequirement; import hudson.Extension; import hudson.RelativePath; import hudson.model.Item; @@ -40,6 +39,8 @@ import java.util.Collections; import java.util.List; +import javax.annotation.Nonnull; + @Extension public final class HudsonNotificationPropertyDescriptor extends JobPropertyDescriptor { @@ -48,7 +49,7 @@ public HudsonNotificationPropertyDescriptor() { load(); } - private List endpoints = new ArrayList(); + private List endpoints = new ArrayList<>(); public boolean isEnabled() { return !endpoints.isEmpty(); @@ -59,19 +60,24 @@ public List getTargets() { } public void setEndpoints(List endpoints) { - this.endpoints = new ArrayList( endpoints ); + this.endpoints = new ArrayList<>(endpoints); } @Override - public boolean isApplicable(@SuppressWarnings("rawtypes") Class jobType) { + public boolean isApplicable(Class jobType) { return true; } + @Nonnull @Override public String getDisplayName() { return "Hudson Job Notification"; } + public String getDefaultBranch(){ + return Endpoint.DEFAULT_BRANCH; + } + public int getDefaultTimeout(){ return Endpoint.DEFAULT_TIMEOUT; } @@ -82,7 +88,7 @@ public int getDefaultRetries(){ @Override public HudsonNotificationProperty newInstance(StaplerRequest req, JSONObject formData) throws FormException { - List endpoints = new ArrayList(); + List endpoints = new ArrayList<>(); if (formData != null && !formData.isNullObject()) { JSON endpointsData = (JSON) formData.get("endpoints"); if (endpointsData != null && !endpointsData.isEmpty()) { @@ -90,21 +96,21 @@ public HudsonNotificationProperty newInstance(StaplerRequest req, JSONObject for JSONArray endpointsArrayData = (JSONArray) endpointsData; for (int i = 0; i < endpointsArrayData.size(); i++) { JSONObject endpointsObject = endpointsArrayData.getJSONObject(i); - endpoints.add(convertJson((JSONObject) endpointsObject)); + endpoints.add(convertJson(endpointsObject)); } } else { endpoints.add(convertJson((JSONObject) endpointsData)); } } } - HudsonNotificationProperty notificationProperty = new HudsonNotificationProperty(endpoints); - return notificationProperty; + + return new HudsonNotificationProperty(endpoints); } private Endpoint convertJson(JSONObject endpointObjectData) throws FormException { // Transform the data to get the public/secret URL data JSONObject urlInfoData = endpointObjectData.getJSONObject("urlInfo"); - UrlInfo urlInfo = null; + UrlInfo urlInfo; if (urlInfoData.containsKey("publicUrl")) { urlInfo = new UrlInfo(UrlType.PUBLIC, urlInfoData.getString("publicUrl")); } @@ -114,6 +120,7 @@ else if (urlInfoData.containsKey("secretUrl")) { else { throw new FormException("Expected either a public url or secret url id", "urlInfo"); } + Endpoint endpoint = new Endpoint(urlInfo); endpoint.setEvent(endpointObjectData.getString("event")); endpoint.setFormat(Format.valueOf(endpointObjectData.getString("format"))); @@ -122,6 +129,8 @@ else if (urlInfoData.containsKey("secretUrl")) { endpoint.setRetries(endpointObjectData.getInt("retries")); endpoint.setLoglines(endpointObjectData.getInt("loglines")); endpoint.setBuildNotes(endpointObjectData.getString("notes")); + endpoint.setBranch(endpointObjectData.getString("branch")); + return endpoint; } @@ -170,10 +179,10 @@ public ListBoxModel doFillSecretUrlItems(@AncestorInPath Item owner, @QueryParam // as we cannot select from a user's credentials unless they are the only user submitting the build // (which we cannot assume) thus ACL.SYSTEM is correct here. AbstractIdCredentialsListBoxModel model = new StandardListBoxModel() - .withEmptySelection() + .includeEmptyValue() .withAll( CredentialsProvider.lookupCredentials( - StringCredentials.class, owner, ACL.SYSTEM, Collections.emptyList())); + StringCredentials.class, owner, ACL.SYSTEM, Collections.emptyList())); if (!StringUtils.isEmpty(secretUrl)) { // Select current value, add if missing for (ListBoxModel.Option option : model) { @@ -192,5 +201,4 @@ public boolean configure(StaplerRequest req, JSONObject formData) { save(); return true; } - -} \ No newline at end of file +} diff --git a/src/main/java/com/tikal/hudson/plugins/notification/NotifyStep.java b/src/main/java/com/tikal/hudson/plugins/notification/NotifyStep.java new file mode 100644 index 0000000..0214842 --- /dev/null +++ b/src/main/java/com/tikal/hudson/plugins/notification/NotifyStep.java @@ -0,0 +1,130 @@ +package com.tikal.hudson.plugins.notification; + +import hudson.Extension; +import hudson.FilePath; +import hudson.Util; +import hudson.model.Run; +import hudson.model.TaskListener; +import org.eclipse.collections.impl.factory.Sets; +import org.jenkinsci.plugins.workflow.graph.FlowNode; +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 org.kohsuke.stapler.DataBoundSetter; + +import java.io.Serializable; +import java.util.Objects; +import java.util.Set; + +import javax.annotation.CheckForNull; +import javax.annotation.Nonnull; + +public class NotifyStep extends Step implements Serializable { + private static final long serialVersionUID = -2818860651754465006L; + + @CheckForNull + private String notes; + + @CheckForNull + public String getNotes() { + return notes; + } + + @DataBoundSetter + public void setNotes(@CheckForNull String notes) { + this.notes = Util.fixEmpty(notes); + } + + @CheckForNull + private String phase = Phase.STARTED.name(); + + @CheckForNull + public String getPhase() { + return phase; + } + + @DataBoundSetter + public void setPhase(@CheckForNull String phase) { + this.phase = Util.fixEmpty(phase); + } + + @CheckForNull + private String loglines = "0"; + + @CheckForNull + public String getLoglines() { + return loglines; + } + + @DataBoundSetter + public void setLoglines(@CheckForNull String loglines) { + this.loglines = Util.fixEmpty(loglines); + } + + /** + * Creates a new instance of {@link NotifyStep}. + */ + @DataBoundConstructor + public NotifyStep() { + super(); + + // empty constructor required for Stapler + } + + @Override + public StepExecution start(final StepContext context) { + return new Execution(context, this); + } + + /** + * Actually performs the execution of the associated step. + */ + static class Execution extends StepExecution { + private static final long serialVersionUID = -2840020502160375407L; + + private final NotifyStep notifyStep; + + Execution(@Nonnull final StepContext context, final NotifyStep step) { + super(context); + notifyStep = step; + } + + @Override + public boolean start() throws Exception { + String logLines = notifyStep.getLoglines(); + + Phase.NONE.handle(Objects.requireNonNull(getContext().get(Run.class)), getContext().get(TaskListener.class), System.currentTimeMillis(), true, + notifyStep.getNotes(), Integer.parseInt(logLines != null ? logLines : "0"), Phase.valueOf(notifyStep.getPhase())); + + getContext().onSuccess(null); + + return true; + } + } + + /** + * Descriptor for this step: defines the context and the UI labels. + */ + @Extension + @SuppressWarnings("unused") // most methods are used by the corresponding jelly view + public static class Descriptor extends StepDescriptor { + @Override + public String getFunctionName() { + return "notifyEndpoints"; + } + + @Nonnull + @Override + public String getDisplayName() { + return Messages.Notify_DisplayName(); + } + + @Override + public Set> getRequiredContext() { + return Sets.immutable.of(FilePath.class, FlowNode.class, Run.class, TaskListener.class) + .castToSet(); + } + } +} diff --git a/src/main/java/com/tikal/hudson/plugins/notification/Phase.java b/src/main/java/com/tikal/hudson/plugins/notification/Phase.java index 606d885..ab83cdb 100755 --- a/src/main/java/com/tikal/hudson/plugins/notification/Phase.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/Phase.java @@ -41,12 +41,13 @@ import java.io.PrintStream; import java.util.ArrayList; import java.util.List; +import java.util.Objects; import java.util.Set; @SuppressWarnings({ "unchecked", "rawtypes" }) public enum Phase { - QUEUED, STARTED, COMPLETED, FINALIZED; + QUEUED, STARTED, COMPLETED, FINALIZED, NONE; private Result findLastBuildThatFinished(Run run){ Run previousRun = run.getPreviousCompletedBuild(); @@ -65,63 +66,7 @@ private Result findLastBuildThatFinished(Run run){ @SuppressWarnings( "CastToConcreteClass" ) public void handle(Run run, TaskListener listener, long timestamp) { - - HudsonNotificationProperty property = (HudsonNotificationProperty) run.getParent().getProperty(HudsonNotificationProperty.class); - if ( property == null ){ return; } - - Result previousCompletedRunResults = findLastBuildThatFinished(run); - - for ( Endpoint target : property.getEndpoints()) { - if (isRun(target, run.getResult(), previousCompletedRunResults) && !Utils.isEmpty(target.getUrlInfo().getUrlOrId())) { - int triesRemaining = target.getRetries(); - boolean failed = false; - do { - // Represents a string that will be put into the log - // if there is an error contacting the target. - String urlIdString = "url 'unknown'"; - try { - EnvVars environment = run.getEnvironment(listener); - // Expand out the URL from environment + url. - String expandedUrl; - UrlInfo urlInfo = target.getUrlInfo(); - switch (urlInfo.getUrlType()) { - case PUBLIC: - expandedUrl = environment.expand(urlInfo.getUrlOrId()); - urlIdString = String.format("url '%s'", expandedUrl); - break; - case SECRET: - String urlSecretId = urlInfo.getUrlOrId(); - String actualUrl = Utils.getSecretUrl(urlSecretId); - expandedUrl = environment.expand(actualUrl); - urlIdString = String.format("credentials id '%s'", urlSecretId); - break; - default: - throw new UnsupportedOperationException("Unknown URL type"); - } - - if(! isURLValid(urlIdString, expandedUrl, listener.getLogger())){ - return; - } - - listener.getLogger().println( String.format( "Notifying endpoint with %s", urlIdString)); - JobState jobState = buildJobState(run.getParent(), run, listener, timestamp, target); - target.getProtocol().send(expandedUrl, - target.getFormat().serialize(jobState), - target.getTimeout(), - target.isJson()); - } catch (Throwable error) { - failed = true; - error.printStackTrace( listener.error( String.format( "Failed to notify endpoint with %s", urlIdString))); - listener.getLogger().println( String.format( "Failed to notify endpoint with %s - %s: %s", - urlIdString, error.getClass().getName(), error.getMessage())); - if (triesRemaining > 0) { - listener.getLogger().println( String.format( "Reattempting to notify endpoint with %s (%d tries remaining)", urlIdString, triesRemaining)); - } - } - } - while (failed && --triesRemaining >= 0); - } - } + handle(run, listener, timestamp, false, null, 0, this); } /** @@ -136,7 +81,7 @@ private boolean isURLValid(String urlInputValue, String expandedUrl, PrintStream boolean isValid= false; //If Jenkins variable was used for URL, and it was unresolvable, log warning and return. if (expandedUrl.contains("$")) { - logger.println( String.format( "Ignoring sending notification due to unresolved variable: %s", urlInputValue)); + logger.printf("Ignoring sending notification due to unresolved variable: %s%n", urlInputValue); }else if(StringUtils.isBlank(expandedUrl)){ logger.println("URL is not set, ignoring call to send notification."); }else{ @@ -165,18 +110,21 @@ private boolean isRun( Endpoint endpoint, Result result, Result previousRunResul case "failedAndFirstSuccess": if (result == null || !this.equals(FINALIZED)) {return false;} if (result.equals(Result.FAILURE)) {return true;} - if (previousRunResult != null && result.equals(Result.SUCCESS) && previousRunResult.equals(Result.FAILURE)) {return true;} - return false; + return previousRunResult != null && result.equals(Result.SUCCESS) + && previousRunResult.equals(Result.FAILURE); + case "manual": + return false; default: return event.equals(this.toString().toLowerCase()); } } - private JobState buildJobState(Job job, Run run, TaskListener listener, long timestamp, Endpoint target) + private JobState buildJobState(Job job, Run run, TaskListener listener, long timestamp, Endpoint target, Phase phase) throws IOException, InterruptedException { + Jenkins jenkins = Jenkins.getInstanceOrNull(); + assert jenkins != null; - Jenkins jenkins = Jenkins.getInstance(); String rootUrl = jenkins.getRootUrl(); JobState jobState = new JobState(); BuildState buildState = new BuildState(); @@ -194,7 +142,7 @@ private JobState buildJobState(Job job, Run run, TaskListener listener, long tim buildState.setNumber( run.number ); buildState.setQueueId( run.getQueueId() ); buildState.setUrl( run.getUrl()); - buildState.setPhase( this ); + buildState.setPhase( phase ); buildState.setTimestamp( timestamp ); buildState.setDuration( run.getDuration() ); buildState.setScm( scmState ); @@ -212,6 +160,7 @@ private JobState buildJobState(Job job, Run run, TaskListener listener, long tim buildState.updateArtifacts( job, run ); + //TODO: Make this optional to reduce chat overload. if ( paramsAction != null ) { EnvVars env = new EnvVars(); for (ParameterValue value : paramsAction.getParameters()){ @@ -328,7 +277,7 @@ private List getCulprits(Run run) { } private StringBuilder getLog(Run run, Endpoint target) { - StringBuilder log = new StringBuilder(""); + StringBuilder log = new StringBuilder(); Integer loglines = target.getLoglines(); if (loglines == null || loglines == 0) { @@ -336,21 +285,97 @@ private StringBuilder getLog(Run run, Endpoint target) { } try { - switch (loglines) { - // The full log - case -1: - log.append(run.getLog()); - break; - default: - List logEntries = run.getLog(loglines); - for (String entry: logEntries) { - log.append(entry); - log.append("\n"); - } + // The full log + if (loglines == -1) { + log.append(run.getLog()); + } else { + List logEntries = run.getLog(loglines); + for (String entry : logEntries) { + log.append(entry); + log.append("\n"); + } } } catch (IOException e) { log.append("Unable to retrieve log"); } return log; } + + public void handle(Run run, TaskListener listener, long timestamp, boolean manual, final String buildNotes, final Integer logLines, Phase phase) { + HudsonNotificationProperty property = (HudsonNotificationProperty) run.getParent().getProperty(HudsonNotificationProperty.class); + if ( property == null ){ return; } + + Result previousCompletedRunResults = findLastBuildThatFinished(run); + + for ( Endpoint target : property.getEndpoints()) { + if ((!manual && !isRun(target, run.getResult(), previousCompletedRunResults)) || Utils.isEmpty(target.getUrlInfo().getUrlOrId())) { + continue; + } + + if(Objects.nonNull(buildNotes)) { + target.setBuildNotes(buildNotes); + } + + if(Objects.nonNull(logLines) && logLines != 0) { + target.setLoglines(logLines); + } + + int triesRemaining = target.getRetries(); + boolean failed = false; + do { + // Represents a string that will be put into the log + // if there is an error contacting the target. + String urlIdString = "url 'unknown'"; + try { + EnvVars environment = run.getEnvironment(listener); + // Expand out the URL from environment + url. + String expandedUrl; + UrlInfo urlInfo = target.getUrlInfo(); + switch (urlInfo.getUrlType()) { + case PUBLIC: + expandedUrl = environment.expand(urlInfo.getUrlOrId()); + urlIdString = String.format("url '%s'", expandedUrl); + break; + case SECRET: + String urlSecretId = urlInfo.getUrlOrId(); + String actualUrl = Utils.getSecretUrl(urlSecretId); + expandedUrl = environment.expand(actualUrl); + urlIdString = String.format("credentials id '%s'", urlSecretId); + break; + default: + throw new UnsupportedOperationException("Unknown URL type"); + } + + if (!isURLValid(urlIdString, expandedUrl, listener.getLogger())) { + continue; + } + + if (!manual && environment.containsKey("BRANCH_NAME") && !environment.get("BRANCH_NAME").matches(target.getBranch())) { + listener.getLogger().printf("Environment variable %s with value %s does not match configured branch filter %s%n", "BRANCH_NAME", environment.get("BRANCH_NAME"), target.getBranch()); + continue; + }else if(!manual && !environment.containsKey("BRANCH_NAME") && !target.getBranch().equals(".*")){ + listener.getLogger().printf("Environment does not contains %s variable%n", "BRANCH_NAME"); + continue; + } + + listener.getLogger().printf("Notifying endpoint with %s%n", urlIdString); + JobState jobState = buildJobState(run.getParent(), run, listener, timestamp, target, phase); + target.getProtocol().send(expandedUrl, + target.getFormat().serialize(jobState), + target.getTimeout(), + target.isJson()); + } catch (Throwable error) { + failed = true; + error.printStackTrace( listener.error( String.format( "Failed to notify endpoint with %s", urlIdString))); + listener.getLogger().printf("Failed to notify endpoint with %s - %s: %s%n", + urlIdString, error.getClass().getName(), error.getMessage()); + if (triesRemaining > 0) { + listener.getLogger().printf( + "Reattempting to notify endpoint with %s (%d tries remaining)%n", urlIdString, triesRemaining); + } + } + } + while (failed && --triesRemaining >= 0); + } + } } diff --git a/src/main/resources/com/tikal/hudson/plugins/notification/HudsonNotificationProperty/config.jelly b/src/main/resources/com/tikal/hudson/plugins/notification/HudsonNotificationProperty/config.jelly index fa37508..197750e 100755 --- a/src/main/resources/com/tikal/hudson/plugins/notification/HudsonNotificationProperty/config.jelly +++ b/src/main/resources/com/tikal/hudson/plugins/notification/HudsonNotificationProperty/config.jelly @@ -41,6 +41,7 @@ Job Finalized Job Failed Job Failed and First Success + No Events - Call manually @@ -91,6 +92,14 @@ + + + + + + + diff --git a/src/main/resources/com/tikal/hudson/plugins/notification/HudsonNotificationProperty/help-branch.html b/src/main/resources/com/tikal/hudson/plugins/notification/HudsonNotificationProperty/help-branch.html new file mode 100644 index 0000000..c63110a --- /dev/null +++ b/src/main/resources/com/tikal/hudson/plugins/notification/HudsonNotificationProperty/help-branch.html @@ -0,0 +1,6 @@ +
    +

    Only notify if branch matches pattern. + Regex rules / pattern definition in + JAVA docs. +

    +
    diff --git a/src/main/resources/com/tikal/hudson/plugins/notification/Messages.properties b/src/main/resources/com/tikal/hudson/plugins/notification/Messages.properties new file mode 100644 index 0000000..e95c3ee --- /dev/null +++ b/src/main/resources/com/tikal/hudson/plugins/notification/Messages.properties @@ -0,0 +1 @@ +Notify.DisplayName=Notify configured endpoints From 5804f578b41a64646656c026823e9120d64ff51e Mon Sep 17 00:00:00 2001 From: Patrick Reinhart Date: Mon, 21 Nov 2022 19:39:35 +0100 Subject: [PATCH 156/214] Fixed missed folder defined credentials (#47) Signed-off-by: Patrick Reinhart Signed-off-by: Patrick Reinhart --- pom.xml | 12 + .../HudsonNotificationPropertyDescriptor.java | 8 +- .../hudson/plugins/notification/Phase.java | 20 +- .../hudson/plugins/notification/Utils.java | 15 +- .../plugins/notification/PhaseTest.java | 298 ++++++++++++------ 5 files changed, 251 insertions(+), 102 deletions(-) diff --git a/pom.xml b/pom.xml index ae6fc02..fcd8e34 100755 --- a/pom.xml +++ b/pom.xml @@ -119,6 +119,18 @@ 1.0.6 test
    + + org.mockito + mockito-core + 4.8.0 + test + + + org.mockito + mockito-inline + 4.8.0 + test +
    diff --git a/src/main/java/com/tikal/hudson/plugins/notification/HudsonNotificationPropertyDescriptor.java b/src/main/java/com/tikal/hudson/plugins/notification/HudsonNotificationPropertyDescriptor.java index a67529b..1b2bf3e 100644 --- a/src/main/java/com/tikal/hudson/plugins/notification/HudsonNotificationPropertyDescriptor.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/HudsonNotificationPropertyDescriptor.java @@ -20,12 +20,14 @@ import hudson.Extension; import hudson.RelativePath; import hudson.model.Item; +import hudson.model.ItemGroup; import hudson.model.Job; import hudson.model.JobPropertyDescriptor; import hudson.security.ACL; import hudson.security.Permission; import hudson.util.FormValidation; import hudson.util.ListBoxModel; +import jenkins.model.Jenkins; import net.sf.json.JSON; import net.sf.json.JSONArray; import net.sf.json.JSONObject; @@ -38,6 +40,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Objects; import javax.annotation.Nonnull; @@ -151,8 +154,11 @@ public FormValidation doCheckSecretUrl( private FormValidation checkUrl(String urlOrId, UrlType urlType, Protocol protocol) { String actualUrl = urlOrId; if (urlType == UrlType.SECRET && !StringUtils.isEmpty(actualUrl)) { + actualUrl = Jenkins.get().getItems(ItemGroup.class).stream() + .map(ig -> Utils.getSecretUrl(urlOrId, ig)) + .filter(Objects::nonNull) + .findFirst().orElse(null); // Get the credentials - actualUrl = Utils.getSecretUrl(urlOrId); if (actualUrl == null) { return FormValidation.error("Could not find secret text credentials with id " + urlOrId); } diff --git a/src/main/java/com/tikal/hudson/plugins/notification/Phase.java b/src/main/java/com/tikal/hudson/plugins/notification/Phase.java index ab83cdb..26a4cad 100755 --- a/src/main/java/com/tikal/hudson/plugins/notification/Phase.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/Phase.java @@ -302,8 +302,11 @@ private StringBuilder getLog(Run run, Endpoint target) { } public void handle(Run run, TaskListener listener, long timestamp, boolean manual, final String buildNotes, final Integer logLines, Phase phase) { - HudsonNotificationProperty property = (HudsonNotificationProperty) run.getParent().getProperty(HudsonNotificationProperty.class); - if ( property == null ){ return; } + final Job job = run.getParent(); + final HudsonNotificationProperty property = (HudsonNotificationProperty) job.getProperty(HudsonNotificationProperty.class); + if ( property == null ) { + return; + } Result previousCompletedRunResults = findLastBuildThatFinished(run); @@ -338,7 +341,7 @@ public void handle(Run run, TaskListener listener, long timestamp, boolean manua break; case SECRET: String urlSecretId = urlInfo.getUrlOrId(); - String actualUrl = Utils.getSecretUrl(urlSecretId); + String actualUrl = Utils.getSecretUrl(urlSecretId, job.getParent()); expandedUrl = environment.expand(actualUrl); urlIdString = String.format("credentials id '%s'", urlSecretId); break; @@ -350,16 +353,17 @@ public void handle(Run run, TaskListener listener, long timestamp, boolean manua continue; } - if (!manual && environment.containsKey("BRANCH_NAME") && !environment.get("BRANCH_NAME").matches(target.getBranch())) { - listener.getLogger().printf("Environment variable %s with value %s does not match configured branch filter %s%n", "BRANCH_NAME", environment.get("BRANCH_NAME"), target.getBranch()); + final String branch = target.getBranch(); + if (!manual && environment.containsKey("BRANCH_NAME") && !environment.get("BRANCH_NAME").matches(branch)) { + listener.getLogger().printf("Environment variable %s with value %s does not match configured branch filter %s%n", "BRANCH_NAME", environment.get("BRANCH_NAME"), branch); continue; - }else if(!manual && !environment.containsKey("BRANCH_NAME") && !target.getBranch().equals(".*")){ - listener.getLogger().printf("Environment does not contains %s variable%n", "BRANCH_NAME"); + }else if(!manual && !environment.containsKey("BRANCH_NAME") && !".*".equals(branch)){ + listener.getLogger().printf("Environment does not contain %s variable%n", "BRANCH_NAME"); continue; } listener.getLogger().printf("Notifying endpoint with %s%n", urlIdString); - JobState jobState = buildJobState(run.getParent(), run, listener, timestamp, target, phase); + JobState jobState = buildJobState(job, run, listener, timestamp, target, phase); target.getProtocol().send(expandedUrl, target.getFormat().serialize(jobState), target.getTimeout(), diff --git a/src/main/java/com/tikal/hudson/plugins/notification/Utils.java b/src/main/java/com/tikal/hudson/plugins/notification/Utils.java index 6c347f5..8a203a6 100644 --- a/src/main/java/com/tikal/hudson/plugins/notification/Utils.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/Utils.java @@ -3,11 +3,14 @@ import com.cloudbees.plugins.credentials.CredentialsMatchers; import com.cloudbees.plugins.credentials.CredentialsProvider; import com.cloudbees.plugins.credentials.domains.DomainRequirement; +import hudson.model.ItemGroup; import hudson.security.ACL; import hudson.util.FormValidation; import hudson.util.Secret; import java.util.Arrays; import java.util.Collections; +import java.util.List; + import jenkins.model.Jenkins; import org.jenkinsci.plugins.plaincredentials.StringCredentials; @@ -63,18 +66,20 @@ public static void verifyNotEmpty( String ... strings ) /** * Get the actual URL from the credential id * @param credentialId Credential id to lookup + * @param itemGroup the item group to look for the credential * @return Actual URL */ - public static String getSecretUrl(String credentialId) { + public static String getSecretUrl(String credentialId, ItemGroup itemGroup) { // Grab the secret text StringCredentials creds = CredentialsMatchers.firstOrNull(CredentialsProvider.lookupCredentials( - StringCredentials.class, Jenkins.getInstance(), ACL.SYSTEM, - Collections.emptyList()), - CredentialsMatchers.withId(credentialId)); + StringCredentials.class, itemGroup, ACL.SYSTEM, Collections.emptyList()), + CredentialsMatchers.withId(credentialId)); if (creds == null) { return null; } Secret secretUrl = creds.getSecret(); - return secretUrl.getPlainText(); + return secretUrl.getPlainText(); } + + } diff --git a/src/test/java/com/tikal/hudson/plugins/notification/PhaseTest.java b/src/test/java/com/tikal/hudson/plugins/notification/PhaseTest.java index e84697a..37412d0 100644 --- a/src/test/java/com/tikal/hudson/plugins/notification/PhaseTest.java +++ b/src/test/java/com/tikal/hudson/plugins/notification/PhaseTest.java @@ -1,101 +1,223 @@ package com.tikal.hudson.plugins.notification; +import static com.tikal.hudson.plugins.notification.UrlType.PUBLIC; +import static com.tikal.hudson.plugins.notification.UrlType.SECRET; +import static java.util.Arrays.asList; import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.*; -import java.lang.reflect.InvocationTargetException; +import java.io.IOException; +import java.io.PrintStream; import java.lang.reflect.Method; +import com.tikal.hudson.plugins.notification.model.JobState; +import hudson.EnvVars; +import hudson.model.*; +import jenkins.model.Jenkins; import org.junit.Test; -import hudson.model.Result; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockedStatic; +import org.mockito.junit.MockitoJUnitRunner; +@RunWith(MockitoJUnitRunner.class) public class PhaseTest { + @Mock + private Run run; + @Mock + private Job job; + @Mock + private TaskListener listener; + @Mock + private HudsonNotificationProperty property; + @Mock + private Endpoint endpoint; + @Mock + private UrlInfo urlInfo; + @Mock + private EnvVars environment; + @Mock + private Protocol protocol; + @Mock + private Format format; + @Mock + private PrintStream logger; + @Mock + private Jenkins jenkins; - @Test - public void testIsRun() { - try { - Endpoint endPoint = new Endpoint(null); - Method isRunMethod = Phase.class.getDeclaredMethod("isRun", Endpoint.class, Result.class, Result.class); - isRunMethod.setAccessible(true); - - assertEquals("returns true for null endpoint event", - isRunMethod.invoke(Phase.QUEUED, endPoint, null, null), Boolean.TRUE); - - endPoint.setEvent("all"); - for (Phase phaseValue : Phase.values()) { - assertEquals("all Event returns true for Phase " + phaseValue.toString(), - isRunMethod.invoke(phaseValue, endPoint, null, null), Boolean.TRUE); - } - - endPoint.setEvent("queued"); - assertEquals("queued Event returns true for Phase Queued", - isRunMethod.invoke(Phase.QUEUED, endPoint, null, null), Boolean.TRUE); - assertEquals("queued Event returns false for Phase Started", - isRunMethod.invoke(Phase.STARTED, endPoint, null, null), Boolean.FALSE); - - endPoint.setEvent("started"); - assertEquals("started Event returns true for Phase Started", - isRunMethod.invoke(Phase.STARTED, endPoint, null, null), Boolean.TRUE); - assertEquals("started Event returns false for Phase Completed", - isRunMethod.invoke(Phase.COMPLETED, endPoint, null, null), Boolean.FALSE); - - - endPoint.setEvent("completed"); - assertEquals("completed Event returns true for Phase Completed", - isRunMethod.invoke(Phase.COMPLETED, endPoint, null, null), Boolean.TRUE); - assertEquals("completed Event returns false for Phase Finalized", - isRunMethod.invoke(Phase.FINALIZED, endPoint, null, null), Boolean.FALSE); - - - endPoint.setEvent("finalized"); - assertEquals("finalized Event returns true for Phase Finalized", - isRunMethod.invoke(Phase.FINALIZED, endPoint, null, null), Boolean.TRUE); - assertEquals("finalized Event returns true for Phase Queued", - isRunMethod.invoke(Phase.QUEUED, endPoint, null, null), Boolean.FALSE); - - - endPoint.setEvent("failed"); - assertEquals("failed Event returns false for Phase Finalized and no status", - isRunMethod.invoke(Phase.FINALIZED, endPoint, null, null), Boolean.FALSE); - assertEquals("failed Event returns false for Phase Finalized and success status", - isRunMethod.invoke(Phase.FINALIZED, endPoint, Result.SUCCESS, null), Boolean.FALSE); - assertEquals("failed Event returns true for Phase Finalized and success failure", - isRunMethod.invoke(Phase.FINALIZED, endPoint, Result.FAILURE, null), Boolean.TRUE); - assertEquals("failed Event returns false for Phase not Finalized and success failure", - isRunMethod.invoke(Phase.COMPLETED, endPoint, Result.FAILURE, null), Boolean.FALSE); - - endPoint.setEvent("failedAndFirstSuccess"); - assertEquals("failedAndFirstSuccess Event returns false for Phase Finalized and no status", - isRunMethod.invoke(Phase.FINALIZED, endPoint, null, null), Boolean.FALSE); - assertEquals("failedAndFirstSuccess Event returns false for Phase Finalized and no previous status", - isRunMethod.invoke(Phase.FINALIZED, endPoint, Result.SUCCESS, null), Boolean.FALSE); - assertEquals("failedAndFirstSuccess Event returns true for Phase Finalized and no previous status and failed status", - isRunMethod.invoke(Phase.FINALIZED, endPoint, Result.FAILURE, null), Boolean.TRUE); - assertEquals("failedAndFirstSuccess Event returns true for Phase Finalized and failed status", - isRunMethod.invoke(Phase.FINALIZED, endPoint, Result.FAILURE, Result.FAILURE), Boolean.TRUE); - assertEquals("failedAndFirstSuccess Event returns true for Phase Finalized and success status with previous status of failure", - isRunMethod.invoke(Phase.FINALIZED, endPoint, Result.SUCCESS, Result.FAILURE), Boolean.TRUE); - assertEquals("failedAndFirstSuccess Event returns false for Phase Finalized and success status with previous status of success", - isRunMethod.invoke(Phase.FINALIZED, endPoint, Result.SUCCESS, Result.SUCCESS), Boolean.FALSE); - assertEquals("failedAndFirstSuccess Event returns false for Phase not Finalized", - isRunMethod.invoke(Phase.COMPLETED, endPoint, Result.SUCCESS, Result.FAILURE), Boolean.FALSE); - - - - - } catch (NoSuchMethodException | SecurityException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } catch (IllegalAccessException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } catch (IllegalArgumentException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } catch (InvocationTargetException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } + @Test + public void testIsRun() throws ReflectiveOperationException { + Endpoint endPoint = new Endpoint(null); + Method isRunMethod = Phase.class.getDeclaredMethod("isRun", Endpoint.class, Result.class, Result.class); + isRunMethod.setAccessible(true); + assertEquals("returns true for null endpoint event", + isRunMethod.invoke(Phase.QUEUED, endPoint, null, null), Boolean.TRUE); + + endPoint.setEvent("all"); + for (Phase phaseValue : Phase.values()) { + assertEquals("all Event returns true for Phase " + phaseValue.toString(), + isRunMethod.invoke(phaseValue, endPoint, null, null), Boolean.TRUE); + } + + endPoint.setEvent("queued"); + assertEquals("queued Event returns true for Phase Queued", + isRunMethod.invoke(Phase.QUEUED, endPoint, null, null), Boolean.TRUE); + assertEquals("queued Event returns false for Phase Started", + isRunMethod.invoke(Phase.STARTED, endPoint, null, null), Boolean.FALSE); + + endPoint.setEvent("started"); + assertEquals("started Event returns true for Phase Started", + isRunMethod.invoke(Phase.STARTED, endPoint, null, null), Boolean.TRUE); + assertEquals("started Event returns false for Phase Completed", + isRunMethod.invoke(Phase.COMPLETED, endPoint, null, null), Boolean.FALSE); + + + endPoint.setEvent("completed"); + assertEquals("completed Event returns true for Phase Completed", + isRunMethod.invoke(Phase.COMPLETED, endPoint, null, null), Boolean.TRUE); + assertEquals("completed Event returns false for Phase Finalized", + isRunMethod.invoke(Phase.FINALIZED, endPoint, null, null), Boolean.FALSE); + + + endPoint.setEvent("finalized"); + assertEquals("finalized Event returns true for Phase Finalized", + isRunMethod.invoke(Phase.FINALIZED, endPoint, null, null), Boolean.TRUE); + assertEquals("finalized Event returns true for Phase Queued", + isRunMethod.invoke(Phase.QUEUED, endPoint, null, null), Boolean.FALSE); + + + endPoint.setEvent("failed"); + assertEquals("failed Event returns false for Phase Finalized and no status", + isRunMethod.invoke(Phase.FINALIZED, endPoint, null, null), Boolean.FALSE); + assertEquals("failed Event returns false for Phase Finalized and success status", + isRunMethod.invoke(Phase.FINALIZED, endPoint, Result.SUCCESS, null), Boolean.FALSE); + assertEquals("failed Event returns true for Phase Finalized and success failure", + isRunMethod.invoke(Phase.FINALIZED, endPoint, Result.FAILURE, null), Boolean.TRUE); + assertEquals("failed Event returns false for Phase not Finalized and success failure", + isRunMethod.invoke(Phase.COMPLETED, endPoint, Result.FAILURE, null), Boolean.FALSE); + + endPoint.setEvent("failedAndFirstSuccess"); + assertEquals("failedAndFirstSuccess Event returns false for Phase Finalized and no status", + isRunMethod.invoke(Phase.FINALIZED, endPoint, null, null), Boolean.FALSE); + assertEquals("failedAndFirstSuccess Event returns false for Phase Finalized and no previous status", + isRunMethod.invoke(Phase.FINALIZED, endPoint, Result.SUCCESS, null), Boolean.FALSE); + assertEquals("failedAndFirstSuccess Event returns true for Phase Finalized and no previous status and failed status", + isRunMethod.invoke(Phase.FINALIZED, endPoint, Result.FAILURE, null), Boolean.TRUE); + assertEquals("failedAndFirstSuccess Event returns true for Phase Finalized and failed status", + isRunMethod.invoke(Phase.FINALIZED, endPoint, Result.FAILURE, Result.FAILURE), Boolean.TRUE); + assertEquals("failedAndFirstSuccess Event returns true for Phase Finalized and success status with previous status of failure", + isRunMethod.invoke(Phase.FINALIZED, endPoint, Result.SUCCESS, Result.FAILURE), Boolean.TRUE); + assertEquals("failedAndFirstSuccess Event returns false for Phase Finalized and success status with previous status of success", + isRunMethod.invoke(Phase.FINALIZED, endPoint, Result.SUCCESS, Result.SUCCESS), Boolean.FALSE); + assertEquals("failedAndFirstSuccess Event returns false for Phase not Finalized", + isRunMethod.invoke(Phase.COMPLETED, endPoint, Result.SUCCESS, Result.FAILURE), Boolean.FALSE); + } + + @Test + public void testRunNoProperty() { + when(run.getParent()).thenReturn(job); + + Phase.STARTED.handle(run, listener, 0L); + + verify(job).getProperty(HudsonNotificationProperty.class); + verifyNoInteractions(listener, endpoint, property); + } + + @Test + public void testRunNoPreviousRunUrlNull() { + when(run.getParent()).thenReturn(job); + when(job.getProperty(HudsonNotificationProperty.class)).thenReturn(property); + when(property.getEndpoints()).thenReturn(asList(endpoint)); + when(endpoint.getUrlInfo()).thenReturn(urlInfo); + + Phase.STARTED.handle(run, listener, 0L); + + verify(run).getPreviousCompletedBuild(); + verifyNoInteractions(listener); + } + + @Test + public void testRunNoPreviousRunUrlTypePublicUnresolvedUrl() throws IOException, InterruptedException { + when(run.getParent()).thenReturn(job); + when(job.getProperty(HudsonNotificationProperty.class)).thenReturn(property); + when(property.getEndpoints()).thenReturn(asList(endpoint)); + when(endpoint.getUrlInfo()).thenReturn(urlInfo); + when(run.getEnvironment(listener)).thenReturn(environment); + when(urlInfo.getUrlOrId()).thenReturn("$someUrl"); + when(urlInfo.getUrlType()).thenReturn(PUBLIC); + when(environment.expand("$someUrl")).thenReturn("$someUrl"); + when(listener.getLogger()).thenReturn(logger); + + Phase.STARTED.handle(run, listener, 0L); + + verify(logger).printf("Ignoring sending notification due to unresolved variable: %s%n", "url '$someUrl'"); + verify(run).getPreviousCompletedBuild(); + } + + @Test + public void testRunPreviousRunUrlTypePublic() throws IOException, InterruptedException { + byte[] data = "data".getBytes(); + try (MockedStatic jenkinsMockedStatic = mockStatic(Jenkins.class)) { + jenkinsMockedStatic.when(Jenkins::getInstanceOrNull).thenReturn(jenkins); + jenkinsMockedStatic.when(Jenkins::getInstance).thenReturn(jenkins); + + when(run.getParent()).thenReturn(job); + when(job.getProperty(HudsonNotificationProperty.class)).thenReturn(property); + when(property.getEndpoints()).thenReturn(asList(endpoint)); + when(endpoint.getUrlInfo()).thenReturn(urlInfo); + when(endpoint.getBranch()).thenReturn("branchName"); + when(run.getEnvironment(listener)).thenReturn(environment); + when(urlInfo.getUrlOrId()).thenReturn("$someUrl"); + when(urlInfo.getUrlType()).thenReturn(PUBLIC); + when(environment.expand("$someUrl")).thenReturn("expandedUrl"); + when(environment.containsKey("BRANCH_NAME")).thenReturn(true); + when(environment.get("BRANCH_NAME")).thenReturn("branchName"); + when(listener.getLogger()).thenReturn(logger); + when(endpoint.getProtocol()).thenReturn(protocol); + when(endpoint.getTimeout()).thenReturn(42); + when(endpoint.getFormat()).thenReturn(format); + when(format.serialize(isA(JobState.class))).thenReturn(data); + + Phase.STARTED.handle(run, listener, 1L); + + verify(logger).printf("Notifying endpoint with %s%n", "url 'expandedUrl'"); + verify(protocol).send("expandedUrl", data, 42, false); + verify(run).getPreviousCompletedBuild(); + } + } + + @Test + public void testRunPreviousRunUrlTypeSecret() throws IOException, InterruptedException { + byte[] data = "data".getBytes(); + try (MockedStatic jenkinsMockedStatic = mockStatic(Jenkins.class); + MockedStatic utilsMockedStatic = mockStatic(Utils.class)) { + jenkinsMockedStatic.when(Jenkins::getInstanceOrNull).thenReturn(jenkins); + jenkinsMockedStatic.when(Jenkins::getInstance).thenReturn(jenkins); + utilsMockedStatic.when(() -> Utils.getSecretUrl("credentialsId", jenkins)).thenReturn("$secretUrl"); + + when(run.getParent()).thenReturn(job); + when(job.getProperty(HudsonNotificationProperty.class)).thenReturn(property); + when(property.getEndpoints()).thenReturn(asList(endpoint)); + when(endpoint.getUrlInfo()).thenReturn(urlInfo); + when(endpoint.getBranch()).thenReturn(".*"); + when(run.getEnvironment(listener)).thenReturn(environment); + when(job.getParent()).thenReturn(jenkins); + when(urlInfo.getUrlOrId()).thenReturn("credentialsId"); + when(urlInfo.getUrlType()).thenReturn(SECRET); + when(environment.expand("$secretUrl")).thenReturn("secretUrl"); + when(listener.getLogger()).thenReturn(logger); + when(endpoint.getProtocol()).thenReturn(protocol); + when(endpoint.getTimeout()).thenReturn(42); + when(endpoint.getFormat()).thenReturn(format); + when(format.serialize(isA(JobState.class))).thenReturn(data); + + Phase.STARTED.handle(run, listener, 1L); + + verify(logger).printf( "Notifying endpoint with %s%n","credentials id 'credentialsId'"); + verify(protocol).send("secretUrl", data, 42, false); + verify(run).getPreviousCompletedBuild(); + } + } } From 87c55b1fd91a4a76965a0d1acdf0fca9640b29a4 Mon Sep 17 00:00:00 2001 From: Dorota <37271098+dcz-purism@users.noreply.github.com> Date: Fri, 21 Apr 2023 11:07:45 +0200 Subject: [PATCH 157/214] SCM: Get info from git plugin (#48) Thanks a lot for this :) --- pom.xml | 4 ++++ .../hudson/plugins/notification/Phase.java | 23 ++++++++++++++++++- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index fcd8e34..f281525 100755 --- a/pom.xml +++ b/pom.xml @@ -70,6 +70,10 @@ gson 2.9.0 + + org.jenkins-ci.plugins + git + org.jenkins-ci.plugins credentials diff --git a/src/main/java/com/tikal/hudson/plugins/notification/Phase.java b/src/main/java/com/tikal/hudson/plugins/notification/Phase.java index 26a4cad..d7411e8 100755 --- a/src/main/java/com/tikal/hudson/plugins/notification/Phase.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/Phase.java @@ -29,6 +29,8 @@ import hudson.model.Run; import hudson.model.TaskListener; import hudson.model.User; +import hudson.plugins.git.util.Build; +import hudson.plugins.git.util.BuildData; import hudson.scm.ChangeLogSet; import hudson.tasks.test.AbstractTestResultAction; import hudson.tasks.test.TestResult; @@ -41,6 +43,7 @@ import java.io.PrintStream; import java.util.ArrayList; import java.util.List; +import java.util.Map; import java.util.Objects; import java.util.Set; @@ -170,10 +173,28 @@ private JobState buildJobState(Job job, Run run, TaskListener listener, long tim } buildState.setParameters(env); } - + + BuildData build = job.getAction(BuildData.class); + + if ( build != null ) { + if ( !build.remoteUrls.isEmpty() ) { + String url = build.remoteUrls.iterator().next(); + if ( url != null ) { + scmState.setUrl( url ); + } + } + for (Map.Entry entry : build.buildsByBranchName.entrySet()) { + if ( entry.getValue().hudsonBuildNumber == run.number ) { + scmState.setBranch( entry.getKey() ); + scmState.setCommit( entry.getValue().revision.getSha1String() ); + } + } + } + if ( environment.get( "GIT_URL" ) != null ) { scmState.setUrl( environment.get( "GIT_URL" )); } + if ( environment.get( "GIT_BRANCH" ) != null ) { scmState.setBranch( environment.get( "GIT_BRANCH" )); From 061df7ebc031a9175650e1ad1844863b5f704078 Mon Sep 17 00:00:00 2001 From: chenco Date: Sun, 23 Apr 2023 08:44:35 +0300 Subject: [PATCH 158/214] [maven-release-plugin] prepare release notification-1.16 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index f281525..e36a987 100755 --- a/pom.xml +++ b/pom.xml @@ -12,7 +12,7 @@ com.tikalk.hudson.plugins notification - ${revision}${changelist} + 1.16 hpi Jenkins Notification plugin Sends notifications about jobs phases and status @@ -170,7 +170,7 @@ scm:git:https://github.com/${gitHubRepo}.git scm:git:git@github.com:${gitHubRepo}.git - ${scmTag} + notification-1.16 https://github.com/${gitHubRepo} From a8543e2fbb9ae4d54d9d6176d11e3e91447a8de1 Mon Sep 17 00:00:00 2001 From: chenco Date: Sun, 23 Apr 2023 09:11:16 +0300 Subject: [PATCH 159/214] Revert "[maven-release-plugin] prepare release notification-1.16" This reverts commit 061df7ebc031a9175650e1ad1844863b5f704078. --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index e36a987..f281525 100755 --- a/pom.xml +++ b/pom.xml @@ -12,7 +12,7 @@ com.tikalk.hudson.plugins notification - 1.16 + ${revision}${changelist} hpi Jenkins Notification plugin Sends notifications about jobs phases and status @@ -170,7 +170,7 @@ scm:git:https://github.com/${gitHubRepo}.git scm:git:git@github.com:${gitHubRepo}.git - notification-1.16 + ${scmTag} https://github.com/${gitHubRepo} From 55d4c442ed327cf13933ff83066fcfc485ef2b87 Mon Sep 17 00:00:00 2001 From: chenco Date: Sun, 23 Apr 2023 09:13:02 +0300 Subject: [PATCH 160/214] [maven-release-plugin] prepare release notification-1.17 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index f281525..1d39855 100755 --- a/pom.xml +++ b/pom.xml @@ -12,7 +12,7 @@ com.tikalk.hudson.plugins notification - ${revision}${changelist} + 1.17 hpi Jenkins Notification plugin Sends notifications about jobs phases and status @@ -170,7 +170,7 @@ scm:git:https://github.com/${gitHubRepo}.git scm:git:git@github.com:${gitHubRepo}.git - ${scmTag} + notification-1.17 https://github.com/${gitHubRepo} From d3ad3a60a163fcbc90c8e5dc8ff506b1d1426a1b Mon Sep 17 00:00:00 2001 From: chenco Date: Sun, 23 Apr 2023 09:13:15 +0300 Subject: [PATCH 161/214] [maven-release-plugin] prepare for next development iteration --- pom.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index 1d39855..a001d20 100755 --- a/pom.xml +++ b/pom.xml @@ -12,14 +12,14 @@ com.tikalk.hudson.plugins notification - 1.17 + ${revision}${changelist} hpi Jenkins Notification plugin Sends notifications about jobs phases and status https://github.com/jenkinsci/${project.artifactId}-plugin - 1.16 + 1.18 -SNAPSHOT 2.289.3 jenkinsci/${project.artifactId}-plugin @@ -170,7 +170,7 @@ scm:git:https://github.com/${gitHubRepo}.git scm:git:git@github.com:${gitHubRepo}.git - notification-1.17 + ${scmTag} https://github.com/${gitHubRepo} From 20cc027abcb3daab5b2576586ef3df3d63a69316 Mon Sep 17 00:00:00 2001 From: chenco Date: Sun, 23 Apr 2023 09:17:39 +0300 Subject: [PATCH 162/214] [maven-release-plugin] rollback the release of notification-1.17 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index a001d20..f281525 100755 --- a/pom.xml +++ b/pom.xml @@ -19,7 +19,7 @@ https://github.com/jenkinsci/${project.artifactId}-plugin - 1.18 + 1.16 -SNAPSHOT 2.289.3 jenkinsci/${project.artifactId}-plugin From d6549c7c16819b9f3de3ddbe49922cf5a4df9376 Mon Sep 17 00:00:00 2001 From: Chen Cohen Date: Tue, 25 Apr 2023 18:04:05 +0300 Subject: [PATCH 163/214] [maven-release-plugin] prepare release notification-1.17 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index f281525..1d39855 100755 --- a/pom.xml +++ b/pom.xml @@ -12,7 +12,7 @@ com.tikalk.hudson.plugins notification - ${revision}${changelist} + 1.17 hpi Jenkins Notification plugin Sends notifications about jobs phases and status @@ -170,7 +170,7 @@ scm:git:https://github.com/${gitHubRepo}.git scm:git:git@github.com:${gitHubRepo}.git - ${scmTag} + notification-1.17 https://github.com/${gitHubRepo} From a312806658a417a2d6d4e18584494903f684515a Mon Sep 17 00:00:00 2001 From: Chen Cohen Date: Tue, 25 Apr 2023 18:04:19 +0300 Subject: [PATCH 164/214] [maven-release-plugin] prepare for next development iteration --- pom.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index 1d39855..a001d20 100755 --- a/pom.xml +++ b/pom.xml @@ -12,14 +12,14 @@ com.tikalk.hudson.plugins notification - 1.17 + ${revision}${changelist} hpi Jenkins Notification plugin Sends notifications about jobs phases and status https://github.com/jenkinsci/${project.artifactId}-plugin - 1.16 + 1.18 -SNAPSHOT 2.289.3 jenkinsci/${project.artifactId}-plugin @@ -170,7 +170,7 @@ scm:git:https://github.com/${gitHubRepo}.git scm:git:git@github.com:${gitHubRepo}.git - notification-1.17 + ${scmTag} https://github.com/${gitHubRepo} From f275bc31a2e592bc06ee33832ef4b6de47c1b0cd Mon Sep 17 00:00:00 2001 From: Boris Yao Date: Tue, 20 Aug 2024 14:54:49 +0200 Subject: [PATCH 165/214] Adapt for jetty 12 --- pom.xml | 7 ++++-- .../plugins/notification/ProtocolTest.java | 24 ++++++++++++++----- 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/pom.xml b/pom.xml index a001d20..1083e43 100755 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ org.jenkins-ci.plugins plugin - 4.40 + 4.86 @@ -21,8 +21,11 @@ 1.18 -SNAPSHOT - 2.289.3 + 2.426.3 jenkinsci/${project.artifactId}-plugin + + 2254.vcff7a_d4969e5 + 17 diff --git a/src/test/java/com/tikal/hudson/plugins/notification/ProtocolTest.java b/src/test/java/com/tikal/hudson/plugins/notification/ProtocolTest.java index 0d5805b..c47a690 100644 --- a/src/test/java/com/tikal/hudson/plugins/notification/ProtocolTest.java +++ b/src/test/java/com/tikal/hudson/plugins/notification/ProtocolTest.java @@ -23,14 +23,16 @@ */ package com.tikal.hudson.plugins.notification; +import com.google.common.base.MoreObjects; import com.google.common.base.Objects; import com.google.common.io.CharStreams; import junit.framework.TestCase; +import org.eclipse.jetty.ee8.servlet.ServletContextHandler; import org.eclipse.jetty.server.Connector; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.ServerConnector; -import org.eclipse.jetty.servlet.ServletHandler; -import org.eclipse.jetty.servlet.ServletHolder; +import org.eclipse.jetty.ee8.servlet.ServletHandler; +import org.eclipse.jetty.ee8.servlet.ServletHolder; import javax.servlet.Servlet; import javax.servlet.ServletException; @@ -92,7 +94,7 @@ public boolean equals(Object obj) { @Override public String toString() { - return Objects.toStringHelper(this) + return MoreObjects.toStringHelper(this) .add("url", url) .add("method", method) .add("body", body) @@ -170,9 +172,19 @@ private UrlFactory startSecureServer(Servlet servlet, String path, String author ServerConnector connector = new ServerConnector(server); server.setConnectors(new Connector[] {connector}); - ServletHandler servletHandler = new ServletHandler(); - server.setHandler(servletHandler); - servletHandler.addServletWithMapping(new ServletHolder(servlet), path); + // Create a ServletContextHandler to handle servlets + ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS); + context.setContextPath("/"); // Root context + + // Add a servlet to handle requests to /hello + context.addServlet(new ServletHolder(servlet), path); + + // Set the context handler to the server + server.setHandler(context); + + //ServletHandler servletHandler = new ServletHandler(); + //server.setHandler(servletHandler); + //servletHandler.addServletWithMapping(new ServletHolder(servlet), path); server.start(); servers.add(server); From bb0a1e169a89079e34674017751ce868667d29fd Mon Sep 17 00:00:00 2001 From: Boris Yao Date: Tue, 20 Aug 2024 15:59:11 +0200 Subject: [PATCH 166/214] fix pom --- pom.xml | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/pom.xml b/pom.xml index 1083e43..a0a8a80 100755 --- a/pom.xml +++ b/pom.xml @@ -21,11 +21,11 @@ 1.18 -SNAPSHOT - 2.426.3 + 2.472 jenkinsci/${project.artifactId}-plugin - 2254.vcff7a_d4969e5 - 17 + 2250.v03a_1295b_0a_30 + 17 @@ -58,8 +58,8 @@ io.jenkins.tools.bom - bom-2.289.x - 1362.v59f2f3db_80ee + bom-weekly + 3258.vcdcf15936a_fd import pom @@ -71,7 +71,13 @@ com.google.code.gson gson - 2.9.0 + 2.11.0 + + + com.google.errorprone + error_prone_annotations + + org.jenkins-ci.plugins From ac4b66823b2ecb19e712965860e65deb72c032d7 Mon Sep 17 00:00:00 2001 From: Boris Yao Date: Tue, 20 Aug 2024 16:03:53 +0200 Subject: [PATCH 167/214] fix jenkinsfile --- Jenkinsfile | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Jenkinsfile b/Jenkinsfile index 77c9ed7..cf3359f 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -1,4 +1,7 @@ #!/usr/bin/env groovy /* `buildPlugin` step provided by: https://github.com/jenkins-infra/pipeline-library */ -buildPlugin() +buildPlugin(useContainerAgent: true, configurations: [ + [platform: 'linux', jdk: 21], + [platform: 'windows', jdk: 17] +]) \ No newline at end of file From d1b4ae6310e59fbad8b0cee76150e6a2fb1ca834 Mon Sep 17 00:00:00 2001 From: Boris Yao Date: Mon, 2 Sep 2024 23:53:13 +0200 Subject: [PATCH 168/214] update pom --- pom.xml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pom.xml b/pom.xml index a0a8a80..2558f09 100755 --- a/pom.xml +++ b/pom.xml @@ -144,6 +144,11 @@ 4.8.0 test + + org.eclipse.collections + eclipse-collections + 9.2.0 + From 20442573725bb08392495bf5f0754f6d58c97dc5 Mon Sep 17 00:00:00 2001 From: Boris Yao Date: Tue, 3 Sep 2024 00:07:36 +0200 Subject: [PATCH 169/214] fix mock issues --- .../plugins/notification/PhaseTest.java | 40 +++++++++++++------ 1 file changed, 28 insertions(+), 12 deletions(-) diff --git a/src/test/java/com/tikal/hudson/plugins/notification/PhaseTest.java b/src/test/java/com/tikal/hudson/plugins/notification/PhaseTest.java index 37412d0..462b50b 100644 --- a/src/test/java/com/tikal/hudson/plugins/notification/PhaseTest.java +++ b/src/test/java/com/tikal/hudson/plugins/notification/PhaseTest.java @@ -38,10 +38,6 @@ public class PhaseTest { @Mock private EnvVars environment; @Mock - private Protocol protocol; - @Mock - private Format format; - @Mock private PrintStream logger; @Mock private Jenkins jenkins; @@ -163,6 +159,16 @@ public void testRunPreviousRunUrlTypePublic() throws IOException, InterruptedExc jenkinsMockedStatic.when(Jenkins::getInstanceOrNull).thenReturn(jenkins); jenkinsMockedStatic.when(Jenkins::getInstance).thenReturn(jenkins); + Protocol httpProtocolSpy = spy(Protocol.HTTP); + when(endpoint.getProtocol()).thenReturn(httpProtocolSpy); + doNothing().when(httpProtocolSpy).send(anyString(), any(byte[].class), anyInt(), anyBoolean()); + + Format jsonFormatSpy = spy(Format.JSON); + JobState jobState = new JobState(); + when(endpoint.getFormat()).thenReturn(jsonFormatSpy); + doReturn(data).when(jsonFormatSpy).serialize(isA(JobState.class)); + assertEquals(data, jsonFormatSpy.serialize(jobState)); + when(run.getParent()).thenReturn(job); when(job.getProperty(HudsonNotificationProperty.class)).thenReturn(property); when(property.getEndpoints()).thenReturn(asList(endpoint)); @@ -175,15 +181,15 @@ public void testRunPreviousRunUrlTypePublic() throws IOException, InterruptedExc when(environment.containsKey("BRANCH_NAME")).thenReturn(true); when(environment.get("BRANCH_NAME")).thenReturn("branchName"); when(listener.getLogger()).thenReturn(logger); - when(endpoint.getProtocol()).thenReturn(protocol); + //when(endpoint.getProtocol()).thenReturn(protocol); when(endpoint.getTimeout()).thenReturn(42); - when(endpoint.getFormat()).thenReturn(format); - when(format.serialize(isA(JobState.class))).thenReturn(data); + //when(endpoint.getFormat()).thenReturn(format); + //when(format.serialize(isA(JobState.class))).thenReturn(data); Phase.STARTED.handle(run, listener, 1L); verify(logger).printf("Notifying endpoint with %s%n", "url 'expandedUrl'"); - verify(protocol).send("expandedUrl", data, 42, false); + verify(httpProtocolSpy).send("expandedUrl", data, 42, false); verify(run).getPreviousCompletedBuild(); } } @@ -197,6 +203,17 @@ public void testRunPreviousRunUrlTypeSecret() throws IOException, InterruptedExc jenkinsMockedStatic.when(Jenkins::getInstance).thenReturn(jenkins); utilsMockedStatic.when(() -> Utils.getSecretUrl("credentialsId", jenkins)).thenReturn("$secretUrl"); + Protocol httpProtocolSpy = spy(Protocol.HTTP); + when(endpoint.getProtocol()).thenReturn(httpProtocolSpy); + doNothing().when(httpProtocolSpy).send(anyString(), any(byte[].class), anyInt(), anyBoolean()); + + Format jsonFormatSpy = spy(Format.JSON); + JobState jobState = new JobState(); + when(endpoint.getFormat()).thenReturn(jsonFormatSpy); + doReturn(data).when(jsonFormatSpy).serialize(isA(JobState.class)); + assertEquals(data, jsonFormatSpy.serialize(jobState)); + + when(run.getParent()).thenReturn(job); when(job.getProperty(HudsonNotificationProperty.class)).thenReturn(property); when(property.getEndpoints()).thenReturn(asList(endpoint)); @@ -208,15 +225,14 @@ public void testRunPreviousRunUrlTypeSecret() throws IOException, InterruptedExc when(urlInfo.getUrlType()).thenReturn(SECRET); when(environment.expand("$secretUrl")).thenReturn("secretUrl"); when(listener.getLogger()).thenReturn(logger); - when(endpoint.getProtocol()).thenReturn(protocol); + //when(endpoint.getProtocol()).thenReturn(protocol); when(endpoint.getTimeout()).thenReturn(42); - when(endpoint.getFormat()).thenReturn(format); - when(format.serialize(isA(JobState.class))).thenReturn(data); + //when(format.serialize(isA(JobState.class))).thenReturn(data); Phase.STARTED.handle(run, listener, 1L); verify(logger).printf( "Notifying endpoint with %s%n","credentials id 'credentialsId'"); - verify(protocol).send("secretUrl", data, 42, false); + verify(httpProtocolSpy).send("secretUrl", data, 42, false); verify(run).getPreviousCompletedBuild(); } } From 0d91c5a9796f44d6b3b530f6f6b82bf7e4384042 Mon Sep 17 00:00:00 2001 From: Boris Yao Date: Tue, 3 Sep 2024 00:28:23 +0200 Subject: [PATCH 170/214] fix pom and tests --- pom.xml | 12 +++--------- .../tikal/hudson/plugins/notification/PhaseTest.java | 6 ------ 2 files changed, 3 insertions(+), 15 deletions(-) diff --git a/pom.xml b/pom.xml index 2558f09..c6b9c4b 100755 --- a/pom.xml +++ b/pom.xml @@ -69,15 +69,9 @@ - com.google.code.gson - gson - 2.11.0 - - - com.google.errorprone - error_prone_annotations - - + io.jenkins.plugins + gson-api + 2.11.0-41.v019fcf6125dc org.jenkins-ci.plugins diff --git a/src/test/java/com/tikal/hudson/plugins/notification/PhaseTest.java b/src/test/java/com/tikal/hudson/plugins/notification/PhaseTest.java index 462b50b..f8fc751 100644 --- a/src/test/java/com/tikal/hudson/plugins/notification/PhaseTest.java +++ b/src/test/java/com/tikal/hudson/plugins/notification/PhaseTest.java @@ -181,10 +181,7 @@ public void testRunPreviousRunUrlTypePublic() throws IOException, InterruptedExc when(environment.containsKey("BRANCH_NAME")).thenReturn(true); when(environment.get("BRANCH_NAME")).thenReturn("branchName"); when(listener.getLogger()).thenReturn(logger); - //when(endpoint.getProtocol()).thenReturn(protocol); when(endpoint.getTimeout()).thenReturn(42); - //when(endpoint.getFormat()).thenReturn(format); - //when(format.serialize(isA(JobState.class))).thenReturn(data); Phase.STARTED.handle(run, listener, 1L); @@ -213,7 +210,6 @@ public void testRunPreviousRunUrlTypeSecret() throws IOException, InterruptedExc doReturn(data).when(jsonFormatSpy).serialize(isA(JobState.class)); assertEquals(data, jsonFormatSpy.serialize(jobState)); - when(run.getParent()).thenReturn(job); when(job.getProperty(HudsonNotificationProperty.class)).thenReturn(property); when(property.getEndpoints()).thenReturn(asList(endpoint)); @@ -225,9 +221,7 @@ public void testRunPreviousRunUrlTypeSecret() throws IOException, InterruptedExc when(urlInfo.getUrlType()).thenReturn(SECRET); when(environment.expand("$secretUrl")).thenReturn("secretUrl"); when(listener.getLogger()).thenReturn(logger); - //when(endpoint.getProtocol()).thenReturn(protocol); when(endpoint.getTimeout()).thenReturn(42); - //when(format.serialize(isA(JobState.class))).thenReturn(data); Phase.STARTED.handle(run, listener, 1L); From 2b1af70a4e3a263b60957e141341e0b30f01a846 Mon Sep 17 00:00:00 2001 From: Boris Yao Date: Tue, 3 Sep 2024 00:29:25 +0200 Subject: [PATCH 171/214] fix pom --- pom.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/pom.xml b/pom.xml index c6b9c4b..a9b4dcf 100755 --- a/pom.xml +++ b/pom.xml @@ -71,7 +71,6 @@ io.jenkins.plugins gson-api - 2.11.0-41.v019fcf6125dc org.jenkins-ci.plugins From 547dcdd28571f8729127eb87c3e4b4664a82a830 Mon Sep 17 00:00:00 2001 From: Boris Yao Date: Tue, 3 Sep 2024 00:32:06 +0200 Subject: [PATCH 172/214] fix jetty code --- .../com/tikal/hudson/plugins/notification/ProtocolTest.java | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/test/java/com/tikal/hudson/plugins/notification/ProtocolTest.java b/src/test/java/com/tikal/hudson/plugins/notification/ProtocolTest.java index c47a690..ef681fd 100644 --- a/src/test/java/com/tikal/hudson/plugins/notification/ProtocolTest.java +++ b/src/test/java/com/tikal/hudson/plugins/notification/ProtocolTest.java @@ -176,16 +176,12 @@ private UrlFactory startSecureServer(Servlet servlet, String path, String author ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS); context.setContextPath("/"); // Root context - // Add a servlet to handle requests to /hello + // Add a servlet to handle requests context.addServlet(new ServletHolder(servlet), path); // Set the context handler to the server server.setHandler(context); - //ServletHandler servletHandler = new ServletHandler(); - //server.setHandler(servletHandler); - //servletHandler.addServletWithMapping(new ServletHolder(servlet), path); - server.start(); servers.add(server); From 1946c677e4dda42142d1baa331564704b978b448 Mon Sep 17 00:00:00 2001 From: Boris Yao Date: Tue, 3 Sep 2024 00:40:38 +0200 Subject: [PATCH 173/214] optimize import --- .../com/tikal/hudson/plugins/notification/ProtocolTest.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/test/java/com/tikal/hudson/plugins/notification/ProtocolTest.java b/src/test/java/com/tikal/hudson/plugins/notification/ProtocolTest.java index ef681fd..a8f2846 100644 --- a/src/test/java/com/tikal/hudson/plugins/notification/ProtocolTest.java +++ b/src/test/java/com/tikal/hudson/plugins/notification/ProtocolTest.java @@ -28,11 +28,10 @@ import com.google.common.io.CharStreams; import junit.framework.TestCase; import org.eclipse.jetty.ee8.servlet.ServletContextHandler; +import org.eclipse.jetty.ee8.servlet.ServletHolder; import org.eclipse.jetty.server.Connector; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.ServerConnector; -import org.eclipse.jetty.ee8.servlet.ServletHandler; -import org.eclipse.jetty.ee8.servlet.ServletHolder; import javax.servlet.Servlet; import javax.servlet.ServletException; From 6c2baf7bf04625efe8ba422629019067c799e016 Mon Sep 17 00:00:00 2001 From: Basil Crow Date: Tue, 3 Sep 2024 10:15:29 -0700 Subject: [PATCH 174/214] Use Mockito from plugin parent POM --- pom.xml | 7 ------- 1 file changed, 7 deletions(-) diff --git a/pom.xml b/pom.xml index a9b4dcf..f0b46aa 100755 --- a/pom.xml +++ b/pom.xml @@ -128,13 +128,6 @@ org.mockito mockito-core - 4.8.0 - test - - - org.mockito - mockito-inline - 4.8.0 test From 168ad58e801f3f21156bc7bf5e06e020a21bc337 Mon Sep 17 00:00:00 2001 From: Basil Crow Date: Tue, 3 Sep 2024 10:18:10 -0700 Subject: [PATCH 175/214] Update pom.xml --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index f0b46aa..c307fbb 100755 --- a/pom.xml +++ b/pom.xml @@ -58,7 +58,7 @@ io.jenkins.tools.bom - bom-weekly + bom-2.462.x 3258.vcdcf15936a_fd import pom From 1e276201104c7aedd4ba5acfa9fe61154de137e0 Mon Sep 17 00:00:00 2001 From: Basil Crow Date: Tue, 3 Sep 2024 10:19:26 -0700 Subject: [PATCH 176/214] Remove eclipse-collections --- pom.xml | 5 ----- .../com/tikal/hudson/plugins/notification/NotifyStep.java | 4 +--- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/pom.xml b/pom.xml index c307fbb..5531b05 100755 --- a/pom.xml +++ b/pom.xml @@ -130,11 +130,6 @@ mockito-core test - - org.eclipse.collections - eclipse-collections - 9.2.0 - diff --git a/src/main/java/com/tikal/hudson/plugins/notification/NotifyStep.java b/src/main/java/com/tikal/hudson/plugins/notification/NotifyStep.java index 0214842..7fde269 100644 --- a/src/main/java/com/tikal/hudson/plugins/notification/NotifyStep.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/NotifyStep.java @@ -5,7 +5,6 @@ import hudson.Util; import hudson.model.Run; import hudson.model.TaskListener; -import org.eclipse.collections.impl.factory.Sets; import org.jenkinsci.plugins.workflow.graph.FlowNode; import org.jenkinsci.plugins.workflow.steps.Step; import org.jenkinsci.plugins.workflow.steps.StepContext; @@ -123,8 +122,7 @@ public String getDisplayName() { @Override public Set> getRequiredContext() { - return Sets.immutable.of(FilePath.class, FlowNode.class, Run.class, TaskListener.class) - .castToSet(); + return Set.of(FilePath.class, FlowNode.class, Run.class, TaskListener.class); } } } From a0d3d46a97ffae6cc6165a192a459cb1420027bc Mon Sep 17 00:00:00 2001 From: Boris Yao Date: Wed, 4 Sep 2024 13:33:31 +0200 Subject: [PATCH 177/214] remove unnecessary comments --- .../tikal/hudson/plugins/notification/ProtocolTest.java | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/test/java/com/tikal/hudson/plugins/notification/ProtocolTest.java b/src/test/java/com/tikal/hudson/plugins/notification/ProtocolTest.java index a8f2846..bff0ef7 100644 --- a/src/test/java/com/tikal/hudson/plugins/notification/ProtocolTest.java +++ b/src/test/java/com/tikal/hudson/plugins/notification/ProtocolTest.java @@ -171,14 +171,9 @@ private UrlFactory startSecureServer(Servlet servlet, String path, String author ServerConnector connector = new ServerConnector(server); server.setConnectors(new Connector[] {connector}); - // Create a ServletContextHandler to handle servlets ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS); - context.setContextPath("/"); // Root context - - // Add a servlet to handle requests + context.setContextPath("/"); context.addServlet(new ServletHolder(servlet), path); - - // Set the context handler to the server server.setHandler(context); server.start(); From 2d80578b9cacd2117ed5410d38571a20513d8f80 Mon Sep 17 00:00:00 2001 From: Boris Yao Date: Thu, 3 Oct 2024 12:02:35 +0200 Subject: [PATCH 178/214] [maven-release-plugin] prepare release notification-1.18 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 5531b05..a7c5458 100755 --- a/pom.xml +++ b/pom.xml @@ -12,7 +12,7 @@ com.tikalk.hudson.plugins notification - ${revision}${changelist} + 1.18 hpi Jenkins Notification plugin Sends notifications about jobs phases and status @@ -165,7 +165,7 @@ scm:git:https://github.com/${gitHubRepo}.git scm:git:git@github.com:${gitHubRepo}.git - ${scmTag} + notification-1.18 https://github.com/${gitHubRepo} From 7593341b87ad2806c48f704b94f2be7412909986 Mon Sep 17 00:00:00 2001 From: Boris Yao Date: Thu, 3 Oct 2024 12:02:51 +0200 Subject: [PATCH 179/214] [maven-release-plugin] prepare for next development iteration --- pom.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index a7c5458..d375007 100755 --- a/pom.xml +++ b/pom.xml @@ -12,14 +12,14 @@ com.tikalk.hudson.plugins notification - 1.18 + ${revision}${changelist} hpi Jenkins Notification plugin Sends notifications about jobs phases and status https://github.com/jenkinsci/${project.artifactId}-plugin - 1.18 + 1.19 -SNAPSHOT 2.472 jenkinsci/${project.artifactId}-plugin @@ -165,7 +165,7 @@ scm:git:https://github.com/${gitHubRepo}.git scm:git:git@github.com:${gitHubRepo}.git - notification-1.18 + ${scmTag} https://github.com/${gitHubRepo} From 1eda6ef06af2b83c2e9ce9eb11247603b3efd939 Mon Sep 17 00:00:00 2001 From: Patrick Reinhart Date: Thu, 3 Oct 2024 17:08:40 +0200 Subject: [PATCH 180/214] Adds dependabot configuration (#50) Improves https://plugins.jenkins.io/notification/healthscore/ by adding automated dependency updates Signed-off-by: Patrick Reinhart --- .github/dependabot.yml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 .github/dependabot.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..391fbe5 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,14 @@ +version: 2 +updates: +# Maintain dependencies for your plugin +- package-ecosystem: maven + directory: / + schedule: + interval: monthly + open-pull-requests-limit: 10 + target-branch: master +# Maintain dependencies for GitHub Actions +- package-ecosystem: github-actions + directory: / + schedule: + interval: monthly From 91850a20ba5a2a217f66475617f0066fa2e006a1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 3 Oct 2024 08:09:44 -0700 Subject: [PATCH 181/214] Bump actions/checkout from 2 to 4 (#52) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql-analysis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 626c2db..68b1d2d 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -39,7 +39,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v2 + uses: actions/checkout@v4 # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL From 54d9a132e43974a63963fabdecfc4289ebbee3bd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 3 Oct 2024 08:10:06 -0700 Subject: [PATCH 182/214] Bump io.jenkins.tools.incrementals:git-changelist-maven-extension (#56) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .mvn/extensions.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.mvn/extensions.xml b/.mvn/extensions.xml index a65d82e..4e0774d 100644 --- a/.mvn/extensions.xml +++ b/.mvn/extensions.xml @@ -2,6 +2,6 @@ io.jenkins.tools.incrementals git-changelist-maven-extension - 1.3 + 1.8 From 28efc14b18ca743d303086e4875e4118a64a7256 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 3 Oct 2024 08:10:25 -0700 Subject: [PATCH 183/214] Bump org.jenkins-ci.plugins:plugin from 4.86 to 4.88 (#53) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) mode change 100755 => 100644 pom.xml diff --git a/pom.xml b/pom.xml old mode 100755 new mode 100644 index d375007..88caaae --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ org.jenkins-ci.plugins plugin - 4.86 + 4.88 From 45bfd8bcef3ac3e2814d5f01d8a9cfadd0ff6661 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 3 Oct 2024 08:17:20 -0700 Subject: [PATCH 184/214] Bump org.jenkins-ci.plugins:s3 from 0.12.1 to 483.vcb_db_3dcee68f (#55) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 88caaae..db28662 100644 --- a/pom.xml +++ b/pom.xml @@ -93,7 +93,7 @@ org.jenkins-ci.plugins s3 - 0.12.1 + 483.vcb_db_3dcee68f true From aae8fca00dee44ca7dadcc050ada66a99b8c21e7 Mon Sep 17 00:00:00 2001 From: Basil Crow Date: Thu, 3 Oct 2024 08:21:05 -0700 Subject: [PATCH 185/214] Enable security scan (#60) --- .github/workflows/codeql-analysis.yml | 71 --------------------- .github/workflows/jenkins-security-scan.yml | 24 +++++++ 2 files changed, 24 insertions(+), 71 deletions(-) delete mode 100644 .github/workflows/codeql-analysis.yml create mode 100644 .github/workflows/jenkins-security-scan.yml diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml deleted file mode 100644 index 68b1d2d..0000000 --- a/.github/workflows/codeql-analysis.yml +++ /dev/null @@ -1,71 +0,0 @@ -# For most projects, this workflow file will not need changing; you simply need -# to commit it to your repository. -# -# You may wish to alter this file to override the set of languages analyzed, -# or to provide custom queries or build logic. -# -# ******** NOTE ******** -# We have attempted to detect the languages in your repository. Please check -# the `language` matrix defined below to confirm you have the correct set of -# supported CodeQL languages. -# -name: "CodeQL" - -on: - push: - branches: [ master ] - pull_request: - # The branches below must be a subset of the branches above - branches: [ master ] - schedule: - - cron: '31 8 * * 0' - -jobs: - analyze: - name: Analyze - runs-on: ubuntu-latest - permissions: - actions: read - contents: read - security-events: write - - strategy: - fail-fast: false - matrix: - language: [ 'java' ] - # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ] - # Learn more: - # https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed - - steps: - - name: Checkout repository - uses: actions/checkout@v4 - - # Initializes the CodeQL tools for scanning. - - name: Initialize CodeQL - uses: github/codeql-action/init@v1 - with: - languages: ${{ matrix.language }} - # If you wish to specify custom queries, you can do so here or in a config file. - # By default, queries listed here will override any specified in a config file. - # Prefix the list here with "+" to use these queries and those in the config file. - # queries: ./path/to/local/query, your-org/your-repo/queries@main - - # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). - # If this step fails, then you should remove it and run the build manually (see below) - - name: Autobuild - uses: github/codeql-action/autobuild@v1 - - # ℹ️ Command-line programs to run using the OS shell. - # 📚 https://git.io/JvXDl - - # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines - # and modify them (or add more) to build your code if your project - # uses a compiled language - - #- run: | - # make bootstrap - # make release - - - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v1 diff --git a/.github/workflows/jenkins-security-scan.yml b/.github/workflows/jenkins-security-scan.yml new file mode 100644 index 0000000..ecda979 --- /dev/null +++ b/.github/workflows/jenkins-security-scan.yml @@ -0,0 +1,24 @@ +# Jenkins Security Scan +# For more information, see: https://www.jenkins.io/doc/developer/security/scan/ +--- +name: Jenkins Security Scan + +on: + push: + branches: + - master + pull_request: + types: [opened, synchronize, reopened] + workflow_dispatch: + +permissions: + security-events: write + contents: read + actions: read + +jobs: + security-scan: + uses: jenkins-infra/jenkins-security-scan/.github/workflows/jenkins-security-scan.yaml@v2 + with: + java-cache: 'maven' # Optionally enable use of a build dependency cache. Specify 'maven' or 'gradle' as appropriate. + # java-version: 21 # Optionally specify what version of Java to set up for the build, or remove to use a recent default. From 4149e39774ed9cd15322627773a3052fdeaf2edd Mon Sep 17 00:00:00 2001 From: Basil Crow Date: Thu, 3 Oct 2024 08:21:18 -0700 Subject: [PATCH 186/214] Enable Release Drafter (#59) --- .github/release-drafter.yml | 3 +++ .github/workflows/release-drafter.yml | 16 ++++++++++++++++ 2 files changed, 19 insertions(+) create mode 100644 .github/release-drafter.yml create mode 100644 .github/workflows/release-drafter.yml diff --git a/.github/release-drafter.yml b/.github/release-drafter.yml new file mode 100644 index 0000000..d55671f --- /dev/null +++ b/.github/release-drafter.yml @@ -0,0 +1,3 @@ +# https://github.com/jenkinsci/.github/blob/master/.github/release-drafter.adoc +_extends: .github +tag-template: notification-$NEXT_MINOR_VERSION diff --git a/.github/workflows/release-drafter.yml b/.github/workflows/release-drafter.yml new file mode 100644 index 0000000..dca81a7 --- /dev/null +++ b/.github/workflows/release-drafter.yml @@ -0,0 +1,16 @@ +# Automates creation of Release Drafts using Release Drafter +# More Info: https://github.com/jenkinsci/.github/blob/master/.github/release-drafter.adoc + +on: + push: + branches: + - master + +jobs: + update_release_draft: + runs-on: ubuntu-latest + steps: + # Drafts your next Release notes as Pull Requests are merged into "master" + - uses: release-drafter/release-drafter@v6 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} From c24e02f82fb5564c894a201b250b3ae4a75ca8cd Mon Sep 17 00:00:00 2001 From: Basil Crow Date: Thu, 3 Oct 2024 08:21:29 -0700 Subject: [PATCH 187/214] Add `CODEOWNERS` (#58) --- .github/CODEOWNERS | 1 + .github/dependabot.yml | 24 ++++++++++++------------ 2 files changed, 13 insertions(+), 12 deletions(-) create mode 100644 .github/CODEOWNERS diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000..0cf0a89 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1 @@ +* @jenkinsci/notification-plugin-developers diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 391fbe5..980b0ae 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,14 +1,14 @@ +# https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file +--- version: 2 updates: -# Maintain dependencies for your plugin -- package-ecosystem: maven - directory: / - schedule: - interval: monthly - open-pull-requests-limit: 10 - target-branch: master -# Maintain dependencies for GitHub Actions -- package-ecosystem: github-actions - directory: / - schedule: - interval: monthly + # Maintain dependencies for your plugin + - package-ecosystem: "maven" + directory: "/" + schedule: + interval: "monthly" + # Maintain dependencies for GitHub Actions + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "monthly" From 1266bf67222638e8a5f6260978984945d54b9d24 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 3 Oct 2024 15:29:29 +0000 Subject: [PATCH 188/214] Bump io.jenkins.tools.bom:bom-2.462.x (#57) --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index db28662..4739be3 100644 --- a/pom.xml +++ b/pom.xml @@ -59,7 +59,7 @@ io.jenkins.tools.bom bom-2.462.x - 3258.vcdcf15936a_fd + 3413.v0d896b_76a_30d import pom From 96e7537e66f73f276d4d001fbc56006222a3a7b0 Mon Sep 17 00:00:00 2001 From: Basil Crow Date: Thu, 3 Oct 2024 09:18:59 -0700 Subject: [PATCH 189/214] Format repository with Spotless (#61) --- pom.xml | 334 ++++++------ .../hudson/plugins/notification/Endpoint.java | 55 +- .../hudson/plugins/notification/Format.java | 11 +- .../HudsonNotificationProperty.java | 82 ++- .../HudsonNotificationPropertyDescriptor.java | 52 +- .../plugins/notification/JobListener.java | 8 +- .../plugins/notification/NotifyStep.java | 200 ++++---- .../hudson/plugins/notification/Phase.java | 282 ++++++----- .../hudson/plugins/notification/Protocol.java | 108 ++-- .../hudson/plugins/notification/UrlInfo.java | 8 +- .../hudson/plugins/notification/Utils.java | 46 +- .../notification/model/BuildState.java | 117 ++--- .../plugins/notification/model/JobState.java | 120 ++--- .../plugins/notification/model/ScmState.java | 22 +- .../plugins/notification/model/TestState.java | 4 +- .../plugins/notification/PhaseTest.java | 479 ++++++++++-------- .../plugins/notification/ProtocolTest.java | 332 ++++++------ .../notification/test/HostnamePortTest.java | 4 +- 18 files changed, 1165 insertions(+), 1099 deletions(-) diff --git a/pom.xml b/pom.xml index 4739be3..02acc28 100644 --- a/pom.xml +++ b/pom.xml @@ -1,181 +1,177 @@ + 4.0.0 + + org.jenkins-ci.plugins + plugin + 4.88 + + - 4.0.0 + com.tikalk.hudson.plugins + notification + ${revision}${changelist} + hpi + Jenkins Notification plugin + Sends notifications about jobs phases and status + https://github.com/jenkinsci/${project.artifactId}-plugin - - org.jenkins-ci.plugins - plugin - 4.88 - - + + + The Apache Software License, Version 2.0 + http://www.apache.org/licenses/LICENSE-2.0.txt + repo + A business-friendly OSS license + + - com.tikalk.hudson.plugins - notification - ${revision}${changelist} - hpi - Jenkins Notification plugin - Sends notifications about jobs phases and status - https://github.com/jenkinsci/${project.artifactId}-plugin + + + markb + Mark Berner + markb@tikalk.com + Tikal Knowledge + http://tikalk.com + + + hagzag + Haggai Philip Zagury + hagzag@tikalk.com + Tikal Knowledge + http://tikalk.com + + + evgenyg + Evgeny Goldin + evgenyg@gmail.com + AKQA + http://akqa.com + + + cohencil + Chen Cohen + chenc@tikalk.com + http://tikalk.com + + - - 1.19 - -SNAPSHOT - 2.472 - jenkinsci/${project.artifactId}-plugin - - 2250.v03a_1295b_0a_30 - 17 - + + scm:git:https://github.com/${gitHubRepo}.git + scm:git:git@github.com:${gitHubRepo}.git + ${scmTag} + https://github.com/${gitHubRepo} + - - - repo.jenkins-ci.org - https://repo.jenkins-ci.org/public/ - - true - - - false - - - + + 1.19 + -SNAPSHOT + 2.472 + jenkinsci/${project.artifactId}-plugin + + 2250.v03a_1295b_0a_30 + 17 + false + - - - repo.jenkins-ci.org - https://repo.jenkins-ci.org/public/ - - true - - - false - - - + + + + io.jenkins.tools.bom + bom-2.462.x + 3413.v0d896b_76a_30d + pom + import + + + - - - - io.jenkins.tools.bom - bom-2.462.x - 3413.v0d896b_76a_30d - import - pom - - - + + + io.jenkins.plugins + gson-api + + + org.jenkins-ci.plugins + credentials + + + org.jenkins-ci.plugins + git + + + org.jenkins-ci.plugins + junit + true + + + org.jenkins-ci.plugins + plain-credentials + + + org.jenkins-ci.plugins + s3 + 483.vcb_db_3dcee68f + true + + + org.apache.commons + commons-lang3 + + + org.apache.httpcomponents + httpclient + + + org.apache.httpcomponents + httpcore + + + org.jenkins-ci + symbol-annotation + + + + + org.jenkins-ci.plugins + token-macro + true + + + net.sf.ezmorph + ezmorph + 1.0.6 + test + + + org.mockito + mockito-core + test + + - - - - io.jenkins.plugins - gson-api - - - org.jenkins-ci.plugins - git - - - org.jenkins-ci.plugins - credentials - - - org.jenkins-ci.plugins - junit - true - - - org.jenkins-ci.plugins - plain-credentials - - - - org.jenkins-ci.plugins - s3 - 483.vcb_db_3dcee68f - true - - - org.apache.httpcomponents - httpclient - - - org.apache.httpcomponents - httpcore - - - org.apache.commons - commons-lang3 - - - org.jenkins-ci - symbol-annotation - - - - - org.jenkins-ci.plugins - token-macro - true - - - net.sf.ezmorph - ezmorph - 1.0.6 - test - - - org.mockito - mockito-core - test - - + + + + true + + + false + + repo.jenkins-ci.org + https://repo.jenkins-ci.org/public/ + + - - - markb - Mark Berner - markb@tikalk.com - Tikal Knowledge - http://tikalk.com - - - hagzag - Haggai Philip Zagury - hagzag@tikalk.com - Tikal Knowledge - http://tikalk.com - - - evgenyg - Evgeny Goldin - evgenyg@gmail.com - AKQA - http://akqa.com - - - cohencil - Chen Cohen - chenc@tikalk.com - http://tikalk.com - - - - - scm:git:https://github.com/${gitHubRepo}.git - scm:git:git@github.com:${gitHubRepo}.git - ${scmTag} - https://github.com/${gitHubRepo} - - - - - The Apache Software License, Version 2.0 - http://www.apache.org/licenses/LICENSE-2.0.txt - repo - A business-friendly OSS license - - + + + + true + + + false + + repo.jenkins-ci.org + https://repo.jenkins-ci.org/public/ + + - diff --git a/src/main/java/com/tikal/hudson/plugins/notification/Endpoint.java b/src/main/java/com/tikal/hudson/plugins/notification/Endpoint.java index 2886dd2..03f6fd0 100644 --- a/src/main/java/com/tikal/hudson/plugins/notification/Endpoint.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/Endpoint.java @@ -11,7 +11,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.tikal.hudson.plugins.notification; import org.kohsuke.stapler.DataBoundConstructor; @@ -20,20 +19,20 @@ public class Endpoint { public static final Integer DEFAULT_TIMEOUT = 30000; - + public static final Integer DEFAULT_RETRIES = 0; public static final String DEFAULT_BRANCH = ".*"; private Protocol protocol = Protocol.HTTP; - + /** * json as default */ private Format format = Format.JSON; - + private UrlInfo urlInfo; - + // For backwards compatbility @Deprecated private transient String url; @@ -45,7 +44,7 @@ public class Endpoint { private Integer loglines = 0; private String buildNotes; - + private Integer retries = DEFAULT_RETRIES; private String branch = ".*"; @@ -61,23 +60,23 @@ public class Endpoint { */ @Deprecated public Endpoint(Protocol protocol, String url, String event, Format format, Integer timeout, Integer loglines) { - setProtocol( protocol ); - setUrlInfo( new UrlInfo(UrlType.PUBLIC, url) ); - setEvent( event ); - setFormat( format ); - setTimeout( timeout ); - setLoglines( loglines ); - } - + setProtocol(protocol); + setUrlInfo(new UrlInfo(UrlType.PUBLIC, url)); + setEvent(event); + setFormat(format); + setTimeout(timeout); + setLoglines(loglines); + } + /** * Adds a new endpoint for notifications * @param urlInfo Information about the target URL for the event. */ @DataBoundConstructor public Endpoint(UrlInfo urlInfo) { - setUrlInfo ( urlInfo ); + setUrlInfo(urlInfo); } - + public UrlInfo getUrlInfo() { if (this.urlInfo == null) { this.urlInfo = new UrlInfo(UrlType.PUBLIC, ""); @@ -99,7 +98,7 @@ public int getTimeout() { */ @DataBoundSetter public void setTimeout(Integer timeout) { - this.timeout = timeout; + this.timeout = timeout; } public Protocol getProtocol() { @@ -107,7 +106,7 @@ public Protocol getProtocol() { } /** - * Sets the protocol for the + * Sets the protocol for the * @param protocol Protocol to use. Valid values are: UDP, TCP, HTTP. Default is HTTP. * HTTP event target urls must start with 'http' */ @@ -116,7 +115,7 @@ public void setProtocol(Protocol protocol) { this.protocol = protocol; } - public String getEvent (){ + public String getEvent() { return event; } @@ -125,12 +124,12 @@ public String getEvent (){ * @param event 'STARTED' - Fire on job started. 'COMPLETED' - Fire on job completed. 'FINALIZED' - Fire on job finalized. */ @DataBoundSetter - public void setEvent ( String event ){ + public void setEvent(String event) { this.event = event; } - + public Format getFormat() { - if (this.format==null){ + if (this.format == null) { this.format = Format.JSON; } return format; @@ -174,11 +173,11 @@ public void setBuildNotes(String buildNotes) { public boolean isJson() { return getFormat() == Format.JSON; } - + public Integer getRetries() { return this.retries == null ? DEFAULT_RETRIES : this.retries; } - + /** * Number of retries before giving up on contacting an endpoint * @param retries - Number of retries. Default 0. @@ -187,11 +186,11 @@ public Integer getRetries() { public void setRetries(Integer retries) { this.retries = retries; } - + protected Object readResolve() { if (url != null) { - // Upgrade, this is a public URL - this.urlInfo = new UrlInfo(UrlType.PUBLIC, url); + // Upgrade, this is a public URL + this.urlInfo = new UrlInfo(UrlType.PUBLIC, url); } return this; } @@ -211,6 +210,6 @@ public void setBranch(final String branch) { @Override public String toString() { - return protocol+":"+urlInfo.getUrlOrId(); + return protocol + ":" + urlInfo.getUrlOrId(); } } diff --git a/src/main/java/com/tikal/hudson/plugins/notification/Format.java b/src/main/java/com/tikal/hudson/plugins/notification/Format.java index 702910b..e6e27cb 100644 --- a/src/main/java/com/tikal/hudson/plugins/notification/Format.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/Format.java @@ -18,25 +18,26 @@ import com.google.gson.GsonBuilder; import com.thoughtworks.xstream.XStream; import com.tikal.hudson.plugins.notification.model.JobState; - import java.io.IOException; public enum Format { XML { - private transient final XStream xstream = new XStream(); + private final transient XStream xstream = new XStream(); @Override protected byte[] serialize(JobState jobState) throws IOException { xstream.processAnnotations(JobState.class); - return xstream.toXML(jobState).getBytes( "UTF-8" ); + return xstream.toXML(jobState).getBytes("UTF-8"); } }, JSON { - private transient final Gson gson = new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES).create(); + private final transient Gson gson = new GsonBuilder() + .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES) + .create(); @Override protected byte[] serialize(JobState jobState) throws IOException { - return gson.toJson(jobState).getBytes( "UTF-8" ); + return gson.toJson(jobState).getBytes("UTF-8"); } }; diff --git a/src/main/java/com/tikal/hudson/plugins/notification/HudsonNotificationProperty.java b/src/main/java/com/tikal/hudson/plugins/notification/HudsonNotificationProperty.java index dc5595a..e6eb959 100755 --- a/src/main/java/com/tikal/hudson/plugins/notification/HudsonNotificationProperty.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/HudsonNotificationProperty.java @@ -1,42 +1,40 @@ -/** - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.tikal.hudson.plugins.notification; - -import hudson.model.Job; -import hudson.model.JobProperty; -import org.kohsuke.stapler.DataBoundConstructor; - -import java.util.ArrayList; -import java.util.List; - -public class HudsonNotificationProperty extends - JobProperty> { - - public final List endpoints; - - @DataBoundConstructor - public HudsonNotificationProperty(List endpoints) { - this.endpoints = new ArrayList( endpoints ); - } - - public List getEndpoints() { - return endpoints; - } - - @SuppressWarnings( "CastToConcreteClass" ) - @Override - public HudsonNotificationPropertyDescriptor getDescriptor() { - return (HudsonNotificationPropertyDescriptor) super.getDescriptor(); - } -} \ No newline at end of file +/** + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.tikal.hudson.plugins.notification; + +import hudson.model.Job; +import hudson.model.JobProperty; +import java.util.ArrayList; +import java.util.List; +import org.kohsuke.stapler.DataBoundConstructor; + +public class HudsonNotificationProperty extends JobProperty> { + + public final List endpoints; + + @DataBoundConstructor + public HudsonNotificationProperty(List endpoints) { + this.endpoints = new ArrayList(endpoints); + } + + public List getEndpoints() { + return endpoints; + } + + @SuppressWarnings("CastToConcreteClass") + @Override + public HudsonNotificationPropertyDescriptor getDescriptor() { + return (HudsonNotificationPropertyDescriptor) super.getDescriptor(); + } +} diff --git a/src/main/java/com/tikal/hudson/plugins/notification/HudsonNotificationPropertyDescriptor.java b/src/main/java/com/tikal/hudson/plugins/notification/HudsonNotificationPropertyDescriptor.java index 1b2bf3e..cc14de5 100644 --- a/src/main/java/com/tikal/hudson/plugins/notification/HudsonNotificationPropertyDescriptor.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/HudsonNotificationPropertyDescriptor.java @@ -27,6 +27,11 @@ import hudson.security.Permission; import hudson.util.FormValidation; import hudson.util.ListBoxModel; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Objects; +import javax.annotation.Nonnull; import jenkins.model.Jenkins; import net.sf.json.JSON; import net.sf.json.JSONArray; @@ -37,13 +42,6 @@ import org.kohsuke.stapler.QueryParameter; import org.kohsuke.stapler.StaplerRequest; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Objects; - -import javax.annotation.Nonnull; - @Extension public final class HudsonNotificationPropertyDescriptor extends JobPropertyDescriptor { @@ -77,15 +75,15 @@ public String getDisplayName() { return "Hudson Job Notification"; } - public String getDefaultBranch(){ + public String getDefaultBranch() { return Endpoint.DEFAULT_BRANCH; } - public int getDefaultTimeout(){ + public int getDefaultTimeout() { return Endpoint.DEFAULT_TIMEOUT; } - - public int getDefaultRetries(){ + + public int getDefaultRetries() { return Endpoint.DEFAULT_RETRIES; } @@ -109,18 +107,16 @@ public HudsonNotificationProperty newInstance(StaplerRequest req, JSONObject for return new HudsonNotificationProperty(endpoints); } - + private Endpoint convertJson(JSONObject endpointObjectData) throws FormException { // Transform the data to get the public/secret URL data JSONObject urlInfoData = endpointObjectData.getJSONObject("urlInfo"); UrlInfo urlInfo; if (urlInfoData.containsKey("publicUrl")) { urlInfo = new UrlInfo(UrlType.PUBLIC, urlInfoData.getString("publicUrl")); - } - else if (urlInfoData.containsKey("secretUrl")) { + } else if (urlInfoData.containsKey("secretUrl")) { urlInfo = new UrlInfo(UrlType.SECRET, urlInfoData.getString("secretUrl")); - } - else { + } else { throw new FormException("Expected either a public url or secret url id", "urlInfo"); } @@ -136,34 +132,35 @@ else if (urlInfoData.containsKey("secretUrl")) { return endpoint; } - + public FormValidation doCheckPublicUrl( @QueryParameter(value = "publicUrl", fixEmpty = true) String publicUrl, - @RelativePath ("..") @QueryParameter(value = "protocol") String protocolParameter) { + @RelativePath("..") @QueryParameter(value = "protocol") String protocolParameter) { Protocol protocol = Protocol.valueOf(protocolParameter); return checkUrl(publicUrl, UrlType.PUBLIC, protocol); } - + public FormValidation doCheckSecretUrl( @QueryParameter(value = "secretUrl", fixEmpty = true) String publicUrl, - @RelativePath ("..") @QueryParameter(value = "protocol") String protocolParameter) { + @RelativePath("..") @QueryParameter(value = "protocol") String protocolParameter) { Protocol protocol = Protocol.valueOf(protocolParameter); return checkUrl(publicUrl, UrlType.SECRET, protocol); } - + private FormValidation checkUrl(String urlOrId, UrlType urlType, Protocol protocol) { String actualUrl = urlOrId; if (urlType == UrlType.SECRET && !StringUtils.isEmpty(actualUrl)) { actualUrl = Jenkins.get().getItems(ItemGroup.class).stream() .map(ig -> Utils.getSecretUrl(urlOrId, ig)) .filter(Objects::nonNull) - .findFirst().orElse(null); + .findFirst() + .orElse(null); // Get the credentials if (actualUrl == null) { return FormValidation.error("Could not find secret text credentials with id " + urlOrId); } } - + try { protocol.validateUrl(actualUrl); return FormValidation.ok(); @@ -175,19 +172,18 @@ private FormValidation checkUrl(String urlOrId, UrlType urlType, Protocol protoc return FormValidation.error(message); } } - + public ListBoxModel doFillSecretUrlItems(@AncestorInPath Item owner, @QueryParameter String secretUrl) { if (owner == null || !owner.hasPermission(Permission.CONFIGURE)) { return new StandardListBoxModel(); } - + // when configuring the job, you only want those credentials that are available to ACL.SYSTEM selectable // as we cannot select from a user's credentials unless they are the only user submitting the build // (which we cannot assume) thus ACL.SYSTEM is correct here. AbstractIdCredentialsListBoxModel model = new StandardListBoxModel() .includeEmptyValue() - .withAll( - CredentialsProvider.lookupCredentials( + .withAll(CredentialsProvider.lookupCredentials( StringCredentials.class, owner, ACL.SYSTEM, Collections.emptyList())); if (!StringUtils.isEmpty(secretUrl)) { // Select current value, add if missing @@ -198,7 +194,7 @@ public ListBoxModel doFillSecretUrlItems(@AncestorInPath Item owner, @QueryParam } } } - + return model; } diff --git a/src/main/java/com/tikal/hudson/plugins/notification/JobListener.java b/src/main/java/com/tikal/hudson/plugins/notification/JobListener.java index c59cfb2..a2387f9 100755 --- a/src/main/java/com/tikal/hudson/plugins/notification/JobListener.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/JobListener.java @@ -14,9 +14,9 @@ package com.tikal.hudson.plugins.notification; import hudson.Extension; -import hudson.model.TaskListener; -import hudson.model.Run; import hudson.model.Executor; +import hudson.model.Run; +import hudson.model.TaskListener; import hudson.model.listeners.RunListener; @Extension @@ -30,7 +30,8 @@ public JobListener() { @Override public void onStarted(Run r, TaskListener listener) { Executor e = r.getExecutor(); - Phase.QUEUED.handle(r, TaskListener.NULL, e != null ? System.currentTimeMillis() - e.getTimeSpentInQueue() : 0L); + Phase.QUEUED.handle( + r, TaskListener.NULL, e != null ? System.currentTimeMillis() - e.getTimeSpentInQueue() : 0L); Phase.STARTED.handle(r, listener, r.getTimeInMillis()); } @@ -43,5 +44,4 @@ public void onCompleted(Run r, TaskListener listener) { public void onFinalized(Run r) { Phase.FINALIZED.handle(r, TaskListener.NULL, System.currentTimeMillis()); } - } diff --git a/src/main/java/com/tikal/hudson/plugins/notification/NotifyStep.java b/src/main/java/com/tikal/hudson/plugins/notification/NotifyStep.java index 7fde269..460e1c7 100644 --- a/src/main/java/com/tikal/hudson/plugins/notification/NotifyStep.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/NotifyStep.java @@ -5,6 +5,11 @@ import hudson.Util; import hudson.model.Run; import hudson.model.TaskListener; +import java.io.Serializable; +import java.util.Objects; +import java.util.Set; +import javax.annotation.CheckForNull; +import javax.annotation.Nonnull; import org.jenkinsci.plugins.workflow.graph.FlowNode; import org.jenkinsci.plugins.workflow.steps.Step; import org.jenkinsci.plugins.workflow.steps.StepContext; @@ -13,116 +18,115 @@ import org.kohsuke.stapler.DataBoundConstructor; import org.kohsuke.stapler.DataBoundSetter; -import java.io.Serializable; -import java.util.Objects; -import java.util.Set; +public class NotifyStep extends Step implements Serializable { + private static final long serialVersionUID = -2818860651754465006L; -import javax.annotation.CheckForNull; -import javax.annotation.Nonnull; + @CheckForNull + private String notes; -public class NotifyStep extends Step implements Serializable { - private static final long serialVersionUID = -2818860651754465006L; - - @CheckForNull - private String notes; - - @CheckForNull - public String getNotes() { - return notes; - } - - @DataBoundSetter - public void setNotes(@CheckForNull String notes) { - this.notes = Util.fixEmpty(notes); - } - - @CheckForNull - private String phase = Phase.STARTED.name(); - - @CheckForNull - public String getPhase() { - return phase; - } - - @DataBoundSetter - public void setPhase(@CheckForNull String phase) { - this.phase = Util.fixEmpty(phase); - } - - @CheckForNull - private String loglines = "0"; - - @CheckForNull - public String getLoglines() { - return loglines; - } - - @DataBoundSetter - public void setLoglines(@CheckForNull String loglines) { - this.loglines = Util.fixEmpty(loglines); - } - - /** - * Creates a new instance of {@link NotifyStep}. - */ - @DataBoundConstructor - public NotifyStep() { - super(); - - // empty constructor required for Stapler - } - - @Override - public StepExecution start(final StepContext context) { - return new Execution(context, this); - } - - /** - * Actually performs the execution of the associated step. - */ - static class Execution extends StepExecution { - private static final long serialVersionUID = -2840020502160375407L; - - private final NotifyStep notifyStep; - - Execution(@Nonnull final StepContext context, final NotifyStep step) { - super(context); - notifyStep = step; + @CheckForNull + public String getNotes() { + return notes; } - @Override - public boolean start() throws Exception { - String logLines = notifyStep.getLoglines(); + @DataBoundSetter + public void setNotes(@CheckForNull String notes) { + this.notes = Util.fixEmpty(notes); + } - Phase.NONE.handle(Objects.requireNonNull(getContext().get(Run.class)), getContext().get(TaskListener.class), System.currentTimeMillis(), true, - notifyStep.getNotes(), Integer.parseInt(logLines != null ? logLines : "0"), Phase.valueOf(notifyStep.getPhase())); + @CheckForNull + private String phase = Phase.STARTED.name(); - getContext().onSuccess(null); + @CheckForNull + public String getPhase() { + return phase; + } - return true; + @DataBoundSetter + public void setPhase(@CheckForNull String phase) { + this.phase = Util.fixEmpty(phase); } - } - - /** - * Descriptor for this step: defines the context and the UI labels. - */ - @Extension - @SuppressWarnings("unused") // most methods are used by the corresponding jelly view - public static class Descriptor extends StepDescriptor { - @Override - public String getFunctionName() { - return "notifyEndpoints"; + + @CheckForNull + private String loglines = "0"; + + @CheckForNull + public String getLoglines() { + return loglines; } - @Nonnull - @Override - public String getDisplayName() { - return Messages.Notify_DisplayName(); + @DataBoundSetter + public void setLoglines(@CheckForNull String loglines) { + this.loglines = Util.fixEmpty(loglines); + } + + /** + * Creates a new instance of {@link NotifyStep}. + */ + @DataBoundConstructor + public NotifyStep() { + super(); + + // empty constructor required for Stapler } @Override - public Set> getRequiredContext() { - return Set.of(FilePath.class, FlowNode.class, Run.class, TaskListener.class); + public StepExecution start(final StepContext context) { + return new Execution(context, this); + } + + /** + * Actually performs the execution of the associated step. + */ + static class Execution extends StepExecution { + private static final long serialVersionUID = -2840020502160375407L; + + private final NotifyStep notifyStep; + + Execution(@Nonnull final StepContext context, final NotifyStep step) { + super(context); + notifyStep = step; + } + + @Override + public boolean start() throws Exception { + String logLines = notifyStep.getLoglines(); + + Phase.NONE.handle( + Objects.requireNonNull(getContext().get(Run.class)), + getContext().get(TaskListener.class), + System.currentTimeMillis(), + true, + notifyStep.getNotes(), + Integer.parseInt(logLines != null ? logLines : "0"), + Phase.valueOf(notifyStep.getPhase())); + + getContext().onSuccess(null); + + return true; + } + } + + /** + * Descriptor for this step: defines the context and the UI labels. + */ + @Extension + @SuppressWarnings("unused") // most methods are used by the corresponding jelly view + public static class Descriptor extends StepDescriptor { + @Override + public String getFunctionName() { + return "notifyEndpoints"; + } + + @Nonnull + @Override + public String getDisplayName() { + return Messages.Notify_DisplayName(); + } + + @Override + public Set> getRequiredContext() { + return Set.of(FilePath.class, FlowNode.class, Run.class, TaskListener.class); + } } - } } diff --git a/src/main/java/com/tikal/hudson/plugins/notification/Phase.java b/src/main/java/com/tikal/hudson/plugins/notification/Phase.java index d7411e8..5649bb9 100755 --- a/src/main/java/com/tikal/hudson/plugins/notification/Phase.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/Phase.java @@ -17,7 +17,6 @@ import com.tikal.hudson.plugins.notification.model.JobState; import com.tikal.hudson.plugins.notification.model.ScmState; import com.tikal.hudson.plugins.notification.model.TestState; - import hudson.EnvVars; import hudson.FilePath; import hudson.model.AbstractBuild; @@ -34,11 +33,6 @@ import hudson.scm.ChangeLogSet; import hudson.tasks.test.AbstractTestResultAction; import hudson.tasks.test.TestResult; -import jenkins.model.Jenkins; -import org.apache.commons.lang.StringUtils; - -import org.jenkinsci.plugins.tokenmacro.TokenMacro; - import java.io.IOException; import java.io.PrintStream; import java.util.ArrayList; @@ -46,30 +40,38 @@ import java.util.Map; import java.util.Objects; import java.util.Set; +import jenkins.model.Jenkins; +import org.apache.commons.lang.StringUtils; +import org.jenkinsci.plugins.tokenmacro.TokenMacro; - -@SuppressWarnings({ "unchecked", "rawtypes" }) +@SuppressWarnings({"unchecked", "rawtypes"}) public enum Phase { - QUEUED, STARTED, COMPLETED, FINALIZED, NONE; + QUEUED, + STARTED, + COMPLETED, + FINALIZED, + NONE; - private Result findLastBuildThatFinished(Run run){ + private Result findLastBuildThatFinished(Run run) { Run previousRun = run.getPreviousCompletedBuild(); - while(previousRun != null){ - Result previousResults = previousRun.getResult(); - if (previousResults == null) { - throw new IllegalStateException("Previous result can't be null here"); - } - if (previousResults.equals(Result.SUCCESS) || previousResults.equals(Result.FAILURE) || previousResults.equals(Result.UNSTABLE)){ - return previousResults; - } - previousRun = previousRun.getPreviousCompletedBuild(); + while (previousRun != null) { + Result previousResults = previousRun.getResult(); + if (previousResults == null) { + throw new IllegalStateException("Previous result can't be null here"); + } + if (previousResults.equals(Result.SUCCESS) + || previousResults.equals(Result.FAILURE) + || previousResults.equals(Result.UNSTABLE)) { + return previousResults; + } + previousRun = previousRun.getPreviousCompletedBuild(); } return null; - } + } - @SuppressWarnings( "CastToConcreteClass" ) + @SuppressWarnings("CastToConcreteClass") public void handle(Run run, TaskListener listener, long timestamp) { - handle(run, listener, timestamp, false, null, 0, this); + handle(run, listener, timestamp, false, null, 0, this); } /** @@ -80,128 +82,133 @@ public void handle(Run run, TaskListener listener, long timestamp) { * @param logger PrintStream used for logging. * @return True if URL is populated with a non-blank value, or a variable that expands into a URL. */ - private boolean isURLValid(String urlInputValue, String expandedUrl, PrintStream logger){ - boolean isValid= false; - //If Jenkins variable was used for URL, and it was unresolvable, log warning and return. + private boolean isURLValid(String urlInputValue, String expandedUrl, PrintStream logger) { + boolean isValid = false; + // If Jenkins variable was used for URL, and it was unresolvable, log warning and return. if (expandedUrl.contains("$")) { logger.printf("Ignoring sending notification due to unresolved variable: %s%n", urlInputValue); - }else if(StringUtils.isBlank(expandedUrl)){ + } else if (StringUtils.isBlank(expandedUrl)) { logger.println("URL is not set, ignoring call to send notification."); - }else{ - isValid=true; + } else { + isValid = true; } return isValid; } - - /** * Determines if the endpoint specified should be notified at the current job phase. */ - private boolean isRun( Endpoint endpoint, Result result, Result previousRunResult ) { + private boolean isRun(Endpoint endpoint, Result result, Result previousRunResult) { String event = endpoint.getEvent(); - if(event == null) - return true; - - switch(event){ - case "all": - return true; - case "failed": - if (result == null) {return false;} - return this.equals(FINALIZED) && result.equals(Result.FAILURE); - case "failedAndFirstSuccess": - if (result == null || !this.equals(FINALIZED)) {return false;} - if (result.equals(Result.FAILURE)) {return true;} - return previousRunResult != null && result.equals(Result.SUCCESS) - && previousRunResult.equals(Result.FAILURE); + if (event == null) { + return true; + } + + switch (event) { + case "all": + return true; + case "failed": + if (result == null) { + return false; + } + return this.equals(FINALIZED) && result.equals(Result.FAILURE); + case "failedAndFirstSuccess": + if (result == null || !this.equals(FINALIZED)) { + return false; + } + if (result.equals(Result.FAILURE)) { + return true; + } + return previousRunResult != null + && result.equals(Result.SUCCESS) + && previousRunResult.equals(Result.FAILURE); case "manual": - return false; - default: - return event.equals(this.toString().toLowerCase()); + return false; + default: + return event.equals(this.toString().toLowerCase()); } } - private JobState buildJobState(Job job, Run run, TaskListener listener, long timestamp, Endpoint target, Phase phase) - throws IOException, InterruptedException - { - Jenkins jenkins = Jenkins.getInstanceOrNull(); + private JobState buildJobState( + Job job, Run run, TaskListener listener, long timestamp, Endpoint target, Phase phase) + throws IOException, InterruptedException { + Jenkins jenkins = Jenkins.getInstanceOrNull(); assert jenkins != null; - String rootUrl = jenkins.getRootUrl(); - JobState jobState = new JobState(); - BuildState buildState = new BuildState(); - ScmState scmState = new ScmState(); - Result result = run.getResult(); - ParametersAction paramsAction = run.getAction(ParametersAction.class); - EnvVars environment = run.getEnvironment( listener ); - StringBuilder log = this.getLog(run, target); + String rootUrl = jenkins.getRootUrl(); + JobState jobState = new JobState(); + BuildState buildState = new BuildState(); + ScmState scmState = new ScmState(); + Result result = run.getResult(); + ParametersAction paramsAction = run.getAction(ParametersAction.class); + EnvVars environment = run.getEnvironment(listener); + StringBuilder log = this.getLog(run, target); - jobState.setName( job.getName()); + jobState.setName(job.getName()); jobState.setDisplayName(job.getDisplayName()); - jobState.setUrl( job.getUrl()); - jobState.setBuild( buildState ); - - buildState.setNumber( run.number ); - buildState.setQueueId( run.getQueueId() ); - buildState.setUrl( run.getUrl()); - buildState.setPhase( phase ); - buildState.setTimestamp( timestamp ); - buildState.setDuration( run.getDuration() ); - buildState.setScm( scmState ); - buildState.setLog( log ); + jobState.setUrl(job.getUrl()); + jobState.setBuild(buildState); + + buildState.setNumber(run.number); + buildState.setQueueId(run.getQueueId()); + buildState.setUrl(run.getUrl()); + buildState.setPhase(phase); + buildState.setTimestamp(timestamp); + buildState.setDuration(run.getDuration()); + buildState.setScm(scmState); + buildState.setLog(log); buildState.setNotes(resolveMacros(run, listener, target.getBuildNotes())); buildState.setTestSummary(getTestResults(run)); - if ( result != null ) { + if (result != null) { buildState.setStatus(result.toString()); } - if ( rootUrl != null ) { + if (rootUrl != null) { buildState.setFullUrl(rootUrl + run.getUrl()); } - buildState.updateArtifacts( job, run ); + buildState.updateArtifacts(job, run); - //TODO: Make this optional to reduce chat overload. - if ( paramsAction != null ) { + // TODO: Make this optional to reduce chat overload. + if (paramsAction != null) { EnvVars env = new EnvVars(); - for (ParameterValue value : paramsAction.getParameters()){ - if ( ! value.isSensitive()) { - value.buildEnvironment( run, env ); + for (ParameterValue value : paramsAction.getParameters()) { + if (!value.isSensitive()) { + value.buildEnvironment(run, env); } } buildState.setParameters(env); } - + BuildData build = job.getAction(BuildData.class); - if ( build != null ) { - if ( !build.remoteUrls.isEmpty() ) { + if (build != null) { + if (!build.remoteUrls.isEmpty()) { String url = build.remoteUrls.iterator().next(); - if ( url != null ) { - scmState.setUrl( url ); + if (url != null) { + scmState.setUrl(url); } } for (Map.Entry entry : build.buildsByBranchName.entrySet()) { - if ( entry.getValue().hudsonBuildNumber == run.number ) { - scmState.setBranch( entry.getKey() ); - scmState.setCommit( entry.getValue().revision.getSha1String() ); + if (entry.getValue().hudsonBuildNumber == run.number) { + scmState.setBranch(entry.getKey()); + scmState.setCommit(entry.getValue().revision.getSha1String()); } } } - - if ( environment.get( "GIT_URL" ) != null ) { - scmState.setUrl( environment.get( "GIT_URL" )); + + if (environment.get("GIT_URL") != null) { + scmState.setUrl(environment.get("GIT_URL")); } - - if ( environment.get( "GIT_BRANCH" ) != null ) { - scmState.setBranch( environment.get( "GIT_BRANCH" )); + if (environment.get("GIT_BRANCH") != null) { + scmState.setBranch(environment.get("GIT_BRANCH")); } - if ( environment.get( "GIT_COMMIT" ) != null ) { - scmState.setCommit( environment.get( "GIT_COMMIT" )); + if (environment.get("GIT_COMMIT") != null) { + scmState.setCommit(environment.get("GIT_COMMIT")); } scmState.setChanges(getChangedFiles(run)); @@ -215,9 +222,9 @@ private String resolveMacros(Run build, TaskListener listener, String text) { String result = text; try { Executor executor = build.getExecutor(); - if(executor != null) { + if (executor != null) { FilePath workspace = executor.getCurrentWorkspace(); - if(workspace != null) { + if (workspace != null) { result = TokenMacro.expandAll(build, workspace, listener, text); } } @@ -234,7 +241,7 @@ private TestState getTestResults(Run build) { TestState resultSummary = null; AbstractTestResultAction testAction = build.getAction(AbstractTestResultAction.class); - if(testAction != null) { + if (testAction != null) { int total = testAction.getTotalCount(); int failCount = testAction.getFailCount(); int skipCount = testAction.getSkipCount(); @@ -247,7 +254,6 @@ private TestState getTestResults(Run build) { resultSummary.setFailedTests(getFailedTestNames(testAction)); } - return resultSummary; } @@ -256,7 +262,7 @@ private List getFailedTestNames(AbstractTestResultAction testResultActio List results = testResultAction.getFailedTests(); - for(TestResult t : results) { + for (TestResult t : results) { failedTests.add(t.getFullName()); } @@ -266,14 +272,14 @@ private List getFailedTestNames(AbstractTestResultAction testResultActio private List getChangedFiles(Run run) { List affectedPaths = new ArrayList<>(); - if(run instanceof AbstractBuild) { + if (run instanceof AbstractBuild) { AbstractBuild build = (AbstractBuild) run; Object[] items = build.getChangeSet().getItems(); - if(items != null && items.length > 0) { - for(Object o : items) { - if(o instanceof ChangeLogSet.Entry) { + if (items != null && items.length > 0) { + for (Object o : items) { + if (o instanceof ChangeLogSet.Entry) { affectedPaths.addAll(((ChangeLogSet.Entry) o).getAffectedPaths()); } } @@ -286,10 +292,10 @@ private List getChangedFiles(Run run) { private List getCulprits(Run run) { List culprits = new ArrayList<>(); - if(run instanceof AbstractBuild) { + if (run instanceof AbstractBuild) { AbstractBuild build = (AbstractBuild) run; Set buildCulprits = build.getCulprits(); - for(User user : buildCulprits) { + for (User user : buildCulprits) { culprits.add(user.getId()); } } @@ -322,25 +328,34 @@ private StringBuilder getLog(Run run, Endpoint target) { return log; } - public void handle(Run run, TaskListener listener, long timestamp, boolean manual, final String buildNotes, final Integer logLines, Phase phase) { + public void handle( + Run run, + TaskListener listener, + long timestamp, + boolean manual, + final String buildNotes, + final Integer logLines, + Phase phase) { final Job job = run.getParent(); - final HudsonNotificationProperty property = (HudsonNotificationProperty) job.getProperty(HudsonNotificationProperty.class); - if ( property == null ) { + final HudsonNotificationProperty property = + (HudsonNotificationProperty) job.getProperty(HudsonNotificationProperty.class); + if (property == null) { return; } Result previousCompletedRunResults = findLastBuildThatFinished(run); - for ( Endpoint target : property.getEndpoints()) { - if ((!manual && !isRun(target, run.getResult(), previousCompletedRunResults)) || Utils.isEmpty(target.getUrlInfo().getUrlOrId())) { + for (Endpoint target : property.getEndpoints()) { + if ((!manual && !isRun(target, run.getResult(), previousCompletedRunResults)) + || Utils.isEmpty(target.getUrlInfo().getUrlOrId())) { continue; } - if(Objects.nonNull(buildNotes)) { + if (Objects.nonNull(buildNotes)) { target.setBuildNotes(buildNotes); } - if(Objects.nonNull(logLines) && logLines != 0) { + if (Objects.nonNull(logLines) && logLines != 0) { target.setLoglines(logLines); } @@ -375,32 +390,43 @@ public void handle(Run run, TaskListener listener, long timestamp, boolean manua } final String branch = target.getBranch(); - if (!manual && environment.containsKey("BRANCH_NAME") && !environment.get("BRANCH_NAME").matches(branch)) { - listener.getLogger().printf("Environment variable %s with value %s does not match configured branch filter %s%n", "BRANCH_NAME", environment.get("BRANCH_NAME"), branch); + if (!manual + && environment.containsKey("BRANCH_NAME") + && !environment.get("BRANCH_NAME").matches(branch)) { + listener.getLogger() + .printf( + "Environment variable %s with value %s does not match configured branch filter %s%n", + "BRANCH_NAME", environment.get("BRANCH_NAME"), branch); continue; - }else if(!manual && !environment.containsKey("BRANCH_NAME") && !".*".equals(branch)){ + } else if (!manual && !environment.containsKey("BRANCH_NAME") && !".*".equals(branch)) { listener.getLogger().printf("Environment does not contain %s variable%n", "BRANCH_NAME"); continue; } listener.getLogger().printf("Notifying endpoint with %s%n", urlIdString); JobState jobState = buildJobState(job, run, listener, timestamp, target, phase); - target.getProtocol().send(expandedUrl, - target.getFormat().serialize(jobState), - target.getTimeout(), - target.isJson()); + target.getProtocol() + .send( + expandedUrl, + target.getFormat().serialize(jobState), + target.getTimeout(), + target.isJson()); } catch (Throwable error) { failed = true; - error.printStackTrace( listener.error( String.format( "Failed to notify endpoint with %s", urlIdString))); - listener.getLogger().printf("Failed to notify endpoint with %s - %s: %s%n", - urlIdString, error.getClass().getName(), error.getMessage()); + error.printStackTrace( + listener.error(String.format("Failed to notify endpoint with %s", urlIdString))); + listener.getLogger() + .printf( + "Failed to notify endpoint with %s - %s: %s%n", + urlIdString, error.getClass().getName(), error.getMessage()); if (triesRemaining > 0) { - listener.getLogger().printf( - "Reattempting to notify endpoint with %s (%d tries remaining)%n", urlIdString, triesRemaining); + listener.getLogger() + .printf( + "Reattempting to notify endpoint with %s (%d tries remaining)%n", + urlIdString, triesRemaining); } } - } - while (failed && --triesRemaining >= 0); + } while (failed && --triesRemaining >= 0); } } } diff --git a/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java b/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java index dbda148..8f2e3b5 100755 --- a/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java @@ -13,23 +13,30 @@ */ package com.tikal.hudson.plugins.notification; - -import jenkins.model.Jenkins; - import java.io.IOException; import java.io.OutputStream; -import java.net.*; +import java.net.DatagramPacket; +import java.net.DatagramSocket; +import java.net.HttpURLConnection; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.MalformedURLException; +import java.net.Proxy; +import java.net.Socket; +import java.net.SocketAddress; +import java.net.URL; import java.nio.charset.Charset; import java.util.Base64; +import jenkins.model.Jenkins; public enum Protocol { - UDP { @Override protected void send(String url, byte[] data, int timeout, boolean isJson) throws IOException { HostnamePort hostnamePort = HostnamePort.parseUrl(url); DatagramSocket socket = new DatagramSocket(); - DatagramPacket packet = new DatagramPacket(data, data.length, InetAddress.getByName(hostnamePort.hostname), hostnamePort.port); + DatagramPacket packet = new DatagramPacket( + data, data.length, InetAddress.getByName(hostnamePort.hostname), hostnamePort.port); socket.send(packet); } }, @@ -37,7 +44,8 @@ protected void send(String url, byte[] data, int timeout, boolean isJson) throws @Override protected void send(String url, byte[] data, int timeout, boolean isJson) throws IOException { HostnamePort hostnamePort = HostnamePort.parseUrl(url); - SocketAddress endpoint = new InetSocketAddress(InetAddress.getByName(hostnamePort.hostname), hostnamePort.port); + SocketAddress endpoint = + new InetSocketAddress(InetAddress.getByName(hostnamePort.hostname), hostnamePort.port); Socket socket = new Socket(); socket.setSoTimeout(timeout); socket.connect(endpoint, timeout); @@ -53,35 +61,38 @@ protected void send(String url, byte[] data, int timeout, boolean isJson) throws URL targetUrl = new URL(url); if (!targetUrl.getProtocol().startsWith("http")) { - throw new IllegalArgumentException("Not an http(s) url: " + url); + throw new IllegalArgumentException("Not an http(s) url: " + url); } // Verifying if the HTTP_PROXY is available final String httpProxyUrl = System.getenv().get("http_proxy"); URL proxyUrl = null; if (httpProxyUrl != null && httpProxyUrl.length() > 0) { - proxyUrl = new URL(httpProxyUrl); - if (!proxyUrl.getProtocol().startsWith("http")) { - throw new IllegalArgumentException("Not an http(s) url: " + httpProxyUrl); - } + proxyUrl = new URL(httpProxyUrl); + if (!proxyUrl.getProtocol().startsWith("http")) { + throw new IllegalArgumentException("Not an http(s) url: " + httpProxyUrl); + } } Proxy proxy = Proxy.NO_PROXY; if (Jenkins.getInstance() != null && Jenkins.getInstance().proxy != null) { - proxy = Jenkins.getInstance().proxy.createProxy(targetUrl.getHost()); + proxy = Jenkins.getInstance().proxy.createProxy(targetUrl.getHost()); } else if (proxyUrl != null) { - // Proxy connection to the address provided - final int proxyPort = proxyUrl.getPort() > 0 ? proxyUrl.getPort() : 80; - proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyUrl.getHost(), proxyPort)); + // Proxy connection to the address provided + final int proxyPort = proxyUrl.getPort() > 0 ? proxyUrl.getPort() : 80; + proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyUrl.getHost(), proxyPort)); } HttpURLConnection connection = (HttpURLConnection) targetUrl.openConnection(proxy); - connection.setRequestProperty("Content-Type", String.format( "application/%s;charset=UTF-8", isJson ? "json" : "xml" )); + connection.setRequestProperty( + "Content-Type", String.format("application/%s;charset=UTF-8", isJson ? "json" : "xml")); String userInfo = targetUrl.getUserInfo(); if (null != userInfo) { - String b64UserInfo = Base64.getEncoder().encodeToString(userInfo.getBytes(Charset.defaultCharset())); // TODO see if UTF-8 can be used instead of platform default encoding - String authorizationHeader = "Basic " + b64UserInfo; - connection.setRequestProperty("Authorization", authorizationHeader); + // TODO see if UTF-8 can be used instead of platform default encoding + String b64UserInfo = Base64.getEncoder().encodeToString(userInfo.getBytes(Charset.defaultCharset())); + + String authorizationHeader = "Basic " + b64UserInfo; + connection.setRequestProperty("Authorization", authorizationHeader); } connection.setFixedLengthStreamingMode(data.length); connection.setDoInput(true); @@ -90,45 +101,46 @@ protected void send(String url, byte[] data, int timeout, boolean isJson) throws connection.setReadTimeout(timeout); connection.connect(); try { - OutputStream output = connection.getOutputStream(); - try { - output.write(data); - output.flush(); - } finally { - output.close(); - } + OutputStream output = connection.getOutputStream(); + try { + output.write(data); + output.flush(); + } finally { + output.close(); + } } finally { - // Follow an HTTP Temporary Redirect if we get one, - // - // NB: Normally using the HttpURLConnection interface, we'd call - // connection.setInstanceFollowRedirects(true) to enable 307 redirect following but - // since we have the connection in streaming mode this does not work and we instead - // re-direct manually. - if (307 == connection.getResponseCode()) { - String location = connection.getHeaderField("Location"); - connection.disconnect(); - send(location, data,timeout, isJson); - } else { - connection.disconnect(); - } + // Follow an HTTP Temporary Redirect if we get one, + // + // NB: Normally using the HttpURLConnection interface, we'd call + // connection.setInstanceFollowRedirects(true) to enable 307 redirect following but + // since we have the connection in streaming mode this does not work and we instead + // re-direct manually. + if (307 == connection.getResponseCode()) { + String location = connection.getHeaderField("Location"); + connection.disconnect(); + send(location, data, timeout, isJson); + } else { + connection.disconnect(); + } } } @Override - public void validateUrl( String url ) { - //do not validate if Jenkins Variable is used. + public void validateUrl(String url) { + // do not validate if Jenkins Variable is used. if (!url.contains("$")) { try { // noinspection ResultOfObjectAllocationIgnored new URL(url); } catch (MalformedURLException e) { - throw new RuntimeException(String.format("%sUse http://hostname:port/path for endpoint URL", isEmpty(url) ? "" : "Invalid URL '" + url + "'. ")); + throw new RuntimeException(String.format( + "%sUse http://hostname:port/path for endpoint URL", + isEmpty(url) ? "" : "Invalid URL '" + url + "'. ")); } } } }; - protected abstract void send(String url, byte[] data, int timeout, boolean isJson) throws IOException; public void validateUrl(String url) { @@ -138,12 +150,12 @@ public void validateUrl(String url) { throw new Exception(); } } catch (Exception e) { - throw new RuntimeException( String.format( "%sUse hostname:port for endpoint URL", - isEmpty ( url ) ? "" : "Invalid URL '" + url + "'. " )); + throw new RuntimeException(String.format( + "%sUse hostname:port for endpoint URL", isEmpty(url) ? "" : "Invalid URL '" + url + "'. ")); } } - private static boolean isEmpty( String s ) { - return (( s == null ) || ( s.trim().length() < 1 )); + private static boolean isEmpty(String s) { + return ((s == null) || (s.trim().length() < 1)); } } diff --git a/src/main/java/com/tikal/hudson/plugins/notification/UrlInfo.java b/src/main/java/com/tikal/hudson/plugins/notification/UrlInfo.java index b5b7416..e9d98c1 100644 --- a/src/main/java/com/tikal/hudson/plugins/notification/UrlInfo.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/UrlInfo.java @@ -22,14 +22,14 @@ * @author mmitche */ public class UrlInfo { - + private String urlOrId; private UrlType urlType; - + @DataBoundConstructor public UrlInfo(UrlType urlType, String urlOrId) { - setUrlOrId ( urlOrId ); - setUrlType ( urlType ); + setUrlOrId(urlOrId); + setUrlType(urlType); } public String getUrlOrId() { diff --git a/src/main/java/com/tikal/hudson/plugins/notification/Utils.java b/src/main/java/com/tikal/hudson/plugins/notification/Utils.java index 8a203a6..afad471 100644 --- a/src/main/java/com/tikal/hudson/plugins/notification/Utils.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/Utils.java @@ -2,44 +2,32 @@ import com.cloudbees.plugins.credentials.CredentialsMatchers; import com.cloudbees.plugins.credentials.CredentialsProvider; -import com.cloudbees.plugins.credentials.domains.DomainRequirement; import hudson.model.ItemGroup; import hudson.security.ACL; -import hudson.util.FormValidation; import hudson.util.Secret; import java.util.Arrays; import java.util.Collections; -import java.util.List; - -import jenkins.model.Jenkins; import org.jenkinsci.plugins.plaincredentials.StringCredentials; - /** * Helper utilities */ -public final class Utils -{ - private Utils () - { - } +public final class Utils { + private Utils() {} /** * Determines if any of Strings specified is either null or empty. * @param strings - Strings to check for empty (whitespace is trimmed) or null. * @return True if any string is empty */ - @SuppressWarnings( "MethodWithMultipleReturnPoints" ) - public static boolean isEmpty( String ... strings ) - { - if (( strings == null ) || ( strings.length < 1 )) { + @SuppressWarnings("MethodWithMultipleReturnPoints") + public static boolean isEmpty(String... strings) { + if ((strings == null) || (strings.length < 1)) { return true; } - for ( String s : strings ) - { - if (( s == null ) || ( s.trim().length() < 1 )) - { + for (String s : strings) { + if ((s == null) || (s.trim().length() < 1)) { return true; } } @@ -47,19 +35,16 @@ public static boolean isEmpty( String ... strings ) return false; } - /** * Verifies neither of Strings specified is null or empty. * @param strings Strings to check for empty (whitespace is trimmed) or null. * @throws java.lang.IllegalArgumentException Throws this exception if any string is empty. */ - @SuppressWarnings( "ReturnOfNull" ) - public static void verifyNotEmpty( String ... strings ) - { - if ( isEmpty( strings )) - { - throw new IllegalArgumentException( String.format( - "Some String arguments are null or empty: %s", Arrays.toString( strings ))); + @SuppressWarnings("ReturnOfNull") + public static void verifyNotEmpty(String... strings) { + if (isEmpty(strings)) { + throw new IllegalArgumentException( + String.format("Some String arguments are null or empty: %s", Arrays.toString(strings))); } } @@ -71,8 +56,9 @@ public static void verifyNotEmpty( String ... strings ) */ public static String getSecretUrl(String credentialId, ItemGroup itemGroup) { // Grab the secret text - StringCredentials creds = CredentialsMatchers.firstOrNull(CredentialsProvider.lookupCredentials( - StringCredentials.class, itemGroup, ACL.SYSTEM, Collections.emptyList()), + StringCredentials creds = CredentialsMatchers.firstOrNull( + CredentialsProvider.lookupCredentials( + StringCredentials.class, itemGroup, ACL.SYSTEM, Collections.emptyList()), CredentialsMatchers.withId(credentialId)); if (creds == null) { return null; @@ -80,6 +66,4 @@ public static String getSecretUrl(String credentialId, ItemGroup itemGroup) { Secret secretUrl = creds.getSecret(); return secretUrl.getPlainText(); } - - } diff --git a/src/main/java/com/tikal/hudson/plugins/notification/model/BuildState.java b/src/main/java/com/tikal/hudson/plugins/notification/model/BuildState.java index 5cd7b42..546694f 100755 --- a/src/main/java/com/tikal/hudson/plugins/notification/model/BuildState.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/model/BuildState.java @@ -13,7 +13,9 @@ */ package com.tikal.hudson.plugins.notification.model; -import static com.tikal.hudson.plugins.notification.Utils.*; +import static com.tikal.hudson.plugins.notification.Utils.isEmpty; +import static com.tikal.hudson.plugins.notification.Utils.verifyNotEmpty; + import com.tikal.hudson.plugins.notification.Phase; import hudson.model.AbstractBuild; import hudson.model.Job; @@ -21,12 +23,11 @@ import hudson.plugins.s3.Entry; import hudson.plugins.s3.S3BucketPublisher; import hudson.util.DescribableList; -import jenkins.model.Jenkins; - import java.io.File; import java.util.HashMap; import java.util.List; import java.util.Map; +import jenkins.model.Jenkins; public class BuildState { @@ -58,9 +59,6 @@ public class BuildState { private TestState testSummary; - - - /** * Map of artifacts: file name => Map of artifact locations ( location name => artifact URL ) * --- @@ -142,10 +140,10 @@ public Map getParameters() { } public void setParameters(Map params) { - this.parameters = new HashMap( params ); + this.parameters = new HashMap(params); } - public Map> getArtifacts () { + public Map> getArtifacts() { return artifacts; } @@ -157,13 +155,11 @@ public String getDisplayName() { return displayName; } - public ScmState getScm () - { + public ScmState getScm() { return scm; } - public void setScm ( ScmState scmState ) - { + public void setScm(ScmState scmState) { this.scm = scmState; } @@ -196,58 +192,66 @@ public void setTestSummary(TestState testSummary) { * @param job Job to update * @param run Run to update */ - public void updateArtifacts ( Job job, Run run ) - { - updateArchivedArtifacts( run ); - updateS3Artifacts( job, run ); + public void updateArtifacts(Job job, Run run) { + updateArchivedArtifacts(run); + updateS3Artifacts(job, run); } - - private void updateArchivedArtifacts ( Run run ) - { - @SuppressWarnings( "unchecked" ) + private void updateArchivedArtifacts(Run run) { + @SuppressWarnings("unchecked") List buildArtifacts = run.getArtifacts(); - for ( Run.Artifact a : buildArtifacts ) { + for (Run.Artifact a : buildArtifacts) { String artifactUrl = Jenkins.getInstance().getRootUrl() + run.getUrl() + "artifact/" + a.getHref(); - updateArtifact( a.relativePath, "archive", artifactUrl ); + updateArtifact(a.relativePath, "archive", artifactUrl); } } + private void updateS3Artifacts(Job job, Run run) { + if (Jenkins.getInstance().getPlugin("s3") == null) { + return; + } + if (!(run instanceof AbstractBuild)) { + return; + } + if (isEmpty(job.getName())) { + return; + } - private void updateS3Artifacts ( Job job, Run run ) - { - if ( Jenkins.getInstance().getPlugin( "s3" ) == null ) { return; } - if ( ! ( run instanceof AbstractBuild )){ return; } - if ( isEmpty( job.getName())){ return; } - - DescribableList publishers = (( AbstractBuild ) run ).getProject().getPublishersList(); - S3BucketPublisher s3Publisher = ( S3BucketPublisher ) publishers.get( S3BucketPublisher.class ); + DescribableList publishers = ((AbstractBuild) run).getProject().getPublishersList(); + S3BucketPublisher s3Publisher = (S3BucketPublisher) publishers.get(S3BucketPublisher.class); - if ( s3Publisher == null ){ return; } + if (s3Publisher == null) { + return; + } - for ( Entry entry : s3Publisher.getEntries()) { + for (Entry entry : s3Publisher.getEntries()) { - if ( isEmpty( entry.sourceFile, entry.selectedRegion, entry.bucket )){ continue; } - String fileName = new File( entry.sourceFile ).getName(); - if ( isEmpty( fileName )){ continue; } + if (isEmpty(entry.sourceFile, entry.selectedRegion, entry.bucket)) { + continue; + } + String fileName = new File(entry.sourceFile).getName(); + if (isEmpty(fileName)) { + continue; + } // https://s3-eu-west-1.amazonaws.com/evgenyg-temp/ - String bucketUrl = String.format( "https://s3-%s.amazonaws.com/%s", - entry.selectedRegion.toLowerCase().replace( '_', '-' ), - entry.bucket ); - - String fileUrl = entry.managedArtifacts ? - // https://s3-eu-west-1.amazonaws.com/evgenyg-temp/jobs/notification-plugin/21/notification.hpi - String.format( "%s/jobs/%s/%s/%s", bucketUrl, job.getName(), run.getNumber(), fileName ) : - // https://s3-eu-west-1.amazonaws.com/evgenyg-temp/notification.hpi - String.format( "%s/%s", bucketUrl, fileName ); - - updateArtifact( fileName, "s3", fileUrl ); + String bucketUrl = String.format( + "https://s3-%s.amazonaws.com/%s", + entry.selectedRegion.toLowerCase().replace('_', '-'), entry.bucket); + + String fileUrl = entry.managedArtifacts + ? + // https://s3-eu-west-1.amazonaws.com/evgenyg-temp/jobs/notification-plugin/21/notification.hpi + String.format("%s/jobs/%s/%s/%s", bucketUrl, job.getName(), run.getNumber(), fileName) + : + // https://s3-eu-west-1.amazonaws.com/evgenyg-temp/notification.hpi + String.format("%s/%s", bucketUrl, fileName); + + updateArtifact(fileName, "s3", fileUrl); } } - /** * Updates an artifact URL. * @@ -255,20 +259,19 @@ private void updateS3Artifacts ( Job job, Run run ) * @param locationName artifact location name, like "s3" or "archive" * @param locationUrl artifact URL at the location specified */ - private void updateArtifact( String fileName, String locationName, String locationUrl ) - { - verifyNotEmpty( fileName, locationName, locationUrl ); + private void updateArtifact(String fileName, String locationName, String locationUrl) { + verifyNotEmpty(fileName, locationName, locationUrl); - if ( ! artifacts.containsKey( fileName )) { - artifacts.put( fileName, new HashMap()); + if (!artifacts.containsKey(fileName)) { + artifacts.put(fileName, new HashMap()); } - if ( artifacts.get( fileName ).containsKey( locationName )) { - throw new RuntimeException( String.format( - "Adding artifacts mapping '%s/%s/%s' - artifacts Map already contains mapping of location '%s': %s", - fileName, locationName, locationUrl, locationName, artifacts )); + if (artifacts.get(fileName).containsKey(locationName)) { + throw new RuntimeException(String.format( + "Adding artifacts mapping '%s/%s/%s' - artifacts Map already contains mapping of location '%s': %s", + fileName, locationName, locationUrl, locationName, artifacts)); } - artifacts.get( fileName ).put( locationName, locationUrl ); + artifacts.get(fileName).put(locationName, locationUrl); } } diff --git a/src/main/java/com/tikal/hudson/plugins/notification/model/JobState.java b/src/main/java/com/tikal/hudson/plugins/notification/model/JobState.java index a8bd06c..0a2d3c5 100755 --- a/src/main/java/com/tikal/hudson/plugins/notification/model/JobState.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/model/JobState.java @@ -1,60 +1,60 @@ -/** - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.tikal.hudson.plugins.notification.model; - -import com.thoughtworks.xstream.annotations.XStreamAlias; - -@XStreamAlias("job") -public class JobState { - - private String name; - - private String displayName; - - private String url; - - private BuildState build; - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getDisplayName() { - return displayName; - } - - public void setDisplayName(String displayName) { - this.displayName = displayName; - } - - public String getUrl() { - return url; - } - - public void setUrl(String url) { - this.url = url; - } - - public BuildState getBuild() { - return build; - } - - public void setBuild(BuildState build) { - this.build = build; - } -} +/** + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.tikal.hudson.plugins.notification.model; + +import com.thoughtworks.xstream.annotations.XStreamAlias; + +@XStreamAlias("job") +public class JobState { + + private String name; + + private String displayName; + + private String url; + + private BuildState build; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getDisplayName() { + return displayName; + } + + public void setDisplayName(String displayName) { + this.displayName = displayName; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public BuildState getBuild() { + return build; + } + + public void setBuild(BuildState build) { + this.build = build; + } +} diff --git a/src/main/java/com/tikal/hudson/plugins/notification/model/ScmState.java b/src/main/java/com/tikal/hudson/plugins/notification/model/ScmState.java index ac392cf..ecaa20a 100644 --- a/src/main/java/com/tikal/hudson/plugins/notification/model/ScmState.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/model/ScmState.java @@ -13,11 +13,9 @@ */ package com.tikal.hudson.plugins.notification.model; - import java.util.List; -public class ScmState -{ +public class ScmState { private String url; private String branch; @@ -28,33 +26,27 @@ public class ScmState private List culprits; - public String getUrl () - { + public String getUrl() { return url; } - public void setUrl ( String url ) - { + public void setUrl(String url) { this.url = url; } - public String getBranch () - { + public String getBranch() { return branch; } - public void setBranch ( String branch ) - { + public void setBranch(String branch) { this.branch = branch; } - public String getCommit () - { + public String getCommit() { return commit; } - public void setCommit ( String commit ) - { + public void setCommit(String commit) { this.commit = commit; } diff --git a/src/main/java/com/tikal/hudson/plugins/notification/model/TestState.java b/src/main/java/com/tikal/hudson/plugins/notification/model/TestState.java index c11eeff..c4854c9 100644 --- a/src/main/java/com/tikal/hudson/plugins/notification/model/TestState.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/model/TestState.java @@ -13,11 +13,9 @@ */ package com.tikal.hudson.plugins.notification.model; - import java.util.List; -public class TestState -{ +public class TestState { private int total; private int failed; private int passed; diff --git a/src/test/java/com/tikal/hudson/plugins/notification/PhaseTest.java b/src/test/java/com/tikal/hudson/plugins/notification/PhaseTest.java index f8fc751..4ea4185 100644 --- a/src/test/java/com/tikal/hudson/plugins/notification/PhaseTest.java +++ b/src/test/java/com/tikal/hudson/plugins/notification/PhaseTest.java @@ -4,18 +4,30 @@ import static com.tikal.hudson.plugins.notification.UrlType.SECRET; import static java.util.Arrays.asList; import static org.junit.Assert.assertEquals; -import static org.mockito.Mockito.*; +import static org.mockito.Mockito.any; +import static org.mockito.Mockito.anyBoolean; +import static org.mockito.Mockito.anyInt; +import static org.mockito.Mockito.anyString; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.isA; +import static org.mockito.Mockito.mockStatic; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoInteractions; +import static org.mockito.Mockito.when; +import com.tikal.hudson.plugins.notification.model.JobState; +import hudson.EnvVars; +import hudson.model.Job; +import hudson.model.Result; +import hudson.model.Run; +import hudson.model.TaskListener; import java.io.IOException; import java.io.PrintStream; import java.lang.reflect.Method; - -import com.tikal.hudson.plugins.notification.model.JobState; -import hudson.EnvVars; -import hudson.model.*; import jenkins.model.Jenkins; import org.junit.Test; - import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.MockedStatic; @@ -23,211 +35,260 @@ @RunWith(MockitoJUnitRunner.class) public class PhaseTest { - @Mock - private Run run; - @Mock - private Job job; - @Mock - private TaskListener listener; - @Mock - private HudsonNotificationProperty property; - @Mock - private Endpoint endpoint; - @Mock - private UrlInfo urlInfo; - @Mock - private EnvVars environment; - @Mock - private PrintStream logger; - @Mock - private Jenkins jenkins; - - @Test - public void testIsRun() throws ReflectiveOperationException { - Endpoint endPoint = new Endpoint(null); - Method isRunMethod = Phase.class.getDeclaredMethod("isRun", Endpoint.class, Result.class, Result.class); - isRunMethod.setAccessible(true); - - assertEquals("returns true for null endpoint event", - isRunMethod.invoke(Phase.QUEUED, endPoint, null, null), Boolean.TRUE); - - endPoint.setEvent("all"); - for (Phase phaseValue : Phase.values()) { - assertEquals("all Event returns true for Phase " + phaseValue.toString(), - isRunMethod.invoke(phaseValue, endPoint, null, null), Boolean.TRUE); + @Mock + private Run run; + + @Mock + private Job job; + + @Mock + private TaskListener listener; + + @Mock + private HudsonNotificationProperty property; + + @Mock + private Endpoint endpoint; + + @Mock + private UrlInfo urlInfo; + + @Mock + private EnvVars environment; + + @Mock + private PrintStream logger; + + @Mock + private Jenkins jenkins; + + @Test + public void testIsRun() throws ReflectiveOperationException { + Endpoint endPoint = new Endpoint(null); + Method isRunMethod = Phase.class.getDeclaredMethod("isRun", Endpoint.class, Result.class, Result.class); + isRunMethod.setAccessible(true); + + assertEquals( + "returns true for null endpoint event", + isRunMethod.invoke(Phase.QUEUED, endPoint, null, null), + Boolean.TRUE); + + endPoint.setEvent("all"); + for (Phase phaseValue : Phase.values()) { + assertEquals( + "all Event returns true for Phase " + phaseValue.toString(), + isRunMethod.invoke(phaseValue, endPoint, null, null), + Boolean.TRUE); + } + + endPoint.setEvent("queued"); + assertEquals( + "queued Event returns true for Phase Queued", + isRunMethod.invoke(Phase.QUEUED, endPoint, null, null), + Boolean.TRUE); + assertEquals( + "queued Event returns false for Phase Started", + isRunMethod.invoke(Phase.STARTED, endPoint, null, null), + Boolean.FALSE); + + endPoint.setEvent("started"); + assertEquals( + "started Event returns true for Phase Started", + isRunMethod.invoke(Phase.STARTED, endPoint, null, null), + Boolean.TRUE); + assertEquals( + "started Event returns false for Phase Completed", + isRunMethod.invoke(Phase.COMPLETED, endPoint, null, null), + Boolean.FALSE); + + endPoint.setEvent("completed"); + assertEquals( + "completed Event returns true for Phase Completed", + isRunMethod.invoke(Phase.COMPLETED, endPoint, null, null), + Boolean.TRUE); + assertEquals( + "completed Event returns false for Phase Finalized", + isRunMethod.invoke(Phase.FINALIZED, endPoint, null, null), + Boolean.FALSE); + + endPoint.setEvent("finalized"); + assertEquals( + "finalized Event returns true for Phase Finalized", + isRunMethod.invoke(Phase.FINALIZED, endPoint, null, null), + Boolean.TRUE); + assertEquals( + "finalized Event returns true for Phase Queued", + isRunMethod.invoke(Phase.QUEUED, endPoint, null, null), + Boolean.FALSE); + + endPoint.setEvent("failed"); + assertEquals( + "failed Event returns false for Phase Finalized and no status", + isRunMethod.invoke(Phase.FINALIZED, endPoint, null, null), + Boolean.FALSE); + assertEquals( + "failed Event returns false for Phase Finalized and success status", + isRunMethod.invoke(Phase.FINALIZED, endPoint, Result.SUCCESS, null), + Boolean.FALSE); + assertEquals( + "failed Event returns true for Phase Finalized and success failure", + isRunMethod.invoke(Phase.FINALIZED, endPoint, Result.FAILURE, null), + Boolean.TRUE); + assertEquals( + "failed Event returns false for Phase not Finalized and success failure", + isRunMethod.invoke(Phase.COMPLETED, endPoint, Result.FAILURE, null), + Boolean.FALSE); + + endPoint.setEvent("failedAndFirstSuccess"); + assertEquals( + "failedAndFirstSuccess Event returns false for Phase Finalized and no status", + isRunMethod.invoke(Phase.FINALIZED, endPoint, null, null), + Boolean.FALSE); + assertEquals( + "failedAndFirstSuccess Event returns false for Phase Finalized and no previous status", + isRunMethod.invoke(Phase.FINALIZED, endPoint, Result.SUCCESS, null), + Boolean.FALSE); + assertEquals( + "failedAndFirstSuccess Event returns true for Phase Finalized and no previous status and failed status", + isRunMethod.invoke(Phase.FINALIZED, endPoint, Result.FAILURE, null), + Boolean.TRUE); + assertEquals( + "failedAndFirstSuccess Event returns true for Phase Finalized and failed status", + isRunMethod.invoke(Phase.FINALIZED, endPoint, Result.FAILURE, Result.FAILURE), + Boolean.TRUE); + assertEquals( + "failedAndFirstSuccess Event returns true for Phase Finalized and success status with previous status of failure", + isRunMethod.invoke(Phase.FINALIZED, endPoint, Result.SUCCESS, Result.FAILURE), + Boolean.TRUE); + assertEquals( + "failedAndFirstSuccess Event returns false for Phase Finalized and success status with previous status of success", + isRunMethod.invoke(Phase.FINALIZED, endPoint, Result.SUCCESS, Result.SUCCESS), + Boolean.FALSE); + assertEquals( + "failedAndFirstSuccess Event returns false for Phase not Finalized", + isRunMethod.invoke(Phase.COMPLETED, endPoint, Result.SUCCESS, Result.FAILURE), + Boolean.FALSE); } - endPoint.setEvent("queued"); - assertEquals("queued Event returns true for Phase Queued", - isRunMethod.invoke(Phase.QUEUED, endPoint, null, null), Boolean.TRUE); - assertEquals("queued Event returns false for Phase Started", - isRunMethod.invoke(Phase.STARTED, endPoint, null, null), Boolean.FALSE); - - endPoint.setEvent("started"); - assertEquals("started Event returns true for Phase Started", - isRunMethod.invoke(Phase.STARTED, endPoint, null, null), Boolean.TRUE); - assertEquals("started Event returns false for Phase Completed", - isRunMethod.invoke(Phase.COMPLETED, endPoint, null, null), Boolean.FALSE); - - - endPoint.setEvent("completed"); - assertEquals("completed Event returns true for Phase Completed", - isRunMethod.invoke(Phase.COMPLETED, endPoint, null, null), Boolean.TRUE); - assertEquals("completed Event returns false for Phase Finalized", - isRunMethod.invoke(Phase.FINALIZED, endPoint, null, null), Boolean.FALSE); - - - endPoint.setEvent("finalized"); - assertEquals("finalized Event returns true for Phase Finalized", - isRunMethod.invoke(Phase.FINALIZED, endPoint, null, null), Boolean.TRUE); - assertEquals("finalized Event returns true for Phase Queued", - isRunMethod.invoke(Phase.QUEUED, endPoint, null, null), Boolean.FALSE); - - - endPoint.setEvent("failed"); - assertEquals("failed Event returns false for Phase Finalized and no status", - isRunMethod.invoke(Phase.FINALIZED, endPoint, null, null), Boolean.FALSE); - assertEquals("failed Event returns false for Phase Finalized and success status", - isRunMethod.invoke(Phase.FINALIZED, endPoint, Result.SUCCESS, null), Boolean.FALSE); - assertEquals("failed Event returns true for Phase Finalized and success failure", - isRunMethod.invoke(Phase.FINALIZED, endPoint, Result.FAILURE, null), Boolean.TRUE); - assertEquals("failed Event returns false for Phase not Finalized and success failure", - isRunMethod.invoke(Phase.COMPLETED, endPoint, Result.FAILURE, null), Boolean.FALSE); - - endPoint.setEvent("failedAndFirstSuccess"); - assertEquals("failedAndFirstSuccess Event returns false for Phase Finalized and no status", - isRunMethod.invoke(Phase.FINALIZED, endPoint, null, null), Boolean.FALSE); - assertEquals("failedAndFirstSuccess Event returns false for Phase Finalized and no previous status", - isRunMethod.invoke(Phase.FINALIZED, endPoint, Result.SUCCESS, null), Boolean.FALSE); - assertEquals("failedAndFirstSuccess Event returns true for Phase Finalized and no previous status and failed status", - isRunMethod.invoke(Phase.FINALIZED, endPoint, Result.FAILURE, null), Boolean.TRUE); - assertEquals("failedAndFirstSuccess Event returns true for Phase Finalized and failed status", - isRunMethod.invoke(Phase.FINALIZED, endPoint, Result.FAILURE, Result.FAILURE), Boolean.TRUE); - assertEquals("failedAndFirstSuccess Event returns true for Phase Finalized and success status with previous status of failure", - isRunMethod.invoke(Phase.FINALIZED, endPoint, Result.SUCCESS, Result.FAILURE), Boolean.TRUE); - assertEquals("failedAndFirstSuccess Event returns false for Phase Finalized and success status with previous status of success", - isRunMethod.invoke(Phase.FINALIZED, endPoint, Result.SUCCESS, Result.SUCCESS), Boolean.FALSE); - assertEquals("failedAndFirstSuccess Event returns false for Phase not Finalized", - isRunMethod.invoke(Phase.COMPLETED, endPoint, Result.SUCCESS, Result.FAILURE), Boolean.FALSE); - } - - @Test - public void testRunNoProperty() { - when(run.getParent()).thenReturn(job); - - Phase.STARTED.handle(run, listener, 0L); - - verify(job).getProperty(HudsonNotificationProperty.class); - verifyNoInteractions(listener, endpoint, property); - } - - @Test - public void testRunNoPreviousRunUrlNull() { - when(run.getParent()).thenReturn(job); - when(job.getProperty(HudsonNotificationProperty.class)).thenReturn(property); - when(property.getEndpoints()).thenReturn(asList(endpoint)); - when(endpoint.getUrlInfo()).thenReturn(urlInfo); - - Phase.STARTED.handle(run, listener, 0L); - - verify(run).getPreviousCompletedBuild(); - verifyNoInteractions(listener); - } - - @Test - public void testRunNoPreviousRunUrlTypePublicUnresolvedUrl() throws IOException, InterruptedException { - when(run.getParent()).thenReturn(job); - when(job.getProperty(HudsonNotificationProperty.class)).thenReturn(property); - when(property.getEndpoints()).thenReturn(asList(endpoint)); - when(endpoint.getUrlInfo()).thenReturn(urlInfo); - when(run.getEnvironment(listener)).thenReturn(environment); - when(urlInfo.getUrlOrId()).thenReturn("$someUrl"); - when(urlInfo.getUrlType()).thenReturn(PUBLIC); - when(environment.expand("$someUrl")).thenReturn("$someUrl"); - when(listener.getLogger()).thenReturn(logger); - - Phase.STARTED.handle(run, listener, 0L); - - verify(logger).printf("Ignoring sending notification due to unresolved variable: %s%n", "url '$someUrl'"); - verify(run).getPreviousCompletedBuild(); - } - - @Test - public void testRunPreviousRunUrlTypePublic() throws IOException, InterruptedException { - byte[] data = "data".getBytes(); - try (MockedStatic jenkinsMockedStatic = mockStatic(Jenkins.class)) { - jenkinsMockedStatic.when(Jenkins::getInstanceOrNull).thenReturn(jenkins); - jenkinsMockedStatic.when(Jenkins::getInstance).thenReturn(jenkins); - - Protocol httpProtocolSpy = spy(Protocol.HTTP); - when(endpoint.getProtocol()).thenReturn(httpProtocolSpy); - doNothing().when(httpProtocolSpy).send(anyString(), any(byte[].class), anyInt(), anyBoolean()); - - Format jsonFormatSpy = spy(Format.JSON); - JobState jobState = new JobState(); - when(endpoint.getFormat()).thenReturn(jsonFormatSpy); - doReturn(data).when(jsonFormatSpy).serialize(isA(JobState.class)); - assertEquals(data, jsonFormatSpy.serialize(jobState)); - - when(run.getParent()).thenReturn(job); - when(job.getProperty(HudsonNotificationProperty.class)).thenReturn(property); - when(property.getEndpoints()).thenReturn(asList(endpoint)); - when(endpoint.getUrlInfo()).thenReturn(urlInfo); - when(endpoint.getBranch()).thenReturn("branchName"); - when(run.getEnvironment(listener)).thenReturn(environment); - when(urlInfo.getUrlOrId()).thenReturn("$someUrl"); - when(urlInfo.getUrlType()).thenReturn(PUBLIC); - when(environment.expand("$someUrl")).thenReturn("expandedUrl"); - when(environment.containsKey("BRANCH_NAME")).thenReturn(true); - when(environment.get("BRANCH_NAME")).thenReturn("branchName"); - when(listener.getLogger()).thenReturn(logger); - when(endpoint.getTimeout()).thenReturn(42); - - Phase.STARTED.handle(run, listener, 1L); - - verify(logger).printf("Notifying endpoint with %s%n", "url 'expandedUrl'"); - verify(httpProtocolSpy).send("expandedUrl", data, 42, false); - verify(run).getPreviousCompletedBuild(); + @Test + public void testRunNoProperty() { + when(run.getParent()).thenReturn(job); + + Phase.STARTED.handle(run, listener, 0L); + + verify(job).getProperty(HudsonNotificationProperty.class); + verifyNoInteractions(listener, endpoint, property); } - } - - @Test - public void testRunPreviousRunUrlTypeSecret() throws IOException, InterruptedException { - byte[] data = "data".getBytes(); - try (MockedStatic jenkinsMockedStatic = mockStatic(Jenkins.class); - MockedStatic utilsMockedStatic = mockStatic(Utils.class)) { - jenkinsMockedStatic.when(Jenkins::getInstanceOrNull).thenReturn(jenkins); - jenkinsMockedStatic.when(Jenkins::getInstance).thenReturn(jenkins); - utilsMockedStatic.when(() -> Utils.getSecretUrl("credentialsId", jenkins)).thenReturn("$secretUrl"); - - Protocol httpProtocolSpy = spy(Protocol.HTTP); - when(endpoint.getProtocol()).thenReturn(httpProtocolSpy); - doNothing().when(httpProtocolSpy).send(anyString(), any(byte[].class), anyInt(), anyBoolean()); - - Format jsonFormatSpy = spy(Format.JSON); - JobState jobState = new JobState(); - when(endpoint.getFormat()).thenReturn(jsonFormatSpy); - doReturn(data).when(jsonFormatSpy).serialize(isA(JobState.class)); - assertEquals(data, jsonFormatSpy.serialize(jobState)); - - when(run.getParent()).thenReturn(job); - when(job.getProperty(HudsonNotificationProperty.class)).thenReturn(property); - when(property.getEndpoints()).thenReturn(asList(endpoint)); - when(endpoint.getUrlInfo()).thenReturn(urlInfo); - when(endpoint.getBranch()).thenReturn(".*"); - when(run.getEnvironment(listener)).thenReturn(environment); - when(job.getParent()).thenReturn(jenkins); - when(urlInfo.getUrlOrId()).thenReturn("credentialsId"); - when(urlInfo.getUrlType()).thenReturn(SECRET); - when(environment.expand("$secretUrl")).thenReturn("secretUrl"); - when(listener.getLogger()).thenReturn(logger); - when(endpoint.getTimeout()).thenReturn(42); - - Phase.STARTED.handle(run, listener, 1L); - - verify(logger).printf( "Notifying endpoint with %s%n","credentials id 'credentialsId'"); - verify(httpProtocolSpy).send("secretUrl", data, 42, false); - verify(run).getPreviousCompletedBuild(); + + @Test + public void testRunNoPreviousRunUrlNull() { + when(run.getParent()).thenReturn(job); + when(job.getProperty(HudsonNotificationProperty.class)).thenReturn(property); + when(property.getEndpoints()).thenReturn(asList(endpoint)); + when(endpoint.getUrlInfo()).thenReturn(urlInfo); + + Phase.STARTED.handle(run, listener, 0L); + + verify(run).getPreviousCompletedBuild(); + verifyNoInteractions(listener); + } + + @Test + public void testRunNoPreviousRunUrlTypePublicUnresolvedUrl() throws IOException, InterruptedException { + when(run.getParent()).thenReturn(job); + when(job.getProperty(HudsonNotificationProperty.class)).thenReturn(property); + when(property.getEndpoints()).thenReturn(asList(endpoint)); + when(endpoint.getUrlInfo()).thenReturn(urlInfo); + when(run.getEnvironment(listener)).thenReturn(environment); + when(urlInfo.getUrlOrId()).thenReturn("$someUrl"); + when(urlInfo.getUrlType()).thenReturn(PUBLIC); + when(environment.expand("$someUrl")).thenReturn("$someUrl"); + when(listener.getLogger()).thenReturn(logger); + + Phase.STARTED.handle(run, listener, 0L); + + verify(logger).printf("Ignoring sending notification due to unresolved variable: %s%n", "url '$someUrl'"); + verify(run).getPreviousCompletedBuild(); + } + + @Test + public void testRunPreviousRunUrlTypePublic() throws IOException, InterruptedException { + byte[] data = "data".getBytes(); + try (MockedStatic jenkinsMockedStatic = mockStatic(Jenkins.class)) { + jenkinsMockedStatic.when(Jenkins::getInstanceOrNull).thenReturn(jenkins); + jenkinsMockedStatic.when(Jenkins::getInstance).thenReturn(jenkins); + + Protocol httpProtocolSpy = spy(Protocol.HTTP); + when(endpoint.getProtocol()).thenReturn(httpProtocolSpy); + doNothing().when(httpProtocolSpy).send(anyString(), any(byte[].class), anyInt(), anyBoolean()); + + Format jsonFormatSpy = spy(Format.JSON); + JobState jobState = new JobState(); + when(endpoint.getFormat()).thenReturn(jsonFormatSpy); + doReturn(data).when(jsonFormatSpy).serialize(isA(JobState.class)); + assertEquals(data, jsonFormatSpy.serialize(jobState)); + + when(run.getParent()).thenReturn(job); + when(job.getProperty(HudsonNotificationProperty.class)).thenReturn(property); + when(property.getEndpoints()).thenReturn(asList(endpoint)); + when(endpoint.getUrlInfo()).thenReturn(urlInfo); + when(endpoint.getBranch()).thenReturn("branchName"); + when(run.getEnvironment(listener)).thenReturn(environment); + when(urlInfo.getUrlOrId()).thenReturn("$someUrl"); + when(urlInfo.getUrlType()).thenReturn(PUBLIC); + when(environment.expand("$someUrl")).thenReturn("expandedUrl"); + when(environment.containsKey("BRANCH_NAME")).thenReturn(true); + when(environment.get("BRANCH_NAME")).thenReturn("branchName"); + when(listener.getLogger()).thenReturn(logger); + when(endpoint.getTimeout()).thenReturn(42); + + Phase.STARTED.handle(run, listener, 1L); + + verify(logger).printf("Notifying endpoint with %s%n", "url 'expandedUrl'"); + verify(httpProtocolSpy).send("expandedUrl", data, 42, false); + verify(run).getPreviousCompletedBuild(); + } + } + + @Test + public void testRunPreviousRunUrlTypeSecret() throws IOException, InterruptedException { + byte[] data = "data".getBytes(); + try (MockedStatic jenkinsMockedStatic = mockStatic(Jenkins.class); + MockedStatic utilsMockedStatic = mockStatic(Utils.class)) { + jenkinsMockedStatic.when(Jenkins::getInstanceOrNull).thenReturn(jenkins); + jenkinsMockedStatic.when(Jenkins::getInstance).thenReturn(jenkins); + utilsMockedStatic + .when(() -> Utils.getSecretUrl("credentialsId", jenkins)) + .thenReturn("$secretUrl"); + + Protocol httpProtocolSpy = spy(Protocol.HTTP); + when(endpoint.getProtocol()).thenReturn(httpProtocolSpy); + doNothing().when(httpProtocolSpy).send(anyString(), any(byte[].class), anyInt(), anyBoolean()); + + Format jsonFormatSpy = spy(Format.JSON); + JobState jobState = new JobState(); + when(endpoint.getFormat()).thenReturn(jsonFormatSpy); + doReturn(data).when(jsonFormatSpy).serialize(isA(JobState.class)); + assertEquals(data, jsonFormatSpy.serialize(jobState)); + + when(run.getParent()).thenReturn(job); + when(job.getProperty(HudsonNotificationProperty.class)).thenReturn(property); + when(property.getEndpoints()).thenReturn(asList(endpoint)); + when(endpoint.getUrlInfo()).thenReturn(urlInfo); + when(endpoint.getBranch()).thenReturn(".*"); + when(run.getEnvironment(listener)).thenReturn(environment); + when(job.getParent()).thenReturn(jenkins); + when(urlInfo.getUrlOrId()).thenReturn("credentialsId"); + when(urlInfo.getUrlType()).thenReturn(SECRET); + when(environment.expand("$secretUrl")).thenReturn("secretUrl"); + when(listener.getLogger()).thenReturn(logger); + when(endpoint.getTimeout()).thenReturn(42); + + Phase.STARTED.handle(run, listener, 1L); + + verify(logger).printf("Notifying endpoint with %s%n", "credentials id 'credentialsId'"); + verify(httpProtocolSpy).send("secretUrl", data, 42, false); + verify(run).getPreviousCompletedBuild(); + } } - } } diff --git a/src/test/java/com/tikal/hudson/plugins/notification/ProtocolTest.java b/src/test/java/com/tikal/hudson/plugins/notification/ProtocolTest.java index bff0ef7..abbea3a 100644 --- a/src/test/java/com/tikal/hudson/plugins/notification/ProtocolTest.java +++ b/src/test/java/com/tikal/hudson/plugins/notification/ProtocolTest.java @@ -26,18 +26,6 @@ import com.google.common.base.MoreObjects; import com.google.common.base.Objects; import com.google.common.io.CharStreams; -import junit.framework.TestCase; -import org.eclipse.jetty.ee8.servlet.ServletContextHandler; -import org.eclipse.jetty.ee8.servlet.ServletHolder; -import org.eclipse.jetty.server.Connector; -import org.eclipse.jetty.server.Server; -import org.eclipse.jetty.server.ServerConnector; - -import javax.servlet.Servlet; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; @@ -46,211 +34,221 @@ import java.util.List; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; +import javax.servlet.Servlet; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import junit.framework.TestCase; +import org.eclipse.jetty.ee8.servlet.ServletContextHandler; +import org.eclipse.jetty.ee8.servlet.ServletHolder; +import org.eclipse.jetty.server.Connector; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.server.ServerConnector; /** * @author Kohsuke Kawaguchi */ public class ProtocolTest extends TestCase { - static class Request { - private final String url; - private final String method; - private final String body; - private final String userInfo; - - Request(HttpServletRequest request) throws IOException { - this.url = request.getRequestURL().toString(); - this.method = request.getMethod(); - this.body = CharStreams.toString(request.getReader()); - String auth = request.getHeader("Authorization"); - this.userInfo = (null == auth) - ? null - : new String(Base64.getDecoder().decode(auth.split(" ")[1])) + "@"; - } + static class Request { + private final String url; + private final String method; + private final String body; + private final String userInfo; + + Request(HttpServletRequest request) throws IOException { + this.url = request.getRequestURL().toString(); + this.method = request.getMethod(); + this.body = CharStreams.toString(request.getReader()); + String auth = request.getHeader("Authorization"); + this.userInfo = + (null == auth) ? null : new String(Base64.getDecoder().decode(auth.split(" ")[1])) + "@"; + } - Request(String url, String method, String body) { - this.url = url; - this.method = method; - this.body = body; - this.userInfo = null; - } + Request(String url, String method, String body) { + this.url = url; + this.method = method; + this.body = body; + this.userInfo = null; + } - @Override - public int hashCode() { - return Objects.hashCode(url, method, body); - } + @Override + public int hashCode() { + return Objects.hashCode(url, method, body); + } - @Override - public boolean equals(Object obj) { - if (!(obj instanceof Request)) { - return false; - } - Request other = (Request) obj; - return Objects.equal(url, other.url) - && Objects.equal(method, other.method) - && Objects.equal(body, other.body); - } + @Override + public boolean equals(Object obj) { + if (!(obj instanceof Request)) { + return false; + } + Request other = (Request) obj; + return Objects.equal(url, other.url) + && Objects.equal(method, other.method) + && Objects.equal(body, other.body); + } - @Override - public String toString() { - return MoreObjects.toStringHelper(this) - .add("url", url) - .add("method", method) - .add("body", body) - .toString(); - } + @Override + public String toString() { + return MoreObjects.toStringHelper(this) + .add("url", url) + .add("method", method) + .add("body", body) + .toString(); + } - public String getUrl() { - return url; - } + public String getUrl() { + return url; + } - public String getUrlWithAuthority() { - if (null == userInfo) { - // Detect possible bug: userInfo never moved from URI to Authorization header - return null; - } - else { - return url.replaceFirst("^http://", "http://" + userInfo); - } + public String getUrlWithAuthority() { + if (null == userInfo) { + // Detect possible bug: userInfo never moved from URI to Authorization header + return null; + } else { + return url.replaceFirst("^http://", "http://" + userInfo); + } + } } - } - static class RecordingServlet extends HttpServlet { - private final BlockingQueue requests; + static class RecordingServlet extends HttpServlet { + private final BlockingQueue requests; - public RecordingServlet(BlockingQueue requests) { - this.requests = requests; - } + public RecordingServlet(BlockingQueue requests) { + this.requests = requests; + } - @Override - protected void doPost(HttpServletRequest httpRequest, HttpServletResponse httpResponse) - throws ServletException, IOException { + @Override + protected void doPost(HttpServletRequest httpRequest, HttpServletResponse httpResponse) + throws ServletException, IOException { - Request request = new Request(httpRequest); - try { - requests.put(request); - } catch (InterruptedException e) { - throw new ServletException(e); - } + Request request = new Request(httpRequest); + try { + requests.put(request); + } catch (InterruptedException e) { + throw new ServletException(e); + } - doPost(request, httpResponse); - } + doPost(request, httpResponse); + } - protected void doPost(Request request, HttpServletResponse httpResponse) throws IOException { - // noop + protected void doPost(Request request, HttpServletResponse httpResponse) throws IOException { + // noop + } } - } - static class RedirectHandler extends RecordingServlet { - private final String redirectURI; + static class RedirectHandler extends RecordingServlet { + private final String redirectURI; + + RedirectHandler(BlockingQueue requests, String redirectURI) { + super(requests); + this.redirectURI = redirectURI; + } - RedirectHandler(BlockingQueue requests, String redirectURI) { - super(requests); - this.redirectURI = redirectURI; + @Override + protected void doPost(Request request, HttpServletResponse httpResponse) throws IOException { + httpResponse.setStatus(HttpServletResponse.SC_TEMPORARY_REDIRECT); + httpResponse.setHeader("Location", redirectURI); + } } - @Override - protected void doPost(Request request, HttpServletResponse httpResponse) throws IOException { - httpResponse.setStatus(HttpServletResponse.SC_TEMPORARY_REDIRECT); - httpResponse.setHeader("Location", redirectURI); + private List servers; + + interface UrlFactory { + String getUrl(String path); } - } - private List servers; + private UrlFactory startServer(Servlet servlet, String path) throws Exception { + return startSecureServer(servlet, path, ""); + } - interface UrlFactory { - String getUrl(String path); - } + private UrlFactory startSecureServer(Servlet servlet, String path, String authority) throws Exception { + Server server = new Server(); + ServerConnector connector = new ServerConnector(server); + server.setConnectors(new Connector[] {connector}); - private UrlFactory startServer(Servlet servlet, String path) throws Exception { - return startSecureServer(servlet, path, ""); - } + ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS); + context.setContextPath("/"); + context.addServlet(new ServletHolder(servlet), path); + server.setHandler(context); - private UrlFactory startSecureServer(Servlet servlet, String path, String authority) throws Exception { - Server server = new Server(); - ServerConnector connector = new ServerConnector(server); - server.setConnectors(new Connector[] {connector}); + server.start(); + servers.add(server); - ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS); - context.setContextPath("/"); - context.addServlet(new ServletHolder(servlet), path); - server.setHandler(context); + if (!authority.isEmpty()) { + authority += "@"; + } - server.start(); - servers.add(server); + final URL serverUrl = new URL(String.format("http://%slocalhost:%d", authority, connector.getLocalPort())); + return new UrlFactory() { + @Override + public String getUrl(String path) { + try { + return new URL(serverUrl, path).toExternalForm(); + } catch (MalformedURLException e) { + throw new IllegalArgumentException(e); + } + } + }; + } - if (!authority.isEmpty()) { - authority += "@"; + @Override + public void setUp() throws Exception { + servers = new LinkedList<>(); } - final URL serverUrl = new URL(String.format("http://%slocalhost:%d", authority, connector.getLocalPort())); - return new UrlFactory() { - public String getUrl(String path) { - try { - return new URL(serverUrl, path).toExternalForm(); - } catch (MalformedURLException e) { - throw new IllegalArgumentException(e); + @Override + public void tearDown() throws Exception { + for (Server server : servers) { + server.stop(); } - } - }; - } - - @Override - public void setUp() throws Exception { - servers = new LinkedList<>(); - } - - @Override - public void tearDown() throws Exception { - for (Server server : servers) { - server.stop(); } - } - public void testHttpPost() throws Exception { - BlockingQueue requests = new LinkedBlockingQueue(); + public void testHttpPost() throws Exception { + BlockingQueue requests = new LinkedBlockingQueue(); - UrlFactory urlFactory = startServer(new RecordingServlet(requests), "/realpath"); + UrlFactory urlFactory = startServer(new RecordingServlet(requests), "/realpath"); - assertTrue(requests.isEmpty()); + assertTrue(requests.isEmpty()); - String uri = urlFactory.getUrl("/realpath"); - Protocol.HTTP.send(uri, "Hello".getBytes(),30000, true); + String uri = urlFactory.getUrl("/realpath"); + Protocol.HTTP.send(uri, "Hello".getBytes(), 30000, true); - assertEquals(new Request(uri, "POST", "Hello"), requests.take()); - assertTrue(requests.isEmpty()); - } + assertEquals(new Request(uri, "POST", "Hello"), requests.take()); + assertTrue(requests.isEmpty()); + } - public void testHttpPostWithBasicAuth() throws Exception { - BlockingQueue requests = new LinkedBlockingQueue(); + public void testHttpPostWithBasicAuth() throws Exception { + BlockingQueue requests = new LinkedBlockingQueue(); - UrlFactory urlFactory = startSecureServer(new RecordingServlet(requests), "/realpath", "fred:foo"); + UrlFactory urlFactory = startSecureServer(new RecordingServlet(requests), "/realpath", "fred:foo"); - assertTrue(requests.isEmpty()); + assertTrue(requests.isEmpty()); - String uri = urlFactory.getUrl("/realpath"); - Protocol.HTTP.send(uri, "Hello".getBytes(),30000, true); + String uri = urlFactory.getUrl("/realpath"); + Protocol.HTTP.send(uri, "Hello".getBytes(), 30000, true); - Request theRequest = requests.take(); - assertTrue(requests.isEmpty()); - assertEquals(new Request(uri, "POST", "Hello").getUrl(), theRequest.getUrlWithAuthority()); - } + Request theRequest = requests.take(); + assertTrue(requests.isEmpty()); + assertEquals(new Request(uri, "POST", "Hello").getUrl(), theRequest.getUrlWithAuthority()); + } - public void testHttpPostWithRedirects() throws Exception { - BlockingQueue requests = new LinkedBlockingQueue(); + public void testHttpPostWithRedirects() throws Exception { + BlockingQueue requests = new LinkedBlockingQueue(); - UrlFactory urlFactory = startServer(new RecordingServlet(requests), "/realpath"); + UrlFactory urlFactory = startServer(new RecordingServlet(requests), "/realpath"); - String redirectUri = urlFactory.getUrl("/realpath"); - UrlFactory redirectorUrlFactory = startServer(new RedirectHandler(requests, redirectUri), "/path"); + String redirectUri = urlFactory.getUrl("/realpath"); + UrlFactory redirectorUrlFactory = startServer(new RedirectHandler(requests, redirectUri), "/path"); - assertTrue(requests.isEmpty()); + assertTrue(requests.isEmpty()); - String uri = redirectorUrlFactory.getUrl("/path"); - Protocol.HTTP.send(uri, "RedirectMe".getBytes(),30000, true); + String uri = redirectorUrlFactory.getUrl("/path"); + Protocol.HTTP.send(uri, "RedirectMe".getBytes(), 30000, true); - assertEquals(new Request(uri, "POST", "RedirectMe"), requests.take()); - assertEquals(new Request(redirectUri, "POST", "RedirectMe"), requests.take()); - assertTrue(requests.isEmpty()); - } + assertEquals(new Request(uri, "POST", "RedirectMe"), requests.take()); + assertEquals(new Request(redirectUri, "POST", "RedirectMe"), requests.take()); + assertTrue(requests.isEmpty()); + } } diff --git a/src/test/java/com/tikal/hudson/plugins/notification/test/HostnamePortTest.java b/src/test/java/com/tikal/hudson/plugins/notification/test/HostnamePortTest.java index 8f80020..d2288b6 100644 --- a/src/test/java/com/tikal/hudson/plugins/notification/test/HostnamePortTest.java +++ b/src/test/java/com/tikal/hudson/plugins/notification/test/HostnamePortTest.java @@ -13,12 +13,10 @@ */ package com.tikal.hudson.plugins.notification.test; +import com.tikal.hudson.plugins.notification.HostnamePort; import junit.framework.Assert; - import org.junit.Test; -import com.tikal.hudson.plugins.notification.HostnamePort; - public class HostnamePortTest { @Test From 2ec1e3058ecbd51948714b239aa357c309b7327f Mon Sep 17 00:00:00 2001 From: Basil Crow Date: Thu, 3 Oct 2024 09:20:52 -0700 Subject: [PATCH 190/214] Add `.git-blame-ignore-revs` (#62) --- .git-blame-ignore-revs | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .git-blame-ignore-revs diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs new file mode 100644 index 0000000..6b42b28 --- /dev/null +++ b/.git-blame-ignore-revs @@ -0,0 +1,3 @@ +# .git-blame-ignore-revs +# Format repository with Spotless (#61) +96e7537e66f73f276d4d001fbc56006222a3a7b0 From 435c3b5617c3cda3c46d6ade939059b6fd2c14fc Mon Sep 17 00:00:00 2001 From: Basil Crow Date: Thu, 3 Oct 2024 09:22:33 -0700 Subject: [PATCH 191/214] Remove redundant suppression --- src/main/java/com/tikal/hudson/plugins/notification/Phase.java | 1 - src/main/java/com/tikal/hudson/plugins/notification/Utils.java | 1 - 2 files changed, 2 deletions(-) diff --git a/src/main/java/com/tikal/hudson/plugins/notification/Phase.java b/src/main/java/com/tikal/hudson/plugins/notification/Phase.java index 5649bb9..7e4dad2 100755 --- a/src/main/java/com/tikal/hudson/plugins/notification/Phase.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/Phase.java @@ -69,7 +69,6 @@ private Result findLastBuildThatFinished(Run run) { return null; } - @SuppressWarnings("CastToConcreteClass") public void handle(Run run, TaskListener listener, long timestamp) { handle(run, listener, timestamp, false, null, 0, this); } diff --git a/src/main/java/com/tikal/hudson/plugins/notification/Utils.java b/src/main/java/com/tikal/hudson/plugins/notification/Utils.java index afad471..aebb904 100644 --- a/src/main/java/com/tikal/hudson/plugins/notification/Utils.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/Utils.java @@ -40,7 +40,6 @@ public static boolean isEmpty(String... strings) { * @param strings Strings to check for empty (whitespace is trimmed) or null. * @throws java.lang.IllegalArgumentException Throws this exception if any string is empty. */ - @SuppressWarnings("ReturnOfNull") public static void verifyNotEmpty(String... strings) { if (isEmpty(strings)) { throw new IllegalArgumentException( From cdbf39748751d623a21454f198107f9c7cec8a46 Mon Sep 17 00:00:00 2001 From: Basil Crow Date: Thu, 3 Oct 2024 09:26:39 -0700 Subject: [PATCH 192/214] Avoid usage of deprecated methods --- .../java/com/tikal/hudson/plugins/notification/Protocol.java | 5 +++-- .../tikal/hudson/plugins/notification/model/BuildState.java | 4 ++-- .../com/tikal/hudson/plugins/notification/PhaseTest.java | 4 ++-- .../hudson/plugins/notification/test/HostnamePortTest.java | 2 +- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java b/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java index 8f2e3b5..800e327 100755 --- a/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java @@ -75,8 +75,9 @@ protected void send(String url, byte[] data, int timeout, boolean isJson) throws } Proxy proxy = Proxy.NO_PROXY; - if (Jenkins.getInstance() != null && Jenkins.getInstance().proxy != null) { - proxy = Jenkins.getInstance().proxy.createProxy(targetUrl.getHost()); + Jenkins jenkins = Jenkins.getInstanceOrNull(); + if (jenkins != null && jenkins.proxy != null) { + proxy = jenkins.proxy.createProxy(targetUrl.getHost()); } else if (proxyUrl != null) { // Proxy connection to the address provided final int proxyPort = proxyUrl.getPort() > 0 ? proxyUrl.getPort() : 80; diff --git a/src/main/java/com/tikal/hudson/plugins/notification/model/BuildState.java b/src/main/java/com/tikal/hudson/plugins/notification/model/BuildState.java index 546694f..fbbcd05 100755 --- a/src/main/java/com/tikal/hudson/plugins/notification/model/BuildState.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/model/BuildState.java @@ -202,13 +202,13 @@ private void updateArchivedArtifacts(Run run) { List buildArtifacts = run.getArtifacts(); for (Run.Artifact a : buildArtifacts) { - String artifactUrl = Jenkins.getInstance().getRootUrl() + run.getUrl() + "artifact/" + a.getHref(); + String artifactUrl = Jenkins.get().getRootUrl() + run.getUrl() + "artifact/" + a.getHref(); updateArtifact(a.relativePath, "archive", artifactUrl); } } private void updateS3Artifacts(Job job, Run run) { - if (Jenkins.getInstance().getPlugin("s3") == null) { + if (Jenkins.get().getPlugin("s3") == null) { return; } if (!(run instanceof AbstractBuild)) { diff --git a/src/test/java/com/tikal/hudson/plugins/notification/PhaseTest.java b/src/test/java/com/tikal/hudson/plugins/notification/PhaseTest.java index 4ea4185..896efa7 100644 --- a/src/test/java/com/tikal/hudson/plugins/notification/PhaseTest.java +++ b/src/test/java/com/tikal/hudson/plugins/notification/PhaseTest.java @@ -216,7 +216,7 @@ public void testRunPreviousRunUrlTypePublic() throws IOException, InterruptedExc byte[] data = "data".getBytes(); try (MockedStatic jenkinsMockedStatic = mockStatic(Jenkins.class)) { jenkinsMockedStatic.when(Jenkins::getInstanceOrNull).thenReturn(jenkins); - jenkinsMockedStatic.when(Jenkins::getInstance).thenReturn(jenkins); + jenkinsMockedStatic.when(Jenkins::get).thenReturn(jenkins); Protocol httpProtocolSpy = spy(Protocol.HTTP); when(endpoint.getProtocol()).thenReturn(httpProtocolSpy); @@ -256,7 +256,7 @@ public void testRunPreviousRunUrlTypeSecret() throws IOException, InterruptedExc try (MockedStatic jenkinsMockedStatic = mockStatic(Jenkins.class); MockedStatic utilsMockedStatic = mockStatic(Utils.class)) { jenkinsMockedStatic.when(Jenkins::getInstanceOrNull).thenReturn(jenkins); - jenkinsMockedStatic.when(Jenkins::getInstance).thenReturn(jenkins); + jenkinsMockedStatic.when(Jenkins::get).thenReturn(jenkins); utilsMockedStatic .when(() -> Utils.getSecretUrl("credentialsId", jenkins)) .thenReturn("$secretUrl"); diff --git a/src/test/java/com/tikal/hudson/plugins/notification/test/HostnamePortTest.java b/src/test/java/com/tikal/hudson/plugins/notification/test/HostnamePortTest.java index d2288b6..c1ed4f2 100644 --- a/src/test/java/com/tikal/hudson/plugins/notification/test/HostnamePortTest.java +++ b/src/test/java/com/tikal/hudson/plugins/notification/test/HostnamePortTest.java @@ -14,7 +14,7 @@ package com.tikal.hudson.plugins.notification.test; import com.tikal.hudson.plugins.notification.HostnamePort; -import junit.framework.Assert; +import org.junit.Assert; import org.junit.Test; public class HostnamePortTest { From dc8548fcb125e048d80405ca0242b2a2b495271d Mon Sep 17 00:00:00 2001 From: Basil Crow Date: Thu, 3 Oct 2024 09:26:49 -0700 Subject: [PATCH 193/214] Use isEmpty() where possible --- .../java/com/tikal/hudson/plugins/notification/Protocol.java | 4 ++-- .../java/com/tikal/hudson/plugins/notification/Utils.java | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java b/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java index 800e327..52bfa26 100755 --- a/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java @@ -67,7 +67,7 @@ protected void send(String url, byte[] data, int timeout, boolean isJson) throws // Verifying if the HTTP_PROXY is available final String httpProxyUrl = System.getenv().get("http_proxy"); URL proxyUrl = null; - if (httpProxyUrl != null && httpProxyUrl.length() > 0) { + if (httpProxyUrl != null && !httpProxyUrl.isEmpty()) { proxyUrl = new URL(httpProxyUrl); if (!proxyUrl.getProtocol().startsWith("http")) { throw new IllegalArgumentException("Not an http(s) url: " + httpProxyUrl); @@ -157,6 +157,6 @@ public void validateUrl(String url) { } private static boolean isEmpty(String s) { - return ((s == null) || (s.trim().length() < 1)); + return ((s == null) || (s.trim().isEmpty())); } } diff --git a/src/main/java/com/tikal/hudson/plugins/notification/Utils.java b/src/main/java/com/tikal/hudson/plugins/notification/Utils.java index aebb904..becfd85 100644 --- a/src/main/java/com/tikal/hudson/plugins/notification/Utils.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/Utils.java @@ -27,7 +27,7 @@ public static boolean isEmpty(String... strings) { } for (String s : strings) { - if ((s == null) || (s.trim().length() < 1)) { + if ((s == null) || (s.trim().isEmpty())) { return true; } } From f3cd85fa92236c234acad5632477ab0933d84376 Mon Sep 17 00:00:00 2001 From: Basil Crow Date: Thu, 3 Oct 2024 09:27:37 -0700 Subject: [PATCH 194/214] Use StandardCharsets where possible --- .../java/com/tikal/hudson/plugins/notification/Format.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/tikal/hudson/plugins/notification/Format.java b/src/main/java/com/tikal/hudson/plugins/notification/Format.java index e6e27cb..01e057e 100644 --- a/src/main/java/com/tikal/hudson/plugins/notification/Format.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/Format.java @@ -19,6 +19,7 @@ import com.thoughtworks.xstream.XStream; import com.tikal.hudson.plugins.notification.model.JobState; import java.io.IOException; +import java.nio.charset.StandardCharsets; public enum Format { XML { @@ -27,7 +28,7 @@ public enum Format { @Override protected byte[] serialize(JobState jobState) throws IOException { xstream.processAnnotations(JobState.class); - return xstream.toXML(jobState).getBytes("UTF-8"); + return xstream.toXML(jobState).getBytes(StandardCharsets.UTF_8); } }, JSON { @@ -37,7 +38,7 @@ protected byte[] serialize(JobState jobState) throws IOException { @Override protected byte[] serialize(JobState jobState) throws IOException { - return gson.toJson(jobState).getBytes("UTF-8"); + return gson.toJson(jobState).getBytes(StandardCharsets.UTF_8); } }; From 803dee621c80fc646c7c4d97c33e7c28df48db97 Mon Sep 17 00:00:00 2001 From: Basil Crow Date: Thu, 3 Oct 2024 09:28:07 -0700 Subject: [PATCH 195/214] Use diamond operator where possible --- .../plugins/notification/HudsonNotificationProperty.java | 2 +- .../tikal/hudson/plugins/notification/model/BuildState.java | 6 +++--- .../com/tikal/hudson/plugins/notification/ProtocolTest.java | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/tikal/hudson/plugins/notification/HudsonNotificationProperty.java b/src/main/java/com/tikal/hudson/plugins/notification/HudsonNotificationProperty.java index e6eb959..58bcf79 100755 --- a/src/main/java/com/tikal/hudson/plugins/notification/HudsonNotificationProperty.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/HudsonNotificationProperty.java @@ -25,7 +25,7 @@ public class HudsonNotificationProperty extends JobProperty> { @DataBoundConstructor public HudsonNotificationProperty(List endpoints) { - this.endpoints = new ArrayList(endpoints); + this.endpoints = new ArrayList<>(endpoints); } public List getEndpoints() { diff --git a/src/main/java/com/tikal/hudson/plugins/notification/model/BuildState.java b/src/main/java/com/tikal/hudson/plugins/notification/model/BuildState.java index fbbcd05..7cd0402 100755 --- a/src/main/java/com/tikal/hudson/plugins/notification/model/BuildState.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/model/BuildState.java @@ -69,7 +69,7 @@ public class BuildState { * notification.jar: * archive: http://localhost:8080/job/notification-plugin/78/artifact/target/notification.jar */ - private final Map> artifacts = new HashMap>(); + private final Map> artifacts = new HashMap<>(); public int getNumber() { return number; @@ -140,7 +140,7 @@ public Map getParameters() { } public void setParameters(Map params) { - this.parameters = new HashMap(params); + this.parameters = new HashMap<>(params); } public Map> getArtifacts() { @@ -263,7 +263,7 @@ private void updateArtifact(String fileName, String locationName, String locatio verifyNotEmpty(fileName, locationName, locationUrl); if (!artifacts.containsKey(fileName)) { - artifacts.put(fileName, new HashMap()); + artifacts.put(fileName, new HashMap<>()); } if (artifacts.get(fileName).containsKey(locationName)) { diff --git a/src/test/java/com/tikal/hudson/plugins/notification/ProtocolTest.java b/src/test/java/com/tikal/hudson/plugins/notification/ProtocolTest.java index abbea3a..579fd97 100644 --- a/src/test/java/com/tikal/hudson/plugins/notification/ProtocolTest.java +++ b/src/test/java/com/tikal/hudson/plugins/notification/ProtocolTest.java @@ -206,7 +206,7 @@ public void tearDown() throws Exception { } public void testHttpPost() throws Exception { - BlockingQueue requests = new LinkedBlockingQueue(); + BlockingQueue requests = new LinkedBlockingQueue<>(); UrlFactory urlFactory = startServer(new RecordingServlet(requests), "/realpath"); @@ -220,7 +220,7 @@ public void testHttpPost() throws Exception { } public void testHttpPostWithBasicAuth() throws Exception { - BlockingQueue requests = new LinkedBlockingQueue(); + BlockingQueue requests = new LinkedBlockingQueue<>(); UrlFactory urlFactory = startSecureServer(new RecordingServlet(requests), "/realpath", "fred:foo"); @@ -235,7 +235,7 @@ public void testHttpPostWithBasicAuth() throws Exception { } public void testHttpPostWithRedirects() throws Exception { - BlockingQueue requests = new LinkedBlockingQueue(); + BlockingQueue requests = new LinkedBlockingQueue<>(); UrlFactory urlFactory = startServer(new RecordingServlet(requests), "/realpath"); From 0f4bce631d00de4b42739e9c93343a792225da17 Mon Sep 17 00:00:00 2001 From: Basil Crow Date: Thu, 3 Oct 2024 09:28:23 -0700 Subject: [PATCH 196/214] Use try-with-resources where possible --- .../java/com/tikal/hudson/plugins/notification/Protocol.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java b/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java index 52bfa26..d1b92c1 100755 --- a/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java @@ -102,12 +102,9 @@ protected void send(String url, byte[] data, int timeout, boolean isJson) throws connection.setReadTimeout(timeout); connection.connect(); try { - OutputStream output = connection.getOutputStream(); - try { + try (OutputStream output = connection.getOutputStream()) { output.write(data); output.flush(); - } finally { - output.close(); } } finally { // Follow an HTTP Temporary Redirect if we get one, From 5b22fab529d3af99d8a2603a3802de333028a907 Mon Sep 17 00:00:00 2001 From: Basil Crow Date: Thu, 3 Oct 2024 09:28:51 -0700 Subject: [PATCH 197/214] Use List.of in tests --- .../tikal/hudson/plugins/notification/PhaseTest.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/test/java/com/tikal/hudson/plugins/notification/PhaseTest.java b/src/test/java/com/tikal/hudson/plugins/notification/PhaseTest.java index 896efa7..04f2b41 100644 --- a/src/test/java/com/tikal/hudson/plugins/notification/PhaseTest.java +++ b/src/test/java/com/tikal/hudson/plugins/notification/PhaseTest.java @@ -2,7 +2,6 @@ import static com.tikal.hudson.plugins.notification.UrlType.PUBLIC; import static com.tikal.hudson.plugins.notification.UrlType.SECRET; -import static java.util.Arrays.asList; import static org.junit.Assert.assertEquals; import static org.mockito.Mockito.any; import static org.mockito.Mockito.anyBoolean; @@ -26,6 +25,7 @@ import java.io.IOException; import java.io.PrintStream; import java.lang.reflect.Method; +import java.util.List; import jenkins.model.Jenkins; import org.junit.Test; import org.junit.runner.RunWith; @@ -184,7 +184,7 @@ public void testRunNoProperty() { public void testRunNoPreviousRunUrlNull() { when(run.getParent()).thenReturn(job); when(job.getProperty(HudsonNotificationProperty.class)).thenReturn(property); - when(property.getEndpoints()).thenReturn(asList(endpoint)); + when(property.getEndpoints()).thenReturn(List.of(endpoint)); when(endpoint.getUrlInfo()).thenReturn(urlInfo); Phase.STARTED.handle(run, listener, 0L); @@ -197,7 +197,7 @@ public void testRunNoPreviousRunUrlNull() { public void testRunNoPreviousRunUrlTypePublicUnresolvedUrl() throws IOException, InterruptedException { when(run.getParent()).thenReturn(job); when(job.getProperty(HudsonNotificationProperty.class)).thenReturn(property); - when(property.getEndpoints()).thenReturn(asList(endpoint)); + when(property.getEndpoints()).thenReturn(List.of(endpoint)); when(endpoint.getUrlInfo()).thenReturn(urlInfo); when(run.getEnvironment(listener)).thenReturn(environment); when(urlInfo.getUrlOrId()).thenReturn("$someUrl"); @@ -230,7 +230,7 @@ public void testRunPreviousRunUrlTypePublic() throws IOException, InterruptedExc when(run.getParent()).thenReturn(job); when(job.getProperty(HudsonNotificationProperty.class)).thenReturn(property); - when(property.getEndpoints()).thenReturn(asList(endpoint)); + when(property.getEndpoints()).thenReturn(List.of(endpoint)); when(endpoint.getUrlInfo()).thenReturn(urlInfo); when(endpoint.getBranch()).thenReturn("branchName"); when(run.getEnvironment(listener)).thenReturn(environment); @@ -273,7 +273,7 @@ public void testRunPreviousRunUrlTypeSecret() throws IOException, InterruptedExc when(run.getParent()).thenReturn(job); when(job.getProperty(HudsonNotificationProperty.class)).thenReturn(property); - when(property.getEndpoints()).thenReturn(asList(endpoint)); + when(property.getEndpoints()).thenReturn(List.of(endpoint)); when(endpoint.getUrlInfo()).thenReturn(urlInfo); when(endpoint.getBranch()).thenReturn(".*"); when(run.getEnvironment(listener)).thenReturn(environment); From ad1442a1a68b28d1d9d2c33e7c10b8cf1009bc55 Mon Sep 17 00:00:00 2001 From: Basil Crow Date: Thu, 3 Oct 2024 09:30:23 -0700 Subject: [PATCH 198/214] Remove redundant throws in tests --- .../com/tikal/hudson/plugins/notification/ProtocolTest.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/test/java/com/tikal/hudson/plugins/notification/ProtocolTest.java b/src/test/java/com/tikal/hudson/plugins/notification/ProtocolTest.java index 579fd97..934e4f7 100644 --- a/src/test/java/com/tikal/hudson/plugins/notification/ProtocolTest.java +++ b/src/test/java/com/tikal/hudson/plugins/notification/ProtocolTest.java @@ -133,7 +133,7 @@ protected void doPost(HttpServletRequest httpRequest, HttpServletResponse httpRe doPost(request, httpResponse); } - protected void doPost(Request request, HttpServletResponse httpResponse) throws IOException { + protected void doPost(Request request, HttpServletResponse httpResponse) { // noop } } @@ -147,7 +147,7 @@ static class RedirectHandler extends RecordingServlet { } @Override - protected void doPost(Request request, HttpServletResponse httpResponse) throws IOException { + protected void doPost(Request request, HttpServletResponse httpResponse) { httpResponse.setStatus(HttpServletResponse.SC_TEMPORARY_REDIRECT); httpResponse.setHeader("Location", redirectURI); } @@ -194,7 +194,7 @@ public String getUrl(String path) { } @Override - public void setUp() throws Exception { + public void setUp() { servers = new LinkedList<>(); } From fd2bb2ad594b32d79f658c9f385db0a3e567f8d0 Mon Sep 17 00:00:00 2001 From: Basil Crow Date: Fri, 4 Oct 2024 13:38:07 -0700 Subject: [PATCH 199/214] Upgrade plugin parent POM to latest (#64) --- pom.xml | 7 ++----- .../hudson/plugins/notification/ProtocolTest.java | 14 +++++++------- 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/pom.xml b/pom.xml index 02acc28..f08a029 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ org.jenkins-ci.plugins plugin - 4.88 + 5.1 @@ -65,11 +65,8 @@ 1.19 -SNAPSHOT - 2.472 + 2.479 jenkinsci/${project.artifactId}-plugin - - 2250.v03a_1295b_0a_30 - 17 false diff --git a/src/test/java/com/tikal/hudson/plugins/notification/ProtocolTest.java b/src/test/java/com/tikal/hudson/plugins/notification/ProtocolTest.java index 934e4f7..ba2e781 100644 --- a/src/test/java/com/tikal/hudson/plugins/notification/ProtocolTest.java +++ b/src/test/java/com/tikal/hudson/plugins/notification/ProtocolTest.java @@ -26,6 +26,11 @@ import com.google.common.base.MoreObjects; import com.google.common.base.Objects; import com.google.common.io.CharStreams; +import jakarta.servlet.Servlet; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServlet; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; @@ -34,14 +39,9 @@ import java.util.List; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; -import javax.servlet.Servlet; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; import junit.framework.TestCase; -import org.eclipse.jetty.ee8.servlet.ServletContextHandler; -import org.eclipse.jetty.ee8.servlet.ServletHolder; +import org.eclipse.jetty.ee9.servlet.ServletContextHandler; +import org.eclipse.jetty.ee9.servlet.ServletHolder; import org.eclipse.jetty.server.Connector; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.ServerConnector; From 6b12e556bde56a63fb250f1f000b251136c37518 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 30 Oct 2024 18:34:24 +0000 Subject: [PATCH 200/214] Bump org.jenkins-ci.plugins:plugin from 5.1 to 5.2 (#66) --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index f08a029..425c33e 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ org.jenkins-ci.plugins plugin - 5.1 + 5.2 From f33358e5d1e66a94a00a02971a63dc1ed9a7bcf4 Mon Sep 17 00:00:00 2001 From: Basil Crow Date: Wed, 30 Oct 2024 12:13:58 -0700 Subject: [PATCH 201/214] Require 2.479.1 LTS or newer (#67) --- pom.xml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index 425c33e..897c922 100644 --- a/pom.xml +++ b/pom.xml @@ -65,7 +65,9 @@ 1.19 -SNAPSHOT - 2.479 + + 2.479 + ${jenkins.baseline}.1 jenkinsci/${project.artifactId}-plugin false @@ -74,8 +76,8 @@ io.jenkins.tools.bom - bom-2.462.x - 3413.v0d896b_76a_30d + bom-${jenkins.baseline}.x + 3482.vc10d4f6da_28a_ pom import From 39dc33d5e3b17995d3009f8719d8b957ff5da8ad Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 1 Nov 2024 10:09:17 +0000 Subject: [PATCH 202/214] Bump io.jenkins.tools.bom:bom-2.479.x Bumps [io.jenkins.tools.bom:bom-2.479.x](https://github.com/jenkinsci/bom) from 3482.vc10d4f6da_28a_ to 3613.v584fca_12cf5c. - [Release notes](https://github.com/jenkinsci/bom/releases) - [Commits](https://github.com/jenkinsci/bom/commits) --- updated-dependencies: - dependency-name: io.jenkins.tools.bom:bom-2.479.x dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 897c922..4613b6c 100644 --- a/pom.xml +++ b/pom.xml @@ -77,7 +77,7 @@ io.jenkins.tools.bom bom-${jenkins.baseline}.x - 3482.vc10d4f6da_28a_ + 3613.v584fca_12cf5c pom import From 185c377fb8eafad5b539c82793373e083e644073 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 1 Feb 2025 10:20:21 +0000 Subject: [PATCH 203/214] Bump org.jenkins-ci.plugins:plugin from 5.2 to 5.6 Bumps [org.jenkins-ci.plugins:plugin](https://github.com/jenkinsci/plugin-pom) from 5.2 to 5.6. - [Release notes](https://github.com/jenkinsci/plugin-pom/releases) - [Changelog](https://github.com/jenkinsci/plugin-pom/blob/master/CHANGELOG.md) - [Commits](https://github.com/jenkinsci/plugin-pom/compare/plugin-5.2...plugin-5.6) --- updated-dependencies: - dependency-name: org.jenkins-ci.plugins:plugin dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 4613b6c..c6bdbdf 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ org.jenkins-ci.plugins plugin - 5.2 + 5.6 From 7fbde74039403990fe39d3544006fd31b06d0a28 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 1 Feb 2025 10:20:29 +0000 Subject: [PATCH 204/214] Bump org.jenkins-ci.plugins:s3 Bumps [org.jenkins-ci.plugins:s3](https://github.com/jenkinsci/s3-plugin) from 483.vcb_db_3dcee68f to 494.v65894c3ef139. - [Release notes](https://github.com/jenkinsci/s3-plugin/releases) - [Changelog](https://github.com/jenkinsci/s3-plugin/blob/master/old-changelog.md) - [Commits](https://github.com/jenkinsci/s3-plugin/commits) --- updated-dependencies: - dependency-name: org.jenkins-ci.plugins:s3 dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 4613b6c..b3bf010 100644 --- a/pom.xml +++ b/pom.xml @@ -109,7 +109,7 @@ org.jenkins-ci.plugins s3 - 483.vcb_db_3dcee68f + 494.v65894c3ef139 true From fae62e409b413cdf39945b2f66feb7e6cc552e24 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 1 Feb 2025 10:20:34 +0000 Subject: [PATCH 205/214] Bump io.jenkins.tools.bom:bom-2.479.x Bumps [io.jenkins.tools.bom:bom-2.479.x](https://github.com/jenkinsci/bom) from 3613.v584fca_12cf5c to 4051.v78dce3ce8b_d6. - [Release notes](https://github.com/jenkinsci/bom/releases) - [Commits](https://github.com/jenkinsci/bom/commits) --- updated-dependencies: - dependency-name: io.jenkins.tools.bom:bom-2.479.x dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 4613b6c..d86bc2c 100644 --- a/pom.xml +++ b/pom.xml @@ -77,7 +77,7 @@ io.jenkins.tools.bom bom-${jenkins.baseline}.x - 3613.v584fca_12cf5c + 4051.v78dce3ce8b_d6 pom import From 25acc41e849129a5c8c8b008dcd4e8ceeb88a6cd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 1 Mar 2025 10:54:44 +0000 Subject: [PATCH 206/214] Bump org.jenkins-ci.plugins:plugin from 5.6 to 5.7 Bumps [org.jenkins-ci.plugins:plugin](https://github.com/jenkinsci/plugin-pom) from 5.6 to 5.7. - [Release notes](https://github.com/jenkinsci/plugin-pom/releases) - [Changelog](https://github.com/jenkinsci/plugin-pom/blob/master/CHANGELOG.md) - [Commits](https://github.com/jenkinsci/plugin-pom/compare/plugin-5.6...plugin-5.7) --- updated-dependencies: - dependency-name: org.jenkins-ci.plugins:plugin dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 427a7cc..1b9550e 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ org.jenkins-ci.plugins plugin - 5.6 + 5.7 From c17657ca8c4a8af33ab6d9855a4525db4c091b8d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 1 Mar 2025 10:54:49 +0000 Subject: [PATCH 207/214] Bump org.jenkins-ci.plugins:s3 Bumps [org.jenkins-ci.plugins:s3](https://github.com/jenkinsci/s3-plugin) from 494.v65894c3ef139 to 496.v320cdd5a_1f65. - [Release notes](https://github.com/jenkinsci/s3-plugin/releases) - [Changelog](https://github.com/jenkinsci/s3-plugin/blob/master/old-changelog.md) - [Commits](https://github.com/jenkinsci/s3-plugin/commits) --- updated-dependencies: - dependency-name: org.jenkins-ci.plugins:s3 dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 427a7cc..4a4e03b 100644 --- a/pom.xml +++ b/pom.xml @@ -109,7 +109,7 @@ org.jenkins-ci.plugins s3 - 494.v65894c3ef139 + 496.v320cdd5a_1f65 true From 1fbe63fed38272a386a5389f1bfdbf9cce36fe03 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 26 Mar 2025 15:46:48 -0700 Subject: [PATCH 208/214] Bump org.jenkins-ci.plugins:plugin from 5.7 to 5.9 (#80) Bumps [org.jenkins-ci.plugins:plugin](https://github.com/jenkinsci/plugin-pom) from 5.7 to 5.9. - [Release notes](https://github.com/jenkinsci/plugin-pom/releases) - [Changelog](https://github.com/jenkinsci/plugin-pom/blob/master/CHANGELOG.md) - [Commits](https://github.com/jenkinsci/plugin-pom/compare/plugin-5.7...plugin-5.9) --- updated-dependencies: - dependency-name: org.jenkins-ci.plugins:plugin dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 320fb03..c11e283 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ org.jenkins-ci.plugins plugin - 5.7 + 5.9 From b560bb102d0329bc9b2bb67008c403628dee28f2 Mon Sep 17 00:00:00 2001 From: Basil Crow Date: Wed, 26 Mar 2025 15:46:55 -0700 Subject: [PATCH 209/214] Convert test to `com.sun.net.httpserver` --- .../plugins/notification/ProtocolTest.java | 110 +++++++++--------- 1 file changed, 54 insertions(+), 56 deletions(-) diff --git a/src/test/java/com/tikal/hudson/plugins/notification/ProtocolTest.java b/src/test/java/com/tikal/hudson/plugins/notification/ProtocolTest.java index ba2e781..71dba4c 100644 --- a/src/test/java/com/tikal/hudson/plugins/notification/ProtocolTest.java +++ b/src/test/java/com/tikal/hudson/plugins/notification/ProtocolTest.java @@ -1,5 +1,5 @@ /* -+ * The MIT License + * The MIT License * * Copyright (c) 2011, CloudBees, Inc. * @@ -24,27 +24,23 @@ package com.tikal.hudson.plugins.notification; import com.google.common.base.MoreObjects; -import com.google.common.base.Objects; -import com.google.common.io.CharStreams; -import jakarta.servlet.Servlet; -import jakarta.servlet.ServletException; -import jakarta.servlet.http.HttpServlet; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpHandler; +import com.sun.net.httpserver.HttpServer; import java.io.IOException; +import java.net.HttpURLConnection; +import java.net.InetAddress; +import java.net.InetSocketAddress; import java.net.MalformedURLException; import java.net.URL; +import java.nio.charset.StandardCharsets; import java.util.Base64; import java.util.LinkedList; import java.util.List; +import java.util.Objects; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; import junit.framework.TestCase; -import org.eclipse.jetty.ee9.servlet.ServletContextHandler; -import org.eclipse.jetty.ee9.servlet.ServletHolder; -import org.eclipse.jetty.server.Connector; -import org.eclipse.jetty.server.Server; -import org.eclipse.jetty.server.ServerConnector; /** * @author Kohsuke Kawaguchi @@ -57,11 +53,14 @@ static class Request { private final String body; private final String userInfo; - Request(HttpServletRequest request) throws IOException { - this.url = request.getRequestURL().toString(); - this.method = request.getMethod(); - this.body = CharStreams.toString(request.getReader()); - String auth = request.getHeader("Authorization"); + Request(HttpExchange he) throws IOException { + InetSocketAddress address = he.getLocalAddress(); + this.url = "http://" + address.getHostString() + ":" + + address.getPort() + + he.getRequestURI().toString(); + this.method = he.getRequestMethod(); + this.body = new String(he.getRequestBody().readAllBytes(), StandardCharsets.UTF_8); + String auth = he.getRequestHeaders().getFirst("Authorization"); this.userInfo = (null == auth) ? null : new String(Base64.getDecoder().decode(auth.split(" ")[1])) + "@"; } @@ -75,7 +74,7 @@ static class Request { @Override public int hashCode() { - return Objects.hashCode(url, method, body); + return Objects.hash(url, method, body); } @Override @@ -84,9 +83,9 @@ public boolean equals(Object obj) { return false; } Request other = (Request) obj; - return Objects.equal(url, other.url) - && Objects.equal(method, other.method) - && Objects.equal(body, other.body); + return Objects.equals(url, other.url) + && Objects.equals(method, other.method) + && Objects.equals(body, other.body); } @Override @@ -112,7 +111,7 @@ public String getUrlWithAuthority() { } } - static class RecordingServlet extends HttpServlet { + static class RecordingServlet implements HttpHandler { private final BlockingQueue requests; public RecordingServlet(BlockingQueue requests) { @@ -120,58 +119,55 @@ public RecordingServlet(BlockingQueue requests) { } @Override - protected void doPost(HttpServletRequest httpRequest, HttpServletResponse httpResponse) - throws ServletException, IOException { + public void handle(HttpExchange he) throws IOException { - Request request = new Request(httpRequest); + Request request = new Request(he); try { requests.put(request); } catch (InterruptedException e) { - throw new ServletException(e); + throw new IOException("Interrupted while adding request to queue", e); } - - doPost(request, httpResponse); - } - - protected void doPost(Request request, HttpServletResponse httpResponse) { - // noop + he.sendResponseHeaders(HttpURLConnection.HTTP_OK, 0); + he.close(); } } - static class RedirectHandler extends RecordingServlet { + static class RedirectHandler implements HttpHandler { + private final BlockingQueue requests; private final String redirectURI; - RedirectHandler(BlockingQueue requests, String redirectURI) { - super(requests); - this.redirectURI = redirectURI; + public RedirectHandler(BlockingQueue requests, String redirectURI) { + this.requests = Objects.requireNonNull(requests); + this.redirectURI = Objects.requireNonNull(redirectURI); } @Override - protected void doPost(Request request, HttpServletResponse httpResponse) { - httpResponse.setStatus(HttpServletResponse.SC_TEMPORARY_REDIRECT); - httpResponse.setHeader("Location", redirectURI); + public void handle(HttpExchange he) throws IOException { + Request request = new Request(he); + try { + requests.put(request); + } catch (InterruptedException e) { + throw new IOException("Interrupted while adding request to queue", e); + } + he.getResponseHeaders().set("Location", redirectURI); + he.sendResponseHeaders(307, -1); + he.close(); } } - private List servers; + private List servers; interface UrlFactory { String getUrl(String path); } - private UrlFactory startServer(Servlet servlet, String path) throws Exception { - return startSecureServer(servlet, path, ""); + private UrlFactory startServer(HttpHandler handler, String path) throws Exception { + return startSecureServer(handler, path, ""); } - private UrlFactory startSecureServer(Servlet servlet, String path, String authority) throws Exception { - Server server = new Server(); - ServerConnector connector = new ServerConnector(server); - server.setConnectors(new Connector[] {connector}); - - ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS); - context.setContextPath("/"); - context.addServlet(new ServletHolder(servlet), path); - server.setHandler(context); + private UrlFactory startSecureServer(HttpHandler handler, String path, String authority) throws Exception { + HttpServer server = HttpServer.create(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0), 0); + server.createContext(path, handler); server.start(); servers.add(server); @@ -180,7 +176,9 @@ private UrlFactory startSecureServer(Servlet servlet, String path, String author authority += "@"; } - final URL serverUrl = new URL(String.format("http://%slocalhost:%d", authority, connector.getLocalPort())); + InetSocketAddress address = server.getAddress(); + final URL serverUrl = + new URL(String.format("http://%s%s:%d", authority, address.getHostString(), address.getPort())); return new UrlFactory() { @Override public String getUrl(String path) { @@ -199,9 +197,9 @@ public void setUp() { } @Override - public void tearDown() throws Exception { - for (Server server : servers) { - server.stop(); + public void tearDown() { + for (HttpServer server : servers) { + server.stop(1); } } From 21908af46af7ac4cd6ac216a01582e5573edb346 Mon Sep 17 00:00:00 2001 From: Basil Crow Date: Wed, 28 May 2025 08:06:36 -0700 Subject: [PATCH 210/214] Refresh plugin for June 2025 (#87) --- pom.xml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index c11e283..d4b026a 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ org.jenkins-ci.plugins plugin - 5.9 + 5.17 @@ -67,7 +67,7 @@ -SNAPSHOT 2.479 - ${jenkins.baseline}.1 + ${jenkins.baseline}.3 jenkinsci/${project.artifactId}-plugin false @@ -77,7 +77,7 @@ io.jenkins.tools.bom bom-${jenkins.baseline}.x - 4051.v78dce3ce8b_d6 + 4836.vdf03ded1f27c pom import @@ -109,7 +109,6 @@ org.jenkins-ci.plugins s3 - 496.v320cdd5a_1f65 true From 02c4f1b451e8a3276ab0b318f4c139486e6d9b38 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 1 Jun 2025 10:23:14 +0000 Subject: [PATCH 211/214] Bump io.jenkins.tools.bom:bom-2.479.x Bumps [io.jenkins.tools.bom:bom-2.479.x](https://github.com/jenkinsci/bom) from 4836.vdf03ded1f27c to 4862.vc32a_71c3e731. - [Release notes](https://github.com/jenkinsci/bom/releases) - [Commits](https://github.com/jenkinsci/bom/commits) --- updated-dependencies: - dependency-name: io.jenkins.tools.bom:bom-2.479.x dependency-version: 4862.vc32a_71c3e731 dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index d4b026a..dc659c3 100644 --- a/pom.xml +++ b/pom.xml @@ -77,7 +77,7 @@ io.jenkins.tools.bom bom-${jenkins.baseline}.x - 4836.vdf03ded1f27c + 4862.vc32a_71c3e731 pom import From 6c7dadd9bfc48e7e9ca9a5e27e57901418787afc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 1 Aug 2025 10:47:12 +0000 Subject: [PATCH 212/214] Bump io.jenkins.tools.bom:bom-2.479.x Bumps [io.jenkins.tools.bom:bom-2.479.x](https://github.com/jenkinsci/bom) from 4862.vc32a_71c3e731 to 5054.v620b_5d2b_d5e6. - [Release notes](https://github.com/jenkinsci/bom/releases) - [Commits](https://github.com/jenkinsci/bom/commits) --- updated-dependencies: - dependency-name: io.jenkins.tools.bom:bom-2.479.x dependency-version: 5054.v620b_5d2b_d5e6 dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index dc659c3..1efba6b 100644 --- a/pom.xml +++ b/pom.xml @@ -77,7 +77,7 @@ io.jenkins.tools.bom bom-${jenkins.baseline}.x - 4862.vc32a_71c3e731 + 5054.v620b_5d2b_d5e6 pom import From 0302d7b40d09c3c233ae2343cabefdf7ea89cd62 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 Oct 2025 10:13:09 +0000 Subject: [PATCH 213/214] Bump org.jenkins-ci.plugins:plugin from 5.17 to 5.26 Bumps [org.jenkins-ci.plugins:plugin](https://github.com/jenkinsci/plugin-pom) from 5.17 to 5.26. - [Release notes](https://github.com/jenkinsci/plugin-pom/releases) - [Changelog](https://github.com/jenkinsci/plugin-pom/blob/master/CHANGELOG.md) - [Commits](https://github.com/jenkinsci/plugin-pom/compare/plugin-5.17...plugin-5.26) --- updated-dependencies: - dependency-name: org.jenkins-ci.plugins:plugin dependency-version: '5.26' dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index dc659c3..10c0079 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ org.jenkins-ci.plugins plugin - 5.17 + 5.26 From 18765904ca9a5a9d6d88033f0f7d9a5242c49495 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 Oct 2025 10:13:34 +0000 Subject: [PATCH 214/214] Bump io.jenkins.tools.incrementals:git-changelist-maven-extension Bumps [io.jenkins.tools.incrementals:git-changelist-maven-extension](https://github.com/jenkinsci/incrementals-tools) from 1.8 to 1.13. - [Release notes](https://github.com/jenkinsci/incrementals-tools/releases) - [Commits](https://github.com/jenkinsci/incrementals-tools/compare/parent-1.8...parent-1.13) --- updated-dependencies: - dependency-name: io.jenkins.tools.incrementals:git-changelist-maven-extension dependency-version: '1.13' dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .mvn/extensions.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.mvn/extensions.xml b/.mvn/extensions.xml index 4e0774d..9440b18 100644 --- a/.mvn/extensions.xml +++ b/.mvn/extensions.xml @@ -2,6 +2,6 @@ io.jenkins.tools.incrementals git-changelist-maven-extension - 1.8 + 1.13