diff --git a/README.md b/README.md index 9937aec59..ff54d9dce 100755 --- a/README.md +++ b/README.md @@ -21,6 +21,13 @@ Create a new ***Secret text*** credential: Select that credential as the value for the ***Integration Token Credential ID*** field: ![image](https://cloud.githubusercontent.com/assets/983526/17971458/ec296bf6-6aa8-11e6-8d19-06d9f1c9d611.png) + +#### Bot user option +This plugin supports sending notifications via bot users. You can enable bot user support from both +global and project configurations. If the notification will be sent to a user via direct message, +default integration sends it via @slackbot, you can use this option if you want to send messages via a bot user. +You need to provide credentials of the bot user for integration token credentials to use this feature. + #### Jenkins Pipeline Support Includes [Jenkins Pipeline](https://github.com/jenkinsci/workflow-plugin) support as of version 2.0: diff --git a/src/main/java/jenkins/plugins/slack/SlackNotifier.java b/src/main/java/jenkins/plugins/slack/SlackNotifier.java index 4878e89aa..05e644d38 100755 --- a/src/main/java/jenkins/plugins/slack/SlackNotifier.java +++ b/src/main/java/jenkins/plugins/slack/SlackNotifier.java @@ -43,6 +43,7 @@ public class SlackNotifier extends Notifier { private String teamDomain; private String authToken; private String authTokenCredentialId; + private boolean botUser; private String room; private String sendAs; private boolean startNotification; @@ -91,6 +92,10 @@ public String getAuthTokenCredentialId() { return authTokenCredentialId; } + public boolean getBotUser() { + return botUser; + } + public String getSendAs() { return sendAs; } @@ -192,7 +197,7 @@ public void setCustomMessage(String customMessage) { } @DataBoundConstructor - public SlackNotifier(final String teamDomain, final String authToken, final String room, final String authTokenCredentialId, + public SlackNotifier(final String teamDomain, final String authToken, final boolean botUser, final String room, final String authTokenCredentialId, final String sendAs, final boolean startNotification, final boolean notifyAborted, final boolean notifyFailure, final boolean notifyNotBuilt, final boolean notifySuccess, final boolean notifyUnstable, final boolean notifyBackToNormal, final boolean notifyRepeatedFailure, final boolean includeTestSummary, CommitInfoChoice commitInfoChoice, @@ -201,6 +206,7 @@ public SlackNotifier(final String teamDomain, final String authToken, final Stri this.teamDomain = teamDomain; this.authToken = authToken; this.authTokenCredentialId = StringUtils.trim(authTokenCredentialId); + this.botUser = botUser; this.room = room; this.sendAs = sendAs; this.startNotification = startNotification; @@ -227,8 +233,10 @@ public SlackService newSlackService(AbstractBuild r, BuildListener listener) { teamDomain = getDescriptor().getTeamDomain(); } String authToken = this.authToken; + boolean botUser = this.botUser; if (StringUtils.isEmpty(authToken)) { authToken = getDescriptor().getToken(); + botUser = getDescriptor().getBotUser(); } String authTokenCredentialId = this.authTokenCredentialId; if (StringUtils.isEmpty(authTokenCredentialId)) { @@ -251,7 +259,7 @@ public SlackService newSlackService(AbstractBuild r, BuildListener listener) { authTokenCredentialId = env.expand(authTokenCredentialId); room = env.expand(room); - return new StandardSlackService(teamDomain, authToken, authTokenCredentialId, room); + return new StandardSlackService(teamDomain, authToken, authTokenCredentialId, botUser, room); } @Override @@ -279,6 +287,7 @@ public static class DescriptorImpl extends BuildStepDescriptor { private String teamDomain; private String token; private String tokenCredentialId; + private boolean botUser; private String room; private String sendAs; @@ -300,6 +309,10 @@ public String getTokenCredentialId() { return tokenCredentialId; } + public boolean getBotUser() { + return botUser; + } + public String getRoom() { return room; } @@ -337,6 +350,7 @@ public SlackNotifier newInstance(StaplerRequest sr, JSONObject json) { String teamDomain = sr.getParameter("slackTeamDomain"); String token = sr.getParameter("slackToken"); String tokenCredentialId = json.getString("tokenCredentialId"); + boolean botUser = "true".equals(sr.getParameter("slackBotUser")); String room = sr.getParameter("slackRoom"); boolean startNotification = "true".equals(sr.getParameter("slackStartNotification")); boolean notifySuccess = "true".equals(sr.getParameter("slackNotifySuccess")); @@ -350,7 +364,7 @@ public SlackNotifier newInstance(StaplerRequest sr, JSONObject json) { CommitInfoChoice commitInfoChoice = CommitInfoChoice.forDisplayName(sr.getParameter("slackCommitInfoChoice")); boolean includeCustomMessage = "on".equals(sr.getParameter("includeCustomMessage")); String customMessage = sr.getParameter("customMessage"); - return new SlackNotifier(teamDomain, token, room, tokenCredentialId, sendAs, startNotification, notifyAborted, + return new SlackNotifier(teamDomain, token, botUser, room, tokenCredentialId, sendAs, startNotification, notifyAborted, notifyFailure, notifyNotBuilt, notifySuccess, notifyUnstable, notifyBackToNormal, notifyRepeatedFailure, includeTestSummary, commitInfoChoice, includeCustomMessage, customMessage); } @@ -360,14 +374,15 @@ public boolean configure(StaplerRequest sr, JSONObject formData) throws FormExce teamDomain = sr.getParameter("slackTeamDomain"); token = sr.getParameter("slackToken"); tokenCredentialId = formData.getJSONObject("slack").getString("tokenCredentialId"); + botUser = "true".equals(sr.getParameter("slackBotUser")); room = sr.getParameter("slackRoom"); sendAs = sr.getParameter("slackSendAs"); save(); return super.configure(sr, formData); } - SlackService getSlackService(final String teamDomain, final String authToken, final String authTokenCredentialId, final String room) { - return new StandardSlackService(teamDomain, authToken, authTokenCredentialId, room); + SlackService getSlackService(final String teamDomain, final String authToken, final String authTokenCredentialId, final boolean botUser, final String room) { + return new StandardSlackService(teamDomain, authToken, authTokenCredentialId, botUser, room); } @Override @@ -378,6 +393,7 @@ public String getDisplayName() { public FormValidation doTestConnection(@QueryParameter("slackTeamDomain") final String teamDomain, @QueryParameter("slackToken") final String authToken, @QueryParameter("tokenCredentialId") final String authTokenCredentialId, + @QueryParameter("slackBotUser") final boolean botUser, @QueryParameter("slackRoom") final String room) throws FormException { try { String targetDomain = teamDomain; @@ -385,8 +401,10 @@ public FormValidation doTestConnection(@QueryParameter("slackTeamDomain") final targetDomain = this.teamDomain; } String targetToken = authToken; + boolean targetBotUser = botUser; if (StringUtils.isEmpty(targetToken)) { targetToken = this.token; + targetBotUser = this.botUser; } String targetTokenCredentialId = authTokenCredentialId; if (StringUtils.isEmpty(targetTokenCredentialId)) { @@ -396,7 +414,7 @@ public FormValidation doTestConnection(@QueryParameter("slackTeamDomain") final if (StringUtils.isEmpty(targetRoom)) { targetRoom = this.room; } - SlackService testSlackService = getSlackService(targetDomain, targetToken, targetTokenCredentialId, targetRoom); + SlackService testSlackService = getSlackService(targetDomain, targetToken, targetTokenCredentialId, targetBotUser, targetRoom); String message = "Slack/Jenkins plugin: you're all set on " + DisplayURLProvider.get().getRoot(); boolean success = testSlackService.publish(message, "good"); return success ? FormValidation.ok("Success") : FormValidation.error("Failure"); @@ -411,6 +429,7 @@ public static class SlackJobProperty extends hudson.model.JobProperty + + + + diff --git a/src/main/resources/jenkins/plugins/slack/SlackNotifier/global.jelly b/src/main/resources/jenkins/plugins/slack/SlackNotifier/global.jelly index 6077129f8..d7725a30a 100755 --- a/src/main/resources/jenkins/plugins/slack/SlackNotifier/global.jelly +++ b/src/main/resources/jenkins/plugins/slack/SlackNotifier/global.jelly @@ -21,6 +21,9 @@ + + + diff --git a/src/main/resources/jenkins/plugins/slack/workflow/SlackSendStep/config.jelly b/src/main/resources/jenkins/plugins/slack/workflow/SlackSendStep/config.jelly index c90e0868c..cf48487ab 100644 --- a/src/main/resources/jenkins/plugins/slack/workflow/SlackSendStep/config.jelly +++ b/src/main/resources/jenkins/plugins/slack/workflow/SlackSendStep/config.jelly @@ -17,6 +17,9 @@ + + + diff --git a/src/main/webapp/help-globalConfig-botUser.html b/src/main/webapp/help-globalConfig-botUser.html new file mode 100644 index 000000000..5fceabb63 --- /dev/null +++ b/src/main/webapp/help-globalConfig-botUser.html @@ -0,0 +1,4 @@ +
+

Bot user option indicates the token belongs to a bot user in Slack.

+

If the notification will be sent to a user via direct message, the default integration sends it via @slackbot, use this option if you want to send messages via a bot user.

+
\ No newline at end of file diff --git a/src/main/webapp/help-projectConfig-botUser.html b/src/main/webapp/help-projectConfig-botUser.html new file mode 100644 index 000000000..5fceabb63 --- /dev/null +++ b/src/main/webapp/help-projectConfig-botUser.html @@ -0,0 +1,4 @@ +
+

Bot user option indicates the token belongs to a bot user in Slack.

+

If the notification will be sent to a user via direct message, the default integration sends it via @slackbot, use this option if you want to send messages via a bot user.

+
\ No newline at end of file diff --git a/src/test/java/jenkins/plugins/slack/SlackNotifierStub.java b/src/test/java/jenkins/plugins/slack/SlackNotifierStub.java index 4a92a96a6..ac84a56d0 100644 --- a/src/test/java/jenkins/plugins/slack/SlackNotifierStub.java +++ b/src/test/java/jenkins/plugins/slack/SlackNotifierStub.java @@ -2,12 +2,12 @@ public class SlackNotifierStub extends SlackNotifier { - public SlackNotifierStub(String teamDomain, String authToken, String authTokenCredentialId, String room, + public SlackNotifierStub(String teamDomain, String authToken, boolean botUser, String room, String authTokenCredentialId, String sendAs, boolean startNotification, boolean notifyAborted, boolean notifyFailure, boolean notifyNotBuilt, boolean notifySuccess, boolean notifyUnstable, boolean notifyBackToNormal, boolean notifyRepeatedFailure, boolean includeTestSummary, CommitInfoChoice commitInfoChoice, boolean includeCustomMessage, String customMessage) { - super(teamDomain, authToken, authTokenCredentialId, room, sendAs, startNotification, notifyAborted, notifyFailure, + super(teamDomain, authToken, botUser, room, authTokenCredentialId, sendAs, startNotification, notifyAborted, notifyFailure, notifyNotBuilt, notifySuccess, notifyUnstable, notifyBackToNormal, notifyRepeatedFailure, includeTestSummary, commitInfoChoice, includeCustomMessage, customMessage); } @@ -21,7 +21,7 @@ public synchronized void load() { } @Override - SlackService getSlackService(final String teamDomain, final String authToken, final String authTokenCredentialId, final String room) { + SlackService getSlackService(final String teamDomain, final String authToken, final String authTokenCredentialId, final boolean botUser, final String room) { return slackService; } diff --git a/src/test/java/jenkins/plugins/slack/SlackNotifierTest.java b/src/test/java/jenkins/plugins/slack/SlackNotifierTest.java index ccc38c8d1..b216681d6 100644 --- a/src/test/java/jenkins/plugins/slack/SlackNotifierTest.java +++ b/src/test/java/jenkins/plugins/slack/SlackNotifierTest.java @@ -52,7 +52,7 @@ public void testDoTestConnection() { } descriptor.setSlackService(slackServiceStub); try { - FormValidation result = descriptor.doTestConnection("teamDomain", "authToken", "authTokenCredentialId", "room"); + FormValidation result = descriptor.doTestConnection("teamDomain", "authToken", "authTokenCredentialId", false,"room"); assertEquals(result.kind, expectedResult); } catch (Descriptor.FormException e) { e.printStackTrace(); diff --git a/src/test/java/jenkins/plugins/slack/StandardSlackServiceStub.java b/src/test/java/jenkins/plugins/slack/StandardSlackServiceStub.java index 2bee39ae7..eb7d6230a 100644 --- a/src/test/java/jenkins/plugins/slack/StandardSlackServiceStub.java +++ b/src/test/java/jenkins/plugins/slack/StandardSlackServiceStub.java @@ -4,8 +4,8 @@ public class StandardSlackServiceStub extends StandardSlackService { private HttpClientStub httpClientStub; - public StandardSlackServiceStub(String teamDomain, String token, String tokenCredentialId, String roomId) { - super(teamDomain, token, tokenCredentialId, roomId); + public StandardSlackServiceStub(String teamDomain, String token, String tokenCredentialId, boolean botUser, String roomId) { + super(teamDomain, token, tokenCredentialId, botUser, roomId); } @Override diff --git a/src/test/java/jenkins/plugins/slack/StandardSlackServiceTest.java b/src/test/java/jenkins/plugins/slack/StandardSlackServiceTest.java index 69539da6a..48f90d1f7 100755 --- a/src/test/java/jenkins/plugins/slack/StandardSlackServiceTest.java +++ b/src/test/java/jenkins/plugins/slack/StandardSlackServiceTest.java @@ -13,7 +13,7 @@ public class StandardSlackServiceTest { */ @Test public void publishWithBadHostShouldNotRethrowExceptions() { - StandardSlackService service = new StandardSlackService("foo", "token", null, "#general"); + StandardSlackService service = new StandardSlackService("foo", "token", null, false, "#general"); service.setHost("hostvaluethatwillcausepublishtofail"); service.publish("message"); } @@ -23,7 +23,7 @@ public void publishWithBadHostShouldNotRethrowExceptions() { */ @Test public void invalidTeamDomainShouldFail() { - StandardSlackService service = new StandardSlackService("my", "token", null, "#general"); + StandardSlackService service = new StandardSlackService("my", "token", null, false, "#general"); service.publish("message"); } @@ -32,13 +32,13 @@ public void invalidTeamDomainShouldFail() { */ @Test public void invalidTokenShouldFail() { - StandardSlackService service = new StandardSlackService("tinyspeck", "token", null, "#general"); + StandardSlackService service = new StandardSlackService("tinyspeck", "token", null, false, "#general"); service.publish("message"); } @Test public void publishToASingleRoomSendsASingleMessage() { - StandardSlackServiceStub service = new StandardSlackServiceStub("domain", "token", null, "#room1"); + StandardSlackServiceStub service = new StandardSlackServiceStub("domain", "token", null, false, "#room1"); HttpClientStub httpClientStub = new HttpClientStub(); service.setHttpClient(httpClientStub); service.publish("message"); @@ -47,7 +47,7 @@ public void publishToASingleRoomSendsASingleMessage() { @Test public void publishToMultipleRoomsSendsAMessageToEveryRoom() { - StandardSlackServiceStub service = new StandardSlackServiceStub("domain", "token", null, "#room1,#room2,#room3"); + StandardSlackServiceStub service = new StandardSlackServiceStub("domain", "token", null, false, "#room1,#room2,#room3"); HttpClientStub httpClientStub = new HttpClientStub(); service.setHttpClient(httpClientStub); service.publish("message"); @@ -56,7 +56,7 @@ public void publishToMultipleRoomsSendsAMessageToEveryRoom() { @Test public void successfulPublishToASingleRoomReturnsTrue() { - StandardSlackServiceStub service = new StandardSlackServiceStub("domain", "token", null, "#room1"); + StandardSlackServiceStub service = new StandardSlackServiceStub("domain", "token", null, false, "#room1"); HttpClientStub httpClientStub = new HttpClientStub(); httpClientStub.setHttpStatus(HttpStatus.SC_OK); service.setHttpClient(httpClientStub); @@ -65,7 +65,7 @@ public void successfulPublishToASingleRoomReturnsTrue() { @Test public void successfulPublishToMultipleRoomsReturnsTrue() { - StandardSlackServiceStub service = new StandardSlackServiceStub("domain", "token", null, "#room1,#room2,#room3"); + StandardSlackServiceStub service = new StandardSlackServiceStub("domain", "token", null, false, "#room1,#room2,#room3"); HttpClientStub httpClientStub = new HttpClientStub(); httpClientStub.setHttpStatus(HttpStatus.SC_OK); service.setHttpClient(httpClientStub); @@ -74,7 +74,7 @@ public void successfulPublishToMultipleRoomsReturnsTrue() { @Test public void failedPublishToASingleRoomReturnsFalse() { - StandardSlackServiceStub service = new StandardSlackServiceStub("domain", "token", null, "#room1"); + StandardSlackServiceStub service = new StandardSlackServiceStub("domain", "token", null, false, "#room1"); HttpClientStub httpClientStub = new HttpClientStub(); httpClientStub.setHttpStatus(HttpStatus.SC_NOT_FOUND); service.setHttpClient(httpClientStub); @@ -83,7 +83,7 @@ public void failedPublishToASingleRoomReturnsFalse() { @Test public void singleFailedPublishToMultipleRoomsReturnsFalse() { - StandardSlackServiceStub service = new StandardSlackServiceStub("domain", "token", null, "#room1,#room2,#room3"); + StandardSlackServiceStub service = new StandardSlackServiceStub("domain", "token", null, false, "#room1,#room2,#room3"); HttpClientStub httpClientStub = new HttpClientStub(); httpClientStub.setFailAlternateResponses(true); httpClientStub.setHttpStatus(HttpStatus.SC_OK); @@ -93,7 +93,17 @@ public void singleFailedPublishToMultipleRoomsReturnsFalse() { @Test public void publishToEmptyRoomReturnsTrue() { - StandardSlackServiceStub service = new StandardSlackServiceStub("domain", "token", null, ""); + StandardSlackServiceStub service = new StandardSlackServiceStub("domain", "token", null, false, ""); + HttpClientStub httpClientStub = new HttpClientStub(); + httpClientStub.setHttpStatus(HttpStatus.SC_OK); + service.setHttpClient(httpClientStub); + assertTrue(service.publish("message")); + } + + + @Test + public void sendAsBotUserReturnsTrue() { + StandardSlackServiceStub service = new StandardSlackServiceStub("domain", "token", null, true, "#room1"); HttpClientStub httpClientStub = new HttpClientStub(); httpClientStub.setHttpStatus(HttpStatus.SC_OK); service.setHttpClient(httpClientStub); diff --git a/src/test/java/jenkins/plugins/slack/config/BackwordsCompatible_1_8_SlackNotifierTest.java b/src/test/java/jenkins/plugins/slack/config/BackwordsCompatible_1_8_SlackNotifierTest.java index f5bf011db..c474200d7 100644 --- a/src/test/java/jenkins/plugins/slack/config/BackwordsCompatible_1_8_SlackNotifierTest.java +++ b/src/test/java/jenkins/plugins/slack/config/BackwordsCompatible_1_8_SlackNotifierTest.java @@ -42,6 +42,7 @@ public void testBasicMigration() { assertEquals("jenkins-slack-plugin", notifier.getTeamDomain()); assertEquals("auth-token-for-test", notifier.getAuthToken()); + assertEquals(false, notifier.getBotUser()); assertEquals("#slack-plugin-testing", notifier.getRoom()); assertFalse(notifier.getStartNotification()); @@ -68,6 +69,7 @@ public void testGlobalSettingsOverriden() { assertEquals("jenkins-slack-plugin", notifier.getTeamDomain()); assertEquals("auth-token-for-test", notifier.getAuthToken()); + assertEquals(false, notifier.getBotUser()); assertEquals("#slack-plugin-testing", notifier.getRoom()); assertFalse(notifier.getStartNotification()); @@ -94,6 +96,7 @@ public void testGlobalSettingsNotOverridden() throws IOException { assertEquals("", notifier.getTeamDomain()); assertEquals("", notifier.getAuthToken()); + assertEquals(false, notifier.getBotUser()); assertEquals("", notifier.getRoom()); assertFalse(notifier.getStartNotification()); @@ -148,6 +151,7 @@ public void testMigrationOfSomeJobs() throws IOException { assertEquals("", notifier.getTeamDomain()); assertEquals("", notifier.getAuthToken()); + assertEquals(false, notifier.getBotUser()); assertEquals("", notifier.getRoom()); assertTrue(notifier.getStartNotification()); diff --git a/src/test/java/jenkins/plugins/slack/workflow/SlackSendStepTest.java b/src/test/java/jenkins/plugins/slack/workflow/SlackSendStepTest.java index f04319352..87fa97201 100644 --- a/src/test/java/jenkins/plugins/slack/workflow/SlackSendStepTest.java +++ b/src/test/java/jenkins/plugins/slack/workflow/SlackSendStepTest.java @@ -56,6 +56,7 @@ public void testStepOverrides() throws Exception { SlackSendStep slackSendStep = new SlackSendStep("message"); slackSendStep.setToken("token"); slackSendStep.setTokenCredentialId("tokenCredentialId"); + slackSendStep.setBotUser(false); slackSendStep.setTeamDomain("teamDomain"); slackSendStep.setChannel("channel"); slackSendStep.setColor("good"); @@ -66,16 +67,16 @@ public void testStepOverrides() throws Exception { stepExecution.listener = taskListenerMock; when(slackDescMock.getToken()).thenReturn("differentToken"); - + when(slackDescMock.getBotUser()).thenReturn(true); when(taskListenerMock.getLogger()).thenReturn(printStreamMock); doNothing().when(printStreamMock).println(); - when(stepExecution.getSlackService(anyString(), anyString(), anyString(), anyString())).thenReturn(slackServiceMock); + when(stepExecution.getSlackService(anyString(), anyString(), anyString(), anyBoolean(), anyString())).thenReturn(slackServiceMock); when(slackServiceMock.publish(anyString(), anyString())).thenReturn(true); stepExecution.run(); - verify(stepExecution, times(1)).getSlackService("teamDomain", "token", "tokenCredentialId", "channel"); + verify(stepExecution, times(1)).getSlackService("teamDomain", "token", "tokenCredentialId", false, "channel"); verify(slackServiceMock, times(1)).publish("message", "good"); assertFalse(stepExecution.step.isFailOnError()); } @@ -93,15 +94,16 @@ public void testValuesForGlobalConfig() throws Exception { when(slackDescMock.getTeamDomain()).thenReturn("globalTeamDomain"); when(slackDescMock.getToken()).thenReturn("globalToken"); when(slackDescMock.getTokenCredentialId()).thenReturn("globalTokenCredentialId"); + when(slackDescMock.getBotUser()).thenReturn(false); when(slackDescMock.getRoom()).thenReturn("globalChannel"); when(taskListenerMock.getLogger()).thenReturn(printStreamMock); doNothing().when(printStreamMock).println(); - when(stepExecution.getSlackService(anyString(), anyString(), anyString(), anyString())).thenReturn(slackServiceMock); + when(stepExecution.getSlackService(anyString(), anyString(), anyString(), anyBoolean(), anyString())).thenReturn(slackServiceMock); stepExecution.run(); - verify(stepExecution, times(1)).getSlackService("globalTeamDomain", "globalToken", "globalTokenCredentialId", "globalChannel"); + verify(stepExecution, times(1)).getSlackService("globalTeamDomain", "globalToken", "globalTokenCredentialId", false, "globalChannel"); verify(slackServiceMock, times(1)).publish("message", ""); assertNull(stepExecution.step.getTeamDomain()); assertNull(stepExecution.step.getToken()); @@ -125,7 +127,7 @@ public void testNonNullEmptyColor() throws Exception { when(taskListenerMock.getLogger()).thenReturn(printStreamMock); doNothing().when(printStreamMock).println(); - when(stepExecution.getSlackService(anyString(), anyString(), anyString(), anyString())).thenReturn(slackServiceMock); + when(stepExecution.getSlackService(anyString(), anyString(), anyString(), anyBoolean(), anyString())).thenReturn(slackServiceMock); stepExecution.run(); verify(slackServiceMock, times(1)).publish("message", ""); diff --git a/src/test/resources/jenkins/plugins/slack/config/BackwordsCompatible_1_8_SlackNotifierTest/testGlobalSettingsNotOverridden/jobs/Test_Slack_Plugin/config.xml b/src/test/resources/jenkins/plugins/slack/config/BackwordsCompatible_1_8_SlackNotifierTest/testGlobalSettingsNotOverridden/jobs/Test_Slack_Plugin/config.xml index 73edbacb6..7b976eaf0 100644 --- a/src/test/resources/jenkins/plugins/slack/config/BackwordsCompatible_1_8_SlackNotifierTest/testGlobalSettingsNotOverridden/jobs/Test_Slack_Plugin/config.xml +++ b/src/test/resources/jenkins/plugins/slack/config/BackwordsCompatible_1_8_SlackNotifierTest/testGlobalSettingsNotOverridden/jobs/Test_Slack_Plugin/config.xml @@ -38,6 +38,7 @@ +