diff options
author | Fabrice Bellingard <fabrice.bellingard@sonarsource.com> | 2013-01-24 16:07:51 +0100 |
---|---|---|
committer | Fabrice Bellingard <fabrice.bellingard@sonarsource.com> | 2013-01-24 16:08:35 +0100 |
commit | 30d668f520e3972de197ab1c8f5bfd4972a481b1 (patch) | |
tree | cfe84ec7f16908313b3635182a59668eaaf20362 /plugins/sonar-email-notifications-plugin/src | |
parent | aac947247b9e0754d4c52344fc2efc00cf40138f (diff) | |
download | sonarqube-30d668f520e3972de197ab1c8f5bfd4972a481b1.tar.gz sonarqube-30d668f520e3972de197ab1c8f5bfd4972a481b1.zip |
SONAR-2746 Email new alerts on favorite projects
Diffstat (limited to 'plugins/sonar-email-notifications-plugin/src')
5 files changed, 364 insertions, 3 deletions
diff --git a/plugins/sonar-email-notifications-plugin/src/main/java/org/sonar/plugins/emailnotifications/EmailNotificationsPlugin.java b/plugins/sonar-email-notifications-plugin/src/main/java/org/sonar/plugins/emailnotifications/EmailNotificationsPlugin.java index bf46289eb47..61051c38e10 100644 --- a/plugins/sonar-email-notifications-plugin/src/main/java/org/sonar/plugins/emailnotifications/EmailNotificationsPlugin.java +++ b/plugins/sonar-email-notifications-plugin/src/main/java/org/sonar/plugins/emailnotifications/EmailNotificationsPlugin.java @@ -22,6 +22,8 @@ package org.sonar.plugins.emailnotifications; import com.google.common.collect.ImmutableList; import org.sonar.api.ServerExtension; import org.sonar.api.SonarPlugin; +import org.sonar.plugins.emailnotifications.alerts.AlertsEmailTemplate; +import org.sonar.plugins.emailnotifications.alerts.AlertsOnMyFavouriteProject; import org.sonar.plugins.emailnotifications.newviolations.NewViolationsEmailTemplate; import org.sonar.plugins.emailnotifications.newviolations.NewViolationsOnMyFavouriteProject; import org.sonar.plugins.emailnotifications.reviews.ChangesInReviewAssignedToMeOrCreatedByMe; @@ -32,10 +34,16 @@ import java.util.List; public class EmailNotificationsPlugin extends SonarPlugin { public List<Class<? extends ServerExtension>> getExtensions() { return ImmutableList.of( - ChangesInReviewAssignedToMeOrCreatedByMe.class, EmailNotificationChannel.class, - NewViolationsEmailTemplate.class, + // Notify incoming violations on my favourite projects NewViolationsOnMyFavouriteProject.class, - ReviewEmailTemplate.class); + NewViolationsEmailTemplate.class, + // Notify reviews changes + ChangesInReviewAssignedToMeOrCreatedByMe.class, + ReviewEmailTemplate.class, + // Notify alerts on my favourite projects + AlertsOnMyFavouriteProject.class, + AlertsEmailTemplate.class + ); } } diff --git a/plugins/sonar-email-notifications-plugin/src/main/java/org/sonar/plugins/emailnotifications/alerts/AlertsEmailTemplate.java b/plugins/sonar-email-notifications-plugin/src/main/java/org/sonar/plugins/emailnotifications/alerts/AlertsEmailTemplate.java new file mode 100644 index 00000000000..96d96cb3ad7 --- /dev/null +++ b/plugins/sonar-email-notifications-plugin/src/main/java/org/sonar/plugins/emailnotifications/alerts/AlertsEmailTemplate.java @@ -0,0 +1,107 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2012 SonarSource + * mailto:contact AT sonarsource DOT com + * + * Sonar is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * Sonar is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.emailnotifications.alerts; + +import org.apache.commons.lang.StringUtils; +import org.sonar.api.config.EmailSettings; +import org.sonar.api.measures.Metric; +import org.sonar.api.notifications.Notification; +import org.sonar.plugins.emailnotifications.api.EmailMessage; +import org.sonar.plugins.emailnotifications.api.EmailTemplate; + +/** + * Creates email message for notification "alerts". + * + * @since 3.5 + */ +public class AlertsEmailTemplate extends EmailTemplate { + + private EmailSettings configuration; + + public AlertsEmailTemplate(EmailSettings configuration) { + this.configuration = configuration; + } + + @Override + public EmailMessage format(Notification notification) { + if (!"alerts".equals(notification.getType())) { + return null; + } + + // Retrieve useful values + String projectId = notification.getFieldValue("projectId"); + String projectKey = notification.getFieldValue("projectKey"); + String projectName = notification.getFieldValue("projectName"); + String alertName = notification.getFieldValue("alertName"); + String alertText = notification.getFieldValue("alertText"); + String alertLevel = notification.getFieldValue("alertLevel"); + boolean isNewAlert = Boolean.valueOf(notification.getFieldValue("isNewAlert")); + + // Generate text + String subject = generateSubject(projectName, alertLevel, isNewAlert); + String messageBody = generateMessageBody(projectName, projectKey, alertName, alertText, isNewAlert); + + // And finally return the email that will be sent + return new EmailMessage() + .setMessageId("alerts/" + projectId) + .setSubject(subject) + .setMessage(messageBody); + } + + private String generateSubject(String projectName, String alertLevel, boolean isNewAlert) { + StringBuilder subjectBuilder = new StringBuilder(); + if (Metric.Level.OK.toString().equals(alertLevel)) { + subjectBuilder.append("\"").append(projectName).append("\" is back to green"); + } else if (isNewAlert) { + subjectBuilder.append("New alert on \"").append(projectName).append("\""); + } else { + subjectBuilder.append("Alert level changed on \"").append(projectName).append("\""); + } + return subjectBuilder.toString(); + } + + private String generateMessageBody(String projectName, String projectKey, String alertName, String alertText, boolean isNewAlert) { + StringBuilder messageBody = new StringBuilder(); + messageBody.append("Project: ").append(projectName).append("\n"); + messageBody.append("Alert level: ").append(alertName).append("\n\n"); + + String[] alerts = StringUtils.split(alertText, ","); + if (alerts.length > 0) { + if (isNewAlert) { + messageBody.append("New alert"); + } else { + messageBody.append("Alert"); + } + if (alerts.length == 1) { + messageBody.append(": ").append(alerts[0].trim()).append("\n"); + } else { + messageBody.append("s:\n"); + for (String alert : alerts) { + messageBody.append(" - ").append(alert.trim()).append("\n"); + } + } + } + + messageBody.append("\n").append("See it in Sonar: ").append(configuration.getServerBaseURL()).append("/dashboard/index/").append(projectKey); + + return messageBody.toString(); + } + +} diff --git a/plugins/sonar-email-notifications-plugin/src/main/java/org/sonar/plugins/emailnotifications/alerts/AlertsOnMyFavouriteProject.java b/plugins/sonar-email-notifications-plugin/src/main/java/org/sonar/plugins/emailnotifications/alerts/AlertsOnMyFavouriteProject.java new file mode 100644 index 00000000000..38a46a6ca49 --- /dev/null +++ b/plugins/sonar-email-notifications-plugin/src/main/java/org/sonar/plugins/emailnotifications/alerts/AlertsOnMyFavouriteProject.java @@ -0,0 +1,53 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2012 SonarSource + * mailto:contact AT sonarsource DOT com + * + * Sonar is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * Sonar is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.emailnotifications.alerts; + +import org.apache.commons.lang.StringUtils; +import org.sonar.api.notifications.Notification; +import org.sonar.api.notifications.NotificationDispatcher; +import org.sonar.core.properties.PropertiesDao; + +import java.util.List; + +/** + * This dispatcher means: "notify me when alerts are raised on projects that I flagged as favourite". + * + * @since 3.5 + */ +public class AlertsOnMyFavouriteProject extends NotificationDispatcher { + + private PropertiesDao propertiesDao; + + public AlertsOnMyFavouriteProject(PropertiesDao propertiesDao) { + this.propertiesDao = propertiesDao; + } + + @Override + public void dispatch(Notification notification, Context context) { + if (StringUtils.equals(notification.getType(), "alerts")) { + Long projectId = Long.parseLong(notification.getFieldValue("projectId")); + List<String> userLogins = propertiesDao.findUserIdsForFavouriteResource(projectId); + for (String userLogin : userLogins) { + context.addUser(userLogin); + } + } + } + +} diff --git a/plugins/sonar-email-notifications-plugin/src/test/java/org/sonar/plugins/emailnotifications/alerts/AlertsEmailTemplateTest.java b/plugins/sonar-email-notifications-plugin/src/test/java/org/sonar/plugins/emailnotifications/alerts/AlertsEmailTemplateTest.java new file mode 100644 index 00000000000..1a68497f1c9 --- /dev/null +++ b/plugins/sonar-email-notifications-plugin/src/test/java/org/sonar/plugins/emailnotifications/alerts/AlertsEmailTemplateTest.java @@ -0,0 +1,131 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2012 SonarSource + * mailto:contact AT sonarsource DOT com + * + * Sonar is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * Sonar is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.emailnotifications.alerts; + +import org.junit.Before; +import org.junit.Test; +import org.sonar.api.config.EmailSettings; +import org.sonar.api.notifications.Notification; +import org.sonar.plugins.emailnotifications.api.EmailMessage; + +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.nullValue; +import static org.junit.Assert.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class AlertsEmailTemplateTest { + + private AlertsEmailTemplate template; + + @Before + public void setUp() { + EmailSettings configuration = mock(EmailSettings.class); + when(configuration.getServerBaseURL()).thenReturn("http://nemo.sonarsource.org"); + template = new AlertsEmailTemplate(configuration); + } + + @Test + public void shouldNotFormatIfNotCorrectNotification() { + Notification notification = new Notification("other-notif"); + EmailMessage message = template.format(notification); + assertThat(message, nullValue()); + } + + @Test + public void shouldFormatAlertWithSeveralMessages() { + Notification notification = createNotification("Orange (was Red)", "violations > 4, coverage < 75%", "WARN", "false"); + + EmailMessage message = template.format(notification); + assertThat(message.getMessageId(), is("alerts/45")); + assertThat(message.getSubject(), is("Alert level changed on \"Foo\"")); + assertThat(message.getMessage(), is("" + + "Project: Foo\n" + + "Alert level: Orange (was Red)\n" + + "\n" + + "Alerts:\n" + + " - violations > 4\n" + + " - coverage < 75%\n" + + "\n" + + "See it in Sonar: http://nemo.sonarsource.org/dashboard/index/org.sonar.foo:foo")); + } + + @Test + public void shouldFormatNewAlertWithSeveralMessages() { + Notification notification = createNotification("Orange (was Red)", "violations > 4, coverage < 75%", "WARN", "true"); + + EmailMessage message = template.format(notification); + assertThat(message.getMessageId(), is("alerts/45")); + assertThat(message.getSubject(), is("New alert on \"Foo\"")); + assertThat(message.getMessage(), is("" + + "Project: Foo\n" + + "Alert level: Orange (was Red)\n" + + "\n" + + "New alerts:\n" + + " - violations > 4\n" + + " - coverage < 75%\n" + + "\n" + + "See it in Sonar: http://nemo.sonarsource.org/dashboard/index/org.sonar.foo:foo")); + } + + @Test + public void shouldFormatNewAlertWithOneMessage() { + Notification notification = createNotification("Orange (was Red)", "violations > 4", "WARN", "true"); + + EmailMessage message = template.format(notification); + assertThat(message.getMessageId(), is("alerts/45")); + assertThat(message.getSubject(), is("New alert on \"Foo\"")); + assertThat(message.getMessage(), is("" + + "Project: Foo\n" + + "Alert level: Orange (was Red)\n" + + "\n" + + "New alert: violations > 4\n" + + "\n" + + "See it in Sonar: http://nemo.sonarsource.org/dashboard/index/org.sonar.foo:foo")); + } + + @Test + public void shouldFormatBackToGreenMessage() { + Notification notification = createNotification("Green (was Red)", "", "OK", "false"); + + EmailMessage message = template.format(notification); + assertThat(message.getMessageId(), is("alerts/45")); + assertThat(message.getSubject(), is("\"Foo\" is back to green")); + assertThat(message.getMessage(), is("" + + "Project: Foo\n" + + "Alert level: Green (was Red)\n" + + "\n" + + "\n" + + "See it in Sonar: http://nemo.sonarsource.org/dashboard/index/org.sonar.foo:foo")); + } + + private Notification createNotification(String alertName, String alertText, String alertLevel, String isNewAlert) { + Notification notification = new Notification("alerts") + .setFieldValue("projectName", "Foo") + .setFieldValue("projectKey", "org.sonar.foo:foo") + .setFieldValue("projectId", "45") + .setFieldValue("alertName", alertName) + .setFieldValue("alertText", alertText) + .setFieldValue("alertLevel", alertLevel) + .setFieldValue("isNewAlert", isNewAlert); + return notification; + } + +} diff --git a/plugins/sonar-email-notifications-plugin/src/test/java/org/sonar/plugins/emailnotifications/alerts/AlertsOnMyFavouriteProjectTest.java b/plugins/sonar-email-notifications-plugin/src/test/java/org/sonar/plugins/emailnotifications/alerts/AlertsOnMyFavouriteProjectTest.java new file mode 100644 index 00000000000..fe29748d332 --- /dev/null +++ b/plugins/sonar-email-notifications-plugin/src/test/java/org/sonar/plugins/emailnotifications/alerts/AlertsOnMyFavouriteProjectTest.java @@ -0,0 +1,62 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2012 SonarSource + * mailto:contact AT sonarsource DOT com + * + * Sonar is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * Sonar is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.emailnotifications.alerts; + +import com.google.common.collect.Lists; +import org.junit.Test; +import org.sonar.api.notifications.Notification; +import org.sonar.api.notifications.NotificationDispatcher; +import org.sonar.core.properties.PropertiesDao; + +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.when; + +public class AlertsOnMyFavouriteProjectTest { + + @Test + public void shouldNotDispatchIfNotNewViolationsNotification() throws Exception { + NotificationDispatcher.Context context = mock(NotificationDispatcher.Context.class); + AlertsOnMyFavouriteProject dispatcher = new AlertsOnMyFavouriteProject(null); + Notification notification = new Notification("other-notif"); + dispatcher.dispatch(notification, context); + + verify(context, never()).addUser(any(String.class)); + } + + @Test + public void shouldDispatchToUsersWhoHaveFlaggedProjectAsFavourite() { + NotificationDispatcher.Context context = mock(NotificationDispatcher.Context.class); + PropertiesDao propertiesDao = mock(PropertiesDao.class); + when(propertiesDao.findUserIdsForFavouriteResource(34L)).thenReturn(Lists.newArrayList("user1", "user2")); + AlertsOnMyFavouriteProject dispatcher = new AlertsOnMyFavouriteProject(propertiesDao); + + Notification notification = new Notification("alerts").setFieldValue("projectId", "34"); + dispatcher.dispatch(notification, context); + + verify(context).addUser("user1"); + verify(context).addUser("user2"); + verifyNoMoreInteractions(context); + } + +} |