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;
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) {
}
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());
}
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;
.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));
}