]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-16316 Fill report data
authorDuarte Meneses <duarte.meneses@sonarsource.com>
Wed, 4 May 2022 20:47:32 +0000 (15:47 -0500)
committersonartech <sonartech@sonarsource.com>
Wed, 25 May 2022 20:03:16 +0000 (20:03 +0000)
19 files changed:
server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/qualitygate/QualityGate.java
server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/qualitygate/QualityGateService.java
server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/qualitygate/QualityGateServiceImpl.java
server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/LoadQualityGateStep.java
server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/qualitygate/QualityGateServiceImplTest.java
server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/LoadQualityGateStepTest.java
server/sonar-db-dao/src/main/java/org/sonar/db/measure/LiveMeasureDao.java
server/sonar-db-dao/src/main/java/org/sonar/db/qualitygate/QualityGateDao.java
server/sonar-db-dao/src/main/java/org/sonar/db/qualitygate/QualityGateMapper.java
server/sonar-db-dao/src/main/java/org/sonar/db/qualityprofile/QualityProfileDao.java
server/sonar-db-dao/src/main/resources/org/sonar/db/qualitygate/QualityGateMapper.xml
server/sonar-db-dao/src/test/java/org/sonar/db/qualityprofile/QualityProfileDaoTest.java
server/sonar-server-common/src/main/java/org/sonar/server/qualitygate/QualityGateFinder.java
server/sonar-server-common/src/test/java/org/sonar/server/qualitygate/QualityGateFinderTest.java
server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/live/LiveQualityGateComputerImpl.java
server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualitygate/ws/GetByProjectAction.java
server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/ws/SearchAction.java
server/sonar-webserver-webapi/src/main/java/org/sonar/server/ui/ws/ComponentAction.java
server/sonar-webserver-webapi/src/test/java/org/sonar/server/qualitygate/RegisterQualityGatesTest.java

index 3c1fd4e542d61cc32e5c98c2747a61a22000d0a4..b65f47660462ba10628195a6427c4474ab30fd61 100644 (file)
  */
 package org.sonar.ce.task.projectanalysis.qualitygate;
 
+import java.util.Collection;
+import java.util.LinkedHashSet;
 import java.util.Objects;
 import java.util.Set;
 import javax.annotation.concurrent.Immutable;
 
-import static com.google.common.base.Predicates.notNull;
-import static com.google.common.collect.FluentIterable.from;
+import static java.util.Collections.unmodifiableSet;
 
 @Immutable
 public class QualityGate {
@@ -32,10 +33,10 @@ public class QualityGate {
   private final String name;
   private final Set<Condition> conditions;
 
-  public QualityGate(String uuid, String name, Iterable<Condition> conditions) {
+  public QualityGate(String uuid, String name, Collection<Condition> conditions) {
     this.uuid = uuid;
     this.name = Objects.requireNonNull(name);
-    this.conditions = from(conditions).filter(notNull()).toSet();
+    this.conditions = unmodifiableSet(new LinkedHashSet<>(conditions));
   }
 
   public String getUuid() {
index 69d2373f9e772967958c28e3d39d63e595e4d9f3..88d5dec22ffa7a6b82830ef5380f4e4d9a077293 100644 (file)
  */
 package org.sonar.ce.task.projectanalysis.qualitygate;
 
-import java.util.Optional;
 import org.sonar.server.project.Project;
 
 public interface QualityGateService {
-
-  /**
-   * Retrieve the {@link QualityGate} from the database with the specified uuid, if it exists.
-   */
-  Optional<QualityGate> findByUuid(String uuid);
-
   /**
-   * Retrieve the {@link QualityGate} from the database.
-   * @throws IllegalStateException if database is corrupted and default gate can't be found.
+   * Retrieve the {@link QualityGate} from the database associated with project. If there's none, it returns the default quality gate.
    */
-  QualityGate findDefaultQualityGate();
-
-  /**
-   * Retrieve the {@link QualityGate} from the database associated with project.
-   */
-  Optional<QualityGate> findQualityGate(Project project);
-
+  QualityGate findEffectiveQualityGate(Project project);
 }
index 53377ab04eeba336fb1a8e052f522e5a29bccc2a..649a2fd82e5c32d938023bfd5c09d0af12a4d124 100644 (file)
@@ -25,7 +25,6 @@ import java.util.Optional;
 import org.sonar.ce.task.projectanalysis.metric.MetricRepository;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
-import org.sonar.db.property.PropertyDto;
 import org.sonar.db.qualitygate.QualityGateConditionDto;
 import org.sonar.db.qualitygate.QualityGateDto;
 import org.sonar.server.project.Project;
@@ -33,8 +32,6 @@ import org.sonar.server.project.Project;
 import static org.sonar.core.util.stream.MoreCollectors.toList;
 
 public class QualityGateServiceImpl implements QualityGateService {
-  private static final String DEFAULT_QUALITY_GATE_PROPERTY_NAME = "qualitygate.default";
-
   private final DbClient dbClient;
   private final MetricRepository metricRepository;
 
@@ -44,20 +41,13 @@ public class QualityGateServiceImpl implements QualityGateService {
   }
 
   @Override
-  public Optional<QualityGate> findByUuid(String uuid) {
-    try (DbSession dbSession = dbClient.openSession(false)) {
-      QualityGateDto qualityGateDto = dbClient.qualityGateDao().selectByUuid(dbSession, uuid);
-      if (qualityGateDto == null) {
-        return Optional.empty();
-      }
-      return Optional.of(toQualityGate(dbSession, qualityGateDto));
-    }
+  public QualityGate findEffectiveQualityGate(Project project) {
+    return findQualityGate(project).orElseGet(this::findDefaultQualityGate);
   }
 
-  @Override
-  public QualityGate findDefaultQualityGate() {
+  private QualityGate findDefaultQualityGate() {
     try (DbSession dbSession = dbClient.openSession(false)) {
-      QualityGateDto qualityGateDto = getDefaultQualityGate(dbSession);
+      QualityGateDto qualityGateDto = dbClient.qualityGateDao().selectDefault(dbSession);
       if (qualityGateDto == null) {
         throw new IllegalStateException("The default Quality gate is missing");
       }
@@ -65,29 +55,17 @@ public class QualityGateServiceImpl implements QualityGateService {
     }
   }
 
-  private QualityGateDto getDefaultQualityGate(DbSession dbSession) {
-    PropertyDto propertyDto = Optional.ofNullable(dbClient.propertiesDao()
-      .selectGlobalProperty(dbSession, DEFAULT_QUALITY_GATE_PROPERTY_NAME))
-      .orElseThrow(() -> new IllegalStateException("The default Quality Gate property is missing"));
-    return Optional.ofNullable(dbClient.qualityGateDao().selectByUuid(dbSession, propertyDto.getValue()))
-      .orElseThrow(() -> new IllegalStateException("The default Quality gate is missing"));
-  }
-
-  @Override
-  public Optional<QualityGate> findQualityGate(Project project) {
+  private Optional<QualityGate> findQualityGate(Project project) {
     try (DbSession dbSession = dbClient.openSession(false)) {
-      QualityGateDto qualityGateDto = dbClient.qualityGateDao().selectByProjectUuid(dbSession, project.getUuid());
-      if (qualityGateDto == null) {
-        return Optional.empty();
-      }
-      return Optional.of(toQualityGate(dbSession, qualityGateDto));
+      return Optional.ofNullable(dbClient.qualityGateDao().selectByProjectUuid(dbSession, project.getUuid()))
+        .map(qg -> toQualityGate(dbSession, qg));
     }
   }
 
   private QualityGate toQualityGate(DbSession dbSession, QualityGateDto qualityGateDto) {
     Collection<QualityGateConditionDto> dtos = dbClient.gateConditionDao().selectForQualityGate(dbSession, qualityGateDto.getUuid());
 
-    Iterable<Condition> conditions = dtos.stream()
+    Collection<Condition> conditions = dtos.stream()
       .map(input -> metricRepository.getOptionalByUuid(input.getMetricUuid())
         .map(metric -> new Condition(metric, input.getOperator(), input.getErrorThreshold()))
         .orElse(null))
index d37230ed824fc5fd0f506775adac20405fe18f59..8b81211272522e8c63b89ab7e0cbf207d558925a 100644 (file)
@@ -19,7 +19,6 @@
  */
 package org.sonar.ce.task.projectanalysis.step;
 
-import java.util.Optional;
 import java.util.stream.Collectors;
 import org.sonar.ce.task.projectanalysis.analysis.AnalysisMetadataHolder;
 import org.sonar.ce.task.projectanalysis.qualitygate.Condition;
@@ -39,8 +38,7 @@ public class LoadQualityGateStep implements ComputationStep {
   private final MutableQualityGateHolder qualityGateHolder;
   private final AnalysisMetadataHolder analysisMetadataHolder;
 
-  public LoadQualityGateStep(QualityGateService qualityGateService, MutableQualityGateHolder qualityGateHolder,
-                             AnalysisMetadataHolder analysisMetadataHolder) {
+  public LoadQualityGateStep(QualityGateService qualityGateService, MutableQualityGateHolder qualityGateHolder, AnalysisMetadataHolder analysisMetadataHolder) {
     this.qualityGateService = qualityGateService;
     this.qualityGateHolder = qualityGateHolder;
     this.analysisMetadataHolder = analysisMetadataHolder;
@@ -48,31 +46,22 @@ public class LoadQualityGateStep implements ComputationStep {
 
   @Override
   public void execute(ComputationStep.Context context) {
-    Optional<QualityGate> qualityGate = getProjectQualityGate();
-    if (!qualityGate.isPresent()) {
-      // No QG defined for the project, let's retrieve the default QG
-      qualityGate = Optional.of(getDefaultQualityGate());
-    }
+    QualityGate qualityGate = getProjectQualityGate();
 
     if (analysisMetadataHolder.isPullRequest()) {
       qualityGate = filterQGForPR(qualityGate);
     }
 
-    qualityGateHolder.setQualityGate(qualityGate.orElseThrow(() -> new IllegalStateException("Quality gate not present")));
+    qualityGateHolder.setQualityGate(qualityGate);
   }
 
-  private static Optional<QualityGate> filterQGForPR(Optional<QualityGate> qualityGate) {
-    return qualityGate.map(qg -> new QualityGate(qg.getUuid(), qg.getName(),
-      qg.getConditions().stream().filter(Condition::useVariation).collect(Collectors.toList())));
+  private static QualityGate filterQGForPR(QualityGate qg) {
+    return new QualityGate(qg.getUuid(), qg.getName(), qg.getConditions().stream().filter(Condition::useVariation).collect(Collectors.toList()));
   }
 
-  private Optional<QualityGate> getProjectQualityGate() {
+  private QualityGate getProjectQualityGate() {
     Project project = analysisMetadataHolder.getProject();
-    return qualityGateService.findQualityGate(project);
-  }
-
-  private QualityGate getDefaultQualityGate() {
-    return qualityGateService.findDefaultQualityGate();
+    return qualityGateService.findEffectiveQualityGate(project);
   }
 
   @Override
index 28dda85086789b5ab3d4e53cd2612c21d60933e4..12d564dfe46322ae2ec73f14466fa264aef56349 100644 (file)
@@ -57,80 +57,22 @@ public class QualityGateServiceImplTest {
 
   private final QualityGateDao qualityGateDao = mock(QualityGateDao.class);
   private final QualityGateConditionDao qualityGateConditionDao = mock(QualityGateConditionDao.class);
-  private final PropertiesDao propertiesDao = mock(PropertiesDao.class);
   private final MetricRepository metricRepository = mock(MetricRepository.class);
   private final DbClient dbClient = mock(DbClient.class);
-  private final QualityGateServiceImpl underTest = new QualityGateServiceImpl(dbClient, metricRepository);
+  private final QualityGateService underTest = new QualityGateServiceImpl(dbClient, metricRepository);
 
   @Before
   public void setUp() {
     when(dbClient.qualityGateDao()).thenReturn(qualityGateDao);
     when(dbClient.gateConditionDao()).thenReturn(qualityGateConditionDao);
-    when(dbClient.propertiesDao()).thenReturn(propertiesDao);
 
     when(METRIC_1.getKey()).thenReturn("metric");
     when(METRIC_2.getKey()).thenReturn("new_metric");
   }
 
-  @Test
-  public void findById_returns_absent_when_QualityGateDto_does_not_exist() {
-    assertThat(underTest.findByUuid(SOME_UUID)).isNotPresent();
-  }
-
-  @Test
-  public void findById_returns_QualityGate_with_empty_set_of_conditions_when_there_is_none_in_DB() {
-    when(qualityGateDao.selectByUuid(any(), eq(SOME_UUID))).thenReturn(QUALITY_GATE_DTO);
-    when(qualityGateConditionDao.selectForQualityGate(any(), eq(SOME_UUID))).thenReturn(Collections.emptyList());
-
-    Optional<QualityGate> res = underTest.findByUuid(SOME_UUID);
-
-    assertThat(res).isPresent();
-    assertThat(res.get().getUuid()).isEqualTo(SOME_UUID);
-    assertThat(res.get().getName()).isEqualTo(SOME_NAME);
-    assertThat(res.get().getConditions()).isEmpty();
-  }
-
-  @Test
-  public void findById_returns_conditions_when_there_is_some_in_DB() {
-    when(qualityGateDao.selectByUuid(any(), eq(SOME_UUID))).thenReturn(QUALITY_GATE_DTO);
-    when(qualityGateConditionDao.selectForQualityGate(any(), eq(SOME_UUID))).thenReturn(ImmutableList.of(CONDITION_1, CONDITION_2));
-    // metrics are always supposed to be there
-    when(metricRepository.getOptionalByUuid(METRIC_UUID_1)).thenReturn(Optional.of(METRIC_1));
-    when(metricRepository.getOptionalByUuid(METRIC_UUID_2)).thenReturn(Optional.of(METRIC_2));
-
-    Optional<QualityGate> res = underTest.findByUuid(SOME_UUID);
-
-    assertThat(res).isPresent();
-    assertThat(res.get().getUuid()).isEqualTo(SOME_UUID);
-    assertThat(res.get().getName()).isEqualTo(SOME_NAME);
-    assertThat(res.get().getConditions()).containsOnly(
-      new Condition(METRIC_1, CONDITION_1.getOperator(), CONDITION_1.getErrorThreshold()),
-      new Condition(METRIC_2, CONDITION_2.getOperator(), CONDITION_2.getErrorThreshold()));
-  }
-
-  @Test
-  public void findById_ignores_conditions_on_missing_metrics() {
-    when(qualityGateDao.selectByUuid(any(), eq(SOME_UUID))).thenReturn(QUALITY_GATE_DTO);
-    when(qualityGateConditionDao.selectForQualityGate(any(), eq(SOME_UUID))).thenReturn(ImmutableList.of(CONDITION_1, CONDITION_2));
-    // metrics are always supposed to be there
-    when(metricRepository.getOptionalByUuid(METRIC_UUID_1)).thenReturn(Optional.empty());
-    when(metricRepository.getOptionalByUuid(METRIC_UUID_2)).thenReturn(Optional.of(METRIC_2));
-
-    Optional<QualityGate> res = underTest.findByUuid(SOME_UUID);
-
-    assertThat(res).isPresent();
-    assertThat(res.get().getUuid()).isEqualTo(SOME_UUID);
-    assertThat(res.get().getName()).isEqualTo(SOME_NAME);
-    assertThat(res.get().getConditions()).containsOnly(
-      new Condition(METRIC_2, CONDITION_2.getOperator(), CONDITION_2.getErrorThreshold()));
-  }
-
   @Test
   public void findDefaultQualityGate_by_property_not_found() {
-    when(propertiesDao.selectGlobalProperty(any(), any())).thenReturn(null);
-
-    assertThatThrownBy(() -> underTest.findDefaultQualityGate())
-      .isInstanceOf(IllegalStateException.class);
+    assertThatThrownBy(() -> underTest.findEffectiveQualityGate(mock(Project.class))).isInstanceOf(IllegalStateException.class);
   }
 
   @Test
@@ -138,46 +80,33 @@ public class QualityGateServiceImplTest {
     QualityGateDto qualityGateDto = new QualityGateDto();
     qualityGateDto.setUuid(QUALITY_GATE_DTO.getUuid());
     qualityGateDto.setName(QUALITY_GATE_DTO.getName());
-    when(propertiesDao.selectGlobalProperty(any(), any())).thenReturn(new PropertyDto().setValue(QUALITY_GATE_DTO.getUuid()));
 
-    when(qualityGateDao.selectByUuid(any(), any())).thenReturn(qualityGateDto);
+    when(qualityGateDao.selectDefault(any())).thenReturn(qualityGateDto);
     when(qualityGateConditionDao.selectForQualityGate(any(), eq(SOME_UUID))).thenReturn(ImmutableList.of(CONDITION_1, CONDITION_2));
     when(metricRepository.getOptionalByUuid(METRIC_UUID_1)).thenReturn(Optional.empty());
     when(metricRepository.getOptionalByUuid(METRIC_UUID_2)).thenReturn(Optional.of(METRIC_2));
 
-    QualityGate result = underTest.findDefaultQualityGate();
+    QualityGate result = underTest.findEffectiveQualityGate(mock(Project.class));
 
     assertThat(result).isNotNull();
     assertThat(result.getUuid()).isEqualTo(QUALITY_GATE_DTO.getUuid());
-    assertThat(result.getName()).isNotBlank();
     assertThat(result.getName()).isEqualTo(QUALITY_GATE_DTO.getName());
   }
 
-  @Test
-  public void findQualityGate_by_project_not_found() {
-    when(qualityGateDao.selectByProjectUuid(any(), any())).thenReturn(null);
-    Optional<QualityGate> result = underTest.findQualityGate(mock(Project.class));
-    assertThat(result).isEmpty();
-  }
-
   @Test
   public void findQualityGate_by_project_found() {
     QualityGateDto qualityGateDto = new QualityGateDto();
     qualityGateDto.setUuid(QUALITY_GATE_DTO.getUuid());
     qualityGateDto.setName(QUALITY_GATE_DTO.getName());
+
     when(qualityGateDao.selectByProjectUuid(any(), any())).thenReturn(qualityGateDto);
     when(qualityGateConditionDao.selectForQualityGate(any(), eq(SOME_UUID))).thenReturn(ImmutableList.of(CONDITION_1, CONDITION_2));
     when(metricRepository.getOptionalByUuid(METRIC_UUID_1)).thenReturn(Optional.empty());
     when(metricRepository.getOptionalByUuid(METRIC_UUID_2)).thenReturn(Optional.of(METRIC_2));
 
-    Optional<QualityGate> result = underTest.findQualityGate(mock(Project.class));
+    QualityGate result = underTest.findEffectiveQualityGate(mock(Project.class));
 
-    assertThat(result).isNotNull();
-    assertThat(result).isNotEmpty();
-
-    QualityGate resultData = result.get();
-    assertThat(resultData.getUuid()).isEqualTo(QUALITY_GATE_DTO.getUuid());
-    assertThat(resultData.getName()).isNotBlank();
-    assertThat(resultData.getName()).isEqualTo(QUALITY_GATE_DTO.getName());
+    assertThat(result.getUuid()).isEqualTo(QUALITY_GATE_DTO.getUuid());
+    assertThat(result.getName()).isEqualTo(QUALITY_GATE_DTO.getName());
   }
 }
index f0d791aae40dc28040d706aa51df4e8b46e00930..5d49766a47d9eff146a5aa38c78fbadca5fdfe59 100644 (file)
@@ -20,7 +20,6 @@
 package org.sonar.ce.task.projectanalysis.step;
 
 import java.util.Arrays;
-import java.util.Optional;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -30,28 +29,27 @@ import org.sonar.ce.task.projectanalysis.metric.MetricImpl;
 import org.sonar.ce.task.projectanalysis.qualitygate.Condition;
 import org.sonar.ce.task.projectanalysis.qualitygate.MutableQualityGateHolderRule;
 import org.sonar.ce.task.projectanalysis.qualitygate.QualityGate;
-import org.sonar.ce.task.projectanalysis.qualitygate.QualityGateService;
+import org.sonar.ce.task.projectanalysis.qualitygate.QualityGateServiceImpl;
 import org.sonar.ce.task.step.TestComputationStepContext;
 import org.sonar.server.project.Project;
 
-import static java.util.Collections.emptyList;
 import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
 public class LoadQualityGateStepTest {
-
   @Rule
   public MutableQualityGateHolderRule mutableQualityGateHolder = new MutableQualityGateHolderRule();
 
   private final AnalysisMetadataHolder analysisMetadataHolder = mock(AnalysisMetadataHolder.class);
-  private final QualityGateService qualityGateService = mock(QualityGateService.class);
+  private final QualityGateServiceImpl qualityGateService = mock(QualityGateServiceImpl.class);
 
   private final LoadQualityGateStep underTest = new LoadQualityGateStep(qualityGateService, mutableQualityGateHolder, analysisMetadataHolder);
+  private final Project project = mock(Project.class);
 
   @Before
-  public void setUp() {
+  public void before() {
+    when(analysisMetadataHolder.getProject()).thenReturn(project);
   }
 
   @Test
@@ -63,7 +61,7 @@ public class LoadQualityGateStepTest {
 
     when(analysisMetadataHolder.isPullRequest()).thenReturn(true);
     QualityGate defaultGate = new QualityGate("1", "qg", Arrays.asList(variation, condition));
-    when(qualityGateService.findDefaultQualityGate()).thenReturn(defaultGate);
+    when(qualityGateService.findEffectiveQualityGate(project)).thenReturn(defaultGate);
 
     underTest.execute(new TestComputationStepContext());
 
@@ -71,25 +69,12 @@ public class LoadQualityGateStepTest {
   }
 
   @Test
-  public void execute_sets_default_QualityGate_when_project_has_no_settings() {
-    QualityGate defaultGate = mock(QualityGate.class);
-    when(qualityGateService.findDefaultQualityGate()).thenReturn(defaultGate);
+  public void execute_sets_effective_quality_gate() {
+    QualityGate qg = mock(QualityGate.class);
+    when(qualityGateService.findEffectiveQualityGate(project)).thenReturn(qg);
 
     underTest.execute(new TestComputationStepContext());
 
-    assertThat(mutableQualityGateHolder.getQualityGate().get()).isSameAs(defaultGate);
+    assertThat(mutableQualityGateHolder.getQualityGate()).containsSame(qg);
   }
-
-  @Test
-  public void execute_sets_QualityGate_if_it_can_be_found_by_service() {
-    QualityGate qualityGate = new QualityGate("10", "name", emptyList());
-
-    when(analysisMetadataHolder.getProject()).thenReturn(mock(Project.class));
-    when(qualityGateService.findQualityGate(any(Project.class))).thenReturn(Optional.of(qualityGate));
-
-    underTest.execute(new TestComputationStepContext());
-
-    assertThat(mutableQualityGateHolder.getQualityGate().get()).isSameAs(qualityGate);
-  }
-
 }
index 3b1659aaa95c77b6070e5c05c650f7d6f43eb6a9..7bbdd0c44e6b9efd63e69e3f8d55ed18cd8d034d 100644 (file)
@@ -52,8 +52,7 @@ public class LiveMeasureDao implements Dao {
       componentUuids -> mapper(dbSession).selectByComponentUuidsAndMetricUuids(componentUuids, metricUuis));
   }
 
-  public void scrollSelectByComponentUuidAndMetricKeys(DbSession dbSession, String componentUuid, Collection<String> metricKeys,
-    ResultHandler<LiveMeasureDto> handler) {
+  public void scrollSelectByComponentUuidAndMetricKeys(DbSession dbSession, String componentUuid, Collection<String> metricKeys, ResultHandler<LiveMeasureDto> handler) {
     if (metricKeys.isEmpty()) {
       return;
     }
index e51ee8e4ff3834e33d8c7c5c94e41402f6a6af4c..d05ce597cb0228bd6c886562898d3ff32e4723b0 100644 (file)
@@ -56,6 +56,11 @@ public class QualityGateDao implements Dao {
     return mapper(session).selectByUuid(uuid);
   }
 
+  @CheckForNull
+  public QualityGateDto selectDefault(DbSession session) {
+    return mapper(session).selectDefault();
+  }
+
   public void delete(QualityGateDto qGate, DbSession session) {
     mapper(session).delete(qGate.getUuid());
   }
@@ -81,6 +86,7 @@ public class QualityGateDao implements Dao {
     return session.getMapper(QualityGateMapper.class);
   }
 
+  @CheckForNull
   public QualityGateDto selectByProjectUuid(DbSession dbSession, String projectUuid) {
     return mapper(dbSession).selectByProjectUuid(projectUuid);
   }
index 5bb80ba9467457814d9005c665efae2a9cc23c7f..ec4901e102b33fe64867d1a15b3f9cdafec59a5c 100644 (file)
@@ -43,5 +43,7 @@ public interface QualityGateMapper {
 
   QualityGateDto selectByUuid(String uuid);
 
+  QualityGateDto selectDefault();
+
   QualityGateDto selectByProjectUuid(@Param("projectUuid") String projectUuid);
 }
index 315027c18e68741aec65ffa0657ad7569783cbc0..b692d37f315b41b9e58e35d4df4483fa13f68f26 100644 (file)
@@ -159,8 +159,12 @@ public class QualityProfileDao implements Dao {
     return mapper(dbSession).selectAssociatedToProjectUuidAndLanguage(project.getUuid(), language);
   }
 
-  public List<QProfileDto> selectAssociatedToProjectUuidAndLanguages(DbSession dbSession, ProjectDto project, Collection<String> languages) {
-    return executeLargeInputs(languages, partition -> mapper(dbSession).selectAssociatedToProjectUuidAndLanguages(project.getUuid(), partition));
+  public List<QProfileDto> selectAssociatedToProjectUuidAndLanguages(DbSession dbSession, String projectUuid, Collection<String> languages) {
+    return executeLargeInputs(languages, partition -> mapper(dbSession).selectAssociatedToProjectUuidAndLanguages(projectUuid, partition));
+  }
+
+  public List<QProfileDto> selectAssociatedToProjectAndLanguages(DbSession dbSession, ProjectDto project, Collection<String> languages) {
+    return selectAssociatedToProjectUuidAndLanguages(dbSession, project.getUuid(), languages);
   }
 
   public List<QProfileDto> selectByLanguage(DbSession dbSession, String language) {
index 494bccb3f6d6e45639b0ae0c6895c319ad4b013f..0b52c10da77d90821948dd9b642bcdd11ba01fab 100644 (file)
@@ -4,7 +4,7 @@
 <mapper namespace="org.sonar.db.qualitygate.QualityGateMapper">
 
   <sql id="gateColumns">
-      uuid, name, is_built_in as isBuiltIn, created_at as createdAt, updated_at as updatedAt
+      qg.uuid, qg.name, qg.is_built_in as isBuiltIn, qg.created_at as createdAt, qg.updated_at as updatedAt
   </sql>
 
   <insert id="insertQualityGate" parameterType="QualityGate" useGeneratedKeys="false">
   <select id="selectByName" parameterType="String" resultType="QualityGate">
     select
     <include refid="gateColumns"/>
-    from quality_gates
+    from quality_gates qg
     where name=#{name, jdbcType=VARCHAR}
   </select>
 
   <select id="selectByUuid" parameterType="String" resultType="QualityGate">
     select
     <include refid="gateColumns"/>
-    from quality_gates
+    from quality_gates qg
     where uuid=#{uuid, jdbcType=VARCHAR}
   </select>
 
   <select id="selectBuiltIn" resultType="org.sonar.db.qualitygate.QualityGateDto">
     SELECT
       <include refid="gateColumns"/>
-    FROM quality_gates
+    FROM quality_gates qg
     WHERE
       is_built_in = ${_true}
   </select>
 
+  <select id="selectDefault" resultType="org.sonar.db.qualitygate.QualityGateDto">
+    SELECT
+      <include refid="gateColumns"/>
+    FROM quality_gates qg INNER JOIN properties p ON qg.uuid = p.text_value
+    WHERE
+      p.prop_key = 'qualitygate.default'
+      and p.component_uuid is null
+      and p.user_uuid is null
+  </select>
+
   <update id="delete" parameterType="String">
     delete from quality_gates where uuid=#{uuid}
   </update>
index 45d0290e2dd70a0e42d0a18db35d057def666ed8..026fb17668eead6c424cccdb3fa239bfa6ec765d 100644 (file)
@@ -656,17 +656,17 @@ public class QualityProfileDaoTest {
     QProfileDto jsProfile = db.qualityProfiles().insert(p -> p.setLanguage("js"));
     db.qualityProfiles().associateWithProject(project1, javaProfile, jsProfile);
 
-    assertThat(underTest.selectAssociatedToProjectUuidAndLanguages(dbSession, project1, singletonList("java")))
+    assertThat(underTest.selectAssociatedToProjectAndLanguages(dbSession, project1, singletonList("java")))
       .extracting(QProfileDto::getKee).containsOnly(javaProfile.getKee());
-    assertThat(underTest.selectAssociatedToProjectUuidAndLanguages(dbSession, project1, singletonList("unknown")))
+    assertThat(underTest.selectAssociatedToProjectAndLanguages(dbSession, project1, singletonList("unknown")))
       .isEmpty();
-    assertThat(underTest.selectAssociatedToProjectUuidAndLanguages(dbSession, project1, of("java", "unknown")))
+    assertThat(underTest.selectAssociatedToProjectAndLanguages(dbSession, project1, of("java", "unknown")))
       .extracting(QProfileDto::getKee).containsExactly(javaProfile.getKee());
-    assertThat(underTest.selectAssociatedToProjectUuidAndLanguages(dbSession, project1, of("java", "js")))
+    assertThat(underTest.selectAssociatedToProjectAndLanguages(dbSession, project1, of("java", "js")))
       .extracting(QProfileDto::getKee).containsExactlyInAnyOrder(javaProfile.getKee(), jsProfile.getKee());
-    assertThat(underTest.selectAssociatedToProjectUuidAndLanguages(dbSession, project2, singletonList("java")))
+    assertThat(underTest.selectAssociatedToProjectAndLanguages(dbSession, project2, singletonList("java")))
       .isEmpty();
-    assertThat(underTest.selectAssociatedToProjectUuidAndLanguages(dbSession, project2, Collections.emptyList()))
+    assertThat(underTest.selectAssociatedToProjectAndLanguages(dbSession, project2, Collections.emptyList()))
       .isEmpty();
   }
 
index b54651cade1b922b9449683c19063e7277097c64..0dd9bd82eab2cdbaa8a84ff41cda69c151ca24db 100644 (file)
@@ -23,25 +23,20 @@ import java.util.Optional;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.project.ProjectDto;
-import org.sonar.db.property.PropertyDto;
 import org.sonar.db.qualitygate.QualityGateDto;
 
-import static com.google.common.base.Preconditions.checkState;
-
 public class QualityGateFinder {
-  private static final String DEFAULT_QUALITY_GATE_PROPERTY_NAME = "qualitygate.default";
-
   private final DbClient dbClient;
 
   public QualityGateFinder(DbClient dbClient) {
     this.dbClient = dbClient;
   }
 
-  public QualityGateData getQualityGate(DbSession dbSession, ProjectDto projectDto) {
-    return getQualityGate(dbSession, projectDto.getUuid());
+  public QualityGateData getEffectiveQualityGate(DbSession dbSession, ProjectDto projectDto) {
+    return getEffectiveQualityGate(dbSession, projectDto.getUuid());
   }
 
-  public QualityGateData getQualityGate(DbSession dbSession, String projectUuid) {
+  public QualityGateData getEffectiveQualityGate(DbSession dbSession, String projectUuid) {
     Optional<QualityGateData> res = getQualityGateForProject(dbSession, projectUuid);
     if (res.isPresent()) {
       return res.get();
@@ -57,30 +52,32 @@ public class QualityGateFinder {
   }
 
   public QualityGateDto getDefault(DbSession dbSession) {
-    PropertyDto qGateDefaultUuidProperty = dbClient.propertiesDao().selectGlobalProperty(dbSession, DEFAULT_QUALITY_GATE_PROPERTY_NAME);
-    checkState(qGateDefaultUuidProperty != null, "Default quality gate property is missing");
-    dbClient.qualityGateDao().selectByUuid(dbSession, qGateDefaultUuidProperty.getValue());
-    return Optional.ofNullable(dbClient.qualityGateDao().selectByUuid(dbSession, qGateDefaultUuidProperty.getValue()))
-      .orElseThrow(() -> new IllegalStateException("Default quality gate is missing"));
-  }
-
-  public QualityGateDto getBuiltInQualityGate(DbSession dbSession) {
-    QualityGateDto builtIn = dbClient.qualityGateDao().selectBuiltIn(dbSession);
-    checkState(builtIn != null, "Builtin quality gate is missing.");
-    return builtIn;
+    return Optional.ofNullable(dbClient.qualityGateDao().selectDefault(dbSession)).orElseThrow(() -> new IllegalStateException("Default quality gate is missing"));
   }
 
   public static class QualityGateData {
-    private final QualityGateDto qualityGate;
+    private final String uuid;
+    private final String name;
     private final boolean isDefault;
+    private final boolean builtIn;
 
     private QualityGateData(QualityGateDto qualityGate, boolean isDefault) {
-      this.qualityGate = qualityGate;
+      this.uuid = qualityGate.getUuid();
+      this.name = qualityGate.getName();
       this.isDefault = isDefault;
+      this.builtIn = qualityGate.isBuiltIn();
+    }
+
+    public boolean isBuiltIn() {
+      return builtIn;
+    }
+
+    public String getUuid() {
+      return uuid;
     }
 
-    public QualityGateDto getQualityGate() {
-      return qualityGate;
+    public String getName() {
+      return name;
     }
 
     public boolean isDefault() {
index f90437139a3651a73edac44733f5c591f3467fe4..7b5ac3714afd42a42c1a9efcbf7d43d30bc4ecd9 100644 (file)
@@ -44,9 +44,9 @@ public class QualityGateFinderTest {
     ProjectDto project = db.components().insertPrivateProjectDto();
     QualityGateDto dbQualityGate = db.qualityGates().createDefaultQualityGate(qg -> qg.setName("Sonar way"));
 
-    QualityGateFinder.QualityGateData result = underTest.getQualityGate(dbSession, project);
+    QualityGateFinder.QualityGateData result = underTest.getEffectiveQualityGate(dbSession, project);
 
-    assertThat(result.getQualityGate().getUuid()).isEqualTo(dbQualityGate.getUuid());
+    assertThat(result.getUuid()).isEqualTo(dbQualityGate.getUuid());
     assertThat(result.isDefault()).isTrue();
   }
 
@@ -57,9 +57,9 @@ public class QualityGateFinderTest {
     QualityGateDto dbQualityGate = db.qualityGates().insertQualityGate(qg -> qg.setName("My team QG"));
     db.qualityGates().associateProjectToQualityGate(project, dbQualityGate);
 
-    QualityGateFinder.QualityGateData result = underTest.getQualityGate(dbSession, project);
+    QualityGateFinder.QualityGateData result = underTest.getEffectiveQualityGate(dbSession, project);
 
-    assertThat(result.getQualityGate().getUuid()).isEqualTo(dbQualityGate.getUuid());
+    assertThat(result.getUuid()).isEqualTo(dbQualityGate.getUuid());
     assertThat(result.isDefault()).isFalse();
   }
 
@@ -70,7 +70,7 @@ public class QualityGateFinderTest {
     db.getDbClient().qualityGateDao().delete(dbQualityGate, dbSession);
     db.commit();
 
-    assertThatThrownBy(() -> underTest.getQualityGate(dbSession, project))
+    assertThatThrownBy(() -> underTest.getEffectiveQualityGate(dbSession, project))
       .isInstanceOf(IllegalStateException.class)
       .hasMessage("Default quality gate is missing");
   }
@@ -83,7 +83,7 @@ public class QualityGateFinderTest {
     db.qualityGates().associateProjectToQualityGate(project, dbQualityGate);
     db.getDbClient().qualityGateDao().delete(dbQualityGate, dbSession);
 
-    assertThatThrownBy(() -> underTest.getQualityGate(dbSession, project))
+    assertThatThrownBy(() -> underTest.getEffectiveQualityGate(dbSession, project))
       .isInstanceOf(IllegalStateException.class)
       .hasMessage("Default quality gate is missing");
   }
@@ -94,9 +94,9 @@ public class QualityGateFinderTest {
     QualityGateDto dbQualityGate = db.qualityGates().insertQualityGate(qg -> qg.setName("My team QG"));
     db.getDbClient().qualityGateDao().delete(dbQualityGate, dbSession);
 
-    assertThatThrownBy(() -> underTest.getQualityGate(dbSession, project))
+    assertThatThrownBy(() -> underTest.getEffectiveQualityGate(dbSession, project))
       .isInstanceOf(IllegalStateException.class)
-      .hasMessage("Default quality gate property is missing");
+      .hasMessage("Default quality gate is missing");
   }
 
   @Test
index a844ae43f300d801261f04e7f5a127144f6fa6fb..dd40744a261d28448a96f90205905a5a5cd11a12 100644 (file)
@@ -38,13 +38,13 @@ import org.sonar.db.measure.LiveMeasureDto;
 import org.sonar.db.metric.MetricDto;
 import org.sonar.db.project.ProjectDto;
 import org.sonar.db.qualitygate.QualityGateConditionDto;
-import org.sonar.db.qualitygate.QualityGateDto;
 import org.sonar.server.qualitygate.Condition;
 import org.sonar.server.qualitygate.EvaluatedQualityGate;
 import org.sonar.server.qualitygate.QualityGate;
 import org.sonar.server.qualitygate.QualityGateConverter;
 import org.sonar.server.qualitygate.QualityGateEvaluator;
 import org.sonar.server.qualitygate.QualityGateFinder;
+import org.sonar.server.qualitygate.QualityGateFinder.QualityGateData;
 
 import static org.sonar.core.util.stream.MoreCollectors.toHashSet;
 import static org.sonar.core.util.stream.MoreCollectors.uniqueIndex;
@@ -63,9 +63,8 @@ public class LiveQualityGateComputerImpl implements LiveQualityGateComputer {
 
   @Override
   public QualityGate loadQualityGate(DbSession dbSession, ProjectDto project, BranchDto branch) {
-    QualityGateDto gateDto = qGateFinder.getQualityGate(dbSession, project)
-      .getQualityGate();
-    Collection<QualityGateConditionDto> conditionDtos = dbClient.gateConditionDao().selectForQualityGate(dbSession, gateDto.getUuid());
+    QualityGateData qg = qGateFinder.getEffectiveQualityGate(dbSession, project);
+    Collection<QualityGateConditionDto> conditionDtos = dbClient.gateConditionDao().selectForQualityGate(dbSession, qg.getUuid());
     Set<String> metricUuids = conditionDtos.stream().map(QualityGateConditionDto::getMetricUuid)
       .collect(toHashSet(conditionDtos.size()));
     Map<String, MetricDto> metricsByUuid = dbClient.metricDao().selectByUuids(dbSession, metricUuids).stream()
@@ -81,7 +80,7 @@ public class LiveQualityGateComputerImpl implements LiveQualityGateComputer {
       conditions = conditions.filter(Condition::isOnLeakPeriod);
     }
 
-    return new QualityGate(String.valueOf(gateDto.getUuid()), gateDto.getName(), conditions.collect(toHashSet(conditionDtos.size())));
+    return new QualityGate(String.valueOf(qg.getUuid()), qg.getName(), conditions.collect(toHashSet(conditionDtos.size())));
   }
 
   @Override
index 4463d72c11b2e1b5606cce0dd39c454fcf31f2c1..98e0c48bfed533abf633c49e63af3acbc2b9752e 100644 (file)
@@ -91,20 +91,19 @@ public class GetByProjectAction implements QualityGatesWsAction {
         throw insufficientPrivilegesException();
       }
 
-      QualityGateData data = qualityGateFinder.getQualityGate(dbSession, project);
+      QualityGateData data = qualityGateFinder.getEffectiveQualityGate(dbSession, project);
 
       writeProtobuf(buildResponse(data), request, response);
     }
   }
 
-  private static GetByProjectResponse buildResponse(QualityGateData data) {
-    QualityGateDto qualityGate = data.getQualityGate();
+  private static GetByProjectResponse buildResponse(QualityGateData qg) {
     GetByProjectResponse.Builder response = GetByProjectResponse.newBuilder();
 
     response.getQualityGateBuilder()
-      .setId(qualityGate.getUuid())
-      .setName(qualityGate.getName())
-      .setDefault(data.isDefault());
+      .setId(qg.getUuid())
+      .setName(qg.getName())
+      .setDefault(qg.isDefault());
 
     return response.build();
   }
index eae65ad2edacdf39a9dac5c05a40a8d14bdd07f4..4c696b13ff8ccd2f00a038659d5ad0306f48b171 100644 (file)
@@ -219,7 +219,7 @@ public class SearchAction implements QProfileWsAction {
       return p -> true;
     }
     Map<String, QProfileDto> effectiveProfiles = defaultProfiles.stream().collect(Collectors.toMap(QProfileDto::getLanguage, identity()));
-    effectiveProfiles.putAll(dbClient.qualityProfileDao().selectAssociatedToProjectUuidAndLanguages(dbSession, project, getLanguageKeys()).stream()
+    effectiveProfiles.putAll(dbClient.qualityProfileDao().selectAssociatedToProjectAndLanguages(dbSession, project, getLanguageKeys()).stream()
       .collect(MoreCollectors.uniqueIndex(QProfileDto::getLanguage)));
     return p -> Objects.equals(p.getKee(), effectiveProfiles.get(p.getLanguage()).getKee());
   }
index 3726be2a3ee9be18a7deea68f78ea2aa34a5b740..163d8074269ce474de9fe5251330afde1c08548a 100644 (file)
@@ -259,11 +259,10 @@ public class ComponentAction implements NavigationWsAction {
   }
 
   private void writeQualityGate(JsonWriter json, DbSession session, ComponentDto component) {
-    QualityGateFinder.QualityGateData qualityGateData = qualityGateFinder.getQualityGate(session, component.uuid());
-    QualityGateDto qualityGateDto = qualityGateData.getQualityGate();
+    var qualityGateData = qualityGateFinder.getEffectiveQualityGate(session, component.uuid());
     json.name("qualityGate").beginObject()
-      .prop("key", qualityGateDto.getUuid())
-      .prop("name", qualityGateDto.getName())
+      .prop("key", qualityGateData.getUuid())
+      .prop("name", qualityGateData.getName())
       .prop("isDefault", qualityGateData.isDefault())
       .endObject();
   }
index 22a71234a67c80bcda38cd97f1c2f14c8eba515b..bfb1dc89d63a9d5b45a840e8d8b34a9ddb8a771d 100644 (file)
@@ -199,17 +199,6 @@ public class RegisterQualityGatesTest {
       logTester.logs(LoggerLevel.INFO).contains("Built-in quality gate's conditions of [Sonar way] has been updated")).isTrue();
   }
 
-  @Test
-  public void ensure_only_that_builtin_is_set_as_default_when_no_default_quality_gate() {
-    insertMetrics();
-    QualityGateDto builtInQualityGate = db.qualityGates().insertBuiltInQualityGate();
-
-    underTest.start();
-
-    assertThat(qualityGateFinder.getBuiltInQualityGate(dbSession)).isNotNull();
-    assertThat(qualityGateFinder.getBuiltInQualityGate(dbSession).getUuid()).isEqualTo(builtInQualityGate.getUuid());
-  }
-
   @Test
   public void builtin_quality_gate_with_incorrect_metricuuid_should_not_throw_an_exception() {
     insertMetrics();