Skip to content

Commit

Permalink
SONAR-10085 webhook now use shared model of QualityGate
Browse files Browse the repository at this point in the history
  • Loading branch information
sns-seb committed Nov 24, 2017
1 parent ef1259e commit dd8f115
Show file tree
Hide file tree
Showing 11 changed files with 166 additions and 435 deletions.
Expand Up @@ -24,7 +24,6 @@
import java.util.Map; import java.util.Map;
import java.util.Optional; import java.util.Optional;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors;
import javax.annotation.CheckForNull; import javax.annotation.CheckForNull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import org.sonar.api.ce.posttask.Analysis; import org.sonar.api.ce.posttask.Analysis;
Expand All @@ -37,6 +36,7 @@
import org.sonar.api.utils.System2; import org.sonar.api.utils.System2;
import org.sonar.api.utils.log.Logger; import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers; import org.sonar.api.utils.log.Loggers;
import org.sonar.core.util.stream.MoreCollectors;
import org.sonar.server.computation.task.projectanalysis.analysis.AnalysisMetadataHolder; import org.sonar.server.computation.task.projectanalysis.analysis.AnalysisMetadataHolder;
import org.sonar.server.computation.task.projectanalysis.batch.BatchReportReader; import org.sonar.server.computation.task.projectanalysis.batch.BatchReportReader;
import org.sonar.server.computation.task.projectanalysis.qualitygate.Condition; import org.sonar.server.computation.task.projectanalysis.qualitygate.Condition;
Expand Down Expand Up @@ -191,7 +191,8 @@ private static QualityGate.Status convert(QualityGateStatus status) {


private static Collection<QualityGate.Condition> convert(Set<Condition> conditions, Map<Condition, ConditionStatus> statusPerConditions) { private static Collection<QualityGate.Condition> convert(Set<Condition> conditions, Map<Condition, ConditionStatus> statusPerConditions) {
return conditions.stream() return conditions.stream()
.map(new ConditionToCondition(statusPerConditions)::apply).collect(Collectors.toList()); .map(new ConditionToCondition(statusPerConditions)::apply)
.collect(MoreCollectors.toList(statusPerConditions.size()));
} }


private static class ProjectAnalysisImpl implements PostProjectAnalysisTask.ProjectAnalysis { private static class ProjectAnalysisImpl implements PostProjectAnalysisTask.ProjectAnalysis {
Expand Down
Expand Up @@ -21,15 +21,18 @@


import java.util.Map; import java.util.Map;
import java.util.Optional; import java.util.Optional;
import java.util.stream.Collectors; import java.util.Set;
import org.sonar.api.ce.posttask.PostProjectAnalysisTask; import org.sonar.api.ce.posttask.PostProjectAnalysisTask;
import org.sonar.api.config.Configuration; import org.sonar.api.config.Configuration;
import org.sonar.core.util.stream.MoreCollectors;
import org.sonar.server.computation.task.projectanalysis.component.ConfigurationRepository; import org.sonar.server.computation.task.projectanalysis.component.ConfigurationRepository;
import org.sonar.server.qualitygate.Condition;
import org.sonar.server.qualitygate.EvaluatedCondition;
import org.sonar.server.qualitygate.EvaluatedQualityGate;
import org.sonar.server.webhook.Analysis; import org.sonar.server.webhook.Analysis;
import org.sonar.server.webhook.Branch; import org.sonar.server.webhook.Branch;
import org.sonar.server.webhook.CeTask; import org.sonar.server.webhook.CeTask;
import org.sonar.server.webhook.Project; import org.sonar.server.webhook.Project;
import org.sonar.server.webhook.QualityGate;
import org.sonar.server.webhook.WebHooks; import org.sonar.server.webhook.WebHooks;
import org.sonar.server.webhook.WebhookPayloadFactory; import org.sonar.server.webhook.WebhookPayloadFactory;


Expand Down Expand Up @@ -63,16 +66,23 @@ private static org.sonar.server.webhook.ProjectAnalysis convert(ProjectAnalysis
Project project = new Project(projectAnalysis.getProject().getUuid(), projectAnalysis.getProject().getKey(), projectAnalysis.getProject().getName()); Project project = new Project(projectAnalysis.getProject().getUuid(), projectAnalysis.getProject().getKey(), projectAnalysis.getProject().getName());
Analysis analysis = projectAnalysis.getAnalysis().map(a -> new Analysis(a.getAnalysisUuid(), a.getDate().getTime())).orElse(null); Analysis analysis = projectAnalysis.getAnalysis().map(a -> new Analysis(a.getAnalysisUuid(), a.getDate().getTime())).orElse(null);
Branch branch = projectAnalysis.getBranch().map(b -> new Branch(b.isMain(), b.getName().orElse(null), Branch.Type.valueOf(b.getType().name()))).orElse(null); Branch branch = projectAnalysis.getBranch().map(b -> new Branch(b.isMain(), b.getName().orElse(null), Branch.Type.valueOf(b.getType().name()))).orElse(null);
QualityGate qualityGate = Optional.ofNullable(projectAnalysis.getQualityGate()) EvaluatedQualityGate qualityGate = Optional.ofNullable(projectAnalysis.getQualityGate())
.map(qg -> new QualityGate( .map(qg -> {
qg.getId(), EvaluatedQualityGate.Builder builder = EvaluatedQualityGate.newBuilder();
qg.getName(), Set<Condition> conditions = qg.getConditions().stream()
QualityGate.Status.valueOf(qg.getStatus().name()), .map(q -> {
qg.getConditions().stream() Condition condition = new Condition(q.getMetricKey(), Condition.Operator.valueOf(q.getOperator().name()),
.map(c -> new QualityGate.Condition(QualityGate.EvaluationStatus.valueOf(c.getStatus().name()), c.getMetricKey(), QualityGate.Operator.valueOf(c.getOperator().name()), q.getErrorThreshold(), q.getWarningThreshold(), q.isOnLeakPeriod());
c.getErrorThreshold(), c.getWarningThreshold(), c.isOnLeakPeriod(), builder.addCondition(condition,
c.getStatus() == org.sonar.api.ce.posttask.QualityGate.EvaluationStatus.NO_VALUE ? null : c.getValue())) EvaluatedCondition.EvaluationStatus.valueOf(q.getStatus().name()),
.collect(Collectors.toSet()))) q.getStatus() == org.sonar.api.ce.posttask.QualityGate.EvaluationStatus.NO_VALUE ? null : q.getValue());
return condition;
})
.collect(MoreCollectors.toSet());
return builder.setQualityGate(new org.sonar.server.qualitygate.QualityGate(qg.getId(), qg.getName(), conditions))
.setStatus(EvaluatedQualityGate.Status.valueOf(qg.getStatus().name()))
.build();
})
.orElse(null); .orElse(null);
Long date = projectAnalysis.getAnalysis().map(a -> a.getDate().getTime()).orElse(null); Long date = projectAnalysis.getAnalysis().map(a -> a.getDate().getTime()).orElse(null);
Map<String, String> properties = projectAnalysis.getScannerContext().getProperties(); Map<String, String> properties = projectAnalysis.getScannerContext().getProperties();
Expand Down
Expand Up @@ -46,14 +46,17 @@
import org.sonar.server.es.SearchOptions; import org.sonar.server.es.SearchOptions;
import org.sonar.server.issue.IssueQuery; import org.sonar.server.issue.IssueQuery;
import org.sonar.server.issue.index.IssueIndex; import org.sonar.server.issue.index.IssueIndex;
import org.sonar.server.qualitygate.Condition;
import org.sonar.server.qualitygate.EvaluatedCondition;
import org.sonar.server.qualitygate.EvaluatedCondition.EvaluationStatus;
import org.sonar.server.qualitygate.EvaluatedQualityGate;
import org.sonar.server.qualitygate.ShortLivingBranchQualityGate; import org.sonar.server.qualitygate.ShortLivingBranchQualityGate;
import org.sonar.server.rule.index.RuleIndex; import org.sonar.server.rule.index.RuleIndex;
import org.sonar.server.settings.ProjectConfigurationLoader; import org.sonar.server.settings.ProjectConfigurationLoader;
import org.sonar.server.webhook.Analysis; import org.sonar.server.webhook.Analysis;
import org.sonar.server.webhook.Branch; import org.sonar.server.webhook.Branch;
import org.sonar.server.webhook.Project; import org.sonar.server.webhook.Project;
import org.sonar.server.webhook.ProjectAnalysis; import org.sonar.server.webhook.ProjectAnalysis;
import org.sonar.server.webhook.QualityGate;
import org.sonar.server.webhook.WebHooks; import org.sonar.server.webhook.WebHooks;
import org.sonar.server.webhook.WebhookPayload; import org.sonar.server.webhook.WebhookPayload;
import org.sonar.server.webhook.WebhookPayloadFactory; import org.sonar.server.webhook.WebhookPayloadFactory;
Expand Down Expand Up @@ -170,7 +173,7 @@ private WebhookPayload buildWebHookPayload(DbSession dbSession, ComponentDto bra
return webhookPayloadFactory.create(projectAnalysis); return webhookPayloadFactory.create(projectAnalysis);
} }


private QualityGate createQualityGate(ComponentDto branch, IssueIndex issueIndex) { private EvaluatedQualityGate createQualityGate(ComponentDto branch, IssueIndex issueIndex) {
SearchResponse searchResponse = issueIndex.search(IssueQuery.builder() SearchResponse searchResponse = issueIndex.search(IssueQuery.builder()
.projectUuids(singletonList(branch.getMainBranchProjectUuid())) .projectUuids(singletonList(branch.getMainBranchProjectUuid()))
.branchUuid(branch.uuid()) .branchUuid(branch.uuid())
Expand All @@ -182,43 +185,48 @@ private QualityGate createQualityGate(ComponentDto branch, IssueIndex issueIndex
LinkedHashMap<String, Long> typeFacet = new Facets(searchResponse, system2.getDefaultTimeZone()) LinkedHashMap<String, Long> typeFacet = new Facets(searchResponse, system2.getDefaultTimeZone())
.get(RuleIndex.FACET_TYPES); .get(RuleIndex.FACET_TYPES);


Set<QualityGate.Condition> conditions = ShortLivingBranchQualityGate.CONDITIONS.stream() EvaluatedQualityGate.Builder builder = EvaluatedQualityGate.newBuilder();
.map(c -> toCondition(typeFacet, c)) Set<Condition> conditions = ShortLivingBranchQualityGate.CONDITIONS.stream()
.map(c -> {
long measure = getMeasure(typeFacet, c);
EvaluationStatus status = measure > 0 ? EvaluationStatus.ERROR : EvaluationStatus.OK;
Condition condition = new Condition(c.getMetricKey(), toOperator(c), c.getErrorThreshold(), c.getWarnThreshold(), c.isOnLeak());
builder.addCondition(condition, status, valueOf(measure));
return condition;
})
.collect(toSet(ShortLivingBranchQualityGate.CONDITIONS.size())); .collect(toSet(ShortLivingBranchQualityGate.CONDITIONS.size()));
builder
.setQualityGate(
new org.sonar.server.qualitygate.QualityGate(
valueOf(ShortLivingBranchQualityGate.ID),
ShortLivingBranchQualityGate.NAME,
conditions))
.setStatus(qgStatusFrom(builder.getEvaluatedConditions()));


return new QualityGate(valueOf(ShortLivingBranchQualityGate.ID), ShortLivingBranchQualityGate.NAME, qgStatusFrom(conditions), conditions); return builder.build();
} }


private static QualityGate.Condition toCondition(LinkedHashMap<String, Long> typeFacet, ShortLivingBranchQualityGate.Condition c) { private static Condition.Operator toOperator(ShortLivingBranchQualityGate.Condition c) {
long measure = getMeasure(typeFacet, c);
QualityGate.EvaluationStatus status = measure > 0 ? QualityGate.EvaluationStatus.ERROR : QualityGate.EvaluationStatus.OK;
return new QualityGate.Condition(status, c.getMetricKey(),
toOperator(c),
c.getErrorThreshold(), c.getWarnThreshold(), c.isOnLeak(),
valueOf(measure));
}

private static QualityGate.Operator toOperator(ShortLivingBranchQualityGate.Condition c) {
String operator = c.getOperator(); String operator = c.getOperator();
switch (operator) { switch (operator) {
case QualityGateConditionDto.OPERATOR_GREATER_THAN: case QualityGateConditionDto.OPERATOR_GREATER_THAN:
return QualityGate.Operator.GREATER_THAN; return Condition.Operator.GREATER_THAN;
case QualityGateConditionDto.OPERATOR_LESS_THAN: case QualityGateConditionDto.OPERATOR_LESS_THAN:
return QualityGate.Operator.LESS_THAN; return Condition.Operator.LESS_THAN;
case QualityGateConditionDto.OPERATOR_EQUALS: case QualityGateConditionDto.OPERATOR_EQUALS:
return QualityGate.Operator.EQUALS; return Condition.Operator.EQUALS;
case QualityGateConditionDto.OPERATOR_NOT_EQUALS: case QualityGateConditionDto.OPERATOR_NOT_EQUALS:
return QualityGate.Operator.NOT_EQUALS; return Condition.Operator.NOT_EQUALS;
default: default:
throw new IllegalArgumentException(format("Unsupported Condition operator '%s'", operator)); throw new IllegalArgumentException(format("Unsupported Condition operator '%s'", operator));
} }
} }


private static QualityGate.Status qgStatusFrom(Set<QualityGate.Condition> conditions) { private static EvaluatedQualityGate.Status qgStatusFrom(Set<EvaluatedCondition> conditions) {
if (conditions.stream().anyMatch(c -> c.getStatus() == QualityGate.EvaluationStatus.ERROR)) { if (conditions.stream().anyMatch(c -> c.getStatus() == EvaluationStatus.ERROR)) {
return QualityGate.Status.ERROR; return EvaluatedQualityGate.Status.ERROR;
} }
return QualityGate.Status.OK; return EvaluatedQualityGate.Status.OK;
} }


private static long getMeasure(LinkedHashMap<String, Long> typeFacet, ShortLivingBranchQualityGate.Condition c) { private static long getMeasure(LinkedHashMap<String, Long> typeFacet, ShortLivingBranchQualityGate.Condition c) {
Expand Down
Expand Up @@ -23,6 +23,7 @@
import java.util.Objects; import java.util.Objects;
import java.util.Optional; import java.util.Optional;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import org.sonar.server.qualitygate.EvaluatedQualityGate;


import static com.google.common.collect.ImmutableMap.copyOf; import static com.google.common.collect.ImmutableMap.copyOf;
import static java.util.Objects.requireNonNull; import static java.util.Objects.requireNonNull;
Expand All @@ -31,13 +32,13 @@ public class ProjectAnalysis {
private final Project project; private final Project project;
private final CeTask ceTask; private final CeTask ceTask;
private final Branch branch; private final Branch branch;
private final QualityGate qualityGate; private final EvaluatedQualityGate qualityGate;
private final Long updatedAt; private final Long updatedAt;
private final Map<String, String> properties; private final Map<String, String> properties;
private final Analysis analysis; private final Analysis analysis;


public ProjectAnalysis(Project project, @Nullable CeTask ceTask, @Nullable Analysis analysis, public ProjectAnalysis(Project project, @Nullable CeTask ceTask, @Nullable Analysis analysis,
@Nullable Branch branch, @Nullable QualityGate qualityGate, @Nullable Long updatedAt, @Nullable Branch branch, @Nullable EvaluatedQualityGate qualityGate, @Nullable Long updatedAt,
Map<String, String> properties) { Map<String, String> properties) {
this.project = requireNonNull(project, "project can't be null"); this.project = requireNonNull(project, "project can't be null");
this.ceTask = ceTask; this.ceTask = ceTask;
Expand All @@ -60,7 +61,7 @@ public Optional<Branch> getBranch() {
return Optional.ofNullable(branch); return Optional.ofNullable(branch);
} }


public Optional<QualityGate> getQualityGate() { public Optional<EvaluatedQualityGate> getQualityGate() {
return Optional.ofNullable(qualityGate); return Optional.ofNullable(qualityGate);
} }


Expand Down

0 comments on commit dd8f115

Please sign in to comment.