Added message for when a reviewer is added. Change-Id: I7b76c60aa572071546c51b1d9f605b0fe484e44e (cherry picked from commit 0bc17448ce3347136a3ab6738130e1b12c39667f)
diff --git a/README.md b/README.md index 4b563ec..bd82f8f 100644 --- a/README.md +++ b/README.md
@@ -112,3 +112,6 @@ publish-on-comment-added - boolean (true/false) Whether a Slack notification should be published when a comment is added to a review. + publish-on-reviewer-added - boolean (true/false) + Whether a Slack notification should be published when a reviewer is + added to a review.
diff --git a/src/main/java/com/cisco/gerrit/plugins/slack/PublishEventListener.java b/src/main/java/com/cisco/gerrit/plugins/slack/PublishEventListener.java index 26a288e..677a586 100644 --- a/src/main/java/com/cisco/gerrit/plugins/slack/PublishEventListener.java +++ b/src/main/java/com/cisco/gerrit/plugins/slack/PublishEventListener.java
@@ -28,6 +28,7 @@ import com.google.gerrit.server.events.CommentAddedEvent; import com.google.gerrit.server.events.Event; import com.google.gerrit.server.events.PatchSetCreatedEvent; +import com.google.gerrit.server.events.ReviewerAddedEvent; import com.google.inject.Inject; import com.google.inject.Singleton; import org.slf4j.Logger; @@ -89,6 +90,17 @@ messageGenerator = MessageGeneratorFactory.newInstance( commentAddedEvent, config); } + else if (event instanceof ReviewerAddedEvent) + { + ReviewerAddedEvent reviewerAddedEvent; + reviewerAddedEvent = (ReviewerAddedEvent) event; + + config = new ProjectConfig(configFactory, + reviewerAddedEvent.change.get().project); + + messageGenerator = MessageGeneratorFactory.newInstance( + reviewerAddedEvent, config); + } else { LOGGER.debug("Event " + event + " not currently supported");
diff --git a/src/main/java/com/cisco/gerrit/plugins/slack/config/ProjectConfig.java b/src/main/java/com/cisco/gerrit/plugins/slack/config/ProjectConfig.java index 717037e..6c83713 100644 --- a/src/main/java/com/cisco/gerrit/plugins/slack/config/ProjectConfig.java +++ b/src/main/java/com/cisco/gerrit/plugins/slack/config/ProjectConfig.java
@@ -50,6 +50,7 @@ private boolean publishOnPatchSetCreated; private boolean publishOnChangeMerged; private boolean publishOnCommentAdded; + private boolean publishOnReviewerAdded; /** * Creates a new instance of the ProjectConfig class for the given project. @@ -100,6 +101,11 @@ configFactory.getFromProjectConfigWithInheritance( projectNameKey, CONFIG_NAME).getBoolean( "publish-on-comment-added", true); + + publishOnReviewerAdded = + configFactory.getFromProjectConfigWithInheritance( + projectNameKey, CONFIG_NAME).getBoolean( + "publish-on-reviewer-added", true); } catch (NoSuchProjectException e) { @@ -147,4 +153,9 @@ { return publishOnCommentAdded; } + + public boolean shouldPublishOnReviewerAdded() + { + return publishOnReviewerAdded; + } }
diff --git a/src/main/java/com/cisco/gerrit/plugins/slack/message/CommentAddedMessageGenerator.java b/src/main/java/com/cisco/gerrit/plugins/slack/message/CommentAddedMessageGenerator.java index 9c21abe..b319ee1 100644 --- a/src/main/java/com/cisco/gerrit/plugins/slack/message/CommentAddedMessageGenerator.java +++ b/src/main/java/com/cisco/gerrit/plugins/slack/message/CommentAddedMessageGenerator.java
@@ -26,7 +26,7 @@ /** * A specific MessageGenerator implementation that can generate a message for - * a commend added event. + * a comment added event. * * @author Kenneth Pedersen */
diff --git a/src/main/java/com/cisco/gerrit/plugins/slack/message/MessageGeneratorFactory.java b/src/main/java/com/cisco/gerrit/plugins/slack/message/MessageGeneratorFactory.java index a068c51..90147d9 100644 --- a/src/main/java/com/cisco/gerrit/plugins/slack/message/MessageGeneratorFactory.java +++ b/src/main/java/com/cisco/gerrit/plugins/slack/message/MessageGeneratorFactory.java
@@ -22,6 +22,7 @@ import com.google.gerrit.server.events.CommentAddedEvent; import com.google.gerrit.server.events.Event; import com.google.gerrit.server.events.PatchSetCreatedEvent; +import com.google.gerrit.server.events.ReviewerAddedEvent; /** * Factory used to create event specific MessageGenerator instances. @@ -72,11 +73,11 @@ /** * Creates a new MessageGenerator for comment added events. * - * @param event A CommendAddedEvent instance + * @param event A CommentAddedEvent instance * @param config A ProjectConfig instance for the given event * * @return A MessageGenerator instance capable of generating a message for - * a CommendAddedEvent. + * a CommentAddedEvent. */ public static MessageGenerator newInstance(CommentAddedEvent event, ProjectConfig config) @@ -87,6 +88,23 @@ return messageGenerator; } + /** + * Creates a new MessageGenerator for reviewer added events. + * + * @param event A ReviewerAddedEvent instance + * @param config A ProjectConfig instance for the given event + * + * @return A MessageGenerator instance capable of generating a message for + * a ReviewerAddedEvent. + */ + public static MessageGenerator newInstance(ReviewerAddedEvent event, + ProjectConfig config) + { + ReviewerAddedMessageGenerator messageGenerator; + messageGenerator = new ReviewerAddedMessageGenerator(event, config); + + return messageGenerator; + } /** * Creates a new MessageGenerator for unsupported events.
diff --git a/src/main/java/com/cisco/gerrit/plugins/slack/message/ReviewerAddedMessageGenerator.java b/src/main/java/com/cisco/gerrit/plugins/slack/message/ReviewerAddedMessageGenerator.java new file mode 100644 index 0000000..587b599 --- /dev/null +++ b/src/main/java/com/cisco/gerrit/plugins/slack/message/ReviewerAddedMessageGenerator.java
@@ -0,0 +1,104 @@ +/* + * Copyright 2016 Cisco Systems, Inc. + * + * 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.cisco.gerrit.plugins.slack.message; + +import com.cisco.gerrit.plugins.slack.config.ProjectConfig; +import com.cisco.gerrit.plugins.slack.util.ResourceHelper; +import com.google.common.base.Ascii; +import com.google.gerrit.server.events.ReviewerAddedEvent; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * A specific MessageGenerator implementation that can generate a message for + * a reviewer added event. + * + * @author Nathan Wall + */ +public class ReviewerAddedMessageGenerator extends MessageGenerator +{ + /** + * The class logger instance. + */ + private static final Logger LOGGER = + LoggerFactory.getLogger(ReviewerAddedMessageGenerator.class); + + private ProjectConfig config; + private ReviewerAddedEvent event; + + /** + * Creates a new ReviewerAddedMessageGenerator instance using the provided + * ReviewerAddedEvent instance. + * + * @param event The ReviewerAddedEvent instance to generate a message for. + */ + protected ReviewerAddedMessageGenerator(ReviewerAddedEvent event, + ProjectConfig config) + { + if (event == null) + { + throw new NullPointerException("event cannot be null"); + } + + this.event = event; + this.config = config; + } + + @Override + public boolean shouldPublish() + { + return config.isEnabled() && config.shouldPublishOnReviewerAdded(); + } + + @Override + public String generate() + { + String message; + message = ""; + + try + { + String template; + template = ResourceHelper.loadNamedResourceAsString( + "basic-message-template.json"); + + StringBuilder text; + text = new StringBuilder(); + + text.append(escape(event.reviewer.get().name)); + text.append(" was added to review\\n>>>"); + text.append(escape(event.change.get().project)); + text.append(" ("); + text.append(escape(event.change.get().branch)); + text.append("): "); + text.append(escape(event.change.get().commitMessage.split("\n")[0])); + text.append(" ("); + text.append(escape(event.change.get().url)); + text.append(")"); + + message = String.format(template, text, config.getChannel(), + config.getUsername()); + } + catch (Exception e) + { + LOGGER.error("Error generating message: " + e.getMessage(), e); + } + + return message; + } +}
diff --git a/src/test/java/com/cisco/gerrit/plugins/slack/config/ProjectConfigTest.java b/src/test/java/com/cisco/gerrit/plugins/slack/config/ProjectConfigTest.java index 48c92c8..a0cfc78 100644 --- a/src/test/java/com/cisco/gerrit/plugins/slack/config/ProjectConfigTest.java +++ b/src/test/java/com/cisco/gerrit/plugins/slack/config/ProjectConfigTest.java
@@ -84,6 +84,8 @@ .thenReturn(true); when(mockPluginConfig.getBoolean("publish-on-comment-added", true)) .thenReturn(true); + when(mockPluginConfig.getBoolean("publish-on-reviewer-added", true)) + .thenReturn(true); config = new ProjectConfig(mockConfigFactory, PROJECT_NAME); } @@ -129,4 +131,10 @@ { assertThat(config.shouldPublishOnCommentAdded(), is(equalTo(true))); } + + @Test + public void testShouldPublishOnReviewerAdded() throws Exception + { + assertThat(config.shouldPublishOnReviewerAdded(), is(equalTo(true))); + } }
diff --git a/src/test/java/com/cisco/gerrit/plugins/slack/message/ReviewerAddedMessageGeneratorTest.java b/src/test/java/com/cisco/gerrit/plugins/slack/message/ReviewerAddedMessageGeneratorTest.java new file mode 100644 index 0000000..875622c --- /dev/null +++ b/src/test/java/com/cisco/gerrit/plugins/slack/message/ReviewerAddedMessageGeneratorTest.java
@@ -0,0 +1,189 @@ +/* + * Copyright 2016 Cisco Systems, Inc. + * + * 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.cisco.gerrit.plugins.slack.message; + +import com.cisco.gerrit.plugins.slack.config.ProjectConfig; +import com.google.common.base.Suppliers; +import com.google.gerrit.reviewdb.client.Project; +import com.google.gerrit.server.config.PluginConfig; +import com.google.gerrit.server.config.PluginConfigFactory; +import com.google.gerrit.server.data.AccountAttribute; +import com.google.gerrit.server.data.ChangeAttribute; +import com.google.gerrit.server.events.ReviewerAddedEvent; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.powermock.api.mockito.PowerMockito; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.core.Is.is; +import static org.junit.Assert.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +/** + * Tests for the ReviewerAddedMessageGeneratorTest class. The expected behavior + * is that the ReviewerAddedMessageGeneratorTest should publish if both the plugin + * and publish-on-reviewer-added are enabled. + */ +@RunWith(PowerMockRunner.class) +@PrepareForTest({Project.NameKey.class}) +public class ReviewerAddedMessageGeneratorTest +{ + private static final String PROJECT_NAME = "test-project"; + + private Project.NameKey mockNameKey = + mock(Project.NameKey.class); + + private PluginConfigFactory mockConfigFactory = + mock(PluginConfigFactory.class); + + private PluginConfig mockPluginConfig = + mock(PluginConfig.class); + + private ReviewerAddedEvent mockEvent = mock(ReviewerAddedEvent.class); + private AccountAttribute mockAccount = mock(AccountAttribute.class); + private ChangeAttribute mockChange = mock(ChangeAttribute.class); + + @Before + public void setup() throws Exception + { + PowerMockito.mockStatic(Project.NameKey.class); + when(Project.NameKey.parse(PROJECT_NAME)).thenReturn(mockNameKey); + } + + private ProjectConfig getConfig(boolean publishOnReviewerAdded) throws Exception + { + Project.NameKey projectNameKey; + projectNameKey = Project.NameKey.parse(PROJECT_NAME); + + // Setup mocks + when(mockConfigFactory.getFromProjectConfigWithInheritance( + projectNameKey, ProjectConfig.CONFIG_NAME)) + .thenReturn(mockPluginConfig); + + when(mockPluginConfig.getBoolean("enabled", false)) + .thenReturn(true); + when(mockPluginConfig.getString("webhookurl", "")) + .thenReturn("https://webook/"); + when(mockPluginConfig.getString("channel", "general")) + .thenReturn("testchannel"); + when(mockPluginConfig.getString("username", "gerrit")) + .thenReturn("testuser"); + when(mockPluginConfig.getString("ignore", "")) + .thenReturn("^WIP.*"); + when(mockPluginConfig.getBoolean("publish-on-reviewer-added", true)) + .thenReturn(publishOnReviewerAdded); + + return new ProjectConfig(mockConfigFactory, PROJECT_NAME); + } + + private ProjectConfig getConfig() throws Exception + { + return getConfig(true /* publishOnReviewerAdded */); + } + + @Test + public void factoryCreatesExpectedType() throws Exception + { + ProjectConfig config = getConfig(); + MessageGenerator messageGenerator; + messageGenerator = MessageGeneratorFactory.newInstance( + mockEvent, config); + + assertThat(messageGenerator instanceof ReviewerAddedMessageGenerator, + is(true)); + } + + @Test + public void publishesWhenExpected() throws Exception + { + // Setup mocks + ProjectConfig config = getConfig(); + + // Test + MessageGenerator messageGenerator; + messageGenerator = MessageGeneratorFactory.newInstance( + mockEvent, config); + + assertThat(messageGenerator.shouldPublish(), is(true)); + } + + @Test + public void doesNotPublishWhenTurnedOff() throws Exception + { + // Setup mocks + ProjectConfig config = getConfig(false /* publishOnReviewerAdded */); + + // Test + MessageGenerator messageGenerator; + messageGenerator = MessageGeneratorFactory.newInstance( + mockEvent, config); + + assertThat(messageGenerator.shouldPublish(), is(false)); + } + + @Test + public void handlesInvalidIgnorePatterns() throws Exception + { + ProjectConfig config = getConfig(); + when(mockPluginConfig.getString("ignore", "")) + .thenReturn(null); + + // Test + MessageGenerator messageGenerator; + messageGenerator = MessageGeneratorFactory.newInstance( + mockEvent, config); + + assertThat(messageGenerator.shouldPublish(), is(true)); + } + + @Test + public void generatesExpectedMessage() throws Exception + { + // Setup mocks + ProjectConfig config = getConfig(); + mockEvent.change = Suppliers.ofInstance(mockChange); + mockEvent.reviewer = Suppliers.ofInstance(mockAccount); + + mockChange.project = "testproject"; + mockChange.branch = "master"; + mockChange.commitMessage = "This is the first line\nAnd the second line."; + mockChange.url = "https://change/"; + + mockAccount.name = "Unit Tester"; + + // Test + MessageGenerator messageGenerator; + messageGenerator = MessageGeneratorFactory.newInstance( + mockEvent, config); + + String expectedResult; + expectedResult = "{\"text\": \"Unit Tester was added to review\\n>>>" + + "testproject (master): This is the first line" + + " (https://change/)\",\"channel\": \"#testchannel\"," + + "\"username\": \"testuser\"}\n"; + + String actualResult; + actualResult = messageGenerator.generate(); + + assertThat(actualResult, is(equalTo(expectedResult))); + } +}