diff options
10 files changed, 248 insertions, 0 deletions
diff --git a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/container/ProjectAnalysisTaskContainerPopulator.java b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/container/ProjectAnalysisTaskContainerPopulator.java index 476ca2cf47f..c7df68041a4 100644 --- a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/container/ProjectAnalysisTaskContainerPopulator.java +++ b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/container/ProjectAnalysisTaskContainerPopulator.java @@ -125,6 +125,7 @@ import org.sonar.ce.task.projectanalysis.qualitymodel.RatingSettings; import org.sonar.ce.task.projectanalysis.qualitymodel.ReliabilityAndSecurityRatingMeasuresVisitor; import org.sonar.ce.task.projectanalysis.qualitymodel.SecurityReviewMeasuresVisitor; import org.sonar.ce.task.projectanalysis.qualityprofile.ActiveRulesHolderImpl; +import org.sonar.ce.task.projectanalysis.qualityprofile.PrioritizedRulesHolderImpl; import org.sonar.ce.task.projectanalysis.qualityprofile.QProfileStatusRepositoryImpl; import org.sonar.ce.task.projectanalysis.qualityprofile.QualityProfileRuleChangeResolver; import org.sonar.ce.task.projectanalysis.scm.ScmInfoDbLoader; @@ -206,6 +207,7 @@ public final class ProjectAnalysisTaskContainerPopulator implements ContainerPop BatchReportDirectoryHolderImpl.class, TreeRootHolderImpl.class, PeriodHolderImpl.class, + PrioritizedRulesHolderImpl.class, QualityGateHolderImpl.class, QualityGateStatusHolderImpl.class, RatingSettings.class, diff --git a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/qualityprofile/PrioritizedRulesHolder.java b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/qualityprofile/PrioritizedRulesHolder.java new file mode 100644 index 00000000000..0f09079f1dc --- /dev/null +++ b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/qualityprofile/PrioritizedRulesHolder.java @@ -0,0 +1,35 @@ +/* + * SonarQube + * Copyright (C) 2009-2024 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +package org.sonar.ce.task.projectanalysis.qualityprofile; + +import java.util.Set; + +/** + * Repository of prioritized rules defined in the quality profile + **/ +public interface PrioritizedRulesHolder { + + /** + * Returns the rules Uuids marked as "Priority rules" + */ + Set<String> getPrioritizedRulesUuids(); + +} diff --git a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/qualityprofile/PrioritizedRulesHolderImpl.java b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/qualityprofile/PrioritizedRulesHolderImpl.java new file mode 100644 index 00000000000..45a0ec8c436 --- /dev/null +++ b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/qualityprofile/PrioritizedRulesHolderImpl.java @@ -0,0 +1,37 @@ +/* + * SonarQube + * Copyright (C) 2009-2024 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.ce.task.projectanalysis.qualityprofile; + +import com.google.common.collect.ImmutableSet; +import java.util.Set; + +public class PrioritizedRulesHolderImpl implements PrioritizedRulesHolder{ + + private Set<String> prioritizedRulesUuids; + + @Override + public Set<String> getPrioritizedRulesUuids() { + return ImmutableSet.copyOf(prioritizedRulesUuids); + } + + public void setPrioritizedRulesUuids(Set<String> prioritizedRulesUuids) { + this.prioritizedRulesUuids = prioritizedRulesUuids; + } +} diff --git a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/LoadPrioritizedRulesStep.java b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/LoadPrioritizedRulesStep.java new file mode 100644 index 00000000000..ce35ccd1be8 --- /dev/null +++ b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/LoadPrioritizedRulesStep.java @@ -0,0 +1,63 @@ +/* + * SonarQube + * Copyright (C) 2009-2024 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.ce.task.projectanalysis.step; + +import java.util.Set; +import java.util.stream.Collectors; +import org.sonar.ce.task.projectanalysis.analysis.AnalysisMetadataHolder; +import org.sonar.ce.task.projectanalysis.qualityprofile.PrioritizedRulesHolderImpl; +import org.sonar.ce.task.step.ComputationStep; +import org.sonar.db.DbClient; +import org.sonar.db.DbSession; +import org.sonar.server.qualityprofile.QualityProfile; + +/** + * Populates the {@link org.sonar.ce.task.projectanalysis.qualityprofile.PrioritizedRulesHolder} + */ +public class LoadPrioritizedRulesStep implements ComputationStep { + + private final AnalysisMetadataHolder analysisMetadataHolder; + private final PrioritizedRulesHolderImpl prioritizedRulesHolder; + private final DbClient dbClient; + + public LoadPrioritizedRulesStep(AnalysisMetadataHolder analysisMetadataHolder, PrioritizedRulesHolderImpl prioritizedRulesHolder, + DbClient dbClient) { + this.analysisMetadataHolder = analysisMetadataHolder; + this.prioritizedRulesHolder = prioritizedRulesHolder; + this.dbClient = dbClient; + } + + @Override + public String getDescription() { + return "Load prioritized rules"; + } + + @Override + public void execute(Context context) { + + Set<String> qpKeys = + analysisMetadataHolder.getQProfilesByLanguage().values().stream().map(QualityProfile::getQpKey).collect(Collectors.toSet()); + + try (DbSession dbSession = dbClient.openSession(false)) { + Set<String> prioritizedRulesUuids = dbClient.activeRuleDao().selectPrioritizedRulesUuids(dbSession, qpKeys); + prioritizedRulesHolder.setPrioritizedRulesUuids(prioritizedRulesUuids); + } + } +} diff --git a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/ReportComputationSteps.java b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/ReportComputationSteps.java index ce87c20288b..6095afe8a71 100644 --- a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/ReportComputationSteps.java +++ b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/ReportComputationSteps.java @@ -60,6 +60,7 @@ public class ReportComputationSteps extends AbstractComputationSteps { LoadFileHashesAndStatusStep.class, LoadQualityGateStep.class, LoadPeriodsStep.class, + LoadPrioritizedRulesStep.class, FileMoveDetectionStep.class, PullRequestFileMoveDetectionStep.class, diff --git a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/LoadPrioritizedRulesStepTest.java b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/LoadPrioritizedRulesStepTest.java new file mode 100644 index 00000000000..afeb3ef180f --- /dev/null +++ b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/LoadPrioritizedRulesStepTest.java @@ -0,0 +1,72 @@ +/* + * SonarQube + * Copyright (C) 2009-2024 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.ce.task.projectanalysis.step; + +import java.util.HashSet; +import java.util.Set; +import org.junit.jupiter.api.Test; +import org.sonar.ce.task.projectanalysis.analysis.AnalysisMetadataHolder; +import org.sonar.ce.task.projectanalysis.qualityprofile.PrioritizedRulesHolderImpl; +import org.sonar.ce.task.step.ComputationStep; +import org.sonar.db.DbClient; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +class LoadPrioritizedRulesStepTest { + + AnalysisMetadataHolder analysisMetadataHolder = mock(); + DbClient dbClient = mock(); + PrioritizedRulesHolderImpl prioritizedRulesHolder = new PrioritizedRulesHolderImpl(); + LoadPrioritizedRulesStep underTest = new LoadPrioritizedRulesStep(analysisMetadataHolder, prioritizedRulesHolder, dbClient); + + @Test + void execute_whenNoPrioritizedRules_shouldHaveEmptyHolder() { + when(dbClient.activeRuleDao()).thenReturn(mock()); + when(dbClient.activeRuleDao().selectPrioritizedRulesUuids(any(), any())).thenReturn(new HashSet<>()); + underTest.execute(mock()); + assertThat(prioritizedRulesHolder.getPrioritizedRulesUuids()).isEmpty(); + } + + @Test + void execute_whenPrioritizedRules_shouldHaveNonEmptyHolder() { + when(dbClient.activeRuleDao()).thenReturn(mock()); + when(dbClient.activeRuleDao().selectPrioritizedRulesUuids(any(), any())).thenReturn(Set.of("ruleUuid")); + underTest.execute(mock()); + assertThat(prioritizedRulesHolder.getPrioritizedRulesUuids()).isNotEmpty(); + } + + @Test + void execute_whenDBError_shouldThrow() { + when(dbClient.activeRuleDao()).thenReturn(mock()); + when(dbClient.activeRuleDao().selectPrioritizedRulesUuids(any(), any())).thenThrow(new RuntimeException()); + + ComputationStep.Context context = mock(); + assertThatThrownBy(() -> underTest.execute(context)).isInstanceOf(RuntimeException.class); + } + + @Test + void getDescription_shouldReturnValue() { + assertThat(underTest.getDescription()).isEqualTo("Load prioritized rules"); + } +} diff --git a/server/sonar-db-dao/src/it/java/org/sonar/db/qualityprofile/ActiveRuleDaoIT.java b/server/sonar-db-dao/src/it/java/org/sonar/db/qualityprofile/ActiveRuleDaoIT.java index 7ecb3ba0cba..a5915d7cac9 100644 --- a/server/sonar-db-dao/src/it/java/org/sonar/db/qualityprofile/ActiveRuleDaoIT.java +++ b/server/sonar-db-dao/src/it/java/org/sonar/db/qualityprofile/ActiveRuleDaoIT.java @@ -23,6 +23,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Objects; +import java.util.Set; import java.util.function.Consumer; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -150,6 +151,12 @@ class ActiveRuleDaoIT { } @Test + void selectPrioritizedRulesUuids() { + db.qualityProfiles().activateRule(profile1, rule1, r -> r.setPrioritizedRule(true)); + assertThat(underTest.selectPrioritizedRulesUuids(dbSession, Set.of(profile1.getKee()))).contains(rule1.getUuid()); + } + + @Test void selectByProfileUuid_ignores_removed_rules() { ActiveRuleDto activeRule = createFor(profile1, removedRule).setSeverity(BLOCKER); underTest.insert(dbSession, activeRule); diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/qualityprofile/ActiveRuleDao.java b/server/sonar-db-dao/src/main/java/org/sonar/db/qualityprofile/ActiveRuleDao.java index 385e4a84f08..3d5cfb32854 100644 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/qualityprofile/ActiveRuleDao.java +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/qualityprofile/ActiveRuleDao.java @@ -24,6 +24,7 @@ import java.util.Collection; import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.Set; import java.util.function.Consumer; import org.sonar.core.util.UuidFactory; import org.sonar.db.Dao; @@ -69,6 +70,10 @@ public class ActiveRuleDao implements Dao { return executeLargeInputs(uuids, chunk -> mapper(dbSession).selectByRuleUuids(chunk)); } + public Set<String> selectPrioritizedRulesUuids(DbSession dbSession, Set<String> qprofileUuids) { + return mapper(dbSession).selectPrioritizedRulesUuids(qprofileUuids); + } + /** * Active rule on removed rule are NOT returned */ diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/qualityprofile/ActiveRuleMapper.java b/server/sonar-db-dao/src/main/java/org/sonar/db/qualityprofile/ActiveRuleMapper.java index 5e8429cc5ed..02a353dda7d 100644 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/qualityprofile/ActiveRuleMapper.java +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/qualityprofile/ActiveRuleMapper.java @@ -21,6 +21,7 @@ package org.sonar.db.qualityprofile; import java.util.Collection; import java.util.List; +import java.util.Set; import javax.annotation.CheckForNull; import javax.annotation.Nullable; import org.apache.ibatis.annotations.Param; @@ -59,6 +60,8 @@ public interface ActiveRuleMapper { @Param("ruleUuids") Collection<String> ruleUuids, @Param("ruleProfileUuids") Collection<String> ruleProfileUuids); + Set<String> selectPrioritizedRulesUuids(@Param("ruleProfileUuids") Collection<String> ruleProfileUuids); + void insertParameter(ActiveRuleParamDto dto); void updateParameter(ActiveRuleParamDto dto); diff --git a/server/sonar-db-dao/src/main/resources/org/sonar/db/qualityprofile/ActiveRuleMapper.xml b/server/sonar-db-dao/src/main/resources/org/sonar/db/qualityprofile/ActiveRuleMapper.xml index 3facaac4dba..4c9d25e0318 100644 --- a/server/sonar-db-dao/src/main/resources/org/sonar/db/qualityprofile/ActiveRuleMapper.xml +++ b/server/sonar-db-dao/src/main/resources/org/sonar/db/qualityprofile/ActiveRuleMapper.xml @@ -148,6 +148,29 @@ and rp.uuid in <foreach collection="ruleProfileUuids" item="ruleProfileUuid" separator="," open="(" close=")">#{ruleProfileUuid, jdbcType=VARCHAR}</foreach> </select> + <select id="selectPrioritizedRulesUuids" parameterType="map" resultType="string"> + select ar.rule_uuid + from active_rules ar + inner join rules_profiles rp on rp.uuid = ar.profile_uuid + inner join org_qprofiles oq on oq.rules_profile_uuid = rp.uuid + and oq.uuid in + <foreach item="qprofile_uuid" collection="ruleProfileUuids" open="(" separator="," close=")"> + #{qprofile_uuid, jdbcType=VARCHAR} + </foreach> + <include refid="isPrioritizedRule"/> + </select> + + <sql id="isPrioritizedRule" databaseId="mssql"> + where ar.prioritized_rule = 1 + </sql> + <sql id="isPrioritizedRule" databaseId="oracle"> + where ar.prioritized_rule = 1 + </sql> + <sql id="isPrioritizedRule"> + where ar.prioritized_rule = true + </sql> + + <select id="selectOrgByRuleUuid" parameterType="map" resultType="org.sonar.db.qualityprofile.OrgActiveRuleDto"> select <include refid="orgActiveRuleColumns"/> |