From 07fde014056504340f7ac44f2f697f1680983792 Mon Sep 17 00:00:00 2001 From: Aurelien Poscia Date: Thu, 7 Dec 2023 10:19:52 +0100 Subject: [PATCH] SONAR-21204 Add info message to /api/ce/activity --- .../sonar/server/ce/ws/ActivityActionIT.java | 30 +++++++++++++++---- .../sonar/server/ce/ws/ActivityAction.java | 3 +- .../org/sonar/server/ce/ws/TaskFormatter.java | 13 ++++++++ .../sonar/server/ce/ws/activity-example.json | 4 +++ .../sonar/server/ce/ws/TaskFormatterTest.java | 25 ++++++++++++++-- sonar-ws/src/main/protobuf/ws-ce.proto | 1 + 6 files changed, 68 insertions(+), 8 deletions(-) diff --git a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/ce/ws/ActivityActionIT.java b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/ce/ws/ActivityActionIT.java index faeb14c405b..411dc6a4501 100644 --- a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/ce/ws/ActivityActionIT.java +++ b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/ce/ws/ActivityActionIT.java @@ -250,9 +250,9 @@ public class ActivityActionIT { insertActivity("T1", project1, SUCCESS); insertActivity("T2", project2, FAILED); insertQueue("T3", project1, IN_PROGRESS); - List messagesT1 = insertMessages("T1", 2); - List messagesT2 = insertMessages("T2", 1); - insertMessages("T3", 5); + List messagesT1 = insertMessages(MessageType.GENERIC,"T1", 2); + List messagesT2 = insertMessages(MessageType.GENERIC,"T2", 1); + insertMessages(MessageType.GENERIC,"T3", 5); ActivityResponse activityResponse = call(ws.newRequest() .setParam(Param.PAGE_SIZE, Integer.toString(10)) @@ -262,13 +262,33 @@ public class ActivityActionIT { .containsOnly(tuple("T1", messagesT1.size(), messagesT1), tuple("T2", messagesT2.size(), messagesT2), tuple("T3", 0, emptyList())); } - private List insertMessages(String taskUuid, int messageCount) { + @Test + public void return_infoMessages() { + logInAsSystemAdministrator(); + ProjectData project1 = db.components().insertPrivateProject(); + ProjectData project2 = db.components().insertPrivateProject(); + insertActivity("T1", project1, SUCCESS); + insertActivity("T2", project2, FAILED); + insertQueue("T3", project1, IN_PROGRESS); + List messagesT1 = insertMessages(MessageType.INFO,"T1", 2); + List messagesT2 = insertMessages(MessageType.INFO,"T2", 1); + insertMessages(MessageType.INFO,"T3", 5); + + ActivityResponse activityResponse = call(ws.newRequest() + .setParam(Param.PAGE_SIZE, Integer.toString(10)) + .setParam(PARAM_STATUS, "SUCCESS,FAILED,CANCELED,IN_PROGRESS,PENDING")); + assertThat(activityResponse.getTasksList()) + .extracting(Task::getId, Task::getInfoMessagesList) + .containsOnly(tuple("T1", messagesT1), tuple("T2", messagesT2), tuple("T3", emptyList())); + } + + private List insertMessages(MessageType messageType, String taskUuid, int messageCount) { List ceTaskMessageDtos = IntStream.range(0, messageCount) .mapToObj(i -> new CeTaskMessageDto() .setUuid("uuid_" + taskUuid + "_" + i) .setTaskUuid(taskUuid) .setMessage("m_" + taskUuid + "_" + i) - .setType(MessageType.GENERIC) + .setType(messageType) .setCreatedAt(taskUuid.hashCode() + i)) .toList(); diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/ce/ws/ActivityAction.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/ce/ws/ActivityAction.java index e9b72c81f61..1de49c9da31 100644 --- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/ce/ws/ActivityAction.java +++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/ce/ws/ActivityAction.java @@ -113,7 +113,8 @@ public class ActivityAction implements CeWsAction { new Change("8.8", "field \"logs\" is dropped"), new Change("10.0", "Remove deprecated field 'componentId'"), new Change("10.1", String.format("The use of module keys in parameter '%s' is removed", PARAM_COMPONENT)), - new Change("10.1", "Warnings field will be now be filled (it was always empty in the past).") + new Change("10.1", "Warnings field will be now be filled (it was always empty in the past)."), + new Change("10.4", "field \"infoMessages\" added to response") ) .setSince("5.2"); diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/ce/ws/TaskFormatter.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/ce/ws/TaskFormatter.java index 673cbe2f363..10523235792 100644 --- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/ce/ws/TaskFormatter.java +++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/ce/ws/TaskFormatter.java @@ -21,6 +21,7 @@ package org.sonar.server.ce.ws; import com.google.common.collect.Multimap; import java.util.Collection; +import java.util.Comparator; import java.util.Date; import java.util.List; import java.util.Map; @@ -41,6 +42,7 @@ import org.sonar.db.ce.CeQueueDto; import org.sonar.db.ce.CeTaskCharacteristicDto; import org.sonar.db.ce.CeTaskMessageDto; import org.sonar.db.component.ComponentDto; +import org.sonar.db.dismissmessage.MessageType; import org.sonar.db.user.UserDto; import org.sonarqube.ws.Ce; import org.sonarqube.ws.Common; @@ -129,6 +131,9 @@ public class TaskFormatter { builder.setWarningCount(warnings.size()); warnings.forEach(builder::addWarnings); + List infoMessages = extractInfoMessages(activityDto); + builder.addAllInfoMessages(infoMessages); + return builder.build(); } @@ -168,6 +173,14 @@ public class TaskFormatter { .toList(); } + private static List extractInfoMessages(CeActivityDto activityDto) { + return activityDto.getCeTaskMessageDtos().stream() + .filter(ceTaskMessageDto -> MessageType.INFO.equals(ceTaskMessageDto.getType())) + .sorted(Comparator.comparing(CeTaskMessageDto::getCreatedAt)) + .map(CeTaskMessageDto::getMessage) + .toList(); + } + private static class DtoCache { private final Map componentsByUuid; private final Multimap characteristicsByTaskUuid; diff --git a/server/sonar-webserver-webapi/src/main/resources/org/sonar/server/ce/ws/activity-example.json b/server/sonar-webserver-webapi/src/main/resources/org/sonar/server/ce/ws/activity-example.json index 65cb3713b4d..7d858fa2479 100644 --- a/server/sonar-webserver-webapi/src/main/resources/org/sonar/server/ce/ws/activity-example.json +++ b/server/sonar-webserver-webapi/src/main/resources/org/sonar/server/ce/ws/activity-example.json @@ -19,6 +19,10 @@ "warnings": [ "The properties \u0027sonar.login\u0027 and \u0027sonar.password\u0027 are deprecated and will be removed in the future. Please pass a token with the \u0027sonar.token\u0027 property instead.", "Missing blame information for 2 files. This may lead to some features not working correctly. Please check the analysis logs and refer to \u003ca href\u003d\"https://docs.sonarsource.com/sonarqube/latest/analyzing-source-code/scm-integration/\" rel\u003d\"noopener noreferrer\" target\u003d\"_blank\"\u003ethe documentation\u003c/a\u003e." + ] , + "infoMessages": [ + "Successfully synchronized 5 users.", + "Other information message" ] }, { diff --git a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/ce/ws/TaskFormatterTest.java b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/ce/ws/TaskFormatterTest.java index e8d1bec6d22..33bcd0e3839 100644 --- a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/ce/ws/TaskFormatterTest.java +++ b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/ce/ws/TaskFormatterTest.java @@ -23,6 +23,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.Date; import java.util.List; +import java.util.Set; import java.util.stream.IntStream; import javax.annotation.Nullable; import org.junit.Rule; @@ -45,6 +46,7 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import static org.sonar.db.ce.CeQueueTesting.makeInProgress; import static org.sonar.db.dismissmessage.MessageType.INFO; +import static org.sonar.db.dismissmessage.MessageType.PROJECT_NCD_PAGE_90; public class TaskFormatterTest { @@ -186,6 +188,7 @@ public class TaskFormatterTest { assertThat(wsTask.hasScannerContext()).isFalse(); assertThat(wsTask.getWarningCount()).isZero(); assertThat(wsTask.getWarningsList()).isEmpty(); + assertThat(wsTask.getInfoMessagesList()).isEmpty(); } @Test @@ -200,7 +203,7 @@ public class TaskFormatterTest { } @Test - public void formatActivity_filterNonWarnings_andSetMessagesAndCount() { + public void formatActivity_filterWarnings_andSetWarningsAndCount() { TestActivityDto dto = newActivity("UUID", "COMPONENT_UUID", CeActivityDto.Status.FAILED, null); CeTaskMessageDto warning1 = createCeTaskMessageDto(1998, MessageType.GENERIC); CeTaskMessageDto warning2 = createCeTaskMessageDto(1999, MessageType.GENERIC); @@ -216,6 +219,24 @@ public class TaskFormatterTest { assertThat(wsTask.getWarningsList()).hasSameElementsAs(getMessagesText(List.of(warning1, warning2))); } + @Test + public void formatActivity_filterInformation_andSetInformationMessages() { + TestActivityDto dto = newActivity("UUID", "COMPONENT_UUID", CeActivityDto.Status.FAILED, null); + CeTaskMessageDto nonInfo1 = createCeTaskMessageDto(1998, MessageType.SUGGEST_DEVELOPER_EDITION_UPGRADE); + CeTaskMessageDto nonInfo2 = createCeTaskMessageDto(1999, MessageType.GENERIC); + CeTaskMessageDto nonInfo3 = createCeTaskMessageDto(2000, MessageType.BRANCH_NCD_90); + CeTaskMessageDto info2 = createCeTaskMessageDto(2002, INFO); + CeTaskMessageDto info1 = createCeTaskMessageDto(2001, INFO); + + List ceTaskMessageDtos = new ArrayList<>(dto.getCeTaskMessageDtos()); + ceTaskMessageDtos.addAll(Set.of(nonInfo1, nonInfo2, nonInfo3, info1, info2)); + dto.setCeTaskMessageDtos(ceTaskMessageDtos); + + Ce.Task wsTask = underTest.formatActivity(db.getSession(), dto, null); + + assertThat(wsTask.getInfoMessagesList()).hasSameElementsAs(getMessagesText(List.of(info1, info2))); + } + private static List getMessagesText(List ceTaskMessageDtos) { return ceTaskMessageDtos.stream().map(CeTaskMessageDto::getMessage).toList(); } @@ -282,7 +303,7 @@ public class TaskFormatterTest { TestActivityDto testActivityDto = new TestActivityDto(queueDto); List ceTaskMessageDtos = IntStream.range(0, WARNING_COUNT) - .mapToObj(i -> createCeTaskMessageDto(i, INFO)) + .mapToObj(i -> createCeTaskMessageDto(i, PROJECT_NCD_PAGE_90)) .toList(); testActivityDto.setCeTaskMessageDtos(ceTaskMessageDtos); return (TestActivityDto) testActivityDto diff --git a/sonar-ws/src/main/protobuf/ws-ce.proto b/sonar-ws/src/main/protobuf/ws-ce.proto index 3c19f02a691..ab51fba97ca 100644 --- a/sonar-ws/src/main/protobuf/ws-ce.proto +++ b/sonar-ws/src/main/protobuf/ws-ce.proto @@ -136,6 +136,7 @@ message Task { optional int32 warningCount = 26; repeated string warnings = 27; optional string nodeName = 28; + repeated string infoMessages = 29; } enum TaskStatus { -- 2.39.5