From 66aa167dc20fe1f6e434f61a7a74cd64a1844bf4 Mon Sep 17 00:00:00 2001 From: Lukasz Jarocki Date: Thu, 29 Apr 2021 08:31:43 +0200 Subject: [PATCH] SONAR-14570 making text sent by email about QG more clear to the user --- .../notification/QGChangeEmailTemplate.java | 36 +++++++++- .../QGChangeEmailTemplateTest.java | 68 ++++++++++++++----- 2 files changed, 84 insertions(+), 20 deletions(-) diff --git a/server/sonar-server-common/src/main/java/org/sonar/server/qualitygate/notification/QGChangeEmailTemplate.java b/server/sonar-server-common/src/main/java/org/sonar/server/qualitygate/notification/QGChangeEmailTemplate.java index b67658a046a..4766df2eecb 100644 --- a/server/sonar-server-common/src/main/java/org/sonar/server/qualitygate/notification/QGChangeEmailTemplate.java +++ b/server/sonar-server-common/src/main/java/org/sonar/server/qualitygate/notification/QGChangeEmailTemplate.java @@ -27,6 +27,9 @@ import org.sonar.api.measures.Metric; import org.sonar.api.notifications.Notification; import org.sonar.server.issue.notification.EmailMessage; import org.sonar.server.issue.notification.EmailTemplate; +import org.sonar.server.measure.Rating; + +import java.util.regex.Pattern; /** * Creates email message for notification "alerts". @@ -35,7 +38,9 @@ import org.sonar.server.issue.notification.EmailTemplate; */ public class QGChangeEmailTemplate implements EmailTemplate { - private EmailSettings configuration; + private static final Pattern alertRatingRegex = Pattern.compile(".*>\\s\\d$"); + + private final EmailSettings configuration; public QGChangeEmailTemplate(EmailSettings configuration) { this.configuration = configuration; @@ -111,11 +116,11 @@ public class QGChangeEmailTemplate implements EmailTemplate { messageBody.append("Quality gate threshold"); } if (alerts.length == 1) { - messageBody.append(": ").append(alerts[0].trim()).append("\n"); + messageBody.append(": ").append(formatRating(alerts[0].trim())).append("\n"); } else { messageBody.append("s:\n"); for (String alert : alerts) { - messageBody.append(" - ").append(alert.trim()).append("\n"); + messageBody.append(" - ").append(formatRating(alert.trim())).append("\n"); } } } @@ -128,4 +133,29 @@ public class QGChangeEmailTemplate implements EmailTemplate { return messageBody.toString(); } + /** + * Converts the ratings from digits to a rating letter {@see org.sonar.server.measure.Rating}, based on the + * raw text passed to this template. + * + * Examples: + * Reliability rating > 4 will be converted to Reliability rating worse than D + * Security rating on New Code > 1 will be converted to Security rating on New Code worse than A + * Code Coverage < 50% will not be converted and returned as is. + * + * @param alert + * @return full raw alert with converted ratings + */ + private static String formatRating(String alert) { + if(!alertRatingRegex.matcher(alert).matches()) { + return alert; + } + + StringBuilder builder = new StringBuilder(); + builder.append(alert, 0, alert.length() - 3); + builder.append("worse than "); + String rating = alert.substring(alert.length() - 1); + builder.append(Rating.valueOf(Integer.parseInt(rating)).name()); + return builder.toString(); + } + } diff --git a/server/sonar-server-common/src/test/java/org/sonar/server/qualitygate/notification/QGChangeEmailTemplateTest.java b/server/sonar-server-common/src/test/java/org/sonar/server/qualitygate/notification/QGChangeEmailTemplateTest.java index a8e77877c13..5a956a4df10 100644 --- a/server/sonar-server-common/src/test/java/org/sonar/server/qualitygate/notification/QGChangeEmailTemplateTest.java +++ b/server/sonar-server-common/src/test/java/org/sonar/server/qualitygate/notification/QGChangeEmailTemplateTest.java @@ -19,8 +19,12 @@ */ package org.sonar.server.qualitygate.notification; +import com.tngtech.java.junit.dataprovider.DataProvider; +import com.tngtech.java.junit.dataprovider.DataProviderRunner; +import com.tngtech.java.junit.dataprovider.UseDataProvider; import org.junit.Before; import org.junit.Test; +import org.junit.runner.RunWith; import org.sonar.api.config.EmailSettings; import org.sonar.api.notifications.Notification; import org.sonar.server.issue.notification.EmailMessage; @@ -31,6 +35,7 @@ import static org.junit.Assert.assertThat; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; +@RunWith(DataProviderRunner.class) public class QGChangeEmailTemplateTest { private QGChangeEmailTemplate template; @@ -62,7 +67,7 @@ public class QGChangeEmailTemplateTest { "Quality gate status: Failed\n" + "\n" + "Quality gate thresholds:\n" + - " - violations > 4\n" + + " - violations worse than D\n" + " - coverage < 75%\n" + "\n" + "More details at: http://nemo.sonarsource.org/dashboard?id=org.sonar.foo:foo")); @@ -83,7 +88,7 @@ public class QGChangeEmailTemplateTest { "Quality gate status: Failed\n" + "\n" + "Quality gate thresholds:\n" + - " - violations > 4\n" + + " - violations worse than D\n" + " - coverage < 75%\n" + "\n" + "More details at: http://nemo.sonarsource.org/dashboard?id=org.sonar.foo:foo&branch=feature")); @@ -102,7 +107,7 @@ public class QGChangeEmailTemplateTest { "Quality gate status: Failed\n" + "\n" + "New quality gate thresholds:\n" + - " - violations > 4\n" + + " - violations worse than D\n" + " - coverage < 75%\n" + "\n" + "More details at: http://nemo.sonarsource.org/dashboard?id=org.sonar.foo:foo")); @@ -120,7 +125,7 @@ public class QGChangeEmailTemplateTest { "Version: V1-SNAP\n" + "Quality gate status: Failed\n" + "\n" + - "New quality gate threshold: violations > 4\n" + + "New quality gate threshold: violations worse than D\n" + "\n" + "More details at: http://nemo.sonarsource.org/dashboard?id=org.sonar.foo:foo")); } @@ -137,7 +142,23 @@ public class QGChangeEmailTemplateTest { "Project: Foo\n" + "Quality gate status: Failed\n" + "\n" + - "New quality gate threshold: violations > 4\n" + + "New quality gate threshold: violations worse than D\n" + + "\n" + + "More details at: http://nemo.sonarsource.org/dashboard?id=org.sonar.foo:foo")); + } + + @Test + public void shouldFormatBackToGreenMessage() { + Notification notification = createNotification("Passed", "", "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" + + "Version: V1-SNAP\n" + + "Quality gate status: Passed\n" + + "\n" + "\n" + "More details at: http://nemo.sonarsource.org/dashboard?id=org.sonar.foo:foo")); } @@ -156,45 +177,58 @@ public class QGChangeEmailTemplateTest { "Version: V1-SNAP\n" + "Quality gate status: Failed\n" + "\n" + - "New quality gate threshold: violations > 4\n" + + "New quality gate threshold: violations worse than D\n" + "\n" + "More details at: http://nemo.sonarsource.org/dashboard?id=org.sonar.foo:foo&branch=feature")); } @Test - public void shouldFormatBackToGreenMessage() { - Notification notification = createNotification("Passed", "", "OK", "false"); + public void shouldFormatBackToGreenMessageOnBranch() { + Notification notification = createNotification("Passed", "", "OK", "false") + .setFieldValue("branch", "feature"); EmailMessage message = template.format(notification); assertThat(message.getMessageId(), is("alerts/45")); - assertThat(message.getSubject(), is("\"Foo\" is back to green")); + assertThat(message.getSubject(), is("\"Foo (feature)\" is back to green")); assertThat(message.getMessage(), is("" + "Project: Foo\n" + + "Branch: feature\n" + "Version: V1-SNAP\n" + "Quality gate status: Passed\n" + "\n" + "\n" + - "More details at: http://nemo.sonarsource.org/dashboard?id=org.sonar.foo:foo")); + "More details at: http://nemo.sonarsource.org/dashboard?id=org.sonar.foo:foo&branch=feature")); + } + + @DataProvider + public static Object[][] alertTextAndFormattedText() { + return new Object[][] { + {"violations > 1", "violations worse than A"}, + {"violations > 4", "violations worse than D"}, + {"Code Coverage < 50%", "Code Coverage < 50%"}, + {"custom metric condition not met", "custom metric condition not met"} + }; } + @UseDataProvider("alertTextAndFormattedText") @Test - public void shouldFormatBackToGreenMessageOnBranch() { - Notification notification = createNotification("Passed", "", "OK", "false") - .setFieldValue("branch", "feature"); + public void shouldFormatNewAlertWithThresholdProperlyFormatted(String alertText, String expectedFormattedAlertText) { + Notification notification = createNotification("Failed", alertText, "ERROR", "true"); EmailMessage message = template.format(notification); assertThat(message.getMessageId(), is("alerts/45")); - assertThat(message.getSubject(), is("\"Foo (feature)\" is back to green")); + assertThat(message.getSubject(), is("New quality gate threshold reached on \"Foo\"")); assertThat(message.getMessage(), is("" + "Project: Foo\n" + - "Branch: feature\n" + "Version: V1-SNAP\n" + - "Quality gate status: Passed\n" + + "Quality gate status: Failed\n" + "\n" + + "New quality gate threshold: " + expectedFormattedAlertText + "\n" + "\n" + - "More details at: http://nemo.sonarsource.org/dashboard?id=org.sonar.foo:foo&branch=feature")); + "More details at: http://nemo.sonarsource.org/dashboard?id=org.sonar.foo:foo")); } + private Notification createNotification(String alertName, String alertText, String alertLevel, String isNewAlert) { return new Notification("alerts") .setFieldValue("projectName", "Foo") -- 2.39.5