*/
package org.sonar.server.qualitygate;
+import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
-import java.util.stream.Stream;
import org.sonar.api.measures.Metric;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import static org.sonar.core.util.stream.MoreCollectors.uniqueIndex;
public class QualityGateCaycChecker {
- private static final Map<String, Double> CAYC_REQUIREMENTS = Stream.of(
+
+ public static final List<Metric<Integer>> CAYC_METRICS = List.of(
NEW_MAINTAINABILITY_RATING,
NEW_RELIABILITY_RATING,
NEW_SECURITY_HOTSPOTS_REVIEWED,
NEW_SECURITY_RATING
- ).collect(toUnmodifiableMap(Metric::getKey, Metric::getBestValue));
+ );
+
+ private static final Map<String, Double> CAYC_REQUIREMENTS = CAYC_METRICS.stream()
+ .collect(toUnmodifiableMap(Metric::getKey, Metric::getBestValue));
private final DbClient dbClient;
*/
package org.sonar.server.qualitygate.ws;
+import java.util.Map;
import org.sonar.api.server.ws.Change;
import org.sonar.api.server.ws.Request;
import org.sonar.api.server.ws.Response;
import org.sonar.db.DbSession;
import org.sonar.db.permission.GlobalPermission;
import org.sonar.db.qualitygate.QualityGateDto;
+import org.sonar.server.qualitygate.Condition;
+import org.sonar.server.qualitygate.QualityGateConditionsUpdater;
import org.sonar.server.qualitygate.QualityGateUpdater;
import org.sonar.server.user.UserSession;
import org.sonarqube.ws.Qualitygates.CreateResponse;
+import static org.sonar.api.measures.Metric.DIRECTION_BETTER;
+import static org.sonar.api.measures.Metric.DIRECTION_WORST;
+import static org.sonar.server.qualitygate.Condition.Operator.GREATER_THAN;
+import static org.sonar.server.qualitygate.Condition.Operator.LESS_THAN;
+import static org.sonar.server.qualitygate.QualityGateCaycChecker.CAYC_METRICS;
import static org.sonar.server.qualitygate.ws.QualityGatesWsParameters.ACTION_CREATE;
import static org.sonar.server.qualitygate.ws.QualityGatesWsParameters.PARAM_NAME;
import static org.sonar.server.ws.WsUtils.writeProtobuf;
public class CreateAction implements QualityGatesWsAction {
+ private static final Map<Integer, Condition.Operator> OPERATORS_BY_DIRECTION = Map.of(
+ DIRECTION_BETTER, LESS_THAN,
+ DIRECTION_WORST, GREATER_THAN);
+
public static final int NAME_MAXIMUM_LENGTH = 100;
private final DbClient dbClient;
private final UserSession userSession;
private final QualityGateUpdater qualityGateUpdater;
+ private final QualityGateConditionsUpdater qualityGateConditionsUpdater;
- public CreateAction(DbClient dbClient, UserSession userSession, QualityGateUpdater qualityGateUpdater) {
+ public CreateAction(DbClient dbClient, UserSession userSession, QualityGateUpdater qualityGateUpdater, QualityGateConditionsUpdater qualityGateConditionsUpdater) {
this.dbClient = dbClient;
this.userSession = userSession;
this.qualityGateUpdater = qualityGateUpdater;
+ this.qualityGateConditionsUpdater = qualityGateConditionsUpdater;
}
@Override
String name = request.mandatoryParam(PARAM_NAME);
QualityGateDto newQualityGate = qualityGateUpdater.create(dbSession, name);
+ addCaycConditions(dbSession, newQualityGate);
+
CreateResponse.Builder createResponse = CreateResponse.newBuilder()
.setId(newQualityGate.getUuid())
.setName(newQualityGate.getName());
writeProtobuf(createResponse.build(), request, response);
}
}
+
+ private void addCaycConditions(DbSession dbSession, QualityGateDto newQualityGate) {
+ CAYC_METRICS.forEach(m ->
+ qualityGateConditionsUpdater.createCondition(dbSession, newQualityGate, m.getKey(), OPERATORS_BY_DIRECTION.get(m.getDirection()).getDbValue(),
+ String.valueOf(m.getBestValue().intValue()))
+ );
+ }
}
ProjectAndSnapshot projectAndSnapshot = getProjectAndSnapshot(dbSession, analysisId, projectUuid, projectKey, branchKey, pullRequestId);
checkPermission(projectAndSnapshot.project);
Optional<String> measureData = loadQualityGateDetails(dbSession, projectAndSnapshot, analysisId != null);
- var isCaycCompliant = qualityGateCaycChecker.checkCaycCompliantFromProject(dbSession, projectAndSnapshot.project.getUuid());
+ boolean isCaycCompliant = qualityGateCaycChecker.checkCaycCompliantFromProject(dbSession, projectAndSnapshot.project.getUuid());
return ProjectStatusResponse.newBuilder()
.setProjectStatus(new QualityGateDetailsFormatter(measureData.orElse(null), projectAndSnapshot.snapshotDto.orElse(null), isCaycCompliant).format())
import com.tngtech.java.junit.dataprovider.DataProvider;
import com.tngtech.java.junit.dataprovider.DataProviderRunner;
import com.tngtech.java.junit.dataprovider.UseDataProvider;
+import java.util.Collection;
import java.util.Optional;
import javax.annotation.Nullable;
+import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.sonar.api.measures.Metric;
import org.sonar.api.server.ws.WebService;
import org.sonar.api.utils.System2;
import org.sonar.core.util.UuidFactoryFast;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.DbTester;
+import org.sonar.db.qualitygate.QualityGateConditionDto;
import org.sonar.db.qualitygate.QualityGateDto;
import org.sonar.server.exceptions.ForbiddenException;
+import org.sonar.server.qualitygate.QualityGateConditionsUpdater;
import org.sonar.server.qualitygate.QualityGateUpdater;
import org.sonar.server.tester.UserSessionRule;
import org.sonar.server.ws.TestRequest;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.sonar.db.permission.GlobalPermission.ADMINISTER_QUALITY_GATES;
+import static org.sonar.server.qualitygate.QualityGateCaycChecker.CAYC_METRICS;
import static org.sonar.server.qualitygate.ws.QualityGatesWsParameters.PARAM_NAME;
@RunWith(DataProviderRunner.class)
public class CreateActionTest {
-
@Rule
public UserSessionRule userSession = UserSessionRule.standalone();
private final DbClient dbClient = db.getDbClient();
private final DbSession dbSession = db.getSession();
- private final CreateAction underTest = new CreateAction(dbClient, userSession, new QualityGateUpdater(dbClient, UuidFactoryFast.getInstance()));
+ private final CreateAction underTest = new CreateAction(dbClient, userSession, new QualityGateUpdater(dbClient, UuidFactoryFast.getInstance()),
+ new QualityGateConditionsUpdater(dbClient));
private final WsActionTester ws = new WsActionTester(underTest);
- @Test
- public void default_is_used_when_no_parameter() {
- logInAsQualityGateAdmin();
-
- String qgName = "Default";
- CreateResponse response = executeRequest(qgName);
-
- assertThat(response.getName()).isEqualTo(qgName);
- assertThat(response.getId()).isNotNull();
- dbSession.commit();
-
- QualityGateDto qualityGateDto = dbClient.qualityGateDao().selectByName(dbSession, qgName);
- assertThat(qualityGateDto).isNotNull();
+ @Before
+ public void setup() {
+ CAYC_METRICS.forEach(this::insertMetric);
}
@Test
- public void create_quality_gate() {
+ public void create_quality_gate_with_cayc_conditions() {
logInAsQualityGateAdmin();
String qgName = "Default";
QualityGateDto qualityGateDto = dbClient.qualityGateDao().selectByName(dbSession, qgName);
assertThat(qualityGateDto).isNotNull();
+
+ var conditions = getConditions(dbSession, qualityGateDto);
+
+ CAYC_METRICS.stream()
+ .map(m -> dbClient.metricDao().selectByKey(dbSession, m.getKey()))
+ .forEach(metricDto ->
+ assertThat(conditions).anyMatch(c -> metricDto.getUuid().equals(c.getMetricUuid())));
}
@Test
@DataProvider
public static Object[][] nullOrEmpty() {
- return new Object[][]{
+ return new Object[][] {
{null},
{""},
{" "}
};
}
+ private Collection<QualityGateConditionDto> getConditions(DbSession dbSession, QualityGateDto qualityGate) {
+ return dbClient.gateConditionDao().selectForQualityGate(dbSession, qualityGate.getUuid());
+ }
+
private CreateResponse executeRequest(String qualitGateName) {
return ws.newRequest()
.setParam("name", qualitGateName)
private void logInAsQualityGateAdmin() {
userSession.logIn().addPermission(ADMINISTER_QUALITY_GATES);
}
+
+ private void insertMetric(Metric metric) {
+ db.measures().insertMetric(m -> m
+ .setKey(metric.getKey())
+ .setValueType(metric.getType().name())
+ .setHidden(metric.isHidden())
+ .setDirection(metric.getDirection()));
+ }
}