From c482c5f6b1ee3ffc78c6592bfafe1743b9cf6e3b Mon Sep 17 00:00:00 2001 From: Julien Lancelot Date: Fri, 11 Aug 2017 18:51:38 +0200 Subject: [PATCH] SONAR-9616 Add bugs, vulnerabilities and code smells in branches list --- .../server/projectbranch/ws/ListAction.java | 32 ++++++++++++-- .../projectbranch/ws/ListActionTest.java | 44 ++++++++++++++++++- .../main/protobuf/ws-projectbranches.proto | 6 +-- 3 files changed, 74 insertions(+), 8 deletions(-) diff --git a/server/sonar-server/src/main/java/org/sonar/server/projectbranch/ws/ListAction.java b/server/sonar-server/src/main/java/org/sonar/server/projectbranch/ws/ListAction.java index fd34266be0a..77f54fd78b8 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/projectbranch/ws/ListAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/projectbranch/ws/ListAction.java @@ -40,6 +40,7 @@ import org.sonar.db.metric.MetricDto; import org.sonar.server.user.UserSession; import org.sonar.server.ws.WsUtils; import org.sonarqube.ws.WsBranches; +import org.sonarqube.ws.WsBranches.Branch.Status; import static com.google.common.base.Preconditions.checkState; import static java.util.Arrays.asList; @@ -51,6 +52,8 @@ import static org.sonar.core.util.Protobuf.setNullable; import static org.sonar.core.util.stream.MoreCollectors.index; import static org.sonar.core.util.stream.MoreCollectors.toList; import static org.sonar.core.util.stream.MoreCollectors.uniqueIndex; +import static org.sonar.db.component.BranchType.LONG; +import static org.sonar.db.component.BranchType.SHORT; import static org.sonar.server.ws.KeyExamples.KEY_PROJECT_EXAMPLE_001; import static org.sonarqube.ws.client.projectbranches.ProjectBranchesParameters.ACTION_LIST; import static org.sonarqube.ws.client.projectbranches.ProjectBranchesParameters.PARAM_PROJECT; @@ -94,7 +97,7 @@ public class ListAction implements BranchWsAction { throw new IllegalArgumentException("Invalid project key"); } - List metrics = dbClient.metricDao().selectByKeys(dbSession, asList(ALERT_STATUS_KEY)); + List metrics = dbClient.metricDao().selectByKeys(dbSession, asList(ALERT_STATUS_KEY, BUGS_KEY, VULNERABILITIES_KEY, CODE_SMELLS_KEY)); Map metricsById = metrics.stream().collect(uniqueIndex(MetricDto::getId)); Map metricIdsByKey = metrics.stream().collect(uniqueIndex(MetricDto::getKey, MetricDto::getId)); @@ -127,9 +130,30 @@ public class ListAction implements BranchWsAction { setNullable(mergeBranch.getKey(), builder::setMergeBranch); } - int qualityGateStatusMetricId = metricIdsByKey.get(ALERT_STATUS_KEY); - measuresByComponentUuids.get(branch.getUuid()).stream().filter(m -> m.getMetricId() == qualityGateStatusMetricId).findAny() - .ifPresent(measure -> builder.setStatus(WsBranches.Branch.Status.newBuilder().setQualityGateStatus(measure.getData()))); + Status.Builder statusBuilder = Status.newBuilder(); + Collection componentMeasures = measuresByComponentUuids.get(branch.getUuid()); + if (branch.getBranchType().equals(LONG)) { + int qualityGateStatusMetricId = metricIdsByKey.get(ALERT_STATUS_KEY); + componentMeasures.stream().filter(m -> m.getMetricId() == qualityGateStatusMetricId).findAny() + .ifPresent(measure -> statusBuilder.setQualityGateStatus(measure.getData())); + } + + if (branch.getBranchType().equals(SHORT)) { + int bugsMetricId = metricIdsByKey.get(BUGS_KEY); + componentMeasures.stream().filter(m -> m.getMetricId() == bugsMetricId).findAny() + .ifPresent(measure -> statusBuilder.setBugs(measure.getValue().intValue())); + + int vulnerabilitiesMetricId = metricIdsByKey.get(VULNERABILITIES_KEY); + componentMeasures.stream().filter(m -> m.getMetricId() == vulnerabilitiesMetricId).findAny() + .ifPresent(measure -> statusBuilder.setVulnerabilities(measure.getValue().intValue())); + + int codeSmellMetricId = metricIdsByKey.get(CODE_SMELLS_KEY); + componentMeasures.stream().filter(m -> m.getMetricId() == codeSmellMetricId).findAny() + .ifPresent(measure -> statusBuilder.setCodeSmells(measure.getValue().intValue())); + } + + builder.setStatus(statusBuilder); builder.build(); } + } diff --git a/server/sonar-server/src/test/java/org/sonar/server/projectbranch/ws/ListActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/projectbranch/ws/ListActionTest.java index 17fb1a8c086..46c8415b6ce 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/projectbranch/ws/ListActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/projectbranch/ws/ListActionTest.java @@ -19,6 +19,7 @@ */ package org.sonar.server.projectbranch.ws; +import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; @@ -35,13 +36,18 @@ import org.sonar.server.exceptions.NotFoundException; import org.sonar.server.tester.UserSessionRule; import org.sonar.server.ws.WsActionTester; import org.sonarqube.ws.MediaTypes; +import org.sonarqube.ws.WsBranches; import org.sonarqube.ws.WsBranches.Branch; import org.sonarqube.ws.WsBranches.ListWsResponse; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.tuple; import static org.sonar.api.measures.CoreMetrics.ALERT_STATUS_KEY; +import static org.sonar.api.measures.CoreMetrics.BUGS_KEY; +import static org.sonar.api.measures.CoreMetrics.CODE_SMELLS_KEY; +import static org.sonar.api.measures.CoreMetrics.VULNERABILITIES_KEY; import static org.sonar.test.JsonAssert.assertJson; +import static org.sonarqube.ws.WsBranches.Branch.Status; public class ListActionTest { @@ -54,8 +60,21 @@ public class ListActionTest { @Rule public UserSessionRule userSession = UserSessionRule.standalone(); + private MetricDto qualityGateStatus; + private MetricDto bugs; + private MetricDto vulnerabilities; + private MetricDto codeSmells; + public WsActionTester tester = new WsActionTester(new ListAction(db.getDbClient(), userSession)); + @Before + public void setUp() throws Exception { + qualityGateStatus = db.measures().insertMetric(m -> m.setKey(ALERT_STATUS_KEY)); + bugs = db.measures().insertMetric(m -> m.setKey(BUGS_KEY)); + vulnerabilities = db.measures().insertMetric(m -> m.setKey(VULNERABILITIES_KEY)); + codeSmells = db.measures().insertMetric(m -> m.setKey(CODE_SMELLS_KEY)); + } + @Test public void test_definition() { WebService.Action definition = tester.getDef(); @@ -173,7 +192,6 @@ public class ListActionTest { userSession.logIn().addProjectPermission(UserRole.USER, project); ComponentDto branch = db.components().insertProjectBranch(project, b -> b.setBranchType(BranchType.LONG)); SnapshotDto branchAnalysis = db.components().insertSnapshot(branch); - MetricDto qualityGateStatus = db.measures().insertMetric(m -> m.setKey(ALERT_STATUS_KEY)); db.measures().insertMeasure(branch, branchAnalysis, qualityGateStatus, m -> m.setData("OK")); ListWsResponse response = tester.newRequest() @@ -185,6 +203,30 @@ public class ListActionTest { .containsExactlyInAnyOrder(tuple(false, ""), tuple(true, "OK")); } + @Test + public void bugs_vulnerabilities_and_code_smells_on_short_living_branch() { + ComponentDto project = db.components().insertMainBranch(); + userSession.logIn().addProjectPermission(UserRole.USER, project); + ComponentDto longLivingBranch = db.components().insertProjectBranch(project, b -> b.setBranchType(BranchType.LONG)); + ComponentDto shortLivingBranch = db.components().insertProjectBranch(project, + b -> b.setBranchType(BranchType.SHORT).setMergeBranchUuid(longLivingBranch.uuid())); + SnapshotDto branchAnalysis = db.components().insertSnapshot(shortLivingBranch); + db.measures().insertMeasure(shortLivingBranch, branchAnalysis, bugs, m -> m.setValue(1d)); + db.measures().insertMeasure(shortLivingBranch, branchAnalysis, vulnerabilities, m -> m.setValue(2d)); + db.measures().insertMeasure(shortLivingBranch, branchAnalysis, codeSmells, m -> m.setValue(3d)); + + ListWsResponse response = tester.newRequest() + .setParam("project", project.getKey()) + .executeProtobuf(ListWsResponse.class); + + assertThat(response.getBranchesList().stream().map(WsBranches.Branch::getStatus)) + .extracting(Status::hasBugs, Status::getBugs, Status::hasVulnerabilities, Status::getVulnerabilities, Status::hasCodeSmells, Status::getCodeSmells) + .containsExactlyInAnyOrder( + tuple(false, 0, false, 0, false, 0), + tuple(false, 0, false, 0, false, 0), + tuple(true, 1, true, 2, true, 3)); + } + @Test public void test_example() { ComponentDto project = db.components().insertPrivateProject(); diff --git a/sonar-ws/src/main/protobuf/ws-projectbranches.proto b/sonar-ws/src/main/protobuf/ws-projectbranches.proto index 3b32bc08fb8..915e983e788 100644 --- a/sonar-ws/src/main/protobuf/ws-projectbranches.proto +++ b/sonar-ws/src/main/protobuf/ws-projectbranches.proto @@ -43,9 +43,9 @@ message Branch { // Quality gate status is only present for long living branch optional string qualityGateStatus = 1; // Merge bugs, vulnerabilities and codeSmell are only present for short living branch - optional string bugs = 2; - optional string vulnerabilities = 3; - optional string codeSmell = 4; + optional int32 bugs = 2; + optional int32 vulnerabilities = 3; + optional int32 codeSmells = 4; } enum BranchType { -- 2.39.5