From c56748e3b19171b7b7c17b3cf455fe4cbd5ad485 Mon Sep 17 00:00:00 2001 From: Benjamin Raimondi Date: Tue, 7 Feb 2017 14:35:31 +0100 Subject: [PATCH] feat: add the posibility to send attachments. Rocket.chat Rest API allow to send attributes, emoji and avatar with a message. This update allow this. --- .gitignore | 4 +- .../rocketchatnotifier/RocketClient.java | 7 +- .../rocketchatnotifier/RocketClientImpl.java | 35 +++- .../rocketchatnotifier/model/Info.java | 18 ++ .../rocketchatnotifier/model/Response.java | 10 +- .../rocket/LegacyRocketChatClient.java | 49 ++++- .../rocket/RocketChatClient.java | 36 ++++ .../rocket/RocketChatClientImpl.java | 42 +++- .../rocket/RocketChatRestApiV1.java | 18 +- .../workflow/RocketSendStep.java | 86 +++++++- .../attachments/MessageAttachment.java | 188 ++++++++++++++++++ .../workflow/RocketSendStep/config.jelly | 38 ++-- .../workflow/RocketSendStep/help.html | 2 +- .../MessageAttachment/config.jelly | 51 +++++ .../rocketchatnotifier/RocketClientIT.java | 18 +- .../rocket/RocketChatClientIT.java | 26 ++- .../workflow/RocketSendTest.java | 62 ++++++ 17 files changed, 638 insertions(+), 52 deletions(-) create mode 100644 src/main/java/jenkins/plugins/rocketchatnotifier/model/Info.java create mode 100644 src/main/java/jenkins/plugins/rocketchatnotifier/workflow/attachments/MessageAttachment.java create mode 100755 src/main/resources/jenkins/plugins/rocketchatnotifier/workflow/attachments/MessageAttachment/config.jelly create mode 100644 src/test/java/jenkins/plugins/rocketchatnotifier/workflow/RocketSendTest.java diff --git a/.gitignore b/.gitignore index 89f7dac2..c5362aaf 100644 --- a/.gitignore +++ b/.gitignore @@ -13,4 +13,6 @@ buildNumber.properties /.settings .idea/* -rocket-chat-notifier.iml +*.iml +*.iws +*.ipr diff --git a/src/main/java/jenkins/plugins/rocketchatnotifier/RocketClient.java b/src/main/java/jenkins/plugins/rocketchatnotifier/RocketClient.java index 0ab552e8..1907ae77 100644 --- a/src/main/java/jenkins/plugins/rocketchatnotifier/RocketClient.java +++ b/src/main/java/jenkins/plugins/rocketchatnotifier/RocketClient.java @@ -1,9 +1,10 @@ package jenkins.plugins.rocketchatnotifier; - import sun.security.validator.ValidatorException; import java.io.IOException; +import java.util.List; +import java.util.Map; /** * Created by mreinhardt on 08.09.16. @@ -12,5 +13,9 @@ public interface RocketClient { boolean publish(String message); + boolean publish(String message, String emoji, String avatar); + + boolean publish(String message, String emoji, String avatar, List> attachments); + void validate() throws ValidatorException, IOException; } diff --git a/src/main/java/jenkins/plugins/rocketchatnotifier/RocketClientImpl.java b/src/main/java/jenkins/plugins/rocketchatnotifier/RocketClientImpl.java index 04f88f75..ed9aff7f 100644 --- a/src/main/java/jenkins/plugins/rocketchatnotifier/RocketClientImpl.java +++ b/src/main/java/jenkins/plugins/rocketchatnotifier/RocketClientImpl.java @@ -1,12 +1,13 @@ package jenkins.plugins.rocketchatnotifier; - import jenkins.plugins.rocketchatnotifier.rocket.LegacyRocketChatClient; import jenkins.plugins.rocketchatnotifier.rocket.RocketChatClient; import jenkins.plugins.rocketchatnotifier.rocket.RocketChatClientImpl; import sun.security.validator.ValidatorException; import java.io.IOException; +import java.util.List; +import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; @@ -25,7 +26,6 @@ public class RocketClientImpl implements RocketClient { private String channel; - public RocketClientImpl(String serverUrl, String user, String password, String channel) { this.client = new RocketChatClientImpl(serverUrl, user, password); try { @@ -52,11 +52,42 @@ public boolean publish(String message) { } } + @Override + public boolean publish(final String message, final String emoji, final String avatar) { + try { + LOGGER.fine("Starting sending message to channel " + this.channel); + this.client.send(this.channel, message, emoji, avatar); + return true; + } catch (IOException e) { + LOGGER.log(Level.SEVERE, "I/O error error during publishing message", e); + return false; + } catch (Exception e) { + LOGGER.log(Level.SEVERE, "Unknown error error during publishing message", e); + return false; + } + } + + @Override + public boolean publish(final String message, final String emoji, final String avatar, final List> attachments) { + try { + LOGGER.fine("Starting sending message to channel " + this.channel); + this.client.send(this.channel, message, emoji, avatar, attachments); + return true; + } catch (IOException e) { + LOGGER.log(Level.SEVERE, "I/O error error during publishing message", e); + return false; + } catch (Exception e) { + LOGGER.log(Level.SEVERE, "Unknown error error during publishing message", e); + return false; + } + } + @Override public void validate() throws ValidatorException, IOException { LOGGER.fine("Starting validating"); this.client.getChannels(); } + } diff --git a/src/main/java/jenkins/plugins/rocketchatnotifier/model/Info.java b/src/main/java/jenkins/plugins/rocketchatnotifier/model/Info.java new file mode 100644 index 00000000..f34478d9 --- /dev/null +++ b/src/main/java/jenkins/plugins/rocketchatnotifier/model/Info.java @@ -0,0 +1,18 @@ +package jenkins.plugins.rocketchatnotifier.model; + +/** + * Created by ben on 09/02/2017. + */ +public class Info { + + private String version; + + public String getVersion() { + return version; + } + + public void setVersion(final String version) { + this.version = version; + } + +} diff --git a/src/main/java/jenkins/plugins/rocketchatnotifier/model/Response.java b/src/main/java/jenkins/plugins/rocketchatnotifier/model/Response.java index 902ef78f..bdc32f26 100644 --- a/src/main/java/jenkins/plugins/rocketchatnotifier/model/Response.java +++ b/src/main/java/jenkins/plugins/rocketchatnotifier/model/Response.java @@ -1,6 +1,5 @@ package jenkins.plugins.rocketchatnotifier.model; - public class Response { private boolean success; private Message[] messages; @@ -9,6 +8,7 @@ public class Response { private User user; private Room[] channels; private Room channel; + private Info info; public void setSuccess(boolean result) { this.success = result; @@ -69,4 +69,12 @@ public User getUser() { public boolean isUser() { return this.user != null; } + + public Info getInfo() { + return info; + } + + public void setInfo(final Info info) { + this.info = info; + } } diff --git a/src/main/java/jenkins/plugins/rocketchatnotifier/rocket/LegacyRocketChatClient.java b/src/main/java/jenkins/plugins/rocketchatnotifier/rocket/LegacyRocketChatClient.java index 7de9557a..1f37422c 100644 --- a/src/main/java/jenkins/plugins/rocketchatnotifier/rocket/LegacyRocketChatClient.java +++ b/src/main/java/jenkins/plugins/rocketchatnotifier/rocket/LegacyRocketChatClient.java @@ -6,6 +6,7 @@ import com.mashape.unirest.http.JsonNode; import com.mashape.unirest.http.Unirest; import com.mashape.unirest.http.exceptions.UnirestException; +import jenkins.plugins.rocketchatnotifier.model.Info; import jenkins.plugins.rocketchatnotifier.model.Message; import jenkins.plugins.rocketchatnotifier.model.Room; import jenkins.plugins.rocketchatnotifier.model.Rooms; @@ -14,7 +15,11 @@ import sun.security.validator.ValidatorException; import java.io.IOException; -import java.util.*; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; /** * Created by mreinhardt on 26.12.16. @@ -56,7 +61,8 @@ public Set getPublicRooms() throws IOException { private T authenticatedGet(String method, Class reponseClass) throws IOException { try { - HttpResponse e = Unirest.get(this.serverUrl + method).header("X-Auth-Token", this.xAuthToken).header("X-User-Id", this.xUserId).asString(); + HttpResponse e = Unirest.get(this.serverUrl + method).header("X-Auth-Token", this.xAuthToken).header("X-User-Id", + this.xUserId).asString(); if (e.getStatus() == 401) { this.login(); return this.authenticatedGet(method, reponseClass); @@ -72,9 +78,12 @@ private void authenticatedPost(String method, Object request) throws ValidatorEx this.authenticatedPost(method, request, (Class) null); } - private T authenticatedPost(String method, Object request, Class reponseClass) throws ValidatorException, IOException { + private T authenticatedPost(String method, Object request, Class reponseClass) + throws ValidatorException, IOException { try { - HttpResponse e = Unirest.post(this.serverUrl + method).header("X-Auth-Token", this.xAuthToken).header("X-User-Id", this.xUserId).header("Content-Type", "application/json").body(this.jacksonObjectMapper.writeValueAsString(request)).asString(); + HttpResponse e = Unirest.post(this.serverUrl + method).header("X-Auth-Token", this.xAuthToken).header("X-User-Id", + this.xUserId).header( + "Content-Type", "application/json").body(this.jacksonObjectMapper.writeValueAsString(request)).asString(); if (e.getStatus() == 401) { this.login(); return this.authenticatedPost(method, request, reponseClass); @@ -87,7 +96,8 @@ private T authenticatedPost(String method, Object request, Class reponseC } void login() throws UnirestException { - HttpResponse asJson = Unirest.post(this.serverUrl + "login").field("user", this.user).field("password", this.password).asJson(); + HttpResponse asJson = Unirest.post(this.serverUrl + "login").field("user", this.user).field("password", + this.password).asJson(); if (asJson.getStatus() == 401) { throw new UnirestException("401 - Unauthorized"); } else { @@ -99,7 +109,8 @@ void login() throws UnirestException { public void logout() throws IOException { try { - Unirest.post(this.serverUrl + "logout").header("X-Auth-Token", this.xAuthToken).header("X-User-Id", this.xUserId).asJson(); + Unirest.post(this.serverUrl + "logout").header("X-Auth-Token", this.xAuthToken).header("X-User-Id", + this.xUserId).asJson(); } catch (UnirestException var2) { throw new IOException(var2); } @@ -116,7 +127,8 @@ public String getRocketChatVersion() throws IOException { private JSONObject getVersions() throws IOException { if (this.lazyVersions == null) { try { - this.lazyVersions = ((JsonNode) Unirest.get(this.serverUrl + "version").asJson().getBody()).getObject().getJSONObject("versions"); + this.lazyVersions = ((JsonNode) Unirest.get( + this.serverUrl + "version").asJson().getBody()).getObject().getJSONObject("versions"); } catch (UnirestException var2) { throw new IOException(var2); } @@ -128,7 +140,7 @@ private JSONObject getVersions() throws IOException { public void send(String roomName, String message) throws ValidatorException, IOException { Room room = this.getRoom(roomName); if (room == null) { - throw new IOException(String.format("unknown room : %s", new Object[]{roomName})); + throw new IOException(String.format("unknown room : %s", new Object[] { roomName })); } else { this.send(room, message); } @@ -160,6 +172,25 @@ public User getUser(String userId) throws IOException { @Override public Room[] getChannels() throws IOException { - return this.getPublicRooms().toArray(new Room[0]); + return this.getPublicRooms().toArray(new Room[0]); + } + + @Override + public void send(final String channelName, final String message, final String emoji, final String avatar) + throws ValidatorException, IOException { + this.send(channelName, message); + } + + @Override + public void send(final String channelName, final String message, final String emoji, final String avatar, final List> attachments) + throws ValidatorException, IOException { + this.send(channelName, message); + } + + @Override + public Info getInfo() throws IOException { + Info info = new Info(); + info.setVersion(this.getRocketChatVersion()); + return info; } } diff --git a/src/main/java/jenkins/plugins/rocketchatnotifier/rocket/RocketChatClient.java b/src/main/java/jenkins/plugins/rocketchatnotifier/rocket/RocketChatClient.java index 79121b7a..583cea68 100644 --- a/src/main/java/jenkins/plugins/rocketchatnotifier/rocket/RocketChatClient.java +++ b/src/main/java/jenkins/plugins/rocketchatnotifier/rocket/RocketChatClient.java @@ -1,10 +1,13 @@ package jenkins.plugins.rocketchatnotifier.rocket; +import jenkins.plugins.rocketchatnotifier.model.Info; import jenkins.plugins.rocketchatnotifier.model.Room; import jenkins.plugins.rocketchatnotifier.model.User; import sun.security.validator.ValidatorException; import java.io.IOException; +import java.util.List; +import java.util.Map; /** * API used by this Jenkins plugin to communicate to RocketChat server backend @@ -58,4 +61,37 @@ public interface RocketChatClient { */ void send(String channelName, String message) throws ValidatorException, IOException; + /** + * sends a message to a channel. + * If emoji and avatar are difined, only emoji will be displayed + * + * @param channelName to use + * @param message to send + * @param emoji to display + * @param avatar to display + * @throws ValidatorException in case of SSL errors + * @throws IOException in case of communication errors with the RocketChat server backend + */ + void send(String channelName, String message, String emoji, String avatar) throws ValidatorException, IOException; + + /** + * sends a message to a channel. + * If emoji and avatar are difined, only emoji will be displayed + * + * @param channelName to use + * @param message to send + * @param emoji to display + * @param avatar to display + * @param attachments to send + * @throws ValidatorException in case of SSL errors + * @throws IOException in case of communication errors with the RocketChat server backend + */ + void send(String channelName, String message, String emoji, String avatar, List> attachments) + throws ValidatorException, IOException; + + /** + * Retrieves server information + */ + Info getInfo() throws IOException; + } diff --git a/src/main/java/jenkins/plugins/rocketchatnotifier/rocket/RocketChatClientImpl.java b/src/main/java/jenkins/plugins/rocketchatnotifier/rocket/RocketChatClientImpl.java index be9165e0..b64e4606 100644 --- a/src/main/java/jenkins/plugins/rocketchatnotifier/rocket/RocketChatClientImpl.java +++ b/src/main/java/jenkins/plugins/rocketchatnotifier/rocket/RocketChatClientImpl.java @@ -1,6 +1,7 @@ package jenkins.plugins.rocketchatnotifier.rocket; import jenkins.plugins.rocketchatnotifier.RocketClientImpl; +import jenkins.plugins.rocketchatnotifier.model.Info; import jenkins.plugins.rocketchatnotifier.model.Response; import jenkins.plugins.rocketchatnotifier.model.Room; import jenkins.plugins.rocketchatnotifier.model.User; @@ -8,6 +9,7 @@ import java.io.IOException; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.logging.Logger; @@ -36,7 +38,6 @@ public RocketChatClientImpl(String serverUrl, String user, String password) { this.callBuilder = new RocketChatClientCallBuilder(serverUrl, user, password); } - @Override public User[] getUsers() throws IOException { Response res = this.callBuilder.buildCall(RocketChatRestApiV1.UsersList); @@ -54,7 +55,8 @@ public User[] getUsers() throws IOException { @Override public User getUser(String userId) throws IOException { - Response res = this.callBuilder.buildCall(RocketChatRestApiV1.UsersInfo, new RocketChatQueryParams("userId", userId)); + Response res = this.callBuilder.buildCall(RocketChatRestApiV1.UsersInfo, + new RocketChatQueryParams("userId", userId)); if (!res.isSuccessful()) { LOG.severe("Could not read user information: " + res.getMessage().getMsg()); @@ -78,6 +80,17 @@ public Room[] getChannels() throws IOException { return res.getChannels(); } + @Override + public Info getInfo() throws IOException { + Response res = this.callBuilder.buildCall(RocketChatRestApiV1.Info); + + if (!res.isSuccessful()) { + LOG.severe("Could not read information: " + res.getMessage().getMsg()); + throw new IOException("The call to get informations was unsuccessful."); + } + return res.getInfo(); + } + @Override public void send(Room room, String message) throws ValidatorException, IOException { this.send(room.getName(), message); @@ -85,14 +98,35 @@ public void send(Room room, String message) throws ValidatorException, IOExcepti @Override public void send(String channelName, String message) throws ValidatorException, IOException { + this.send(channelName, message, null, null); + } + + @Override + public void send(final String channelName, final String message, final String emoji, final String avatar) + throws ValidatorException, IOException { + this.send(channelName, message, emoji, avatar, null); + } + + @Override + public void send(final String channelName, final String message, final String emoji, final String avatar, final List> attachments) + throws ValidatorException, IOException { Map body = new HashMap(); body.put("channel", "#" + channelName); body.put("text", message); - Response res = this.callBuilder.buildCall(RocketChatRestApiV1.PostMessage, - null, body); + if (this.getInfo().getVersion().compareTo("0.50.1") >= 0) { + if (emoji != null) + body.put("emoji", emoji); + else if (avatar != null) + body.put("avatar", avatar); + if (attachments != null && attachments.size() > 0) + body.put("attachments", attachments); + } + Response res = this.callBuilder.buildCall(RocketChatRestApiV1.PostMessage, null, body); + if (!res.isSuccessful()) { LOG.severe("Could not send message: " + res.getMessage() != null ? res.getMessage().getMsg() : ""); throw new IOException("The send of the message was unsuccessful."); } } + } diff --git a/src/main/java/jenkins/plugins/rocketchatnotifier/rocket/RocketChatRestApiV1.java b/src/main/java/jenkins/plugins/rocketchatnotifier/rocket/RocketChatRestApiV1.java index e373e131..9f9ccacc 100644 --- a/src/main/java/jenkins/plugins/rocketchatnotifier/rocket/RocketChatRestApiV1.java +++ b/src/main/java/jenkins/plugins/rocketchatnotifier/rocket/RocketChatRestApiV1.java @@ -1,6 +1,5 @@ package jenkins.plugins.rocketchatnotifier.rocket; - /** * Enumeration of the available REST API methods. * @@ -12,23 +11,22 @@ public enum RocketChatRestApiV1 { /** * Retrieves a list of all the users in the server. */ - UsersList("users.list", HttpMethods.GET, true), - /** + UsersList("users.list", HttpMethods.GET, true), /** * Retrieves the user information from the server. */ - UsersInfo("users.info", HttpMethods.GET, true), - /** + UsersInfo("users.info", HttpMethods.GET, true), /** * Retrieves a list of all the channels in the server. */ - ChannelsList("channels.list", HttpMethods.GET, true), - /** + ChannelsList("channels.list", HttpMethods.GET, true), /** * Retrieves a list of all the channels in the server. */ - ChannelsInfo("channels.info", HttpMethods.GET, true), - /** + ChannelsInfo("channels.info", HttpMethods.GET, true), /** * Retrieves a list of all the channels in the server. */ - PostMessage("chat.postMessage", HttpMethods.POST, true); + PostMessage("chat.postMessage", HttpMethods.POST, true), /** + * Retrieves miscellaneous information from rocket.chat instance, like version number + */ + Info("info", HttpMethods.GET, false); private String methodName; private HttpMethods httpMethod; diff --git a/src/main/java/jenkins/plugins/rocketchatnotifier/workflow/RocketSendStep.java b/src/main/java/jenkins/plugins/rocketchatnotifier/workflow/RocketSendStep.java index 775b384d..46ac3e08 100644 --- a/src/main/java/jenkins/plugins/rocketchatnotifier/workflow/RocketSendStep.java +++ b/src/main/java/jenkins/plugins/rocketchatnotifier/workflow/RocketSendStep.java @@ -1,8 +1,12 @@ package jenkins.plugins.rocketchatnotifier.workflow; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.introspect.AnnotatedMember; +import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector; import hudson.AbortException; import hudson.Extension; import hudson.Util; +import hudson.model.AbstractDescribableImpl; import hudson.model.Run; import hudson.model.TaskListener; import jenkins.model.Jenkins; @@ -10,6 +14,7 @@ import jenkins.plugins.rocketchatnotifier.RocketChatNotifier; import jenkins.plugins.rocketchatnotifier.RocketClient; import jenkins.plugins.rocketchatnotifier.RocketClientImpl; +import jenkins.plugins.rocketchatnotifier.workflow.attachments.MessageAttachment; import org.jenkinsci.plugins.workflow.steps.AbstractStepDescriptorImpl; import org.jenkinsci.plugins.workflow.steps.AbstractStepImpl; import org.jenkinsci.plugins.workflow.steps.AbstractSynchronousNonBlockingStepExecution; @@ -19,10 +24,12 @@ import javax.annotation.Nonnull; import javax.inject.Inject; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; - /** * Workflow step to send a rocket channel notification. */ @@ -35,6 +42,11 @@ public class RocketSendStep extends AbstractStepImpl { private String channel; private boolean failOnError; + private String emoji; + private String avatar; + private boolean rawMessage; + private List attachments; + @Nonnull public String getMessage() { return message; @@ -44,6 +56,37 @@ public String getChannel() { return channel; } + public String getEmoji() { + return emoji; + } + + public String getAvatar() { + return avatar; + } + + public boolean isRawMessage() { + return rawMessage; + } + + public List getAttachments() { + return attachments; + } + + @DataBoundSetter + public void setEmoji(final String emoji) { + this.emoji = Util.fixEmpty(emoji); + } + + @DataBoundSetter + public void setAvatar(final String avatar) { + this.avatar = Util.fixEmpty(avatar); + } + + @DataBoundSetter + public void setAttachments(final List attachments) { + this.attachments = attachments; + } + @DataBoundSetter public void setChannel(String channel) { this.channel = Util.fixEmpty(channel); @@ -58,12 +101,16 @@ public void setFailOnError(boolean failOnError) { this.failOnError = failOnError; } + @DataBoundSetter + public void setRawMessage(final boolean rawMessage) { + this.rawMessage = rawMessage; + } + @DataBoundConstructor public RocketSendStep(@Nonnull String message) { this.message = message; } - @Extension public static class DescriptorImpl extends AbstractStepDescriptorImpl { @@ -80,6 +127,7 @@ public String getFunctionName() { public String getDisplayName() { return Messages.RocketSendStepDisplayName(); } + } public static class RocketSendStepExecution extends AbstractSynchronousNonBlockingStepExecution { @@ -112,7 +160,8 @@ public void uncaughtException(Thread t, Throwable e) { listener.error(Messages.NotificationFailedWithException(ne)); return null; } - RocketChatNotifier.DescriptorImpl rocketDesc = jenkins.getDescriptorByType(RocketChatNotifier.DescriptorImpl.class); + RocketChatNotifier.DescriptorImpl rocketDesc = jenkins.getDescriptorByType( + RocketChatNotifier.DescriptorImpl.class); String server = rocketDesc.getRocketServerURL(); String user = rocketDesc.getUsername(); String password = rocketDesc.getPassword(); @@ -123,10 +172,13 @@ public void uncaughtException(Thread t, Throwable e) { RocketClient rocketClient = getRocketClient(server, user, password, channel); - String msgWithJobLink = step.message - + "," + run.getFullDisplayName() - + "," + jenkinsUrl + run.getUrl() + ""; - boolean publishSuccess = rocketClient.publish(msgWithJobLink); + String msg = step.message; + if (!step.rawMessage) { + msg += "," + run.getFullDisplayName() + "," + jenkinsUrl + run.getUrl() + ""; + } + + boolean publishSuccess = rocketClient.publish(msg, step.emoji, step.avatar, + convertMessageAttachmentsToMaps(step.attachments)); if (!publishSuccess && step.failOnError) { throw new AbortException(Messages.NotificationFailed()); } else if (!publishSuccess) { @@ -140,5 +192,25 @@ RocketClient getRocketClient(String server, String user, String password, String return new RocketClientImpl(server, user, password, channel); } + protected List> convertMessageAttachmentsToMaps(List attachments) { + List> returnedList = new ArrayList>(); + if (attachments != null && attachments.size() > 0) { + ObjectMapper oMapper = new ObjectMapper(); + oMapper.setAnnotationIntrospector(new IgnoreInheritedIntrospector()); + for (MessageAttachment attachment : attachments) { + returnedList.add(oMapper.convertValue(attachment, Map.class)); + } + } + return returnedList; + + } + + } + + private static class IgnoreInheritedIntrospector extends JacksonAnnotationIntrospector { + @Override + public boolean hasIgnoreMarker(final AnnotatedMember m) { + return m.getDeclaringClass() == AbstractDescribableImpl.class || super.hasIgnoreMarker(m); + } } } diff --git a/src/main/java/jenkins/plugins/rocketchatnotifier/workflow/attachments/MessageAttachment.java b/src/main/java/jenkins/plugins/rocketchatnotifier/workflow/attachments/MessageAttachment.java new file mode 100644 index 00000000..b6f0c6ff --- /dev/null +++ b/src/main/java/jenkins/plugins/rocketchatnotifier/workflow/attachments/MessageAttachment.java @@ -0,0 +1,188 @@ +package jenkins.plugins.rocketchatnotifier.workflow.attachments; + +import com.fasterxml.jackson.annotation.JsonIgnoreType; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import hudson.Extension; +import hudson.model.AbstractDescribableImpl; +import hudson.model.Descriptor; +import org.kohsuke.stapler.DataBoundConstructor; +import org.kohsuke.stapler.DataBoundSetter; + +/** + * Created by ben on 07/02/2017. + */ +@JsonInclude(JsonInclude.Include.NON_NULL) +public class MessageAttachment extends AbstractDescribableImpl { + + private String color; + private String text; + private String ts; + + @JsonProperty("thumb_url") + private String thumbUrl; + @JsonProperty("message_link") + private String messageLink; + private Boolean collapsed; + @JsonProperty("author_name") + private String authorName; + private final String title; + + @JsonProperty("author_link") + private String authorLink; + @JsonProperty("author_icon") + private String authorIcon; + @JsonProperty("title_link") + private String titleLink; + @JsonProperty("title_link_download") + private String titleLinkDownload; + @JsonProperty("image_url") + private String imageUrl; + @JsonProperty("audio_url") + private String audioUrl; + @JsonProperty("video_url") + private String videoUrl; + + @DataBoundConstructor + public MessageAttachment(String title) { + this.title = title; + } + + public String getColor() { + return color; + } + + @DataBoundSetter + public void setColor(final String color) { + this.color = color; + } + + public String getText() { + return text; + } + + @DataBoundSetter + public void setText(final String text) { + this.text = text; + } + + public String getTs() { + return ts; + } + + @DataBoundSetter + public void setTs(final String ts) { + this.ts = ts; + } + + public String getThumbUrl() { + return thumbUrl; + } + + @DataBoundSetter + public void setThumbUrl(final String thumbUrl) { + this.thumbUrl = thumbUrl; + } + + public String getMessageLink() { + return messageLink; + } + + @DataBoundSetter + public void setMessageLink(final String messageLink) { + this.messageLink = messageLink; + } + + @DataBoundSetter + public void setCollapsed(final Boolean collapsed) { + if (collapsed) + this.collapsed = collapsed; + } + + public String getAuthorName() { + return authorName; + } + + @DataBoundSetter + public void setAuthorName(final String authorName) { + this.authorName = authorName; + } + + public String getTitle() { + return title; + } + + public Boolean getCollapsed() { + return collapsed; + } + + public String getAuthorLink() { + return authorLink; + } + + public void setAuthorLink(final String authorLink) { + this.authorLink = authorLink; + } + + public String getAuthorIcon() { + return authorIcon; + } + + @DataBoundSetter + public void setAuthorIcon(final String authorIcon) { + this.authorIcon = authorIcon; + } + + public String getTitleLink() { + return titleLink; + } + + @DataBoundSetter + public void setTitleLink(final String titleLink) { + this.titleLink = titleLink; + } + + public String getTitleLinkDownload() { + return titleLinkDownload; + } + + @DataBoundSetter + public void setTitleLinkDownload(final String titleLinkDownload) { + this.titleLinkDownload = titleLinkDownload; + } + + public String getImageUrl() { + return imageUrl; + } + + @DataBoundSetter + public void setImageUrl(final String imageUrl) { + this.imageUrl = imageUrl; + } + + public String getAudioUrl() { + return audioUrl; + } + + @DataBoundSetter + public void setAudioUrl(final String audioUrl) { + this.audioUrl = audioUrl; + } + + public String getVideoUrl() { + return videoUrl; + } + + @DataBoundSetter + public void setVideoUrl(final String videoUrl) { + this.videoUrl = videoUrl; + } + + @Extension + @JsonIgnoreType + public static class DescriptorImpl extends Descriptor { + public String getDisplayName() { + return ""; + } + } +} diff --git a/src/main/resources/jenkins/plugins/rocketchatnotifier/workflow/RocketSendStep/config.jelly b/src/main/resources/jenkins/plugins/rocketchatnotifier/workflow/RocketSendStep/config.jelly index 16ea37bb..b650efa0 100755 --- a/src/main/resources/jenkins/plugins/rocketchatnotifier/workflow/RocketSendStep/config.jelly +++ b/src/main/resources/jenkins/plugins/rocketchatnotifier/workflow/RocketSendStep/config.jelly @@ -1,15 +1,29 @@ - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/jenkins/plugins/rocketchatnotifier/workflow/RocketSendStep/help.html b/src/main/resources/jenkins/plugins/rocketchatnotifier/workflow/RocketSendStep/help.html index 2b3b1650..34574549 100755 --- a/src/main/resources/jenkins/plugins/rocketchatnotifier/workflow/RocketSendStep/help.html +++ b/src/main/resources/jenkins/plugins/rocketchatnotifier/workflow/RocketSendStep/help.html @@ -1,6 +1,6 @@
Simple step for sending a RocketChat message to specified channel.
- Use the advanced settings to override the Slack Plugin global configuration to include: channel.
+ Use the advanced settings to override the RocketChat Plugin global configuration to include: channel.
Please see the RocketChat Plugin global configuration for more details on the fields. Usage Example:
diff --git a/src/main/resources/jenkins/plugins/rocketchatnotifier/workflow/attachments/MessageAttachment/config.jelly b/src/main/resources/jenkins/plugins/rocketchatnotifier/workflow/attachments/MessageAttachment/config.jelly new file mode 100755 index 00000000..f032f0cb --- /dev/null +++ b/src/main/resources/jenkins/plugins/rocketchatnotifier/workflow/attachments/MessageAttachment/config.jelly @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/test/java/jenkins/plugins/rocketchatnotifier/RocketClientIT.java b/src/test/java/jenkins/plugins/rocketchatnotifier/RocketClientIT.java index 30cec29a..786fa320 100644 --- a/src/test/java/jenkins/plugins/rocketchatnotifier/RocketClientIT.java +++ b/src/test/java/jenkins/plugins/rocketchatnotifier/RocketClientIT.java @@ -3,21 +3,35 @@ import org.junit.Before; import org.junit.Test; +import java.util.ArrayList; +import java.util.Map; + /** * Created by mreinhardt on 27.12.16. */ public class RocketClientIT { - private RocketClient client; @Before public void setup() throws Exception { - this.client = new RocketClientImpl("http://localhost:4443/", "admin", "supersecret", "general"); // TODO read from env + this.client = new RocketClientImpl("http://localhost:4443/", "admin", "supersecret", + "general"); // TODO read from env } @Test public void shouldSendMessage() throws Exception { this.client.publish("test"); } + + @Test + public void shouldSendMessageAndEmoJiAndAvatar() throws Exception { + this.client.publish("test", ":sob:", null); + } + + @Test + public void shouldNotFailWhenSendMessageWithEmptyList() throws Exception { + this.client.publish("test", ":sob:", null, new ArrayList>()); + } + } diff --git a/src/test/java/jenkins/plugins/rocketchatnotifier/rocket/RocketChatClientIT.java b/src/test/java/jenkins/plugins/rocketchatnotifier/rocket/RocketChatClientIT.java index 13353aad..16106225 100644 --- a/src/test/java/jenkins/plugins/rocketchatnotifier/rocket/RocketChatClientIT.java +++ b/src/test/java/jenkins/plugins/rocketchatnotifier/rocket/RocketChatClientIT.java @@ -4,6 +4,11 @@ import org.junit.Before; import org.junit.Test; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; @@ -19,11 +24,12 @@ public void setup() throws Exception { String rocketVersionString = System.getProperty("rocket.version", "0.48.2"); int rocketVersion = 48; try { - rocketVersion= Integer.parseInt(rocketVersionString.split("\\.")[1]); + rocketVersion = Integer.parseInt(rocketVersionString.split("\\.")[1]); } catch (Exception ignored) { } if (rocketVersion >= 48) { - this.client = new RocketChatClientImpl("http://localhost:4443/api/", "admin", "supersecret"); // TODO read from env + this.client = new RocketChatClientImpl("http://localhost:4443/api/", "admin", + "supersecret"); // TODO read from env } else { this.client = new LegacyRocketChatClient("http://localhost:4443/api/", "admin", "supersecret"); } @@ -40,5 +46,21 @@ public void shouldSendMessage() throws Exception { this.client.send("general", "test"); } + @Test + public void shouldSendMessageAndEmojiAndAvatar() throws Exception { + this.client.send("general", "test", ":sod:", + "https://talks.bitexpert.de/zendcon16-jenkins-for-php-projects/images/jenkins.png"); + } + + @Test + public void shouldSendMessageWithAttachment() throws Exception { + List> attachments = new ArrayList>(); + Map attachment = new HashMap(); + attachment.put("color", "green"); + attachment.put("text", "Ok les gars"); + attachment.put("collapsed", Boolean.TRUE); + attachments.add(attachment); + this.client.send("general", "test", null, null, attachments); + } } diff --git a/src/test/java/jenkins/plugins/rocketchatnotifier/workflow/RocketSendTest.java b/src/test/java/jenkins/plugins/rocketchatnotifier/workflow/RocketSendTest.java new file mode 100644 index 00000000..25e002d6 --- /dev/null +++ b/src/test/java/jenkins/plugins/rocketchatnotifier/workflow/RocketSendTest.java @@ -0,0 +1,62 @@ +package jenkins.plugins.rocketchatnotifier.workflow; + +import jenkins.plugins.rocketchatnotifier.workflow.attachments.MessageAttachment; +import org.junit.Assert; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * Created by ben on 08/02/2017. + */ +public class RocketSendTest { + + @Test + public void convertMessageAttachmentsShouldConvertCamelCaseToUnderscore() { + RocketSendStep.RocketSendStepExecution rocketSendStepExecution = new RocketSendStep.RocketSendStepExecution(); + List attachments = new ArrayList(); + MessageAttachment messageAttachment = new MessageAttachment("title"); + messageAttachment.setAuthorName("John Doe"); + attachments.add(messageAttachment); + List> maps = rocketSendStepExecution.convertMessageAttachmentsToMaps(attachments); + + Assert.assertNotNull(maps); + Assert.assertTrue(maps.get(0).containsKey("author_name")); + + } + + @Test + public void convertMessageAttachmentsShouldNotConvertNullPropertie() { + RocketSendStep.RocketSendStepExecution rocketSendStepExecution = new RocketSendStep.RocketSendStepExecution(); + List attachments = new ArrayList(); + MessageAttachment messageAttachment = new MessageAttachment("title"); + attachments.add(messageAttachment); + List> maps = rocketSendStepExecution.convertMessageAttachmentsToMaps(attachments); + + Assert.assertNotNull(maps); + Assert.assertFalse(maps.get(0).containsKey("author_name")); + } + + @Test + public void convertMessageAttachmentsShouldConvertAllMaps() { + RocketSendStep.RocketSendStepExecution rocketSendStepExecution = new RocketSendStep.RocketSendStepExecution(); + List attachments = new ArrayList(); + MessageAttachment messageAttachment = new MessageAttachment("title"); + messageAttachment.setText("yolo"); + attachments.add(messageAttachment); + + MessageAttachment messageAttachment2 = new MessageAttachment("title"); + messageAttachment2.setMessageLink("http://github.com"); + attachments.add(messageAttachment2); + List> maps = rocketSendStepExecution.convertMessageAttachmentsToMaps(attachments); + + Assert.assertNotNull(maps); + Assert.assertEquals(2, maps.size()); + Assert.assertEquals("yolo", maps.get(0).get("text")); + Assert.assertEquals("http://github.com", maps.get(1).get("message_link")); + + } + +}