@@ -34,6 +34,7 @@ import org.sonar.db.DbSession; | |||
import org.sonar.db.component.BranchDto; | |||
import org.sonar.db.component.ComponentDto; | |||
import org.sonar.db.component.SnapshotDto; | |||
import org.sonar.db.measure.LiveMeasureDto; | |||
import org.sonar.db.protobuf.DbProjectBranches; | |||
import org.sonar.server.component.ComponentFinder; | |||
import org.sonar.server.issue.index.BranchStatistics; | |||
@@ -42,7 +43,9 @@ import org.sonar.server.user.UserSession; | |||
import org.sonarqube.ws.ProjectPullRequests; | |||
import static com.google.common.base.Preconditions.checkArgument; | |||
import static java.util.Collections.singletonList; | |||
import static java.util.Objects.requireNonNull; | |||
import static org.sonar.api.measures.CoreMetrics.ALERT_STATUS_KEY; | |||
import static org.sonar.api.resources.Qualifiers.PROJECT; | |||
import static org.sonar.api.utils.DateUtils.formatDateTime; | |||
import static org.sonar.core.util.Protobuf.setNullable; | |||
@@ -98,19 +101,22 @@ public class ListAction implements PullRequestWsAction { | |||
.stream().collect(uniqueIndex(BranchDto::getUuid)); | |||
Map<String, BranchStatistics> branchStatisticsByBranchUuid = issueIndex.searchBranchStatistics(project.uuid(), pullRequestUuids).stream() | |||
.collect(uniqueIndex(BranchStatistics::getBranchUuid, Function.identity())); | |||
Map<String, LiveMeasureDto> qualityGateMeasuresByComponentUuids = dbClient.liveMeasureDao() | |||
.selectByComponentUuidsAndMetricKeys(dbSession, pullRequestUuids, singletonList(ALERT_STATUS_KEY)).stream() | |||
.collect(uniqueIndex(LiveMeasureDto::getComponentUuid)); | |||
Map<String, String> analysisDateByBranchUuid = dbClient.snapshotDao().selectLastAnalysesByRootComponentUuids(dbSession, pullRequestUuids).stream() | |||
.collect(uniqueIndex(SnapshotDto::getComponentUuid, s -> formatDateTime(s.getCreatedAt()))); | |||
ProjectPullRequests.ListWsResponse.Builder protobufResponse = ProjectPullRequests.ListWsResponse.newBuilder(); | |||
pullRequests | |||
.forEach(b -> addPullRequest(protobufResponse, b, mergeBranchesByUuid, branchStatisticsByBranchUuid.get(b.getUuid()), | |||
.forEach(b -> addPullRequest(protobufResponse, b, mergeBranchesByUuid, qualityGateMeasuresByComponentUuids.get(b.getUuid()), branchStatisticsByBranchUuid.get(b.getUuid()), | |||
analysisDateByBranchUuid.get(b.getUuid()))); | |||
writeProtobuf(protobufResponse.build(), request, response); | |||
} | |||
} | |||
private static void addPullRequest(ProjectPullRequests.ListWsResponse.Builder response, BranchDto branch, Map<String, BranchDto> mergeBranchesByUuid, | |||
BranchStatistics branchStatistics, @Nullable String analysisDate) { | |||
@Nullable LiveMeasureDto qualityGateMeasure, BranchStatistics branchStatistics, @Nullable String analysisDate) { | |||
Optional<BranchDto> mergeBranch = Optional.ofNullable(mergeBranchesByUuid.get(branch.getMergeBranchUuid())); | |||
ProjectPullRequests.PullRequest.Builder builder = ProjectPullRequests.PullRequest.newBuilder(); | |||
@@ -128,12 +134,15 @@ public class ListAction implements PullRequestWsAction { | |||
builder.setIsOrphan(true); | |||
} | |||
setNullable(analysisDate, builder::setAnalysisDate); | |||
setBranchStatus(builder, branchStatistics); | |||
setQualityGate(builder, qualityGateMeasure, branchStatistics); | |||
response.addPullRequests(builder); | |||
} | |||
private static void setBranchStatus(ProjectPullRequests.PullRequest.Builder builder, @Nullable BranchStatistics branchStatistics) { | |||
private static void setQualityGate(ProjectPullRequests.PullRequest.Builder builder, @Nullable LiveMeasureDto qualityGateMeasure, @Nullable BranchStatistics branchStatistics) { | |||
ProjectPullRequests.Status.Builder statusBuilder = ProjectPullRequests.Status.newBuilder(); | |||
if (qualityGateMeasure != null) { | |||
setNullable(qualityGateMeasure.getDataAsString(), statusBuilder::setQualityGateStatus); | |||
} | |||
statusBuilder.setBugs(branchStatistics == null ? 0L : branchStatistics.getBugs()); | |||
statusBuilder.setVulnerabilities(branchStatistics == null ? 0L : branchStatistics.getVulnerabilities()); | |||
statusBuilder.setCodeSmells(branchStatistics == null ? 0L : branchStatistics.getCodeSmells()); |
@@ -30,7 +30,6 @@ import javax.annotation.Nullable; | |||
import org.sonar.api.server.ws.Request; | |||
import org.sonar.api.server.ws.Response; | |||
import org.sonar.api.server.ws.WebService; | |||
import org.sonar.core.util.Protobuf; | |||
import org.sonar.core.util.stream.MoreCollectors; | |||
import org.sonar.db.DbClient; | |||
import org.sonar.db.DbSession; | |||
@@ -157,15 +156,15 @@ public class ListAction implements BranchWsAction { | |||
@Nullable BranchStatistics branchStatistics) { | |||
ProjectBranches.Status.Builder statusBuilder = ProjectBranches.Status.newBuilder(); | |||
if (qualityGateMeasure != null) { | |||
Protobuf.setNullable(qualityGateMeasure.getDataAsString(), statusBuilder::setQualityGateStatus); | |||
builder.setStatus(statusBuilder); | |||
setNullable(qualityGateMeasure.getDataAsString(), statusBuilder::setQualityGateStatus); | |||
} | |||
if (branch.getBranchType() == BranchType.SHORT) { | |||
statusBuilder.setBugs(branchStatistics == null ? 0L : branchStatistics.getBugs()); | |||
statusBuilder.setVulnerabilities(branchStatistics == null ? 0L : branchStatistics.getVulnerabilities()); | |||
statusBuilder.setCodeSmells(branchStatistics == null ? 0L : branchStatistics.getCodeSmells()); | |||
builder.setStatus(statusBuilder); | |||
} | |||
builder.setStatus(statusBuilder); | |||
} | |||
private void checkPermission(ComponentDto component) { |
@@ -6,6 +6,7 @@ | |||
"branch": "feature/bar", | |||
"base": "feature/foo", | |||
"status": { | |||
"qualityGateStatus": "OK", | |||
"bugs": 0, | |||
"vulnerabilities": 0, | |||
"codeSmells": 0 |
@@ -19,6 +19,7 @@ | |||
*/ | |||
package org.sonar.server.branch.pr.ws; | |||
import org.junit.Before; | |||
import org.junit.Rule; | |||
import org.junit.Test; | |||
import org.junit.rules.ExpectedException; | |||
@@ -33,7 +34,7 @@ import org.sonar.db.component.BranchType; | |||
import org.sonar.db.component.ComponentDto; | |||
import org.sonar.db.component.ComponentTesting; | |||
import org.sonar.db.component.ResourceTypesRule; | |||
import org.sonar.db.component.SnapshotTesting; | |||
import org.sonar.db.metric.MetricDto; | |||
import org.sonar.db.organization.OrganizationDto; | |||
import org.sonar.db.protobuf.DbProjectBranches; | |||
import org.sonar.db.rule.RuleDefinitionDto; | |||
@@ -58,6 +59,7 @@ import static org.assertj.core.api.Assertions.assertThat; | |||
import static org.assertj.core.api.Assertions.tuple; | |||
import static org.sonar.api.issue.Issue.RESOLUTION_FALSE_POSITIVE; | |||
import static org.sonar.api.issue.Issue.RESOLUTION_FIXED; | |||
import static org.sonar.api.measures.CoreMetrics.ALERT_STATUS_KEY; | |||
import static org.sonar.api.resources.Qualifiers.PROJECT; | |||
import static org.sonar.api.rules.RuleType.BUG; | |||
import static org.sonar.api.rules.RuleType.CODE_SMELL; | |||
@@ -66,6 +68,8 @@ import static org.sonar.api.utils.DateUtils.dateToLong; | |||
import static org.sonar.api.utils.DateUtils.parseDateTime; | |||
import static org.sonar.db.component.BranchType.LONG; | |||
import static org.sonar.db.component.BranchType.PULL_REQUEST; | |||
import static org.sonar.db.component.SnapshotTesting.newAnalysis; | |||
import static org.sonar.server.branch.pr.ws.PullRequestsWsParameters.PARAM_PROJECT; | |||
import static org.sonar.test.JsonAssert.assertJson; | |||
import static org.sonarqube.ws.ProjectPullRequests.Status; | |||
@@ -80,6 +84,8 @@ public class ListActionTest { | |||
@Rule | |||
public UserSessionRule userSession = UserSessionRule.standalone(); | |||
private MetricDto qualityGateStatus; | |||
private ResourceTypes resourceTypes = new ResourceTypesRule().setRootQualifiers(PROJECT); | |||
private IssueIndexer issueIndexer = new IssueIndexer(es.client(), db.getDbClient(), new IssueIteratorFactory(db.getDbClient())); | |||
private IssueIndex issueIndex = new IssueIndex(es.client(), System2.INSTANCE, userSession, new AuthorizationTypeSupport(userSession)); | |||
@@ -87,6 +93,11 @@ public class ListActionTest { | |||
public WsActionTester ws = new WsActionTester(new ListAction(db.getDbClient(), userSession, new ComponentFinder(db.getDbClient(), resourceTypes), issueIndex)); | |||
@Before | |||
public void setUp() { | |||
qualityGateStatus = db.measures().insertMetric(m -> m.setKey(ALERT_STATUS_KEY)); | |||
} | |||
@Test | |||
public void definition() { | |||
WebService.Action definition = ws.getDef(); | |||
@@ -110,18 +121,19 @@ public class ListActionTest { | |||
.setTitle("Add feature X") | |||
.setUrl("https://github.com/SonarSource/sonar-core-plugins/pull/32") | |||
.build())); | |||
db.getDbClient().snapshotDao().insert(db.getSession(), newAnalysis(pullRequest).setLast(true).setCreatedAt(DateUtils.parseDateTime("2017-04-01T01:15:42+0100").getTime())); | |||
db.measures().insertLiveMeasure(pullRequest, qualityGateStatus, m -> m.setData("OK")); | |||
userSession.logIn().addProjectPermission(UserRole.USER, project); | |||
db.getDbClient().snapshotDao().insert(db.getSession(), | |||
SnapshotTesting.newAnalysis(pullRequest).setLast(true).setCreatedAt(DateUtils.parseDateTime("2017-04-01T01:15:42+0100").getTime())); | |||
db.commit(); | |||
String json = ws.newRequest() | |||
.setParam("project", project.getDbKey()) | |||
.setParam(PARAM_PROJECT, project.getKey()) | |||
.execute() | |||
.getInput(); | |||
assertJson(json).isSimilarTo(ws.getDef().responseExampleAsString()); | |||
assertJson(ws.getDef().responseExampleAsString()).isSimilarTo(json); | |||
} | |||
@Test | |||
@@ -235,6 +247,7 @@ public class ListActionTest { | |||
.setBranchType(PULL_REQUEST) | |||
.setMergeBranchUuid(longLivingBranch.uuid()) | |||
.setPullRequestData(DbProjectBranches.PullRequestData.newBuilder().setBranch("feature/bar").build())); | |||
db.measures().insertLiveMeasure(pullRequest, qualityGateStatus, m -> m.setData("ERROR")); | |||
RuleDefinitionDto rule = db.rules().insert(); | |||
db.issues().insert(rule, pullRequest, pullRequest, i -> i.setType(BUG).setResolution(null)); | |||
db.issues().insert(rule, pullRequest, pullRequest, i -> i.setType(BUG).setResolution(RESOLUTION_FIXED)); | |||
@@ -252,8 +265,8 @@ public class ListActionTest { | |||
.executeProtobuf(ListWsResponse.class); | |||
assertThat(response.getPullRequestsList().stream().map(PullRequest::getStatus)) | |||
.extracting(Status::hasBugs, Status::getBugs, Status::hasVulnerabilities, Status::getVulnerabilities, Status::hasCodeSmells, Status::getCodeSmells) | |||
.containsExactlyInAnyOrder(tuple(true, 1L, true, 2L, true, 3L)); | |||
.extracting(Status::getQualityGateStatus, Status::hasBugs, Status::getBugs, Status::hasVulnerabilities, Status::getVulnerabilities, Status::hasCodeSmells, Status::getCodeSmells) | |||
.containsExactlyInAnyOrder(tuple("ERROR", true, 1L, true, 2L, true, 3L)); | |||
} | |||
@Test | |||
@@ -302,11 +315,11 @@ public class ListActionTest { | |||
.setPullRequestData(DbProjectBranches.PullRequestData.newBuilder().setBranch("feature/pr2").build())); | |||
db.getDbClient().snapshotDao().insert(db.getSession(), | |||
SnapshotTesting.newAnalysis(longLivingBranch2).setCreatedAt(lastAnalysisLongLivingBranch)); | |||
newAnalysis(longLivingBranch2).setCreatedAt(lastAnalysisLongLivingBranch)); | |||
db.getDbClient().snapshotDao().insert(db.getSession(), | |||
SnapshotTesting.newAnalysis(pullRequest2).setCreatedAt(previousAnalysisPullRequest).setLast(false)); | |||
newAnalysis(pullRequest2).setCreatedAt(previousAnalysisPullRequest).setLast(false)); | |||
db.getDbClient().snapshotDao().insert(db.getSession(), | |||
SnapshotTesting.newAnalysis(pullRequest2).setCreatedAt(lastAnalysisPullRequest)); | |||
newAnalysis(pullRequest2).setCreatedAt(lastAnalysisPullRequest)); | |||
db.commit(); | |||
issueIndexer.indexOnStartup(emptySet()); | |||
permissionIndexerTester.allowOnlyAnyone(project); |
@@ -43,6 +43,7 @@ message PullRequest { | |||
} | |||
message Status { | |||
optional string qualityGateStatus = 1; | |||
optional int64 bugs = 2; | |||
optional int64 vulnerabilities = 3; | |||
optional int64 codeSmells = 4; |