Add config option for ignoring comments from specific author(s).

The change introduces a new configuration option, ignore-comment-author,
which allows filtering the comment-added events based on the author.
The motivation behind the change is to be able to ignore automated build
messages from a CI/CD system integrated with gerrit (e.g. Jenkins),
thus keeping the noise level of the Slack channel low.

Change-Id: Idda5ba6147cd1a21efb5382580e5c576a4821987
diff --git a/README.md b/README.md
index 2007a3d..e9ecfed 100644
--- a/README.md
+++ b/README.md
@@ -107,6 +107,10 @@
     ignore-private-patch-set - boolean (true/false)
         Whether any Slack notifications regarding a private change shouldn't
         be published (defaults to true).
+    ignore-comment-author - Pattern
+        A "dotall" enabled regular expression pattern that, when matches
+        against the comment author username, will prevent the publishing
+        of comment added event messages (defaults to an empty string).
     publish-on-patch-set-created - boolean (true/false)
         Whether a Slack notification should be published when a new patch set
         is created.
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 088cc4f..050f704 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
@@ -43,6 +43,7 @@
   private boolean ignoreUnchangedPatchSet;
   private boolean ignoreWorkInProgressPatchSet;
   private boolean ignorePrivatePatchSet;
+  private String  ignoreCommentAuthor;
   private boolean publishOnPatchSetCreated;
   private boolean publishOnChangeMerged;
   private boolean publishOnCommentAdded;
@@ -108,6 +109,11 @@
               .getFromProjectConfigWithInheritance(projectNameKey, CONFIG_NAME)
               .getBoolean("ignore-private-patch-set", true);
 
+      ignoreCommentAuthor =
+          configFactory
+              .getFromProjectConfigWithInheritance(projectNameKey, CONFIG_NAME)
+              .getString("ignore-comment-author", "");
+
       publishOnPatchSetCreated =
           configFactory
               .getFromProjectConfigWithInheritance(projectNameKey, CONFIG_NAME)
@@ -184,6 +190,10 @@
     return ignorePrivatePatchSet;
   }
 
+  public String getIgnoreCommentAuthor() {
+    return ignoreCommentAuthor;
+  }
+
   public boolean shouldPublishOnPatchSetCreated() {
     return publishOnPatchSetCreated;
   }
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 2e2a1eb..6f8775a 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
@@ -22,6 +22,8 @@
 import com.cisco.gerrit.plugins.slack.config.ProjectConfig;
 import com.google.gerrit.server.data.ChangeAttribute;
 import com.google.gerrit.server.events.CommentAddedEvent;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -72,7 +74,23 @@
       LOGGER.warn("Error checking private and work-in-progress status", e);
     }
 
-    return true;
+    boolean result;
+    result = true;
+
+    try {
+      Pattern pattern;
+      pattern = Pattern.compile(config.getIgnoreCommentAuthor(), Pattern.DOTALL);
+
+      Matcher matcher;
+      matcher = pattern.matcher(event.author.get().username);
+
+      // If the ignore pattern matches, publishing should not happen
+      result = !matcher.matches();
+    } catch (Exception e) {
+      LOGGER.warn("The specified ignore-comment-author pattern was invalid", e);
+    }
+
+    return result;
   }
 
   @Override
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 0555dd3..ccab779 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
@@ -58,6 +58,7 @@
     when(mockPluginConfig.getString("channel", "general")).thenReturn("test-channel");
     when(mockPluginConfig.getString("username", "gerrit")).thenReturn("test-user");
     when(mockPluginConfig.getString("ignore", "")).thenReturn("^WIP.*");
+    when(mockPluginConfig.getString("ignore-comment-author", "")).thenReturn("^jenkins.*");
     when(mockPluginConfig.getBoolean("publish-on-patch-set-created", true)).thenReturn(true);
     when(mockPluginConfig.getBoolean("publish-on-change-merged", true)).thenReturn(true);
     when(mockPluginConfig.getBoolean("publish-on-comment-added", true)).thenReturn(true);
@@ -87,6 +88,11 @@
   }
 
   @Test
+  public void testGetIgnoreCommentAuthor() throws Exception {
+    assertThat(config.getIgnoreCommentAuthor(), is(equalTo("^jenkins.*")));
+  }
+
+  @Test
   public void testShouldPublishOnPatchSetCreated() throws Exception {
     assertThat(config.shouldPublishOnPatchSetCreated(), is(equalTo(true)));
   }
diff --git a/src/test/java/com/cisco/gerrit/plugins/slack/message/CommentAddedMessageGeneratorTest.java b/src/test/java/com/cisco/gerrit/plugins/slack/message/CommentAddedMessageGeneratorTest.java
index 3509311..f2b7e5f 100644
--- a/src/test/java/com/cisco/gerrit/plugins/slack/message/CommentAddedMessageGeneratorTest.java
+++ b/src/test/java/com/cisco/gerrit/plugins/slack/message/CommentAddedMessageGeneratorTest.java
@@ -70,6 +70,7 @@
     when(mockPluginConfig.getString("channel", "general")).thenReturn("testchannel");
     when(mockPluginConfig.getString("username", "gerrit")).thenReturn("testuser");
     when(mockPluginConfig.getString("ignore", "")).thenReturn("^WIP.*");
+    when(mockPluginConfig.getString("ignore-comment-author", "")).thenReturn("^jenkins.*");
     when(mockPluginConfig.getBoolean("publish-on-comment-added", true))
         .thenReturn(publishOnCommentAdded);
     when(mockPluginConfig.getBoolean("ignore-wip-patch-set", true))
@@ -223,6 +224,21 @@
   }
 
   @Test
+  public void doesNotPublishWhenIgnoreAuthorMatches() throws Exception {
+    // Setup mocks
+    ProjectConfig config = getConfig();
+    mockEvent.change = Suppliers.ofInstance(mockChange);
+    mockEvent.author = Suppliers.ofInstance(mockAccount);
+    mockAccount.username = "jenkins";
+
+    // Test
+    MessageGenerator messageGenerator;
+    messageGenerator = MessageGeneratorFactory.newInstance(mockEvent, config);
+
+    assertThat(messageGenerator.shouldPublish(), is(false));
+  }
+
+  @Test
   public void generatesExpectedMessage() throws Exception {
     // Setup mocks
     ProjectConfig config = getConfig();