aboutsummaryrefslogtreecommitdiffstats
path: root/server/sonar-ce/src
diff options
context:
space:
mode:
authorLéo Geoffroy <leo.geoffroy@sonarsource.com>2023-06-21 09:52:44 +0200
committersonartech <sonartech@sonarsource.com>2023-06-22 20:02:53 +0000
commit025f115ad199361ec591967d64b4d65a1e849f17 (patch)
tree74cbb5e23fd8fb0e3c394ceeb065073672a28f0f /server/sonar-ce/src
parentd349b4f3f74a5d1882e5d1f15cacc504cc629bb5 (diff)
downloadsonarqube-025f115ad199361ec591967d64b4d65a1e849f17.tar.gz
sonarqube-025f115ad199361ec591967d64b4d65a1e849f17.zip
SONAR-19674 Notification for background task failure should apply to all the branches
Diffstat (limited to 'server/sonar-ce/src')
-rw-r--r--server/sonar-ce/src/it/java/org/sonar/ce/notification/ReportAnalysisFailureNotificationExecutionListenerIT.java116
-rw-r--r--server/sonar-ce/src/main/java/org/sonar/ce/notification/ReportAnalysisFailureNotificationExecutionListener.java17
2 files changed, 88 insertions, 45 deletions
diff --git a/server/sonar-ce/src/it/java/org/sonar/ce/notification/ReportAnalysisFailureNotificationExecutionListenerIT.java b/server/sonar-ce/src/it/java/org/sonar/ce/notification/ReportAnalysisFailureNotificationExecutionListenerIT.java
index 75c8812f05c..5e9f98b99b0 100644
--- a/server/sonar-ce/src/it/java/org/sonar/ce/notification/ReportAnalysisFailureNotificationExecutionListenerIT.java
+++ b/server/sonar-ce/src/it/java/org/sonar/ce/notification/ReportAnalysisFailureNotificationExecutionListenerIT.java
@@ -42,13 +42,16 @@ import org.sonar.db.RowNotFoundException;
import org.sonar.db.ce.CeActivityDto;
import org.sonar.db.ce.CeQueueDto;
import org.sonar.db.ce.CeTaskTypes;
+import org.sonar.db.component.BranchDto;
import org.sonar.db.component.ComponentDto;
import org.sonar.db.component.ComponentTesting;
+import org.sonar.db.component.ProjectData;
import org.sonar.db.project.ProjectDto;
import org.sonar.server.notification.NotificationService;
import static java.util.Collections.singleton;
import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric;
+import static org.assertj.core.api.Assertions.anyOf;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.assertj.core.api.Assertions.fail;
@@ -62,7 +65,7 @@ import static org.sonar.db.component.ComponentTesting.newDirectory;
public class ReportAnalysisFailureNotificationExecutionListenerIT {
@Rule
- public DbTester dbTester = DbTester.create(System2.INSTANCE);
+ public DbTester dbTester = DbTester.create(System2.INSTANCE, true);
private final Random random = new Random();
private final DbClient dbClient = dbTester.getDbClient();
@@ -114,29 +117,30 @@ public class ReportAnalysisFailureNotificationExecutionListenerIT {
@Test
public void onEnd_has_no_effect_if_there_is_no_subscriber_for_ReportAnalysisFailureNotification_type() {
- String componentUuid = randomAlphanumeric(6);
+ ProjectData projectData = dbTester.components().insertPrivateProject();
when(ceTaskMock.getType()).thenReturn(CeTaskTypes.REPORT);
- when(ceTaskMock.getComponent()).thenReturn(Optional.of(new CeTask.Component(componentUuid, null, null)));
- when(notificationService.hasProjectSubscribersForTypes(componentUuid, singleton(ReportAnalysisFailureNotification.class)))
+ when(ceTaskMock.getComponent()).thenReturn(Optional.of(new CeTask.Component(projectData.getMainBranchDto().getUuid(), null, null)));
+ when(notificationService.hasProjectSubscribersForTypes(projectData.projectUuid(), singleton(ReportAnalysisFailureNotification.class)))
.thenReturn(false);
- fullMockedUnderTest.onEnd(ceTaskMock, CeActivityDto.Status.FAILED, randomDuration(), ceTaskResultMock, throwableMock);
+ underTest.onEnd(ceTaskMock, CeActivityDto.Status.FAILED, randomDuration(), ceTaskResultMock, throwableMock);
- verifyNoInteractions(ceTaskResultMock, throwableMock, dbClientMock, serializer, system2);
+ verifyNoInteractions(ceTaskResultMock, throwableMock, serializer, system2);
}
@Test
public void onEnd_fails_with_ISE_if_project_does_not_exist_in_DB() {
- String componentUuid = randomAlphanumeric(6);
+ BranchDto branchDto = dbTester.components().insertProjectBranch(new ProjectDto().setUuid("uuid").setKee("kee").setName("name"));
+ String componentUuid = branchDto.getUuid();
when(ceTaskMock.getType()).thenReturn(CeTaskTypes.REPORT);
when(ceTaskMock.getComponent()).thenReturn(Optional.of(new CeTask.Component(componentUuid, null, null)));
- when(notificationService.hasProjectSubscribersForTypes(componentUuid, singleton(ReportAnalysisFailureNotification.class)))
+ when(notificationService.hasProjectSubscribersForTypes(branchDto.getProjectUuid(), singleton(ReportAnalysisFailureNotification.class)))
.thenReturn(true);
Duration randomDuration = randomDuration();
assertThatThrownBy(() -> underTest.onEnd(ceTaskMock, CeActivityDto.Status.FAILED, randomDuration, ceTaskResultMock, throwableMock))
.isInstanceOf(IllegalStateException.class)
- .hasMessage("Could not find project uuid " + componentUuid);
+ .hasMessage("Could not find project uuid " + branchDto.getProjectUuid());
}
@Test
@@ -153,50 +157,49 @@ public class ReportAnalysisFailureNotificationExecutionListenerIT {
Duration randomDuration = randomDuration();
assertThatThrownBy(() -> underTest.onEnd(ceTaskMock, CeActivityDto.Status.FAILED, randomDuration, ceTaskResultMock, throwableMock))
.isInstanceOf(IllegalStateException.class)
- .hasMessage("Could not find a branch for project uuid " + componentUuid);
+ .hasMessage("Could not find a branch with uuid " + componentUuid);
}
@Test
- public void onEnd_fails_with_IAE_if_component_is_not_a_project() {
+ public void onEnd_fails_with_IAE_if_component_is_not_a_branch() {
when(ceTaskMock.getType()).thenReturn(CeTaskTypes.REPORT);
- ComponentDto project = dbTester.components().insertPrivateProject().getMainBranchComponent();
- ComponentDto directory = dbTester.components().insertComponent(newDirectory(project, randomAlphanumeric(12)));
- ComponentDto file = dbTester.components().insertComponent(ComponentTesting.newFileDto(project));
+ ComponentDto mainBranch = dbTester.components().insertPrivateProject().getMainBranchComponent();
+ ComponentDto directory = dbTester.components().insertComponent(newDirectory(mainBranch, randomAlphanumeric(12)));
+ ComponentDto file = dbTester.components().insertComponent(ComponentTesting.newFileDto(mainBranch));
ComponentDto view = dbTester.components().insertComponent(ComponentTesting.newPortfolio());
ComponentDto subView = dbTester.components().insertComponent(ComponentTesting.newSubPortfolio(view));
- ComponentDto projectCopy = dbTester.components().insertComponent(ComponentTesting.newProjectCopy(project, subView));
+ ComponentDto projectCopy = dbTester.components().insertComponent(ComponentTesting.newProjectCopy(mainBranch, subView));
ComponentDto application = dbTester.components().insertComponent(ComponentTesting.newApplication());
Arrays.asList(directory, file, view, subView, projectCopy, application)
.forEach(component -> {
- when(ceTaskMock.getComponent()).thenReturn(Optional.of(new CeTask.Component(component.uuid(), null, null)));
- when(notificationService.hasProjectSubscribersForTypes(component.uuid(), singleton(ReportAnalysisFailureNotification.class)))
- .thenReturn(true);
+ when(ceTaskMock.getComponent()).thenReturn(Optional.of(new CeTask.Component(component.uuid(), null, null)));
+ when(notificationService.hasProjectSubscribersForTypes(component.uuid(), singleton(ReportAnalysisFailureNotification.class)))
+ .thenReturn(true);
Duration randomDuration = randomDuration();
try {
underTest.onEnd(ceTaskMock, CeActivityDto.Status.FAILED, randomDuration, ceTaskResultMock, throwableMock);
fail("An IllegalArgumentException should have been thrown for component " + component);
- } catch (IllegalArgumentException e) {
- assertThat(e.getMessage()).isEqualTo(String.format("Component %s must be a project (qualifier=%s)", component.uuid(), component.qualifier()));
} catch (IllegalStateException e) {
- assertThat(e.getMessage()).isEqualTo("Could not find project uuid " + component.uuid());
+ assertThat(e.getMessage()).isIn("Could not find project uuid " + component.uuid(), "Could not find a branch with uuid " + component.uuid());
}
});
}
@Test
public void onEnd_fails_with_RowNotFoundException_if_activity_for_task_does_not_exist_in_DB() {
- String componentUuid = randomAlphanumeric(6);
+ ProjectData projectData = dbTester.components().insertPrivateProject();
+ ComponentDto mainBranch = projectData.getMainBranchComponent();
String taskUuid = randomAlphanumeric(6);
when(ceTaskMock.getType()).thenReturn(CeTaskTypes.REPORT);
when(ceTaskMock.getUuid()).thenReturn(taskUuid);
- when(ceTaskMock.getComponent()).thenReturn(Optional.of(new CeTask.Component(componentUuid, null, null)));
- when(notificationService.hasProjectSubscribersForTypes(componentUuid, singleton(ReportAnalysisFailureNotification.class)))
+ when(ceTaskMock.getComponent()).thenReturn(Optional.of(new CeTask.Component(mainBranch.uuid(), null, null)));
+ when(notificationService.hasProjectSubscribersForTypes(projectData.projectUuid(), singleton(ReportAnalysisFailureNotification.class)))
.thenReturn(true);
- dbTester.components().insertPrivateProject(s -> s.setUuid(componentUuid)).getMainBranchComponent();
+
Duration randomDuration = randomDuration();
assertThatThrownBy(() -> underTest.onEnd(ceTaskMock, CeActivityDto.Status.FAILED, randomDuration, ceTaskResultMock, throwableMock))
@@ -209,7 +212,7 @@ public class ReportAnalysisFailureNotificationExecutionListenerIT {
String taskUuid = randomAlphanumeric(12);
int createdAt = random.nextInt(999_999);
long executedAt = random.nextInt(999_999);
- ComponentDto project = initMocksToPassConditions(taskUuid, createdAt, executedAt);
+ ProjectData project = initMocksToPassConditions(taskUuid, createdAt, executedAt);
Notification notificationMock = mockSerializer();
underTest.onEnd(ceTaskMock, CeActivityDto.Status.FAILED, randomDuration(), ceTaskResultMock, throwableMock);
@@ -220,9 +223,9 @@ public class ReportAnalysisFailureNotificationExecutionListenerIT {
ReportAnalysisFailureNotificationBuilder reportAnalysisFailureNotificationBuilder = notificationCaptor.getValue();
ReportAnalysisFailureNotificationBuilder.Project notificationProject = reportAnalysisFailureNotificationBuilder.project();
- assertThat(notificationProject.name()).isEqualTo(project.name());
- assertThat(notificationProject.key()).isEqualTo(project.getKey());
- assertThat(notificationProject.uuid()).isEqualTo(project.uuid());
+ assertThat(notificationProject.name()).isEqualTo(project.getProjectDto().getName());
+ assertThat(notificationProject.key()).isEqualTo(project.getProjectDto().getKey());
+ assertThat(notificationProject.uuid()).isEqualTo(project.getProjectDto().getUuid());
assertThat(notificationProject.branchName()).isNull();
ReportAnalysisFailureNotificationBuilder.Task notificationTask = reportAnalysisFailureNotificationBuilder.task();
assertThat(notificationTask.uuid()).isEqualTo(taskUuid);
@@ -231,6 +234,36 @@ public class ReportAnalysisFailureNotificationExecutionListenerIT {
}
@Test
+ public void onEnd_shouldCreateNotificationWithDataFromActivity_whenNonMainBranchIsFailing() {
+ String taskUuid = randomAlphanumeric(12);
+ int createdAt = random.nextInt(999_999);
+ long executedAt = random.nextInt(999_999);
+
+ ProjectData project = random.nextBoolean() ? dbTester.components().insertPrivateProject() : dbTester.components().insertPublicProject();
+ ComponentDto branchComponent = dbTester.components().insertProjectBranch(project.getMainBranchComponent(), b->b.setKey("otherbranch"));
+ initMocksToPassConditionsForBranch(branchComponent, project, taskUuid, createdAt, executedAt);
+
+ Notification notificationMock = mockSerializer();
+
+ underTest.onEnd(ceTaskMock, CeActivityDto.Status.FAILED, randomDuration(), ceTaskResultMock, throwableMock);
+
+ ArgumentCaptor<ReportAnalysisFailureNotificationBuilder> notificationCaptor = verifyAndCaptureSerializedNotification();
+ verify(notificationService).deliver(same(notificationMock));
+
+ ReportAnalysisFailureNotificationBuilder reportAnalysisFailureNotificationBuilder = notificationCaptor.getValue();
+
+ ReportAnalysisFailureNotificationBuilder.Project notificationProject = reportAnalysisFailureNotificationBuilder.project();
+ assertThat(notificationProject.name()).isEqualTo(project.getProjectDto().getName());
+ assertThat(notificationProject.key()).isEqualTo(project.getProjectDto().getKey());
+ assertThat(notificationProject.uuid()).isEqualTo(project.getProjectDto().getUuid());
+ assertThat(notificationProject.branchName()).isEqualTo("otherbranch");
+ ReportAnalysisFailureNotificationBuilder.Task notificationTask = reportAnalysisFailureNotificationBuilder.task();
+ assertThat(notificationTask.uuid()).isEqualTo(taskUuid);
+ assertThat(notificationTask.createdAt()).isEqualTo(createdAt);
+ assertThat(notificationTask.failedAt()).isEqualTo(executedAt);
+ }
+
+ @Test
public void onEnd_creates_notification_with_error_message_from_Throwable_argument_message() {
initMocksToPassConditions(randomAlphanumeric(12), random.nextInt(999_999), (long) random.nextInt(999_999));
String message = randomAlphanumeric(66);
@@ -303,22 +336,31 @@ public class ReportAnalysisFailureNotificationExecutionListenerIT {
return notificationMock;
}
- private ComponentDto initMocksToPassConditions(String taskUuid, int createdAt, @Nullable Long executedAt) {
- ComponentDto project = random.nextBoolean() ? dbTester.components().insertPrivateProject().getMainBranchComponent() : dbTester.components().insertPublicProject().getMainBranchComponent();
+ private ProjectData initMocksToPassConditions(String taskUuid, int createdAt, @Nullable Long executedAt) {
+ ProjectData projectData = random.nextBoolean() ? dbTester.components().insertPrivateProject() : dbTester.components().insertPublicProject();
+ mockCeTask(taskUuid, createdAt, executedAt, projectData, projectData.getMainBranchComponent());
+ return projectData;
+ }
+
+ private ComponentDto initMocksToPassConditionsForBranch(ComponentDto branchComponent, ProjectData projectData, String taskUuid, int createdAt, @Nullable Long executedAt) {
+ mockCeTask(taskUuid, createdAt, executedAt, projectData, branchComponent);
+ return branchComponent;
+ }
+
+ private void mockCeTask(String taskUuid, int createdAt, @org.jetbrains.annotations.Nullable Long executedAt, ProjectData projectData, ComponentDto branchComponent) {
when(ceTaskMock.getType()).thenReturn(CeTaskTypes.REPORT);
- when(ceTaskMock.getComponent()).thenReturn(Optional.of(new CeTask.Component(project.uuid(), null, null)));
+ when(ceTaskMock.getComponent()).thenReturn(Optional.of(new CeTask.Component(branchComponent.uuid(), null, null)));
when(ceTaskMock.getUuid()).thenReturn(taskUuid);
- when(notificationService.hasProjectSubscribersForTypes(project.uuid(), singleton(ReportAnalysisFailureNotification.class)))
+ when(notificationService.hasProjectSubscribersForTypes(projectData.projectUuid(), singleton(ReportAnalysisFailureNotification.class)))
.thenReturn(true);
- insertActivityDto(taskUuid, createdAt, executedAt, project);
- return project;
+ insertActivityDto(taskUuid, createdAt, executedAt, branchComponent);
}
- private void insertActivityDto(String taskUuid, int createdAt, @Nullable Long executedAt, ComponentDto project) {
+ private void insertActivityDto(String taskUuid, int createdAt, @Nullable Long executedAt, ComponentDto branch) {
dbClient.ceActivityDao().insert(dbTester.getSession(), new CeActivityDto(new CeQueueDto()
.setUuid(taskUuid)
.setTaskType(CeTaskTypes.REPORT)
- .setComponentUuid(project.uuid())
+ .setComponentUuid(branch.uuid())
.setCreatedAt(createdAt))
.setExecutedAt(executedAt)
.setStatus(CeActivityDto.Status.FAILED));
diff --git a/server/sonar-ce/src/main/java/org/sonar/ce/notification/ReportAnalysisFailureNotificationExecutionListener.java b/server/sonar-ce/src/main/java/org/sonar/ce/notification/ReportAnalysisFailureNotificationExecutionListener.java
index db89507ff10..179900ccee1 100644
--- a/server/sonar-ce/src/main/java/org/sonar/ce/notification/ReportAnalysisFailureNotificationExecutionListener.java
+++ b/server/sonar-ce/src/main/java/org/sonar/ce/notification/ReportAnalysisFailureNotificationExecutionListener.java
@@ -67,17 +67,18 @@ public class ReportAnalysisFailureNotificationExecutionListener implements CeWor
if (status == CeActivityDto.Status.SUCCESS) {
return;
}
- String projectUuid = ceTask.getComponent().map(CeTask.Component::getUuid).orElse(null);
- if (!CeTaskTypes.REPORT.equals(ceTask.getType()) || projectUuid == null) {
+ String branchUuid = ceTask.getComponent().map(CeTask.Component::getUuid).orElse(null);
+ if (!CeTaskTypes.REPORT.equals(ceTask.getType()) || branchUuid == null) {
return;
}
- if (notificationService.hasProjectSubscribersForTypes(projectUuid, singleton(ReportAnalysisFailureNotification.class))) {
- try (DbSession dbSession = dbClient.openSession(false)) {
- ProjectDto projectDto = dbClient.projectDao().selectByUuid(dbSession, projectUuid)
- .orElseThrow(() -> new IllegalStateException("Could not find project uuid " + projectUuid));
- BranchDto branchDto = dbClient.branchDao().selectByUuid(dbSession, projectDto.getUuid())
- .orElseThrow(() -> new IllegalStateException("Could not find a branch for project uuid " + projectDto.getUuid()));
+ try (DbSession dbSession = dbClient.openSession(false)) {
+ BranchDto branchDto = dbClient.branchDao().selectByUuid(dbSession, branchUuid)
+ .orElseThrow(() -> new IllegalStateException("Could not find a branch with uuid %s".formatted(branchUuid)));
+ if (notificationService.hasProjectSubscribersForTypes(branchDto.getProjectUuid(), singleton(ReportAnalysisFailureNotification.class))) {
+ ProjectDto projectDto = dbClient.projectDao().selectByUuid(dbSession, branchDto.getProjectUuid())
+ .orElseThrow(() -> new IllegalStateException("Could not find project uuid %s".formatted(branchDto.getProjectUuid())));
+
checkQualifier(projectDto);
CeActivityDto ceActivityDto = dbClient.ceActivityDao().selectByUuid(dbSession, ceTask.getUuid())
.orElseThrow(() -> new RowNotFoundException(format("CeActivity with uuid '%s' not found", ceTask.getUuid())));