@@ -83,6 +83,7 @@ | |||
from projects p | |||
where | |||
p.enabled=${_true} | |||
and p.main_branch_project_uuid is null | |||
and p.kee in | |||
<foreach collection="keys" open="(" close=")" item="key" separator=","> | |||
#{key,jdbcType=VARCHAR} |
@@ -25,6 +25,7 @@ import org.sonar.api.measures.CoreMetrics; | |||
import org.sonar.api.notifications.Notification; | |||
import org.sonar.api.utils.log.Logger; | |||
import org.sonar.api.utils.log.Loggers; | |||
import org.sonar.server.computation.task.projectanalysis.analysis.AnalysisMetadataHolder; | |||
import org.sonar.server.computation.task.projectanalysis.component.Component; | |||
import org.sonar.server.computation.task.projectanalysis.component.ComponentVisitor; | |||
import org.sonar.server.computation.task.projectanalysis.component.CrawlerDepthLimit; | |||
@@ -52,15 +53,17 @@ public class QualityGateEventsStep implements ComputationStep { | |||
private final MeasureRepository measureRepository; | |||
private final EventRepository eventRepository; | |||
private final NotificationService notificationService; | |||
private final AnalysisMetadataHolder analysisMetadataHolder; | |||
public QualityGateEventsStep(TreeRootHolder treeRootHolder, | |||
MetricRepository metricRepository, MeasureRepository measureRepository, EventRepository eventRepository, | |||
NotificationService notificationService) { | |||
NotificationService notificationService, AnalysisMetadataHolder analysisMetadataHolder) { | |||
this.treeRootHolder = treeRootHolder; | |||
this.metricRepository = metricRepository; | |||
this.measureRepository = measureRepository; | |||
this.eventRepository = eventRepository; | |||
this.notificationService = notificationService; | |||
this.analysisMetadataHolder = analysisMetadataHolder; | |||
} | |||
@Override | |||
@@ -129,6 +132,7 @@ public class QualityGateEventsStep implements ComputationStep { | |||
.setFieldValue("alertText", rawStatus.getText()) | |||
.setFieldValue("alertLevel", rawStatus.getStatus().toString()) | |||
.setFieldValue("isNewAlert", Boolean.toString(isNewAlert)); | |||
analysisMetadataHolder.getBranch().ifPresent(branch -> notification.setFieldValue("branch", branch.getName().orElse(null))); | |||
notificationService.deliver(notification); | |||
} | |||
@@ -26,6 +26,7 @@ import java.util.Set; | |||
import org.sonar.core.issue.DefaultIssue; | |||
import org.sonar.core.util.CloseableIterator; | |||
import org.sonar.server.computation.task.projectanalysis.analysis.AnalysisMetadataHolder; | |||
import org.sonar.server.computation.task.projectanalysis.analysis.Branch; | |||
import org.sonar.server.computation.task.projectanalysis.component.Component; | |||
import org.sonar.server.computation.task.projectanalysis.component.TreeRootHolder; | |||
import org.sonar.server.computation.task.projectanalysis.issue.IssueCache; | |||
@@ -105,7 +106,8 @@ public class SendIssueNotificationsStep implements ComputationStep { | |||
IssueChangeNotification changeNotification = new IssueChangeNotification(); | |||
changeNotification.setRuleName(rules.getByKey(issue.ruleKey()).getName()); | |||
changeNotification.setIssue(issue); | |||
changeNotification.setProject(project.getKey(), project.getName()); | |||
String branchName = analysisMetadataHolder.getBranch().flatMap(Branch::getName).orElse(null); | |||
changeNotification.setProject(project.getKey(), project.getName(), branchName); | |||
service.deliver(changeNotification); | |||
} | |||
@@ -80,7 +80,7 @@ public class IssueUpdater { | |||
.setIssue(issue) | |||
.setChangeAuthorLogin(context.login()) | |||
.setRuleName(rule.map(RuleDefinitionDto::getName).orElse(null)) | |||
.setProject(project.getDbKey(), project.name()) | |||
.setProject(project.getKey(), project.name(), project.getBranch()) | |||
.setComponent(component) | |||
.setComment(comment)); | |||
return issueDto; |
@@ -52,6 +52,7 @@ public abstract class AbstractNewIssuesEmailTemplate extends EmailTemplate { | |||
static final String FIELD_PROJECT_DATE = "projectDate"; | |||
static final String FIELD_PROJECT_UUID = "projectUuid"; | |||
static final String FIELD_ASSIGNEE = "assignee"; | |||
static final String FIELD_BRANCH = "branch"; | |||
protected final EmailSettings settings; | |||
protected final I18n i18n; | |||
@@ -175,8 +176,13 @@ public abstract class AbstractNewIssuesEmailTemplate extends EmailTemplate { | |||
String dateString = notification.getFieldValue(FIELD_PROJECT_DATE); | |||
if (projectKey != null && dateString != null) { | |||
Date date = DateUtils.parseDateTime(dateString); | |||
String url = String.format("%s/project/issues?id=%s&createdAt=%s", | |||
settings.getServerBaseURL(), encode(projectKey), encode(DateUtils.formatDateTime(date))); | |||
String url = String.format("%s/project/issues?id=%s", | |||
settings.getServerBaseURL(), encode(projectKey)); | |||
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) |
@@ -55,14 +55,15 @@ public class IssueChangeNotification extends Notification { | |||
} | |||
public IssueChangeNotification setProject(ComponentDto project) { | |||
setFieldValue("projectName", project.longName()); | |||
setFieldValue("projectKey", project.getDbKey()); | |||
return this; | |||
return setProject(project.getKey(), project.longName(), project.getBranch()); | |||
} | |||
public IssueChangeNotification setProject(String projectKey, String projectName) { | |||
public IssueChangeNotification setProject(String projectKey, String projectName, @Nullable String branch) { | |||
setFieldValue("projectName", projectName); | |||
setFieldValue("projectKey", projectKey); | |||
if (branch != null) { | |||
setFieldValue("branch", branch); | |||
} | |||
return this; | |||
} | |||
@@ -109,8 +109,12 @@ public class IssueChangesEmailTemplate extends EmailTemplate { | |||
sb.append("See it in SonarQube: ").append(settings.getServerBaseURL()) | |||
.append("/project/issues?id=").append(encode(notification.getFieldValue("projectKey"), "UTF-8")) | |||
.append("&issues=").append(issueKey) | |||
.append("&open=").append(issueKey) | |||
.append(NEW_LINE); | |||
.append("&open=").append(issueKey); | |||
String branchName = notification.getFieldValue("branch"); | |||
if (branchName != null) { | |||
sb.append("&branch=").append(branchName); | |||
} | |||
sb.append(NEW_LINE); | |||
} catch (UnsupportedEncodingException e) { | |||
throw new IllegalStateException("Encoding not supported", e); | |||
} |
@@ -58,13 +58,17 @@ public class MyNewIssuesEmailTemplate extends AbstractNewIssuesEmailTemplate { | |||
String projectUuid = notification.getFieldValue(FIELD_PROJECT_UUID); | |||
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) { | |||
Date date = DateUtils.parseDateTime(dateString); | |||
String url = String.format("%s/issues?projectUuids=%s&assignees=%s&createdAt=%s", | |||
String url = String.format("%s/issues?projectUuids=%s&assignees=%s", | |||
settings.getServerBaseURL(), | |||
encode(projectUuid), | |||
encode(assignee), | |||
encode(DateUtils.formatDateTime(date))); | |||
encode(assignee)); | |||
if (branch != null) { | |||
url += "&branch=" + encode(branch); | |||
} | |||
url += "&createdAt=" + encode(DateUtils.formatDateTime(date)); | |||
message.append("See it in SonarQube: ").append(url).append(NEW_LINE); | |||
} | |||
} |
@@ -129,7 +129,7 @@ public abstract class AbstractUserSession implements UserSession { | |||
protected List<ComponentDto> doKeepAuthorizedComponents(String permission, Collection<ComponentDto> components) { | |||
boolean allowPublicComponent = ProjectPermissions.PUBLIC_PERMISSIONS.contains(permission); | |||
return components.stream() | |||
.filter(c -> (allowPublicComponent && !c.isPrivate()) || hasProjectUuidPermission(permission, c.projectUuid())) | |||
.filter(c -> (allowPublicComponent && !c.isPrivate()) || hasComponentPermission(permission, c)) | |||
.collect(MoreCollectors.toList()); | |||
} | |||
@@ -25,7 +25,9 @@ import org.junit.Rule; | |||
import org.junit.Test; | |||
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.component.Component; | |||
import org.sonar.server.computation.task.projectanalysis.component.DefaultBranchImpl; | |||
import org.sonar.server.computation.task.projectanalysis.component.ReportComponent; | |||
import org.sonar.server.computation.task.projectanalysis.component.TreeRootHolderRule; | |||
import org.sonar.server.computation.task.projectanalysis.event.Event; | |||
@@ -62,6 +64,9 @@ public class QualityGateEventsStepTest { | |||
@Rule | |||
public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule(); | |||
@Rule | |||
public AnalysisMetadataHolderRule analysisMetadataHolder = new AnalysisMetadataHolderRule(); | |||
private ArgumentCaptor<Event> eventArgumentCaptor = ArgumentCaptor.forClass(Event.class); | |||
private ArgumentCaptor<Notification> notificationArgumentCaptor = ArgumentCaptor.forClass(Notification.class); | |||
@@ -71,11 +76,12 @@ public class QualityGateEventsStepTest { | |||
private MeasureRepository measureRepository = mock(MeasureRepository.class); | |||
private EventRepository eventRepository = mock(EventRepository.class); | |||
private NotificationService notificationService = mock(NotificationService.class); | |||
private QualityGateEventsStep underTest = new QualityGateEventsStep(treeRootHolder, metricRepository, measureRepository, eventRepository, notificationService); | |||
private QualityGateEventsStep underTest = new QualityGateEventsStep(treeRootHolder, metricRepository, measureRepository, eventRepository, notificationService, analysisMetadataHolder); | |||
@Before | |||
public void setUp() { | |||
when(metricRepository.getByKey(ALERT_STATUS_KEY)).thenReturn(alertStatusMetric); | |||
analysisMetadataHolder.setBranch(null); | |||
treeRootHolder.setRoot(PROJECT_COMPONENT); | |||
} | |||
@@ -182,6 +188,7 @@ public class QualityGateEventsStepTest { | |||
assertThat(notification.getFieldValue("projectKey")).isEqualTo(PROJECT_COMPONENT.getKey()); | |||
assertThat(notification.getFieldValue("projectUuid")).isEqualTo(PROJECT_COMPONENT.getUuid()); | |||
assertThat(notification.getFieldValue("projectName")).isEqualTo(PROJECT_COMPONENT.getName()); | |||
assertThat(notification.getFieldValue("branch")).isNull(); | |||
assertThat(notification.getFieldValue("alertLevel")).isEqualTo(rawAlterStatus.name()); | |||
assertThat(notification.getFieldValue("alertName")).isEqualTo(expectedLabel); | |||
} | |||
@@ -233,10 +240,33 @@ public class QualityGateEventsStepTest { | |||
assertThat(notification.getFieldValue("projectKey")).isEqualTo(PROJECT_COMPONENT.getKey()); | |||
assertThat(notification.getFieldValue("projectUuid")).isEqualTo(PROJECT_COMPONENT.getUuid()); | |||
assertThat(notification.getFieldValue("projectName")).isEqualTo(PROJECT_COMPONENT.getName()); | |||
assertThat(notification.getFieldValue("branch")).isNull(); | |||
assertThat(notification.getFieldValue("alertLevel")).isEqualTo(newQualityGateStatus.getStatus().name()); | |||
assertThat(notification.getFieldValue("alertName")).isEqualTo(expectedLabel); | |||
reset(measureRepository, eventRepository, notificationService); | |||
} | |||
@Test | |||
public void verify_branch_name_is_set_in_notification() { | |||
String branchName = "feature1"; | |||
analysisMetadataHolder.setBranch(new DefaultBranchImpl(branchName)); | |||
when(measureRepository.getRawMeasure(PROJECT_COMPONENT, alertStatusMetric)).thenReturn(of(Measure.newMeasureBuilder().setQualityGateStatus(WARN_QUALITY_GATE_STATUS).createNoValue())); | |||
when(measureRepository.getBaseMeasure(PROJECT_COMPONENT, alertStatusMetric)).thenReturn( | |||
of(Measure.newMeasureBuilder().setQualityGateStatus(new QualityGateStatus(ERROR)).createNoValue())); | |||
underTest.execute(); | |||
verify(notificationService).deliver(notificationArgumentCaptor.capture()); | |||
Notification notification = notificationArgumentCaptor.getValue(); | |||
assertThat(notification.getType()).isEqualTo("alerts"); | |||
assertThat(notification.getFieldValue("projectKey")).isEqualTo(PROJECT_COMPONENT.getKey()); | |||
assertThat(notification.getFieldValue("projectUuid")).isEqualTo(PROJECT_COMPONENT.getUuid()); | |||
assertThat(notification.getFieldValue("projectName")).isEqualTo(PROJECT_COMPONENT.getName()); | |||
assertThat(notification.getFieldValue("branch")).isEqualTo(branchName); | |||
reset(measureRepository, eventRepository, notificationService); | |||
} | |||
} |
@@ -123,6 +123,26 @@ public class IssueUpdaterTest { | |||
assertThat(issueChangeNotification.getFieldValue("comment")).isEqualTo("increase severity"); | |||
} | |||
@Test | |||
public void verify_notification_on_branch() throws Exception { | |||
RuleDto rule = ruleDbTester.insertRule(newRuleDto()); | |||
ComponentDto project = componentDbTester.insertMainBranch(); | |||
ComponentDto branch = componentDbTester.insertProjectBranch(project); | |||
ComponentDto file = componentDbTester.insertComponent(newFileDto(branch)); | |||
DefaultIssue issue = issueDbTester.insertIssue(IssueTesting.newIssue(rule.getDefinition(), branch, file)).setSeverity(MAJOR).toDefaultIssue(); | |||
IssueChangeContext context = IssueChangeContext.createUser(new Date(), "john"); | |||
issueFieldsSetter.setSeverity(issue, BLOCKER, context); | |||
underTest.saveIssue(dbTester.getSession(), issue, context, "increase severity"); | |||
verify(notificationManager).scheduleForSending(notificationArgumentCaptor.capture()); | |||
IssueChangeNotification issueChangeNotification = notificationArgumentCaptor.getValue(); | |||
assertThat(issueChangeNotification.getFieldValue("key")).isEqualTo(issue.key()); | |||
assertThat(issueChangeNotification.getFieldValue("projectKey")).isEqualTo(project.getDbKey()); | |||
assertThat(issueChangeNotification.getFieldValue("projectName")).isEqualTo(project.name()); | |||
assertThat(issueChangeNotification.getFieldValue("branch")).isEqualTo(branch.getBranch()); | |||
} | |||
@Test | |||
public void verify_notification_when_issue_is_linked_on_removed_rule() throws Exception { | |||
RuleDto rule = ruleDbTester.insertRule(newRuleDto().setStatus(RuleStatus.REMOVED)); |
@@ -84,10 +84,19 @@ public class IssueChangeNotificationTest { | |||
} | |||
@Test | |||
public void set_project() { | |||
IssueChangeNotification result = notification.setProject("MyService", "My Service"); | |||
public void set_project_without_branch() { | |||
IssueChangeNotification result = notification.setProject("MyService", "My Service", null); | |||
assertThat(result.getFieldValue("projectKey")).isEqualTo("MyService"); | |||
assertThat(result.getFieldValue("projectName")).isEqualTo("My Service"); | |||
assertThat(result.getFieldValue("branch")).isNull(); | |||
} | |||
@Test | |||
public void set_project_with_branch() { | |||
IssueChangeNotification result = notification.setProject("MyService", "My Service", "feature1"); | |||
assertThat(result.getFieldValue("projectKey")).isEqualTo("MyService"); | |||
assertThat(result.getFieldValue("projectName")).isEqualTo("My Service"); | |||
assertThat(result.getFieldValue("branch")).isEqualTo("feature1"); | |||
} | |||
@Test |
@@ -147,13 +147,30 @@ public class IssueChangesEmailTemplateTest { | |||
assertThat(email.getFrom()).isNull(); | |||
} | |||
@Test | |||
public void test_email_with_issue_on_branch() throws Exception { | |||
Notification notification = generateNotification() | |||
.setFieldValue("branch", "feature1"); | |||
EmailMessage email = underTest.format(notification); | |||
assertThat(email.getMessageId()).isEqualTo("issue-changes/ABCDE"); | |||
assertThat(email.getSubject()).isEqualTo("Struts, change on issue #ABCDE"); | |||
String message = email.getMessage(); | |||
String expected = Resources.toString(Resources.getResource( | |||
"org/sonar/server/issue/notification/IssueChangesEmailTemplateTest/email_with_issue_on_branch.txt"), | |||
StandardCharsets.UTF_8); | |||
expected = StringUtils.remove(expected, '\r'); | |||
assertThat(message).isEqualTo(expected); | |||
} | |||
@Test | |||
public void notification_sender_should_be_the_author_of_change() { | |||
db.users().insertUser(newUserDto().setLogin("simon").setName("Simon")); | |||
Notification notification = new IssueChangeNotification() | |||
.setChangeAuthorLogin("simon") | |||
.setProject("Struts", "org.apache:struts"); | |||
.setProject("Struts", "org.apache:struts", null); | |||
EmailMessage message = underTest.format(notification); | |||
assertThat(message.getFrom()).isEqualTo("Simon"); | |||
@@ -165,7 +182,7 @@ public class IssueChangesEmailTemplateTest { | |||
Notification notification = new IssueChangeNotification() | |||
.setChangeAuthorLogin("simon") | |||
.setProject("Struts", "org.apache:struts"); | |||
.setProject("Struts", "org.apache:struts", null); | |||
EmailMessage message = underTest.format(notification); | |||
assertThat(message.getFrom()).isEqualTo("simon"); |
@@ -95,7 +95,7 @@ public class MyNewIssuesEmailTemplateTest { | |||
EmailMessage message = underTest.format(notification); | |||
// TODO datetime to be completed when test is isolated from JVM timezone | |||
assertStartsWithFile(message.getMessage(), getClass().getResource("MyNewIssuesEmailTemplateTest/email_with_all_details.txt")); | |||
assertStartsWithFile(message.getMessage(), "MyNewIssuesEmailTemplateTest/email_with_all_details.txt"); | |||
} | |||
@Test | |||
@@ -123,7 +123,18 @@ public class MyNewIssuesEmailTemplateTest { | |||
EmailMessage message = underTest.format(notification); | |||
// TODO datetime to be completed when test is isolated from JVM timezone | |||
assertStartsWithFile(message.getMessage(), getClass().getResource("MyNewIssuesEmailTemplateTest/email_with_no_assignee_tags_components.txt")); | |||
assertStartsWithFile(message.getMessage(), "MyNewIssuesEmailTemplateTest/email_with_no_assignee_tags_components.txt"); | |||
} | |||
@Test | |||
public void format_email_with_issue_on_branch() throws Exception { | |||
Notification notification = newNotification() | |||
.setFieldValue("branch", "feature1"); | |||
EmailMessage message = underTest.format(notification); | |||
// TODO datetime to be completed when test is isolated from JVM timezone | |||
assertStartsWithFile(message.getMessage(), "MyNewIssuesEmailTemplateTest/email_with_issue_on_branch.txt"); | |||
} | |||
@Test | |||
@@ -176,8 +187,8 @@ public class MyNewIssuesEmailTemplateTest { | |||
.setFieldValue(RULE + ".2.count", "5"); | |||
} | |||
private static void assertStartsWithFile(String message, URL file) throws IOException { | |||
String fileContent = IOUtils.toString(file, StandardCharsets.UTF_8); | |||
private void assertStartsWithFile(String message, String resourcePath) throws IOException { | |||
String fileContent = IOUtils.toString(getClass().getResource(resourcePath), StandardCharsets.UTF_8); | |||
assertThat(sanitizeString(message)).startsWith(sanitizeString(fileContent)); | |||
} | |||
@@ -19,6 +19,7 @@ | |||
*/ | |||
package org.sonar.server.issue.notification; | |||
import java.io.IOException; | |||
import org.apache.commons.io.IOUtils; | |||
import org.apache.commons.lang.StringUtils; | |||
import org.junit.Before; | |||
@@ -112,8 +113,7 @@ public class NewIssuesEmailTemplateTest { | |||
EmailMessage message = template.format(notification); | |||
// TODO datetime to be completed when test is isolated from JVM timezone | |||
String expectedContent = IOUtils.toString(getClass().getResource("NewIssuesEmailTemplateTest/email_with_all_details.txt"), StandardCharsets.UTF_8); | |||
assertThat(message.getMessage()).startsWith(StringUtils.remove(expectedContent, '\r')); | |||
assertStartsWithFile(message.getMessage(), "NewIssuesEmailTemplateTest/email_with_all_details.txt"); | |||
} | |||
@Test | |||
@@ -123,8 +123,18 @@ public class NewIssuesEmailTemplateTest { | |||
EmailMessage message = template.format(notification); | |||
// TODO datetime to be completed when test is isolated from JVM timezone | |||
String expectedContent = IOUtils.toString(getClass().getResource("NewIssuesEmailTemplateTest/email_with_partial_details.txt"), StandardCharsets.UTF_8); | |||
assertThat(message.getMessage()).startsWith(StringUtils.remove(expectedContent, '\r')); | |||
assertStartsWithFile(message.getMessage(), "NewIssuesEmailTemplateTest/email_with_partial_details.txt"); | |||
} | |||
@Test | |||
public void format_email_with_issue_on_branch() throws Exception { | |||
Notification notification = newNotification() | |||
.setFieldValue("branch", "feature1"); | |||
EmailMessage message = template.format(notification); | |||
// TODO datetime to be completed when test is isolated from JVM timezone | |||
assertStartsWithFile(message.getMessage(), "NewIssuesEmailTemplateTest/email_with_issue_on_branch.txt"); | |||
} | |||
@Test | |||
@@ -184,4 +194,16 @@ public class NewIssuesEmailTemplateTest { | |||
.setFieldValue(RULE + ".2.label", "Rule the World (Java)") | |||
.setFieldValue(RULE + ".2.count", "5"); | |||
} | |||
private void assertStartsWithFile(String message, String resourcePath) throws IOException { | |||
String fileContent = IOUtils.toString(getClass().getResource(resourcePath), StandardCharsets.UTF_8); | |||
assertThat(sanitizeString(message)).startsWith(sanitizeString(fileContent)); | |||
} | |||
/** | |||
* sanitize EOL and tabs if git clone is badly configured | |||
*/ | |||
private static String sanitizeString(String s) { | |||
return s.replaceAll("\\r\\n|\\r|\\s+", ""); | |||
} | |||
} |
@@ -123,7 +123,7 @@ public class BulkChangeActionTest { | |||
issueWorkflow.start(); | |||
rule = db.rules().insertRule(newRuleDto()); | |||
organization = db.organizations().insert(); | |||
project = db.components().insertPrivateProject(organization); | |||
project = db.components().insertMainBranch(organization); | |||
file = db.components().insertComponent(newFileDto(project)); | |||
user = db.users().insertUser("john"); | |||
when(system2.now()).thenReturn(NOW); | |||
@@ -241,7 +241,6 @@ public class BulkChangeActionTest { | |||
public void send_notification() throws Exception { | |||
setUserProjectPermissions(USER); | |||
IssueDto issueDto = db.issues().insertIssue(newUnresolvedIssue().setType(BUG)); | |||
ArgumentCaptor<IssueChangeNotification> issueChangeNotificationCaptor = ArgumentCaptor.forClass(IssueChangeNotification.class); | |||
BulkChangeWsResponse response = call(BulkChangeRequest.builder() | |||
.setIssues(singletonList(issueDto.getKey())) | |||
@@ -250,6 +249,8 @@ public class BulkChangeActionTest { | |||
.build()); | |||
checkResponse(response, 1, 1, 0, 0); | |||
ArgumentCaptor<IssueChangeNotification> issueChangeNotificationCaptor = ArgumentCaptor.forClass(IssueChangeNotification.class); | |||
verify(notificationManager).scheduleForSending(issueChangeNotificationCaptor.capture()); | |||
assertThat(issueChangeNotificationCaptor.getValue().getFieldValue("key")).isEqualTo(issueDto.getKey()); | |||
assertThat(issueChangeNotificationCaptor.getValue().getFieldValue("componentName")).isEqualTo(file.longName()); | |||
@@ -257,6 +258,35 @@ public class BulkChangeActionTest { | |||
assertThat(issueChangeNotificationCaptor.getValue().getFieldValue("projectKey")).isEqualTo(project.getDbKey()); | |||
assertThat(issueChangeNotificationCaptor.getValue().getFieldValue("ruleName")).isEqualTo(rule.getName()); | |||
assertThat(issueChangeNotificationCaptor.getValue().getFieldValue("changeAuthor")).isEqualTo(user.getLogin()); | |||
assertThat(issueChangeNotificationCaptor.getValue().getFieldValue("branch")).isNull(); | |||
} | |||
@Test | |||
public void send_notification_on_branch() throws Exception { | |||
setUserProjectPermissions(USER); | |||
String branchName = "feature1"; | |||
ComponentDto branch = db.components().insertProjectBranch(project, b -> b.setKey(branchName)); | |||
ComponentDto fileOnBranch = db.components().insertComponent(newFileDto(branch)); | |||
IssueDto issueDto = db.issues().insertIssue(newUnresolvedIssue(rule, fileOnBranch, branch).setType(BUG)); | |||
BulkChangeWsResponse response = call(BulkChangeRequest.builder() | |||
.setIssues(singletonList(issueDto.getKey())) | |||
.setDoTransition("confirm") | |||
.setSendNotifications(true) | |||
.build()); | |||
checkResponse(response, 1, 1, 0, 0); | |||
ArgumentCaptor<IssueChangeNotification> issueChangeNotificationCaptor = ArgumentCaptor.forClass(IssueChangeNotification.class); | |||
verify(notificationManager).scheduleForSending(issueChangeNotificationCaptor.capture()); | |||
assertThat(issueChangeNotificationCaptor.getValue().getFieldValue("key")).isEqualTo(issueDto.getKey()); | |||
assertThat(issueChangeNotificationCaptor.getValue().getFieldValue("componentName")).isEqualTo(fileOnBranch.longName()); | |||
assertThat(issueChangeNotificationCaptor.getValue().getFieldValue("projectName")).isEqualTo(project.longName()); | |||
assertThat(issueChangeNotificationCaptor.getValue().getFieldValue("projectKey")).isEqualTo(project.getDbKey()); | |||
assertThat(issueChangeNotificationCaptor.getValue().getFieldValue("ruleName")).isEqualTo(rule.getName()); | |||
assertThat(issueChangeNotificationCaptor.getValue().getFieldValue("changeAuthor")).isEqualTo(user.getLogin()); | |||
assertThat(issueChangeNotificationCaptor.getValue().getFieldValue("branch")).isEqualTo(branchName); | |||
} | |||
@Test |
@@ -0,0 +1,6 @@ | |||
Action | |||
Rule: Avoid Cycles | |||
Message: Has 3 cycles | |||
See it in SonarQube: http://nemo.sonarsource.org/project/issues?id=org.apache%3Astruts&issues=ABCDE&open=ABCDE&branch=feature1 |
@@ -0,0 +1,8 @@ | |||
Project: Struts | |||
32 new issues (new debt: 1d3h) | |||
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 |
@@ -0,0 +1,8 @@ | |||
Project: Struts | |||
32 new issues (new debt: 1d3h) | |||
Severity | |||
Blocker: 0 Critical: 5 Major: 10 Minor: 3 Info: 1 | |||
See it in SonarQube: http://nemo.sonarsource.org/project/issues?id=org.apache%3Astruts&branch=feature1&createdAt=2010-05-1 |