Notification notification = new Notification("alerts")
.setDefaultMessage(String.format("Alert on %s: %s", project.getName(), label))
.setFieldValue("projectName", project.getName())
- .setFieldValue("projectKey", project.getKey())
+ .setFieldValue("projectKey", getMainBranchProjectKey())
.setFieldValue("projectUuid", project.getUuid())
.setFieldValue("alertName", label)
.setFieldValue("alertText", rawStatus.getText())
public String getDescription() {
return "Generate Quality gate events";
}
+
+ private String getMainBranchProjectKey() {
+ return analysisMetadataHolder.getProject().getKey();
+ }
}
IssueChangeNotification changeNotification = new IssueChangeNotification();
changeNotification.setRuleName(rules.getByKey(issue.ruleKey()).getName());
changeNotification.setIssue(issue);
- String branchName = analysisMetadataHolder.getBranch().flatMap(Branch::getName).orElse(null);
- changeNotification.setProject(project.getKey(), project.getName(), branchName);
+ changeNotification.setProject(getMainBranchProjectKey(), project.getName(), getBranchName());
service.deliver(changeNotification);
}
NewIssuesStatistics.Stats globalStatistics = statistics.globalStatistics();
NewIssuesNotification notification = newIssuesNotificationFactory
.newNewIssuesNotication()
- .setProject(project.getKey(), project.getUuid(), project.getName())
+ .setProject(getMainBranchProjectKey(), project.getUuid(), project.getName(), getBranchName())
.setAnalysisDate(new Date(analysisDate))
.setStatistics(project.getName(), globalStatistics)
.setDebt(globalStatistics.debt());
.newMyNewIssuesNotification()
.setAssignee(assignee);
myNewIssuesNotification
- .setProject(project.getKey(), project.getUuid(), project.getName())
+ .setProject(getMainBranchProjectKey(), project.getUuid(), project.getName(), getBranchName())
.setAnalysisDate(new Date(analysisDate))
.setStatistics(project.getName(), assigneeStatistics)
.setDebt(assigneeStatistics.debt());
return "Send issue notifications";
}
+ private String getBranchName() {
+ return analysisMetadataHolder.getBranch().filter(b -> !b.isMain()).flatMap(Branch::getName).orElse(null);
+ }
+
+ private String getMainBranchProjectKey() {
+ return analysisMetadataHolder.getProject().getKey();
+ }
+
}
public IssueChangeNotification setComponent(ComponentDto component) {
setFieldValue("componentName", component.longName());
+ setFieldValue("componentKey", component.getKey());
return this;
}
@Override
protected void appendFooter(StringBuilder message, Notification notification) {
- String projectUuid = notification.getFieldValue(FIELD_PROJECT_UUID);
+ String projectKey = notification.getFieldValue(FIELD_PROJECT_KEY);
String dateString = notification.getFieldValue(FIELD_PROJECT_DATE);
String assignee = notification.getFieldValue(FIELD_ASSIGNEE);
- String branch = notification.getFieldValue(FIELD_BRANCH);
- if (projectUuid != null && dateString != null && assignee != null) {
+ if (projectKey != null && dateString != null && assignee != null) {
Date date = DateUtils.parseDateTime(dateString);
- String url = String.format("%s/issues?projectUuids=%s&assignees=%s",
+ String url = String.format("%s/project/issues?id=%s&assignees=%s",
settings.getServerBaseURL(),
- encode(projectUuid),
+ encode(projectKey),
encode(assignee));
- if (branch != null) {
- url += "&branch=" + encode(branch);
+ String branchName = notification.getFieldValue("branch");
+ if (branchName != null) {
+ url += "&branch=" + encode(branchName);
}
url += "&createdAt=" + encode(DateUtils.formatDateTime(date));
- message.append("See it in SonarQube: ").append(url).append(NEW_LINE);
+ message
+ .append("See it in SonarQube: ")
+ .append(url)
+ .append(NEW_LINE);
}
}
}
import com.google.common.collect.Multiset;
import java.util.Date;
import java.util.List;
+import javax.annotation.Nullable;
import org.sonar.api.notifications.Notification;
import org.sonar.api.rule.RuleKey;
import org.sonar.api.rule.Severity;
import org.sonar.server.user.index.UserDoc;
import org.sonar.server.user.index.UserIndex;
+import static org.sonar.server.issue.notification.AbstractNewIssuesEmailTemplate.FIELD_BRANCH;
import static org.sonar.server.issue.notification.NewIssuesEmailTemplate.FIELD_PROJECT_DATE;
import static org.sonar.server.issue.notification.NewIssuesEmailTemplate.FIELD_PROJECT_KEY;
import static org.sonar.server.issue.notification.NewIssuesEmailTemplate.FIELD_PROJECT_NAME;
return this;
}
- public NewIssuesNotification setProject(String projectKey, String projectUuid, String projectName) {
+ public NewIssuesNotification setProject(String projectKey, String projectUuid, String projectName, @Nullable String branchName) {
setFieldValue(FIELD_PROJECT_NAME, projectName);
setFieldValue(FIELD_PROJECT_KEY, projectKey);
setFieldValue(FIELD_PROJECT_UUID, projectUuid);
+ if (branchName != null) {
+ setFieldValue(FIELD_BRANCH, branchName);
+ }
return this;
}
*/
package org.sonar.server.notification.email;
+import javax.annotation.Nullable;
import org.apache.commons.lang.StringUtils;
import org.sonar.api.config.EmailSettings;
import org.sonar.api.measures.Metric;
String projectId = notification.getFieldValue("projectId");
String projectKey = notification.getFieldValue("projectKey");
String projectName = notification.getFieldValue("projectName");
+ String branchName = notification.getFieldValue("branch");
String alertName = notification.getFieldValue("alertName");
String alertText = notification.getFieldValue("alertText");
String alertLevel = notification.getFieldValue("alertLevel");
// Generate text
String subject = generateSubject(projectName, alertLevel, isNewAlert);
- String messageBody = generateMessageBody(projectName, projectKey, alertName, alertText, isNewAlert);
+ String messageBody = generateMessageBody(projectName, projectKey, branchName, alertName, alertText, isNewAlert);
// And finally return the email that will be sent
return new EmailMessage()
return subjectBuilder.toString();
}
- private String generateMessageBody(String projectName, String projectKey, String alertName, String alertText, boolean isNewAlert) {
+ private String generateMessageBody(String projectName, String projectKey, @Nullable String branchName, String alertName, String alertText, boolean isNewAlert) {
StringBuilder messageBody = new StringBuilder();
messageBody.append("Project: ").append(projectName).append("\n");
messageBody.append("Quality gate status: ").append(alertName).append("\n\n");
}
messageBody.append("\n").append("See it in SonarQube: ").append(configuration.getServerBaseURL()).append("/dashboard?id=").append(projectKey);
+ if (branchName != null) {
+ messageBody.append("&branch=").append(branchName);
+ }
return messageBody.toString();
}
import org.mockito.ArgumentCaptor;
import org.sonar.api.notifications.Notification;
import org.sonar.server.computation.task.projectanalysis.analysis.AnalysisMetadataHolderRule;
+import org.sonar.server.computation.task.projectanalysis.analysis.Project;
import org.sonar.server.computation.task.projectanalysis.component.Component;
import org.sonar.server.computation.task.projectanalysis.component.DefaultBranchImpl;
import org.sonar.server.computation.task.projectanalysis.component.ReportComponent;
@Before
public void setUp() {
when(metricRepository.getByKey(ALERT_STATUS_KEY)).thenReturn(alertStatusMetric);
+ analysisMetadataHolder.setProject(new Project(PROJECT_COMPONENT.getUuid(), PROJECT_COMPONENT.getKey(), PROJECT_COMPONENT.getName()));
analysisMetadataHolder.setBranch(null);
treeRootHolder.setRoot(PROJECT_COMPONENT);
}
import org.sonar.api.utils.System2;
import org.sonar.core.issue.DefaultIssue;
import org.sonar.server.computation.task.projectanalysis.analysis.AnalysisMetadataHolderRule;
+import org.sonar.server.computation.task.projectanalysis.analysis.Project;
+import org.sonar.server.computation.task.projectanalysis.component.DefaultBranchImpl;
import org.sonar.server.computation.task.projectanalysis.component.TreeRootHolderRule;
import org.sonar.server.computation.task.projectanalysis.component.Component;
import org.sonar.server.computation.task.projectanalysis.component.Component.Type;
static final String PROJECT_KEY = "PROJECT_KEY";
static final String PROJECT_NAME = "PROJECT_NAME";
+ static final String BRANCH_COMPONENT_UUID = "BRANCH_UUID";
+ static final String BRANCH_COMPONENT_KEY = "BRANCH_KEY";
+ static final String BRANCH_COMPONENT_NAME = "BRANCH_NAME";
+ static final String BRANCH_NAME = "feature";
+
static final long ANALYSE_DATE = 123L;
static final Duration ISSUE_DURATION = Duration.create(100L);
static final String ISSUE_ASSIGNEE = "John";
static final Component PROJECT = builder(Type.PROJECT, 1).setUuid(PROJECT_UUID).setKey(PROJECT_KEY).setName(PROJECT_NAME).build();
+ static final Component BRANCH = builder(Type.PROJECT, 2).setUuid(BRANCH_COMPONENT_UUID).setKey(BRANCH_COMPONENT_KEY).setName(BRANCH_COMPONENT_NAME).build();
@Rule
public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule()
@Rule
public AnalysisMetadataHolderRule analysisMetadataHolder = new AnalysisMetadataHolderRule()
+ .setProject(new Project(PROJECT_UUID, PROJECT_KEY, PROJECT_NAME))
+ .setBranch(new DefaultBranchImpl())
.setAnalysisDate(new Date(ANALYSE_DATE));
@Rule
underTest.execute();
verify(notificationService).deliver(any(NewIssuesNotification.class));
- verify(newIssuesNotificationMock).setProject(PROJECT_KEY, PROJECT_UUID, PROJECT_NAME);
+ verify(newIssuesNotificationMock).setProject(PROJECT_KEY, PROJECT_UUID, PROJECT_NAME, null);
verify(newIssuesNotificationMock).setAnalysisDate(new Date(ANALYSE_DATE));
verify(newIssuesNotificationMock).setStatistics(eq(PROJECT_NAME), any(NewIssuesStatistics.Stats.class));
verify(newIssuesNotificationMock).setDebt(ISSUE_DURATION);
}
+ @Test
+ public void send_global_new_issues_notification_on_branch() throws Exception {
+ issueCache.newAppender().append(
+ new DefaultIssue().setSeverity(Severity.BLOCKER).setEffort(ISSUE_DURATION)
+ ).close();
+
+ when(notificationService.hasProjectSubscribersForTypes(BRANCH_COMPONENT_UUID, SendIssueNotificationsStep.NOTIF_TYPES)).thenReturn(true);
+
+ analysisMetadataHolder.setBranch(new DefaultBranchImpl(BRANCH_NAME) {
+ @Override
+ public boolean isMain() {
+ return false;
+ }
+ });
+ treeRootHolder.setRoot(BRANCH);
+
+ underTest.execute();
+
+ verify(notificationService).deliver(any(NewIssuesNotification.class));
+ verify(newIssuesNotificationMock).setProject(PROJECT_KEY, BRANCH_COMPONENT_UUID, BRANCH_COMPONENT_NAME, BRANCH_NAME);
+ verify(newIssuesNotificationMock).setAnalysisDate(new Date(ANALYSE_DATE));
+ verify(newIssuesNotificationMock).setStatistics(eq(BRANCH_COMPONENT_NAME), any(NewIssuesStatistics.Stats.class));
+ verify(newIssuesNotificationMock).setDebt(ISSUE_DURATION);
+ }
+
@Test
public void send_new_issues_notification_to_user() throws Exception {
issueCache.newAppender().append(
verify(notificationService, times(2)).deliver(any(Notification.class));
verify(myNewIssuesNotificationMock).setAssignee(ISSUE_ASSIGNEE);
- verify(myNewIssuesNotificationMock).setProject(PROJECT_KEY, PROJECT_UUID, PROJECT_NAME);
+ verify(myNewIssuesNotificationMock).setProject(PROJECT_KEY, PROJECT_UUID, PROJECT_NAME, null);
verify(myNewIssuesNotificationMock).setAnalysisDate(new Date(ANALYSE_DATE));
verify(myNewIssuesNotificationMock).setStatistics(eq(PROJECT_NAME), any(NewIssuesStatistics.Stats.class));
verify(myNewIssuesNotificationMock).setDebt(ISSUE_DURATION);
private NewIssuesNotification createNewIssuesNotificationMock() {
NewIssuesNotification notification = mock(NewIssuesNotification.class);
- when(notification.setProject(anyString(), anyString(), anyString())).thenReturn(notification);
+ when(notification.setProject(anyString(), anyString(), anyString(), anyString())).thenReturn(notification);
when(notification.setAnalysisDate(any(Date.class))).thenReturn(notification);
when(notification.setStatistics(anyString(), any(NewIssuesStatistics.Stats.class))).thenReturn(notification);
when(notification.setDebt(any(Duration.class))).thenReturn(notification);
private MyNewIssuesNotification createMyNewIssuesNotificationMock() {
MyNewIssuesNotification notification = mock(MyNewIssuesNotification.class);
when(notification.setAssignee(anyString())).thenReturn(notification);
- when(notification.setProject(anyString(), anyString(), anyString())).thenReturn(notification);
+ when(notification.setProject(anyString(), anyString(), anyString(), anyString())).thenReturn(notification);
when(notification.setAnalysisDate(any(Date.class))).thenReturn(notification);
when(notification.setStatistics(anyString(), any(NewIssuesStatistics.Stats.class))).thenReturn(notification);
when(notification.setDebt(any(Duration.class))).thenReturn(notification);
public void set_component() {
IssueChangeNotification result = notification.setComponent(new ComponentDto().setDbKey("MyService").setLongName("My Service"));
assertThat(result.getFieldValue("componentName")).isEqualTo("My Service");
+ assertThat(result.getFieldValue("componentKey")).isEqualTo("MyService");
}
@Test
NewIssuesNotification underTest = new NewIssuesNotification(userIndex, dbClient, durations);
@Test
- public void set_project() {
- underTest.setProject("project-key", "project-uuid", "project-long-name");
+ public void set_project_without_branch() {
+ underTest.setProject("project-key", "project-uuid", "project-long-name", null);
assertThat(underTest.getFieldValue(NewIssuesEmailTemplate.FIELD_PROJECT_NAME)).isEqualTo("project-long-name");
assertThat(underTest.getFieldValue(NewIssuesEmailTemplate.FIELD_PROJECT_UUID)).isEqualTo("project-uuid");
assertThat(underTest.getFieldValue(NewIssuesEmailTemplate.FIELD_PROJECT_KEY)).isEqualTo("project-key");
+ assertThat(underTest.getFieldValue(NewIssuesEmailTemplate.FIELD_BRANCH)).isNull();
+ }
+
+ @Test
+ public void set_project_with_branch() {
+ underTest.setProject("project-key", "project-uuid", "project-long-name", "feature");
+
+ assertThat(underTest.getFieldValue(NewIssuesEmailTemplate.FIELD_PROJECT_NAME)).isEqualTo("project-long-name");
+ assertThat(underTest.getFieldValue(NewIssuesEmailTemplate.FIELD_PROJECT_UUID)).isEqualTo("project-uuid");
+ assertThat(underTest.getFieldValue(NewIssuesEmailTemplate.FIELD_PROJECT_KEY)).isEqualTo("project-key");
+ assertThat(underTest.getFieldValue(NewIssuesEmailTemplate.FIELD_BRANCH)).isEqualTo("feature");
}
@Test
"See it in SonarQube: http://nemo.sonarsource.org/dashboard?id=org.sonar.foo:foo"));
}
+ @Test
+ public void shouldFormatNewAlertWithOneMessageOnBranch() {
+ Notification notification = createNotification("Orange (was Red)", "violations > 4", "WARN", "true")
+ .setFieldValue("branch", "feature");
+
+ EmailMessage message = template.format(notification);
+ assertThat(message.getMessageId(), is("alerts/45"));
+ assertThat(message.getSubject(), is("New quality gate threshold reached on \"Foo\""));
+ assertThat(message.getMessage(), is("" +
+ "Project: Foo\n" +
+ "Quality gate status: Orange (was Red)\n" +
+ "\n" +
+ "New quality gate threshold: violations > 4\n" +
+ "\n" +
+ "See it in SonarQube: http://nemo.sonarsource.org/dashboard?id=org.sonar.foo:foo&branch=feature"));
+ }
+
@Test
public void shouldFormatBackToGreenMessage() {
Notification notification = createNotification("Green (was Red)", "", "OK", "false");
/path/to/file: 3
/path/to/directory: 7
-See it in SonarQube: http://nemo.sonarsource.org/issues?projectUuids=ABCDE&assignees=lo.gin&createdAt=2010-05-1
\ No newline at end of file
+See it in SonarQube: http://nemo.sonarsource.org/project/issues?id=org.apache%3Astruts&assignees=lo.gin&createdAt=2010-05-18
Severity
Blocker: 0 Critical: 5 Major: 10 Minor: 3 Info: 1
-See it in SonarQube: http://nemo.sonarsource.org/issues?projectUuids=ABCDE&assignees=lo.gin&branch=feature1&createdAt=2010-05-1
+See it in SonarQube: http://nemo.sonarsource.org/project/issues?id=org.apache%3Astruts&assignees=lo.gin&branch=feature1&createdAt=2010-05-18
Severity
Blocker: 0 Critical: 5 Major: 10 Minor: 3 Info: 1
-See it in SonarQube: http://nemo.sonarsource.org/issues?projectUuids=ABCDE&assignees=lo.gin&createdAt=2010-05-1
\ No newline at end of file
+See it in SonarQube: http://nemo.sonarsource.org/project/issues?id=org.apache%3Astruts&assignees=lo.gin&createdAt=2010-05-18