aboutsummaryrefslogtreecommitdiffstats
path: root/server
diff options
context:
space:
mode:
authorJeremy Davis <jeremy.davis@sonarsource.com>2022-12-29 17:10:26 +0100
committersonartech <sonartech@sonarsource.com>2023-01-02 20:03:09 +0000
commitb9ccb2eb4f0ef0c13d36a4aaa544104780018a85 (patch)
tree6bfd9944af697d5cbd5cdc1df07520ce57acecbd /server
parent4da2fd9191d43a75c7a6c4cc848cd048e6700844 (diff)
downloadsonarqube-b9ccb2eb4f0ef0c13d36a4aaa544104780018a85.tar.gz
sonarqube-b9ccb2eb4f0ef0c13d36a4aaa544104780018a85.zip
SONAR-17816 Add isCaycCompliant flag to /api/qualitygates/project_status
Diffstat (limited to 'server')
-rw-r--r--server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualitygate/ws/QualityGateDetailsFormatter.java36
-rw-r--r--server/sonar-webserver-webapi/src/test/java/org/sonar/server/qualitygate/ws/QualityGateDetailsFormatterTest.java26
-rw-r--r--server/sonar-webserver-webapi/src/test/resources/org/sonar/server/qualitygate/ws/QualityGateDetailsFormatterTest/cayc_compliant_qg.json41
-rw-r--r--server/sonar-webserver-webapi/src/test/resources/org/sonar/server/qualitygate/ws/QualityGateDetailsFormatterTest/cayc_missing_metric.json32
4 files changed, 134 insertions, 1 deletions
diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualitygate/ws/QualityGateDetailsFormatter.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualitygate/ws/QualityGateDetailsFormatter.java
index d95dd78c98c..fcfbb7391a4 100644
--- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualitygate/ws/QualityGateDetailsFormatter.java
+++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualitygate/ws/QualityGateDetailsFormatter.java
@@ -23,19 +23,34 @@ import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
+import java.util.Map;
import java.util.Optional;
import java.util.function.Predicate;
+import java.util.stream.Stream;
import java.util.stream.StreamSupport;
import javax.annotation.Nullable;
+import org.sonar.api.measures.Metric;
import org.sonar.db.component.SnapshotDto;
import org.sonarqube.ws.Qualitygates.ProjectStatusResponse;
import org.sonarqube.ws.Qualitygates.ProjectStatusResponse.NewCodePeriod;
import org.sonarqube.ws.Qualitygates.ProjectStatusResponse.Period;
import static com.google.common.base.Strings.isNullOrEmpty;
+import static java.util.stream.Collectors.toUnmodifiableMap;
+import static org.sonar.api.measures.CoreMetrics.NEW_MAINTAINABILITY_RATING;
+import static org.sonar.api.measures.CoreMetrics.NEW_RELIABILITY_RATING;
+import static org.sonar.api.measures.CoreMetrics.NEW_SECURITY_HOTSPOTS_REVIEWED;
+import static org.sonar.api.measures.CoreMetrics.NEW_SECURITY_RATING;
import static org.sonar.api.utils.DateUtils.formatDateTime;
public class QualityGateDetailsFormatter {
+ public static final String METRIC_KEY = "metric";
+ private static final Map<String, Double> CAYC_REQUIREMENTS = Stream.of(
+ NEW_MAINTAINABILITY_RATING,
+ NEW_RELIABILITY_RATING,
+ NEW_SECURITY_HOTSPOTS_REVIEWED,
+ NEW_SECURITY_RATING
+ ).collect(toUnmodifiableMap(Metric::getKey, Metric::getBestValue));
private final Optional<String> optionalMeasureData;
private final Optional<SnapshotDto> optionalSnapshot;
private final ProjectStatusResponse.ProjectStatus.Builder projectStatusBuilder;
@@ -58,11 +73,30 @@ public class QualityGateDetailsFormatter {
formatIgnoredConditions(json);
formatConditions(json.getAsJsonArray("conditions"));
+ formatCleanAsYouCodeCompliant(json.getAsJsonArray("conditions"));
formatPeriods();
return projectStatusBuilder.build();
}
+ private void formatCleanAsYouCodeCompliant(@Nullable JsonArray jsonConditions) {
+ if (jsonConditions == null) {
+ return;
+ }
+
+ long matchCount = jsonConditions.asList().stream()
+ .map(JsonElement::getAsJsonObject)
+ .filter(jsonObject -> CAYC_REQUIREMENTS.containsKey(jsonObject.get(METRIC_KEY).getAsString()))
+ .filter(jsonObject -> {
+ String metricKey = jsonObject.get(METRIC_KEY).getAsString();
+ Double value = jsonObject.get("error").getAsDouble();
+ return CAYC_REQUIREMENTS.get(metricKey).compareTo(value) == 0;
+ })
+ .count();
+
+ projectStatusBuilder.setIsCaycCompliant(matchCount == CAYC_REQUIREMENTS.size());
+ }
+
private void formatIgnoredConditions(JsonObject json) {
JsonElement ignoredConditions = json.get("ignoredConditions");
if (ignoredConditions != null) {
@@ -167,7 +201,7 @@ public class QualityGateDetailsFormatter {
}
private static void formatConditionMetric(ProjectStatusResponse.Condition.Builder conditionBuilder, JsonObject jsonCondition) {
- JsonElement metric = jsonCondition.get("metric");
+ JsonElement metric = jsonCondition.get(METRIC_KEY);
if (metric != null && !isNullOrEmpty(metric.getAsString())) {
conditionBuilder.setMetricKey(metric.getAsString());
}
diff --git a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/qualitygate/ws/QualityGateDetailsFormatterTest.java b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/qualitygate/ws/QualityGateDetailsFormatterTest.java
index 7df876bca08..febd8db74bd 100644
--- a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/qualitygate/ws/QualityGateDetailsFormatterTest.java
+++ b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/qualitygate/ws/QualityGateDetailsFormatterTest.java
@@ -21,9 +21,11 @@ package org.sonar.server.qualitygate.ws;
import java.io.IOException;
import java.util.List;
+import java.util.Map;
import java.util.Optional;
import javax.annotation.Nullable;
import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang.text.StrSubstitutor;
import org.junit.Test;
import org.sonar.db.component.SnapshotDto;
import org.sonarqube.ws.Qualitygates.ProjectStatusResponse;
@@ -143,6 +145,30 @@ public class QualityGateDetailsFormatterTest {
.hasMessageContaining("Unknown quality gate comparator 'UNKNOWN'");
}
+ @Test
+ public void verify_cayc_quality_gate_checked() throws IOException {
+ String measureDataRaw = IOUtils.toString(getClass().getResource("QualityGateDetailsFormatterTest/cayc_compliant_qg.json"));
+
+ String measureDataCompliant = StrSubstitutor.replace(measureDataRaw, Map.of("nmr_error", "1.0"));
+ underTest = newQualityGateDetailsFormatter(measureDataCompliant, null);
+ ProjectStatus result = underTest.format();
+ assertThat(result.getIsCaycCompliant()).isTrue();
+
+ String measureDataNonCompliant = StrSubstitutor.replace(measureDataRaw, Map.of("nmr_error", "2.0"));
+ underTest = newQualityGateDetailsFormatter(measureDataNonCompliant, null);
+ result = underTest.format();
+ assertThat(result.getIsCaycCompliant()).isFalse();
+ }
+
+ @Test
+ public void verify_cayc_quality_gate_with_missing_metric() throws IOException {
+ String measureData = IOUtils.toString(getClass().getResource("QualityGateDetailsFormatterTest/cayc_missing_metric.json"));
+
+ underTest = newQualityGateDetailsFormatter(measureData, null);
+ ProjectStatus result = underTest.format();
+ assertThat(result.getIsCaycCompliant()).isFalse();
+ }
+
private static QualityGateDetailsFormatter newQualityGateDetailsFormatter(@Nullable String measureData, @Nullable SnapshotDto snapshotDto) {
return new QualityGateDetailsFormatter(Optional.ofNullable(measureData), Optional.ofNullable(snapshotDto));
}
diff --git a/server/sonar-webserver-webapi/src/test/resources/org/sonar/server/qualitygate/ws/QualityGateDetailsFormatterTest/cayc_compliant_qg.json b/server/sonar-webserver-webapi/src/test/resources/org/sonar/server/qualitygate/ws/QualityGateDetailsFormatterTest/cayc_compliant_qg.json
new file mode 100644
index 00000000000..32d45361fa7
--- /dev/null
+++ b/server/sonar-webserver-webapi/src/test/resources/org/sonar/server/qualitygate/ws/QualityGateDetailsFormatterTest/cayc_compliant_qg.json
@@ -0,0 +1,41 @@
+{
+ "level": "ERROR",
+ "conditions": [
+ {
+ "metric": "new_maintainability_rating",
+ "op": "LT",
+ "period": 1,
+ "warning": "",
+ "error": "${nmr_error}",
+ "actual": "2",
+ "level": "ERROR"
+ },
+ {
+ "metric": "new_reliability_rating",
+ "op": "LT",
+ "period": 1,
+ "warning": "",
+ "error": "1.0",
+ "actual": "1",
+ "level": "OK"
+ },
+ {
+ "metric": "new_security_hotspots_reviewed",
+ "op": "GT",
+ "period": 1,
+ "warning": "",
+ "error": "100.0",
+ "actual": "100.0",
+ "level": "OK"
+ },
+ {
+ "metric": "new_security_rating",
+ "op": "LT",
+ "period": 1,
+ "warning": "",
+ "error": "1.0",
+ "actual": "2",
+ "level": "ERROR"
+ }
+ ]
+}
diff --git a/server/sonar-webserver-webapi/src/test/resources/org/sonar/server/qualitygate/ws/QualityGateDetailsFormatterTest/cayc_missing_metric.json b/server/sonar-webserver-webapi/src/test/resources/org/sonar/server/qualitygate/ws/QualityGateDetailsFormatterTest/cayc_missing_metric.json
new file mode 100644
index 00000000000..45ace94cbc0
--- /dev/null
+++ b/server/sonar-webserver-webapi/src/test/resources/org/sonar/server/qualitygate/ws/QualityGateDetailsFormatterTest/cayc_missing_metric.json
@@ -0,0 +1,32 @@
+{
+ "level": "ERROR",
+ "conditions": [
+ {
+ "metric": "new_reliability_rating",
+ "op": "LT",
+ "period": 1,
+ "warning": "",
+ "error": "1.0",
+ "actual": "1",
+ "level": "OK"
+ },
+ {
+ "metric": "new_security_hotspots_reviewed",
+ "op": "GT",
+ "period": 1,
+ "warning": "",
+ "error": "100.0",
+ "actual": "100.0",
+ "level": "OK"
+ },
+ {
+ "metric": "new_security_rating",
+ "op": "LT",
+ "period": 1,
+ "warning": "",
+ "error": "1.0",
+ "actual": "2",
+ "level": "ERROR"
+ }
+ ]
+}