From ab44500a16a7db03da37c172282399ca3bb90410 Mon Sep 17 00:00:00 2001 From: Marc Guillemot Date: Tue, 4 Sep 2018 16:42:48 +0200 Subject: [PATCH 1/4] simplify and groovify example --- README.md | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 225c8030..a18a69d2 100644 --- a/README.md +++ b/README.md @@ -69,18 +69,18 @@ Additionally you can pass a JSONArray as a String in order to send complex messages, as per the example: ``` -import net.sf.json.JSONArray; -import net.sf.json.JSONObject; -node { - JSONArray attachments = new JSONArray(); - JSONObject attachment = new JSONObject(); - - attachment.put('text','I find your lack of faith disturbing!'); - attachment.put('fallback','Hey, Vader seems to be mad at you.'); - attachment.put('color','#ff0000'); +import groovy.json.JsonOutput - attachments.add(attachment); - slackSend(color: '#00FF00', channel: '@gustavo.maia', attachments: attachments.toString()) +node { + def attachments = [ + [ + text: 'I find your lack of faith disturbing!', + fallback: 'Hey, Vader seems to be mad at you.', + color: '#ff0000' + ] + ] + + slackSend(color: '#00FF00', channel: '@gustavo.maia', attachments: JsonOutput.toJson(attachments)) } ``` For more information about slack messages see [Slack Messages Api](https://api.slack.com/docs/messages) From 5a4fe7d3b23f2ac51efbbadf06b865d4b97316ec Mon Sep 17 00:00:00 2001 From: Marc Guillemot Date: Wed, 6 Mar 2019 11:43:12 +0100 Subject: [PATCH 2/4] use JsonOutput.toJSON to convert attachments to JSON --- .../plugins/slack/workflow/SlackSendStep.java | 84 +++++++++++-------- .../slack/workflow/SlackSendStepTest.java | 75 ++++++++++++----- 2 files changed, 106 insertions(+), 53 deletions(-) diff --git a/src/main/java/jenkins/plugins/slack/workflow/SlackSendStep.java b/src/main/java/jenkins/plugins/slack/workflow/SlackSendStep.java index 89cb66a4..fe34f2d2 100644 --- a/src/main/java/jenkins/plugins/slack/workflow/SlackSendStep.java +++ b/src/main/java/jenkins/plugins/slack/workflow/SlackSendStep.java @@ -1,8 +1,28 @@ package jenkins.plugins.slack.workflow; +import static com.cloudbees.plugins.credentials.CredentialsProvider.lookupCredentials; + +import java.util.Objects; +import java.util.Set; + +import javax.annotation.Nonnull; + +import org.jenkinsci.plugins.plaincredentials.StringCredentials; +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.jenkinsci.plugins.workflow.steps.SynchronousNonBlockingStepExecution; +import org.kohsuke.stapler.AncestorInPath; +import org.kohsuke.stapler.DataBoundConstructor; +import org.kohsuke.stapler.DataBoundSetter; +import org.kohsuke.stapler.QueryParameter; + import com.cloudbees.plugins.credentials.common.StandardListBoxModel; import com.cloudbees.plugins.credentials.domains.HostnameRequirement; import com.google.common.collect.ImmutableSet; + +import groovy.json.JsonOutput; import hudson.AbortException; import hudson.Extension; import hudson.Util; @@ -23,22 +43,6 @@ import net.sf.json.JSONException; import net.sf.json.JSONObject; import net.sf.json.groovy.JsonSlurper; -import org.jenkinsci.plugins.plaincredentials.StringCredentials; -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.jenkinsci.plugins.workflow.steps.SynchronousNonBlockingStepExecution; -import org.kohsuke.stapler.AncestorInPath; -import org.kohsuke.stapler.DataBoundConstructor; -import org.kohsuke.stapler.DataBoundSetter; -import org.kohsuke.stapler.QueryParameter; - -import java.util.Objects; -import java.util.Set; -import javax.annotation.Nonnull; - -import static com.cloudbees.plugins.credentials.CredentialsProvider.lookupCredentials; /** * Workflow step to send a Slack channel notification. @@ -54,7 +58,7 @@ public class SlackSendStep extends Step { private String baseUrl; private String teamDomain; private boolean failOnError; - private String attachments; + private Object attachments; private boolean replyBroadcast; @@ -139,11 +143,11 @@ public void setFailOnError(boolean failOnError) { } @DataBoundSetter - public void setAttachments(String attachments) { + public void setAttachments(Object attachments) { this.attachments = attachments; } - public String getAttachments() { + public Object getAttachments() { return attachments; } @@ -254,22 +258,9 @@ protected SlackResponse run() throws Exception { SlackService slackService = getSlackService( baseUrl, teamDomain, token, tokenCredentialId, botUser, channel, step.replyBroadcast ); - boolean publishSuccess; + final boolean publishSuccess; if (step.attachments != null) { - JsonSlurper jsonSlurper = new JsonSlurper(); - JSON json; - try { - json = jsonSlurper.parseText(step.attachments); - } catch (JSONException e) { - listener.error(Messages.NotificationFailedWithException(e)); - return null; - } - if (!(json instanceof JSONArray)) { - listener.error(Messages - .NotificationFailedWithException(new IllegalArgumentException("Attachments must be JSONArray"))); - return null; - } - JSONArray jsonArray = (JSONArray) json; + JSONArray jsonArray = getAttachmentsAsJSONArray(); for (Object object : jsonArray) { if (object instanceof JSONObject) { JSONObject jsonNode = ((JSONObject) object); @@ -310,6 +301,31 @@ protected SlackResponse run() throws Exception { return response; } + JSONArray getAttachmentsAsJSONArray() throws Exception { + final TaskListener listener = getContext().get(TaskListener.class); + final String jsonString; + if (step.attachments instanceof String) { + jsonString = (String) step.attachments; + } + else { + jsonString = JsonOutput.toJson(step.attachments); + } + + JsonSlurper jsonSlurper = new JsonSlurper(); + JSON json = null; + try { + json = jsonSlurper.parseText(jsonString); + } catch (JSONException e) { + listener.error(Messages.NotificationFailedWithException(e)); + return null; + } + if(!(json instanceof JSONArray)){ + listener.error(Messages.NotificationFailedWithException(new IllegalArgumentException("Attachments must be JSONArray"))); + return null; + } + return (JSONArray) json; + } + private String defaultIfEmpty(String value) { return Util.fixEmpty(value) != null ? value : Messages.SlackSendStepValuesEmptyMessage(); } diff --git a/src/test/java/jenkins/plugins/slack/workflow/SlackSendStepTest.java b/src/test/java/jenkins/plugins/slack/workflow/SlackSendStepTest.java index bbbd178f..c27ac77e 100644 --- a/src/test/java/jenkins/plugins/slack/workflow/SlackSendStepTest.java +++ b/src/test/java/jenkins/plugins/slack/workflow/SlackSendStepTest.java @@ -1,11 +1,22 @@ package jenkins.plugins.slack.workflow; -import hudson.model.TaskListener; -import jenkins.model.Jenkins; -import jenkins.plugins.slack.SlackNotifier; -import jenkins.plugins.slack.SlackService; -import net.sf.json.JSONArray; -import net.sf.json.JSONObject; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.mockito.Matchers.anyBoolean; +import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import static org.powermock.api.mockito.PowerMockito.spy; + +import java.io.IOException; +import java.io.PrintStream; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + import org.apache.commons.io.IOUtils; import org.jenkinsci.plugins.workflow.steps.StepContext; import org.junit.Before; @@ -16,19 +27,12 @@ import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; -import java.io.IOException; -import java.io.PrintStream; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.mockito.Mockito.anyBoolean; -import static org.mockito.Mockito.anyString; -import static org.mockito.Mockito.doNothing; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; -import static org.powermock.api.mockito.PowerMockito.spy; +import hudson.model.TaskListener; +import jenkins.model.Jenkins; +import jenkins.plugins.slack.SlackNotifier; +import jenkins.plugins.slack.SlackService; +import net.sf.json.JSONArray; +import net.sf.json.JSONObject; /** * Traditional Unit tests, allows testing null Jenkins.get() @@ -114,6 +118,39 @@ public void testStepWithAttachments() throws Exception { } + @Test + public void testStepWithAttachmentsAsListOfMap() throws Exception { + SlackSendStep step = new SlackSendStep(); + step.setMessage("message"); + + Map attachment1 = new HashMap<>(); + attachment1.put("title", "Title of the message"); + attachment1.put("author_name", "Name of the author"); + attachment1.put("author_icon", "Avatar for author"); + + step.setAttachments(Arrays.asList(attachment1)); + SlackSendStep.SlackSendStepExecution stepExecution = spy(new SlackSendStep.SlackSendStepExecution(step, stepContextMock)); + + when(Jenkins.get()).thenReturn(jenkins); + + when(taskListenerMock.getLogger()).thenReturn(printStreamMock); + doNothing().when(printStreamMock).println(); + + when(stepExecution.getSlackService(anyString(), anyString(), anyString(), anyString(), anyBoolean(), anyString(), anyBoolean())).thenReturn(slackServiceMock); + + stepExecution.run(); + verify(slackServiceMock, times(0)).publish("message", ""); + + JSONArray expectedAttachments = new JSONArray(); + JSONObject jsonObject = new JSONObject(); + jsonObject.put("title","Title of the message"); + jsonObject.put("author_name","Name of the author"); + jsonObject.put("author_icon","Avatar for author"); + jsonObject.put("fallback","message"); + expectedAttachments.add(jsonObject); + verify(slackServiceMock, times(1)).publish("message", expectedAttachments, ""); + } + @Test public void testValuesForGlobalConfig() throws Exception { SlackSendStep step = new SlackSendStep(); From a97c9977d7c13b42e44db92298cd477c956bc6bf Mon Sep 17 00:00:00 2001 From: Marc Guillemot Date: Wed, 6 Mar 2019 11:44:32 +0100 Subject: [PATCH 3/4] simplify example with attachments --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index 0abb9a20..e090fb7c 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,6 @@ Additionally you can pass a JSONArray as a String in order to send complex messages, as per the example: ``` -import groovy.json.JsonOutput node { def attachments = [ @@ -43,7 +42,7 @@ node { ] ] - slackSend(color: '#00FF00', channel: '@gustavo.maia', attachments: JsonOutput.toJson(attachments)) + slackSend(color: '#00FF00', channel: '@gustavo.maia', attachments: attachments) } ``` For more information about slack messages see [Slack Messages Api](https://api.slack.com/docs/messages) From 74e087db0f50c81aba57aa9e8fbbfb2325821ad2 Mon Sep 17 00:00:00 2001 From: Marc Guillemot Date: Fri, 15 Mar 2019 10:38:43 +0100 Subject: [PATCH 4/4] changed import order --- .../plugins/slack/workflow/SlackSendStep.java | 35 +++++++-------- .../slack/workflow/SlackSendStepTest.java | 45 +++++++++---------- 2 files changed, 38 insertions(+), 42 deletions(-) diff --git a/src/main/java/jenkins/plugins/slack/workflow/SlackSendStep.java b/src/main/java/jenkins/plugins/slack/workflow/SlackSendStep.java index fe34f2d2..ae92bf5d 100644 --- a/src/main/java/jenkins/plugins/slack/workflow/SlackSendStep.java +++ b/src/main/java/jenkins/plugins/slack/workflow/SlackSendStep.java @@ -1,27 +1,8 @@ package jenkins.plugins.slack.workflow; -import static com.cloudbees.plugins.credentials.CredentialsProvider.lookupCredentials; - -import java.util.Objects; -import java.util.Set; - -import javax.annotation.Nonnull; - -import org.jenkinsci.plugins.plaincredentials.StringCredentials; -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.jenkinsci.plugins.workflow.steps.SynchronousNonBlockingStepExecution; -import org.kohsuke.stapler.AncestorInPath; -import org.kohsuke.stapler.DataBoundConstructor; -import org.kohsuke.stapler.DataBoundSetter; -import org.kohsuke.stapler.QueryParameter; - import com.cloudbees.plugins.credentials.common.StandardListBoxModel; import com.cloudbees.plugins.credentials.domains.HostnameRequirement; import com.google.common.collect.ImmutableSet; - import groovy.json.JsonOutput; import hudson.AbortException; import hudson.Extension; @@ -43,6 +24,22 @@ import net.sf.json.JSONException; import net.sf.json.JSONObject; import net.sf.json.groovy.JsonSlurper; +import org.jenkinsci.plugins.plaincredentials.StringCredentials; +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.jenkinsci.plugins.workflow.steps.SynchronousNonBlockingStepExecution; +import org.kohsuke.stapler.AncestorInPath; +import org.kohsuke.stapler.DataBoundConstructor; +import org.kohsuke.stapler.DataBoundSetter; +import org.kohsuke.stapler.QueryParameter; + +import java.util.Objects; +import java.util.Set; +import javax.annotation.Nonnull; + +import static com.cloudbees.plugins.credentials.CredentialsProvider.lookupCredentials; /** * Workflow step to send a Slack channel notification. diff --git a/src/test/java/jenkins/plugins/slack/workflow/SlackSendStepTest.java b/src/test/java/jenkins/plugins/slack/workflow/SlackSendStepTest.java index c27ac77e..f8b7e7e1 100644 --- a/src/test/java/jenkins/plugins/slack/workflow/SlackSendStepTest.java +++ b/src/test/java/jenkins/plugins/slack/workflow/SlackSendStepTest.java @@ -1,22 +1,11 @@ package jenkins.plugins.slack.workflow; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.mockito.Matchers.anyBoolean; -import static org.mockito.Matchers.anyString; -import static org.mockito.Mockito.doNothing; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; -import static org.powermock.api.mockito.PowerMockito.spy; - -import java.io.IOException; -import java.io.PrintStream; -import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; - +import hudson.model.TaskListener; +import jenkins.model.Jenkins; +import jenkins.plugins.slack.SlackNotifier; +import jenkins.plugins.slack.SlackService; +import net.sf.json.JSONArray; +import net.sf.json.JSONObject; import org.apache.commons.io.IOUtils; import org.jenkinsci.plugins.workflow.steps.StepContext; import org.junit.Before; @@ -27,12 +16,22 @@ import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; -import hudson.model.TaskListener; -import jenkins.model.Jenkins; -import jenkins.plugins.slack.SlackNotifier; -import jenkins.plugins.slack.SlackService; -import net.sf.json.JSONArray; -import net.sf.json.JSONObject; +import java.io.IOException; +import java.io.PrintStream; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.mockito.Mockito.anyBoolean; +import static org.mockito.Mockito.anyString; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import static org.powermock.api.mockito.PowerMockito.spy; /** * Traditional Unit tests, allows testing null Jenkins.get()