diff options
author | Nolwenn Cadic <98824442+Nolwenn-cadic-sonarsource@users.noreply.github.com> | 2023-10-26 14:30:36 +0200 |
---|---|---|
committer | sonartech <sonartech@sonarsource.com> | 2023-10-26 20:02:58 +0000 |
commit | 2eaf4da9b14cc5bfa73719b660c5db706672d182 (patch) | |
tree | 0070c5710f6f0c90f5aa333bc373c1a5d29c81a3 /server/sonar-server-common | |
parent | c49df4a6f7ee55283c891139d79418a482538769 (diff) | |
download | sonarqube-2eaf4da9b14cc5bfa73719b660c5db706672d182.tar.gz sonarqube-2eaf4da9b14cc5bfa73719b660c5db706672d182.zip |
SONAR-20787 Add telemetry about quality gate conditions and sonar way (#9743)
Diffstat (limited to 'server/sonar-server-common')
6 files changed, 112 insertions, 19 deletions
diff --git a/server/sonar-server-common/src/main/java/org/sonar/server/qualitygate/QualityGate.java b/server/sonar-server-common/src/main/java/org/sonar/server/qualitygate/QualityGate.java index c03a0d8f6e6..d4082e0288c 100644 --- a/server/sonar-server-common/src/main/java/org/sonar/server/qualitygate/QualityGate.java +++ b/server/sonar-server-common/src/main/java/org/sonar/server/qualitygate/QualityGate.java @@ -28,6 +28,8 @@ import static java.util.Objects.requireNonNull; @Immutable public class QualityGate { + + public static final String BUILTIN_QUALITY_GATE_NAME = "Sonar way"; private final String id; private final String name; private final Set<Condition> conditions; diff --git a/server/sonar-server-common/src/main/java/org/sonar/server/qualitygate/QualityGateFinder.java b/server/sonar-server-common/src/main/java/org/sonar/server/qualitygate/QualityGateFinder.java index 32dad6ce43c..1bc482d9145 100644 --- a/server/sonar-server-common/src/main/java/org/sonar/server/qualitygate/QualityGateFinder.java +++ b/server/sonar-server-common/src/main/java/org/sonar/server/qualitygate/QualityGateFinder.java @@ -25,6 +25,9 @@ import org.sonar.db.DbSession; import org.sonar.db.project.ProjectDto; import org.sonar.db.qualitygate.QualityGateDto; +import static java.lang.String.format; +import static org.sonar.server.qualitygate.QualityGate.BUILTIN_QUALITY_GATE_NAME; + public class QualityGateFinder { private final DbClient dbClient; @@ -55,6 +58,11 @@ public class QualityGateFinder { return Optional.ofNullable(dbClient.qualityGateDao().selectDefault(dbSession)).orElseThrow(() -> new IllegalStateException("Default quality gate is missing")); } + public QualityGateDto getSonarWay(DbSession dbSession) { + return Optional.ofNullable(dbClient.qualityGateDao().selectByName(dbSession, BUILTIN_QUALITY_GATE_NAME)).orElseThrow(() -> + new IllegalStateException(format("%s quality gate is missing", BUILTIN_QUALITY_GATE_NAME))); + } + public static class QualityGateData { private final String uuid; private final String name; diff --git a/server/sonar-server-common/src/main/java/org/sonar/server/telemetry/TelemetryData.java b/server/sonar-server-common/src/main/java/org/sonar/server/telemetry/TelemetryData.java index 6ec247b38b7..18e545d6ae5 100644 --- a/server/sonar-server-common/src/main/java/org/sonar/server/telemetry/TelemetryData.java +++ b/server/sonar-server-common/src/main/java/org/sonar/server/telemetry/TelemetryData.java @@ -31,6 +31,7 @@ import org.sonar.core.platform.EditionProvider; import org.sonar.core.platform.EditionProvider.Edition; import org.sonar.db.project.CreationMethod; import org.sonar.db.user.UserTelemetryDto; +import org.sonar.server.qualitygate.Condition; import static java.util.Objects.requireNonNullElse; import static org.sonar.db.newcodeperiod.NewCodePeriodType.PREVIOUS_VERSION; @@ -43,6 +44,7 @@ public class TelemetryData { private final Database database; private final EditionProvider.Edition edition; private final String defaultQualityGate; + private final String sonarWayQualityGate; private final Long installationDate; private final String installationVersion; private final boolean inContainer; @@ -68,6 +70,7 @@ public class TelemetryData { database = builder.database; edition = builder.edition; defaultQualityGate = builder.defaultQualityGate; + sonarWayQualityGate = builder.sonarWayQualityGate; installationDate = builder.installationDate; installationVersion = builder.installationVersion; inContainer = builder.inContainer; @@ -114,6 +117,10 @@ public class TelemetryData { return defaultQualityGate; } + public String getSonarWayQualityGate() { + return sonarWayQualityGate; + } + public Long getInstallationDate() { return installationDate; } @@ -190,6 +197,8 @@ public class TelemetryData { private Database database; private Edition edition; private String defaultQualityGate; + + private String sonarWayQualityGate; private Long installationDate; private String installationVersion; private boolean inContainer = false; @@ -246,6 +255,11 @@ public class TelemetryData { return this; } + Builder setSonarWayQualityGate(String sonarWayQualityGate) { + this.sonarWayQualityGate = sonarWayQualityGate; + return this; + } + Builder setInstallationDate(@Nullable Long installationDate) { this.installationDate = installationDate; return this; @@ -360,7 +374,7 @@ public class TelemetryData { record Project(String projectUuid, Long lastAnalysis, String language, String qualityProfile, Long loc) { } - record QualityGate(String uuid, String caycStatus) { + record QualityGate(String uuid, String caycStatus, List<Condition> conditions) { } public record QualityProfile(String uuid, @Nullable String parentUuid, String language, boolean isDefault, diff --git a/server/sonar-server-common/src/main/java/org/sonar/server/telemetry/TelemetryDataJsonWriter.java b/server/sonar-server-common/src/main/java/org/sonar/server/telemetry/TelemetryDataJsonWriter.java index 94315180324..b3148e9ddb3 100644 --- a/server/sonar-server-common/src/main/java/org/sonar/server/telemetry/TelemetryDataJsonWriter.java +++ b/server/sonar-server-common/src/main/java/org/sonar/server/telemetry/TelemetryDataJsonWriter.java @@ -63,6 +63,7 @@ public class TelemetryDataJsonWriter { json.prop(NCD_ID, telemetryData.getNcdId()); telemetryData.getEdition().ifPresent(e -> json.prop("edition", e.name().toLowerCase(Locale.ENGLISH))); json.prop("defaultQualityGate", telemetryData.getDefaultQualityGate()); + json.prop("sonarway_quality_gate_uuid", telemetryData.getSonarWayQualityGate()); json.name("database"); json.beginObject(); json.prop("name", telemetryData.getDatabase().name()); @@ -222,6 +223,16 @@ public class TelemetryDataJsonWriter { json.beginObject(); json.prop("uuid", qualityGate.uuid()); json.prop("caycStatus", qualityGate.caycStatus()); + json.name("conditions"); + json.beginArray(); + qualityGate.conditions().forEach(condition -> { + json.beginObject(); + json.prop("metric", condition.getMetricKey()); + json.prop("comparison_operator", condition.getOperator().getDbValue()); + json.prop("error_value", condition.getErrorThreshold()); + json.endObject(); + }); + json.endArray(); json.endObject(); }); json.endArray(); diff --git a/server/sonar-server-common/src/test/java/org/sonar/server/qualitygate/ConditionTest.java b/server/sonar-server-common/src/test/java/org/sonar/server/qualitygate/ConditionTest.java index f3f24f7a822..947a8e29537 100644 --- a/server/sonar-server-common/src/test/java/org/sonar/server/qualitygate/ConditionTest.java +++ b/server/sonar-server-common/src/test/java/org/sonar/server/qualitygate/ConditionTest.java @@ -40,7 +40,7 @@ public class ConditionTest { } @Test - public void constructor_throws_NPE_if_operator_is_null() { + public void constructor_throws_NPE_if_operator_operator_is_null() { assertThatThrownBy(() -> new Condition(METRIC_KEY, null, ERROR_THRESHOLD)) .isInstanceOf(NullPointerException.class) .hasMessage("operator can't be null"); diff --git a/server/sonar-server-common/src/test/java/org/sonar/server/telemetry/TelemetryDataJsonWriterTest.java b/server/sonar-server-common/src/test/java/org/sonar/server/telemetry/TelemetryDataJsonWriterTest.java index bc98e99ad77..b523f5b0d4a 100644 --- a/server/sonar-server-common/src/test/java/org/sonar/server/telemetry/TelemetryDataJsonWriterTest.java +++ b/server/sonar-server-common/src/test/java/org/sonar/server/telemetry/TelemetryDataJsonWriterTest.java @@ -42,6 +42,7 @@ import org.sonar.core.platform.EditionProvider; import org.sonar.core.telemetry.TelemetryExtension; import org.sonar.db.project.CreationMethod; import org.sonar.db.user.UserTelemetryDto; +import org.sonar.server.qualitygate.Condition; import static java.util.stream.Collectors.joining; import static org.apache.commons.lang.RandomStringUtils.randomAlphabetic; @@ -50,6 +51,7 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import static org.sonar.db.newcodeperiod.NewCodePeriodType.NUMBER_OF_DAYS; import static org.sonar.db.newcodeperiod.NewCodePeriodType.PREVIOUS_VERSION; +import static org.sonar.server.qualitygate.Condition.Operator.fromDbValue; import static org.sonar.test.JsonAssert.assertJson; @RunWith(DataProviderRunner.class) @@ -121,6 +123,20 @@ public class TelemetryDataJsonWriterTest { } @Test + public void writes_sonarWay_qg() { + TelemetryData data = telemetryBuilder() + .setSonarWayQualityGate("sonarWayUUID") + .build(); + + String json = writeTelemetryData(data); + assertJson(json).isSimilarTo(""" + { + "sonarway_quality_gate_uuid": "%s" + } + """.formatted(data.getSonarWayQualityGate())); + } + + @Test public void writes_database() { String name = randomAlphabetic(12); String version = randomAlphabetic(10); @@ -517,20 +533,56 @@ public class TelemetryDataJsonWriterTest { assertJson(json).isSimilarTo(""" { "quality-gates": [ - { - "uuid": "uuid-0", - "caycStatus": "non-compliant" - }, - { - "uuid": "uuid-1", - "caycStatus": "compliant" - }, - { - "uuid": "uuid-2", - "caycStatus": "over-compliant" - } - ] - } + { + "uuid": "uuid-0", + "caycStatus": "non-compliant", + "conditions": [ + { + "metric": "new_coverage", + "comparison_operator": "LT", + "error_value": "80" + }, + { + "metric": "new_duplicated_lines_density", + "comparison_operator": "GT", + "error_value": "3" + } + ] + }, + { + "uuid": "uuid-1", + "caycStatus": "compliant", + "conditions": [ + { + "metric": "new_coverage", + "comparison_operator": "LT", + "error_value": "80" + }, + { + "metric": "new_duplicated_lines_density", + "comparison_operator": "GT", + "error_value": "3" + } + ] + }, + { + "uuid": "uuid-2", + "caycStatus": "over-compliant", + "conditions": [ + { + "metric": "new_coverage", + "comparison_operator": "LT", + "error_value": "80" + }, + { + "metric": "new_duplicated_lines_density", + "comparison_operator": "GT", + "error_value": "3" + } + ] + } + ] + } """); } @@ -693,9 +745,15 @@ public class TelemetryDataJsonWriterTest { } private List<TelemetryData.QualityGate> attachQualityGates() { - return List.of(new TelemetryData.QualityGate("uuid-0", "non-compliant"), - new TelemetryData.QualityGate("uuid-1", "compliant"), - new TelemetryData.QualityGate("uuid-2", "over-compliant")); + List<Condition> qualityGateConditions = attachQualityGateConditions(); + return List.of(new TelemetryData.QualityGate("uuid-0", "non-compliant", qualityGateConditions), + new TelemetryData.QualityGate("uuid-1", "compliant", qualityGateConditions), + new TelemetryData.QualityGate("uuid-2", "over-compliant", qualityGateConditions)); + } + + private List<Condition> attachQualityGateConditions() { + return List.of(new Condition("new_coverage", fromDbValue("LT"), "80"), + new Condition("new_duplicated_lines_density", fromDbValue("GT"), "3")); } private List<TelemetryData.Branch> attachBranches() { |