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".
*/
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;
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");
}
}
}
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();
+ }
+
}
*/
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;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
+@RunWith(DataProviderRunner.class)
public class QGChangeEmailTemplateTest {
private QGChangeEmailTemplate template;
"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"));
"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"));
"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"));
"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"));
}
"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"));
}
"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")