import java.util.Map;
import java.util.Optional;
import java.util.Set;
-import java.util.stream.Collectors;
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
import org.sonar.api.ce.posttask.Analysis;
import org.sonar.api.utils.System2;
import org.sonar.api.utils.log.Logger;
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.batch.BatchReportReader;
import org.sonar.server.computation.task.projectanalysis.qualitygate.Condition;
private static Collection<QualityGate.Condition> convert(Set<Condition> conditions, Map<Condition, ConditionStatus> statusPerConditions) {
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 {
import java.util.Map;
import java.util.Optional;
-import java.util.stream.Collectors;
+import java.util.Set;
import org.sonar.api.ce.posttask.PostProjectAnalysisTask;
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.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.Branch;
import org.sonar.server.webhook.CeTask;
import org.sonar.server.webhook.Project;
-import org.sonar.server.webhook.QualityGate;
import org.sonar.server.webhook.WebHooks;
import org.sonar.server.webhook.WebhookPayloadFactory;
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);
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())
- .map(qg -> new QualityGate(
- qg.getId(),
- qg.getName(),
- QualityGate.Status.valueOf(qg.getStatus().name()),
- qg.getConditions().stream()
- .map(c -> new QualityGate.Condition(QualityGate.EvaluationStatus.valueOf(c.getStatus().name()), c.getMetricKey(), QualityGate.Operator.valueOf(c.getOperator().name()),
- c.getErrorThreshold(), c.getWarningThreshold(), c.isOnLeakPeriod(),
- c.getStatus() == org.sonar.api.ce.posttask.QualityGate.EvaluationStatus.NO_VALUE ? null : c.getValue()))
- .collect(Collectors.toSet())))
+ EvaluatedQualityGate qualityGate = Optional.ofNullable(projectAnalysis.getQualityGate())
+ .map(qg -> {
+ EvaluatedQualityGate.Builder builder = EvaluatedQualityGate.newBuilder();
+ Set<Condition> conditions = qg.getConditions().stream()
+ .map(q -> {
+ Condition condition = new Condition(q.getMetricKey(), Condition.Operator.valueOf(q.getOperator().name()),
+ q.getErrorThreshold(), q.getWarningThreshold(), q.isOnLeakPeriod());
+ builder.addCondition(condition,
+ EvaluatedCondition.EvaluationStatus.valueOf(q.getStatus().name()),
+ 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);
Long date = projectAnalysis.getAnalysis().map(a -> a.getDate().getTime()).orElse(null);
Map<String, String> properties = projectAnalysis.getScannerContext().getProperties();
import org.sonar.server.es.SearchOptions;
import org.sonar.server.issue.IssueQuery;
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.rule.index.RuleIndex;
import org.sonar.server.settings.ProjectConfigurationLoader;
import org.sonar.server.webhook.Branch;
import org.sonar.server.webhook.Project;
import org.sonar.server.webhook.ProjectAnalysis;
-import org.sonar.server.webhook.QualityGate;
import org.sonar.server.webhook.WebHooks;
import org.sonar.server.webhook.WebhookPayload;
import org.sonar.server.webhook.WebhookPayloadFactory;
return webhookPayloadFactory.create(projectAnalysis);
}
- private QualityGate createQualityGate(ComponentDto branch, IssueIndex issueIndex) {
+ private EvaluatedQualityGate createQualityGate(ComponentDto branch, IssueIndex issueIndex) {
SearchResponse searchResponse = issueIndex.search(IssueQuery.builder()
.projectUuids(singletonList(branch.getMainBranchProjectUuid()))
.branchUuid(branch.uuid())
LinkedHashMap<String, Long> typeFacet = new Facets(searchResponse, system2.getDefaultTimeZone())
.get(RuleIndex.FACET_TYPES);
- Set<QualityGate.Condition> conditions = ShortLivingBranchQualityGate.CONDITIONS.stream()
- .map(c -> toCondition(typeFacet, c))
+ EvaluatedQualityGate.Builder builder = EvaluatedQualityGate.newBuilder();
+ 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()));
+ 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) {
- 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) {
+ private static Condition.Operator toOperator(ShortLivingBranchQualityGate.Condition c) {
String operator = c.getOperator();
switch (operator) {
case QualityGateConditionDto.OPERATOR_GREATER_THAN:
- return QualityGate.Operator.GREATER_THAN;
+ return Condition.Operator.GREATER_THAN;
case QualityGateConditionDto.OPERATOR_LESS_THAN:
- return QualityGate.Operator.LESS_THAN;
+ return Condition.Operator.LESS_THAN;
case QualityGateConditionDto.OPERATOR_EQUALS:
- return QualityGate.Operator.EQUALS;
+ return Condition.Operator.EQUALS;
case QualityGateConditionDto.OPERATOR_NOT_EQUALS:
- return QualityGate.Operator.NOT_EQUALS;
+ return Condition.Operator.NOT_EQUALS;
default:
throw new IllegalArgumentException(format("Unsupported Condition operator '%s'", operator));
}
}
- private static QualityGate.Status qgStatusFrom(Set<QualityGate.Condition> conditions) {
- if (conditions.stream().anyMatch(c -> c.getStatus() == QualityGate.EvaluationStatus.ERROR)) {
- return QualityGate.Status.ERROR;
+ private static EvaluatedQualityGate.Status qgStatusFrom(Set<EvaluatedCondition> conditions) {
+ if (conditions.stream().anyMatch(c -> c.getStatus() == EvaluationStatus.ERROR)) {
+ return EvaluatedQualityGate.Status.ERROR;
}
- return QualityGate.Status.OK;
+ return EvaluatedQualityGate.Status.OK;
}
private static long getMeasure(LinkedHashMap<String, Long> typeFacet, ShortLivingBranchQualityGate.Condition c) {
import java.util.Objects;
import java.util.Optional;
import javax.annotation.Nullable;
+import org.sonar.server.qualitygate.EvaluatedQualityGate;
import static com.google.common.collect.ImmutableMap.copyOf;
import static java.util.Objects.requireNonNull;
private final Project project;
private final CeTask ceTask;
private final Branch branch;
- private final QualityGate qualityGate;
+ private final EvaluatedQualityGate qualityGate;
private final Long updatedAt;
private final Map<String, String> properties;
private final 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) {
this.project = requireNonNull(project, "project can't be null");
this.ceTask = ceTask;
return Optional.ofNullable(branch);
}
- public Optional<QualityGate> getQualityGate() {
+ public Optional<EvaluatedQualityGate> getQualityGate() {
return Optional.ofNullable(qualityGate);
}
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2017 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.webhook;
-
-import com.google.common.collect.ImmutableSet;
-import java.util.Collection;
-import java.util.Objects;
-import java.util.Optional;
-import java.util.Set;
-import javax.annotation.Nullable;
-
-import static java.util.Objects.requireNonNull;
-
-public final class QualityGate {
- private final String id;
- private final String name;
- private final Status status;
- private final Set<Condition> conditions;
-
- public QualityGate(String id, String name, Status status, Set<Condition> conditions) {
- this.id = requireNonNull(id, "id can't be null");
- this.name = requireNonNull(name, "name can't be null");
- this.status = requireNonNull(status, "status can't be null");
- this.conditions = ImmutableSet.copyOf(requireNonNull(conditions, "conditions can't be null"));
- }
-
- public String getId() {
- return id;
- }
-
- public String getName() {
- return name;
- }
-
- public Status getStatus() {
- return status;
- }
-
- public Collection<Condition> getConditions() {
- return conditions;
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) {
- return true;
- }
- if (o == null || getClass() != o.getClass()) {
- return false;
- }
- QualityGate that = (QualityGate) o;
- return Objects.equals(id, that.id) &&
- Objects.equals(name, that.name) &&
- status == that.status &&
- Objects.equals(conditions, that.conditions);
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(id, name, status, conditions);
- }
-
- @Override
- public String toString() {
- return "QualityGate{" +
- "id='" + id + '\'' +
- ", name='" + name + '\'' +
- ", status=" + status +
- ", conditions=" + conditions +
- '}';
- }
-
- public enum Status {
- OK,
- WARN,
- ERROR
- }
-
- public static final class Condition {
- private final EvaluationStatus status;
- private final String metricKey;
- private final Operator operator;
- private final String errorThreshold;
- private final String warnThreshold;
- private final boolean onLeakPeriod;
- private final String value;
-
- public Condition(EvaluationStatus status, String metricKey, Operator operator,
- @Nullable String errorThreshold, @Nullable String warnThreshold,
- boolean onLeakPeriod, @Nullable String value) {
- this.status = requireNonNull(status, "status can't be null");
- this.metricKey = requireNonNull(metricKey, "metricKey can't be null");
- this.operator = requireNonNull(operator, "operator can't be null");
- this.errorThreshold = errorThreshold;
- this.warnThreshold = warnThreshold;
- this.onLeakPeriod = onLeakPeriod;
- this.value = value;
- }
-
- public EvaluationStatus getStatus() {
- return status;
- }
-
- public String getMetricKey() {
- return metricKey;
- }
-
- public Operator getOperator() {
- return operator;
- }
-
- public Optional<String> getErrorThreshold() {
- return Optional.ofNullable(errorThreshold);
- }
-
- public Optional<String> getWarningThreshold() {
- return Optional.ofNullable(warnThreshold);
- }
-
- public boolean isOnLeakPeriod() {
- return onLeakPeriod;
- }
-
- public Optional<String> getValue() {
- return Optional.ofNullable(value);
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) {
- return true;
- }
- if (o == null || getClass() != o.getClass()) {
- return false;
- }
- Condition condition = (Condition) o;
- return onLeakPeriod == condition.onLeakPeriod &&
- status == condition.status &&
- Objects.equals(metricKey, condition.metricKey) &&
- operator == condition.operator &&
- Objects.equals(errorThreshold, condition.errorThreshold) &&
- Objects.equals(warnThreshold, condition.warnThreshold) &&
- Objects.equals(value, condition.value);
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(status, metricKey, operator, errorThreshold, warnThreshold, onLeakPeriod, value);
- }
-
- @Override
- public String toString() {
- return "Condition{" +
- "status=" + status +
- ", metricKey='" + metricKey + '\'' +
- ", operator=" + operator +
- ", errorThreshold='" + errorThreshold + '\'' +
- ", warnThreshold='" + warnThreshold + '\'' +
- ", onLeakPeriod=" + onLeakPeriod +
- ", value='" + value + '\'' +
- '}';
- }
- }
-
- /**
- * Quality Gate condition operator.
- */
- public enum Operator {
- EQUALS, NOT_EQUALS, GREATER_THAN, LESS_THAN
- }
-
- /**
- * Quality gate condition evaluation status.
- */
- public enum EvaluationStatus {
- /**
- * No measure found or measure had no value. The condition has not been evaluated and therefor ignored in
- * the computation of the Quality Gate status.
- */
- NO_VALUE,
- /**
- * Condition evaluated as OK, neither error nor warning thresholds have been reached.
- */
- OK,
- /**
- * Condition evaluated as WARN, only warning thresholds has been reached.
- */
- WARN,
- /**
- * Condition evaluated as ERROR, error thresholds has been reached (and most likely warning thresholds too).
- */
- ERROR
- }
-}
import org.sonar.api.platform.Server;
import org.sonar.api.utils.System2;
import org.sonar.api.utils.text.JsonWriter;
+import org.sonar.server.qualitygate.Condition;
+import org.sonar.server.qualitygate.EvaluatedCondition;
+import org.sonar.server.qualitygate.EvaluatedQualityGate;
import static java.lang.String.format;
import static org.sonar.core.config.WebhookProperties.ANALYSIS_PROPERTY_PREFIX;
}
}
- private static void writeQualityGate(JsonWriter writer, QualityGate gate) {
+ private static void writeQualityGate(JsonWriter writer, EvaluatedQualityGate gate) {
writer
.name("qualityGate")
.beginObject()
- .prop("name", gate.getName())
+ .prop("name", gate.getQualityGate().getName())
.prop(PROPERTY_STATUS, gate.getStatus().toString())
.name("conditions")
.beginArray();
- for (QualityGate.Condition condition : gate.getConditions()) {
+ for (EvaluatedCondition evaluatedCondition : gate.getEvaluatedConditions()) {
+ Condition condition = evaluatedCondition.getCondition();
writer
.beginObject()
.prop("metric", condition.getMetricKey())
.prop("operator", condition.getOperator().name());
- condition.getValue().ifPresent(t -> writer.prop("value", t));
+ evaluatedCondition.getValue().ifPresent(t -> writer.prop("value", t));
writer
- .prop(PROPERTY_STATUS, condition.getStatus().name())
+ .prop(PROPERTY_STATUS, evaluatedCondition.getStatus().name())
.prop("onLeakPeriod", condition.isOnLeakPeriod())
.prop("errorThreshold", condition.getErrorThreshold().orElse(null))
.prop("warningThreshold", condition.getWarningThreshold().orElse(null))
import org.sonar.api.ce.posttask.QualityGate;
import org.sonar.api.config.Configuration;
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.ProjectAnalysis;
import org.sonar.server.webhook.WebHooks;
assertThat(supplierCaptor.getValue().get()).isSameAs(webhookPayload);
- org.sonar.server.webhook.QualityGate webQualityGate = null;
+ EvaluatedQualityGate webQualityGate = null;
if (qualityGate != null) {
QualityGate.Condition condition = qualityGate.getConditions().iterator().next();
- webQualityGate = new org.sonar.server.webhook.QualityGate(qualityGate.getId(), qualityGate.getName(),
- org.sonar.server.webhook.QualityGate.Status.valueOf(qualityGate.getStatus().name()),
- Collections.singleton(new org.sonar.server.webhook.QualityGate.Condition(
- org.sonar.server.webhook.QualityGate.EvaluationStatus.valueOf(condition.getStatus().name()),
- condition.getMetricKey(),
- org.sonar.server.webhook.QualityGate.Operator.valueOf(condition.getOperator().name()),
- condition.getErrorThreshold(),
- condition.getWarningThreshold(),
- condition.isOnLeakPeriod(),
- condition.getValue())));
+ Condition qgCondition = new Condition(
+ condition.getMetricKey(),
+ Condition.Operator.valueOf(condition.getOperator().name()),
+ condition.getErrorThreshold(),
+ condition.getWarningThreshold(),
+ condition.isOnLeakPeriod());
+ webQualityGate = EvaluatedQualityGate.newBuilder()
+ .setQualityGate(new org.sonar.server.qualitygate.QualityGate(qualityGate.getId(), qualityGate.getName(), Collections.singleton(qgCondition)))
+ .setStatus(EvaluatedQualityGate.Status.valueOf(qualityGate.getStatus().name()))
+ .addCondition(qgCondition, EvaluatedCondition.EvaluationStatus.valueOf(condition.getStatus().name()), condition.getValue())
+ .build();
}
verify(payloadFactory).create(new ProjectAnalysis(
import org.sonar.api.config.internal.MapSettings;
import org.sonar.api.issue.DefaultTransitions;
import org.sonar.api.issue.Issue;
-import org.sonar.api.measures.CoreMetrics;
import org.sonar.api.rules.RuleType;
import org.sonar.api.utils.System2;
import org.sonar.core.issue.IssueChangeContext;
import org.sonar.server.issue.index.IssueIteratorFactory;
import org.sonar.server.issue.webhook.IssueChangeWebhook.IssueChange;
import org.sonar.server.permission.index.AuthorizationTypeSupport;
+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.QualityGate;
import org.sonar.server.qualitygate.ShortLivingBranchQualityGate;
import org.sonar.server.settings.ProjectConfigurationLoader;
import org.sonar.server.tester.UserSessionRule;
import org.sonar.server.webhook.Branch;
import org.sonar.server.webhook.Project;
import org.sonar.server.webhook.ProjectAnalysis;
-import org.sonar.server.webhook.QualityGate;
-import org.sonar.server.webhook.QualityGate.EvaluationStatus;
import org.sonar.server.webhook.WebHooks;
import org.sonar.server.webhook.WebhookPayload;
import org.sonar.server.webhook.WebhookPayloadFactory;
import static org.sonar.api.measures.CoreMetrics.CODE_SMELLS_KEY;
import static org.sonar.api.measures.CoreMetrics.VULNERABILITIES_KEY;
import static org.sonar.core.util.stream.MoreCollectors.toArrayList;
-import static org.sonar.server.webhook.QualityGate.Operator.GREATER_THAN;
+import static org.sonar.server.qualitygate.Condition.Operator.GREATER_THAN;
@RunWith(DataProviderRunner.class)
public class IssueChangeWebhookImplTest {
private IssueChangeWebhookImpl underTest = new IssueChangeWebhookImpl(spiedOnDbClient, webHooks, projectConfigurationLoader, webhookPayloadFactory, issueIndex, System2.INSTANCE);
private DbClient mockedDbClient = mock(DbClient.class);
private IssueIndex spiedOnIssueIndex = spy(issueIndex);
- private IssueChangeWebhookImpl mockedUnderTest = new IssueChangeWebhookImpl(mockedDbClient, webHooks, projectConfigurationLoader, webhookPayloadFactory, spiedOnIssueIndex, System2.INSTANCE);
+ private IssueChangeWebhookImpl mockedUnderTest = new IssueChangeWebhookImpl(mockedDbClient, webHooks, projectConfigurationLoader, webhookPayloadFactory, spiedOnIssueIndex,
+ System2.INSTANCE);
@Test
public void on_type_change_has_no_effect_if_SearchResponseData_has_no_issue() {
underTest.onChange(issueChangeData(newIssueDto(branch)), issueChange, userChangeContext);
ProjectAnalysis projectAnalysis = verifyWebhookCalledAndExtractPayloadFactoryArgument(branch, configuration, analysis);
+ Condition condition1 = new Condition(BUGS_KEY, GREATER_THAN, "0", null, false);
+ Condition condition2 = new Condition(VULNERABILITIES_KEY, GREATER_THAN, "0", null, false);
+ Condition condition3 = new Condition(CODE_SMELLS_KEY, GREATER_THAN, "0", null, false);
assertThat(projectAnalysis).isEqualTo(
new ProjectAnalysis(
new Project(project.uuid(), project.getKey(), project.name()),
null,
new Analysis(analysis.getUuid(), analysis.getCreatedAt()),
new Branch(false, "foo", Branch.Type.SHORT),
- new QualityGate(
- valueOf(ShortLivingBranchQualityGate.ID),
- ShortLivingBranchQualityGate.NAME,
- QualityGate.Status.OK,
- ImmutableSet.of(
- new QualityGate.Condition(EvaluationStatus.OK, BUGS_KEY, GREATER_THAN, "0", null, false, "0"),
- new QualityGate.Condition(EvaluationStatus.OK, CoreMetrics.VULNERABILITIES_KEY, GREATER_THAN, "0", null, false, "0"),
- new QualityGate.Condition(EvaluationStatus.OK, CODE_SMELLS_KEY, GREATER_THAN, "0", null, false, "0"))),
+ EvaluatedQualityGate.newBuilder()
+ .setQualityGate(new QualityGate(
+ valueOf(ShortLivingBranchQualityGate.ID),
+ ShortLivingBranchQualityGate.NAME,
+ ImmutableSet.of(condition1, condition2, condition3)))
+ .setStatus(EvaluatedQualityGate.Status.OK)
+ .addCondition(condition1, EvaluationStatus.OK, "0")
+ .addCondition(condition2, EvaluationStatus.OK, "0")
+ .addCondition(condition3, EvaluationStatus.OK, "0")
+ .build(),
null,
properties));
}
underTest.onChange(issueChangeData(newIssueDto(branch)), new IssueChange(randomRuleType), userChangeContext);
ProjectAnalysis projectAnalysis = verifyWebhookCalledAndExtractPayloadFactoryArgument(branch, configuration, analysis);
- QualityGate qualityGate = projectAnalysis.getQualityGate().get();
- assertThat(qualityGate.getStatus()).isEqualTo(QualityGate.Status.OK);
- assertThat(qualityGate.getConditions())
- .extracting(QualityGate.Condition::getStatus, QualityGate.Condition::getValue)
+ EvaluatedQualityGate qualityGate = projectAnalysis.getQualityGate().get();
+ assertThat(qualityGate.getStatus()).isEqualTo(EvaluatedQualityGate.Status.OK);
+ assertThat(qualityGate.getEvaluatedConditions())
+ .extracting(EvaluatedCondition::getStatus, EvaluatedCondition::getValue)
.containsOnly(Tuple.tuple(EvaluationStatus.OK, Optional.of("0")));
}
underTest.onChange(issueChangeData(newIssueDto(branch)), new IssueChange(randomRuleType), userChangeContext);
ProjectAnalysis projectAnalysis = verifyWebhookCalledAndExtractPayloadFactoryArgument(branch, configuration, analysis);
- QualityGate qualityGate = projectAnalysis.getQualityGate().get();
- assertThat(qualityGate.getStatus()).isEqualTo(QualityGate.Status.ERROR);
- assertThat(qualityGate.getConditions())
- .extracting(QualityGate.Condition::getMetricKey, QualityGate.Condition::getStatus, QualityGate.Condition::getValue)
+ EvaluatedQualityGate qualityGate = projectAnalysis.getQualityGate().get();
+ assertThat(qualityGate.getStatus()).isEqualTo(EvaluatedQualityGate.Status.ERROR);
+ assertThat(qualityGate.getEvaluatedConditions())
+ .extracting(s -> s.getCondition().getMetricKey(), EvaluatedCondition::getStatus, EvaluatedCondition::getValue)
.containsOnly(expectedQGConditions);
}
underTest.onChange(issueChangeData(newIssueDto(branch)), new IssueChange(randomRuleType), userChangeContext);
ProjectAnalysis projectAnalysis = verifyWebhookCalledAndExtractPayloadFactoryArgument(branch, configuration, analysis);
- QualityGate qualityGate = projectAnalysis.getQualityGate().get();
- assertThat(qualityGate.getStatus()).isEqualTo(QualityGate.Status.ERROR);
- assertThat(qualityGate.getConditions())
- .extracting(QualityGate.Condition::getMetricKey, QualityGate.Condition::getStatus, QualityGate.Condition::getValue)
+ EvaluatedQualityGate qualityGate = projectAnalysis.getQualityGate().get();
+ assertThat(qualityGate.getStatus()).isEqualTo(EvaluatedQualityGate.Status.ERROR);
+ assertThat(qualityGate.getEvaluatedConditions())
+ .extracting(s -> s.getCondition().getMetricKey(), EvaluatedCondition::getStatus, EvaluatedCondition::getValue)
.containsOnly(
Tuple.tuple(BUGS_KEY, EvaluationStatus.ERROR, Optional.of(valueOf(unresolvedBugs))),
Tuple.tuple(VULNERABILITIES_KEY, EvaluationStatus.ERROR, Optional.of(valueOf(unresolvedVulnerabilities))),
Configuration configuration2 = mock(Configuration.class);
Configuration configuration3 = mock(Configuration.class);
mockLoadProjectConfigurations(
- branch1, configuration1,
- branch2, configuration2,
- branch3, configuration3);
+ branch1, configuration1,
+ branch2, configuration2,
+ branch3, configuration3);
mockWebhookEnabled(configuration1, configuration2, configuration3);
mockPayloadSupplierConsumedByWebhooks();
ComponentDao componentDaoSpy = spy(dbClient.componentDao());
when(spiedOnDbClient.componentDao()).thenReturn(componentDaoSpy);
underTest.onChange(
- issueChangeData(issueDtos, branch1, branch2, branch3),
- new IssueChange(randomRuleType),
- userChangeContext);
+ issueChangeData(issueDtos, branch1, branch2, branch3),
+ new IssueChange(randomRuleType),
+ userChangeContext);
verifyWebhookCalled(branch1, configuration1, analysis1);
verifyWebhookCalled(branch2, configuration2, analysis2);
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
+import org.sonar.server.qualitygate.EvaluatedQualityGate;
+import org.sonar.server.qualitygate.QualityGate;
import static java.util.Collections.emptyMap;
import static java.util.Collections.emptySet;
private final Project project = new Project("uuid", "key", "name");
private final Analysis analysis = new Analysis("analysis_uuid", 1_500L);
private final Branch branch = new Branch(true, "name", Branch.Type.SHORT);
- private final QualityGate qualityGate = new QualityGate("id", "name", QualityGate.Status.WARN, emptySet());
+ private final EvaluatedQualityGate qualityGate = EvaluatedQualityGate.newBuilder()
+ .setQualityGate(new QualityGate("id", "name", emptySet()))
+ .setStatus(EvaluatedQualityGate.Status.WARN)
+ .build();
private final Map<String, String> properties = ImmutableMap.of("a", "b");
private ProjectAnalysis underTest = new ProjectAnalysis(project, ceTask, analysis, branch, qualityGate, 1L, properties);
assertThat(underTest).isNotEqualTo(new ProjectAnalysis(project, ceTask, analysis, null, qualityGate, 1L, properties));
assertThat(underTest).isNotEqualTo(new ProjectAnalysis(project, ceTask, analysis, new Branch(false, "B", Branch.Type.SHORT), qualityGate, 1L, properties));
assertThat(underTest).isNotEqualTo(new ProjectAnalysis(project, ceTask, analysis, branch, null, 1L, properties));
- assertThat(underTest).isNotEqualTo(new ProjectAnalysis(project, ceTask, analysis, branch, new QualityGate("A", "B", QualityGate.Status.WARN, emptySet()), 1L, properties));
+ EvaluatedQualityGate otherQualityGate = EvaluatedQualityGate.newBuilder()
+ .setQualityGate(new QualityGate("A", "B", emptySet()))
+ .setStatus(EvaluatedQualityGate.Status.WARN)
+ .build();
+ assertThat(underTest).isNotEqualTo(new ProjectAnalysis(project, ceTask, analysis, branch, otherQualityGate, 1L, properties));
assertThat(underTest).isNotEqualTo(new ProjectAnalysis(project, ceTask, analysis, branch, qualityGate, null, properties));
assertThat(underTest).isNotEqualTo(new ProjectAnalysis(project, ceTask, analysis, branch, qualityGate, 2L, properties));
assertThat(underTest).isNotEqualTo(new ProjectAnalysis(project, ceTask, analysis, branch, qualityGate, 1L, emptyMap()));
assertThat(underTest.hashCode())
.isNotEqualTo(new ProjectAnalysis(project, ceTask, analysis, new Branch(false, "B", Branch.Type.SHORT), qualityGate, 1L, properties).hashCode());
assertThat(underTest.hashCode()).isNotEqualTo(new ProjectAnalysis(project, ceTask, analysis, branch, null, 1L, properties).hashCode());
+ EvaluatedQualityGate otherQualityGate = EvaluatedQualityGate.newBuilder()
+ .setQualityGate(new QualityGate("A", "B", emptySet()))
+ .setStatus(EvaluatedQualityGate.Status.WARN)
+ .build();
assertThat(underTest.hashCode())
- .isNotEqualTo(new ProjectAnalysis(project, ceTask, analysis, branch, new QualityGate("A", "B", QualityGate.Status.WARN, emptySet()), 1L, properties).hashCode());
- assertThat(underTest.hashCode()).isNotEqualTo(new ProjectAnalysis(project, ceTask, analysis, branch, qualityGate, null, properties).hashCode());
- assertThat(underTest.hashCode()).isNotEqualTo(new ProjectAnalysis(project, ceTask, analysis, branch, qualityGate, 2L, properties).hashCode());
- assertThat(underTest.hashCode()).isNotEqualTo(new ProjectAnalysis(project, ceTask, analysis, branch, qualityGate, 1L, emptyMap()).hashCode());
- assertThat(underTest.hashCode()).isNotEqualTo(new ProjectAnalysis(project, ceTask, analysis, branch, qualityGate, 1L, ImmutableMap.of("B", "C")).hashCode());
+ .isNotEqualTo(new ProjectAnalysis(project, ceTask, analysis, branch, otherQualityGate, 1L, properties).hashCode());
+ assertThat(underTest.hashCode()).isNotEqualTo(new ProjectAnalysis(project, ceTask, analysis, branch, this.qualityGate, null, properties).hashCode());
+ assertThat(underTest.hashCode()).isNotEqualTo(new ProjectAnalysis(project, ceTask, analysis, branch, this.qualityGate, 2L, properties).hashCode());
+ assertThat(underTest.hashCode()).isNotEqualTo(new ProjectAnalysis(project, ceTask, analysis, branch, this.qualityGate, 1L, emptyMap()).hashCode());
+ assertThat(underTest.hashCode()).isNotEqualTo(new ProjectAnalysis(project, ceTask, analysis, branch, this.qualityGate, 1L, ImmutableMap.of("B", "C")).hashCode());
}
@Test
public void verify_toString() {
assertThat(underTest.toString()).isEqualTo(
- "ProjectAnalysis{project=Project{uuid='uuid', key='key', name='name'}, ceTask=CeTask{id='id', status=SUCCESS}, branch=Branch{main=true, name='name', type=SHORT}, qualityGate=QualityGate{id='id', name='name', status=WARN, conditions=[]}, updatedAt=1, properties={a=b}, analysis=Analysis{uuid='analysis_uuid', date=1500}}");
+ "ProjectAnalysis{project=Project{uuid='uuid', key='key', name='name'}, ceTask=CeTask{id='id', status=SUCCESS}, branch=Branch{main=true, name='name', type=SHORT}, qualityGate=EvaluatedQualityGate{qualityGate=QualityGate{id=id, name='name', conditions=[]}, status=WARN, evaluatedConditions=[]}, updatedAt=1, properties={a=b}, analysis=Analysis{uuid='analysis_uuid', date=1500}}");
}
}
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2017 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.webhook;
-
-import java.util.Random;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-
-import static java.util.Collections.singleton;
-import static org.assertj.core.api.Assertions.assertThat;
-
-public class QualityGateTest {
- @Rule
- public ExpectedException expectedException = ExpectedException.none();
-
- private final Random random = new Random();
- private boolean onLeak = random.nextBoolean();
- private QualityGate.EvaluationStatus randomEvaluationStatus = QualityGate.EvaluationStatus.values()[random.nextInt(QualityGate.EvaluationStatus.values().length)];
- private QualityGate.Condition condition = new QualityGate.Condition(
- randomEvaluationStatus, "k", QualityGate.Operator.GREATER_THAN, "l", "m", onLeak, "val");
- private QualityGate.Status randomStatus = QualityGate.Status.values()[random.nextInt(QualityGate.Status.values().length)];
- private QualityGate underTest = new QualityGate("i", "j", randomStatus, singleton(condition));
-
- @Test
- public void constructor_throws_NPE_if_id_is_null() {
- expectedException.expect(NullPointerException.class);
- expectedException.expectMessage("id can't be null");
-
- new QualityGate(null, "j", QualityGate.Status.WARN, singleton(condition));
- }
-
- @Test
- public void constructor_throws_NPE_if_name_is_null() {
- expectedException.expect(NullPointerException.class);
- expectedException.expectMessage("name can't be null");
-
- new QualityGate("i", null, QualityGate.Status.WARN, singleton(condition));
- }
-
- @Test
- public void constructor_throws_NPE_if_status_is_null() {
- expectedException.expect(NullPointerException.class);
- expectedException.expectMessage("status can't be null");
-
- new QualityGate("i", "j", null, singleton(condition));
- }
-
- @Test
- public void constructor_throws_NPE_if_conditions_is_null() {
- expectedException.expect(NullPointerException.class);
- expectedException.expectMessage("conditions can't be null");
-
- new QualityGate("i", "j", QualityGate.Status.WARN, null);
- }
-
- @Test
- public void condition_constructor_throws_NPE_if_evaluation_status_is_null() {
- expectedException.expect(NullPointerException.class);
- expectedException.expectMessage("status can't be null");
-
- new QualityGate.Condition(null, "k", QualityGate.Operator.GREATER_THAN, "l", "m", onLeak, "val");
- }
-
- @Test
- public void condition_constructor_throws_NPE_if_metricKey_is_null() {
- expectedException.expect(NullPointerException.class);
- expectedException.expectMessage("metricKey can't be null");
-
- new QualityGate.Condition(randomEvaluationStatus, null, QualityGate.Operator.GREATER_THAN, "l", "m", onLeak, "val");
- }
-
- @Test
- public void condition_constructor_throws_NPE_if_operator_status_is_null() {
- expectedException.expect(NullPointerException.class);
- expectedException.expectMessage("operator can't be null");
-
- new QualityGate.Condition(randomEvaluationStatus, "k", null, "l", "m", onLeak, "val");
- }
-
- @Test
- public void verify_getters() {
- assertThat(underTest.getId()).isEqualTo("i");
- assertThat(underTest.getName()).isEqualTo("j");
- assertThat(underTest.getStatus()).isEqualTo(randomStatus);
- assertThat(underTest.getConditions()).isEqualTo(singleton(condition));
- }
-
- @Test
- public void verify_condition_getters() {
- assertThat(condition.getStatus()).isEqualTo(randomEvaluationStatus);
- assertThat(condition.getMetricKey()).isEqualTo("k");
- assertThat(condition.getErrorThreshold()).contains("l");
- assertThat(condition.getWarningThreshold()).contains("m");
- assertThat(condition.isOnLeakPeriod()).isEqualTo(onLeak);
- assertThat(condition.getValue()).contains("val");
-
- QualityGate.Condition conditionWithNulls = new QualityGate.Condition(
- randomEvaluationStatus, "k", QualityGate.Operator.GREATER_THAN, null, null, onLeak, null);
-
- assertThat(conditionWithNulls.getErrorThreshold()).isEmpty();
- assertThat(conditionWithNulls.getWarningThreshold()).isEmpty();
- assertThat(conditionWithNulls.getValue()).isEmpty();
- }
-}
import org.junit.Test;
import org.sonar.api.platform.Server;
import org.sonar.api.utils.System2;
+import org.sonar.server.qualitygate.Condition;
+import org.sonar.server.qualitygate.EvaluatedCondition;
+import org.sonar.server.qualitygate.EvaluatedQualityGate;
+import org.sonar.server.qualitygate.QualityGate;
import static java.util.Collections.emptyMap;
import static java.util.Collections.emptySet;
@Test
public void create_payload_for_successful_analysis() {
CeTask task = new CeTask("#1", CeTask.Status.SUCCESS);
- QualityGate gate = new QualityGate("G1", "Gate One", QualityGate.Status.WARN, singleton(new QualityGate.Condition(
- QualityGate.EvaluationStatus.WARN,
- "coverage", QualityGate.Operator.GREATER_THAN, "70.0", "75.0", true, "74.0")));
+ Condition condition = new Condition("coverage", Condition.Operator.GREATER_THAN, "70.0", "75.0", true);
+ EvaluatedQualityGate gate = EvaluatedQualityGate.newBuilder()
+ .setQualityGate(new QualityGate("G1", "Gate One", singleton(condition)))
+ .setStatus(EvaluatedQualityGate.Status.WARN)
+ .addCondition(condition, EvaluatedCondition.EvaluationStatus.WARN, "74.0")
+ .build();
ProjectAnalysis analysis = newAnalysis(task, gate, null, 1_500_000_000_000L, emptyMap());
WebhookPayload payload = underTest.create(analysis);
@Test
public void create_payload_with_gate_conditions_without_value() {
CeTask task = new CeTask("#1", CeTask.Status.SUCCESS);
- QualityGate gate = new QualityGate("G1", "Gate One", QualityGate.Status.WARN, singleton(
- new QualityGate.Condition(QualityGate.EvaluationStatus.NO_VALUE, "coverage", QualityGate.Operator.GREATER_THAN, "70.0", "75.0", false, null)));
+
+ Condition condition = new Condition("coverage", Condition.Operator.GREATER_THAN, "70.0", "75.0", false);
+ EvaluatedQualityGate gate = EvaluatedQualityGate.newBuilder()
+ .setQualityGate(new QualityGate("G1", "Gate One", singleton(condition)))
+ .setStatus(EvaluatedQualityGate.Status.WARN)
+ .addCondition(condition, EvaluatedCondition.EvaluationStatus.NO_VALUE, null)
+ .build();
ProjectAnalysis analysis = newAnalysis(task, gate, null, 1_500_000_000_000L, emptyMap());
WebhookPayload payload = underTest.create(analysis);
@Test
public void create_payload_with_analysis_properties() {
CeTask task = new CeTask("#1", CeTask.Status.SUCCESS);
- QualityGate gate = new QualityGate("G1", "Gate One", QualityGate.Status.WARN, emptySet());
+ EvaluatedQualityGate gate = EvaluatedQualityGate.newBuilder()
+ .setQualityGate(new QualityGate("G1", "Gate One", emptySet()))
+ .setStatus(EvaluatedQualityGate.Status.WARN)
+ .build();
Map<String, String> scannerProperties = ImmutableMap.of(
"sonar.analysis.revision", "ab45d24",
"sonar.analysis.buildNumber", "B123",
"}");
}
- private static ProjectAnalysis newAnalysis(@Nullable CeTask task, @Nullable QualityGate gate,
+ private static ProjectAnalysis newAnalysis(@Nullable CeTask task, @Nullable EvaluatedQualityGate gate,
@Nullable Branch branch, @Nullable Long analysisDate, Map<String, String> scannerProperties) {
return new ProjectAnalysis(new Project("P1_UUID", PROJECT_KEY, "Project One"), task, analysisDate == null ? null : new Analysis("A_UUID1", analysisDate), branch,
gate, analysisDate, scannerProperties);