From 32892cadf93a903df4fea8e61518c04c6bd69ad5 Mon Sep 17 00:00:00 2001 From: OrlovAlexander <35396155+OrlovAlexander85@users.noreply.github.com> Date: Fri, 31 May 2024 10:05:52 +0200 Subject: [PATCH] SONAR-22224 update api activate_rule, activate_rules --- .../db/qualityprofile/ActiveRuleDto.java | 4 +- .../qualityprofile/ActiveRuleChange.java | 12 ++ .../server/qualityprofile/QProfileRules.java | 3 +- .../server/qualityprofile/RuleActivation.java | 21 ++- .../qualityprofile/QProfileRuleImplIT.java | 156 ++++++++++-------- .../qualityprofile/QProfileRulesImplIT.java | 28 ++-- .../builtin/RuleActivatorIT.java | 94 ++++++----- .../ws/ActivateRuleActionIT.java | 39 +++-- .../ws/ActivateRulesActionIT.java | 31 ++-- .../qualityprofile/QProfileRulesImpl.java | 5 +- .../qualityprofile/builtin/RuleActivator.java | 103 +++++++++--- .../qualityprofile/ws/ActivateRuleAction.java | 16 +- .../ws/ActivateRulesAction.java | 10 +- .../QualityProfileWsParameters.java | 1 + 14 files changed, 327 insertions(+), 196 deletions(-) diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/qualityprofile/ActiveRuleDto.java b/server/sonar-db-dao/src/main/java/org/sonar/db/qualityprofile/ActiveRuleDto.java index c69dea3971a..96f8b1617a1 100644 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/qualityprofile/ActiveRuleDto.java +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/qualityprofile/ActiveRuleDto.java @@ -174,8 +174,8 @@ public class ActiveRuleDto { return prioritizedRule; } - public ActiveRuleDto setPrioritizedRule(boolean isBlockerRule){ - this.prioritizedRule = isBlockerRule; + public ActiveRuleDto setPrioritizedRule(boolean prioritizedRule){ + this.prioritizedRule = prioritizedRule; return this; } diff --git a/server/sonar-server-common/src/main/java/org/sonar/server/qualityprofile/ActiveRuleChange.java b/server/sonar-server-common/src/main/java/org/sonar/server/qualityprofile/ActiveRuleChange.java index f91396cf486..65412f21a66 100644 --- a/server/sonar-server-common/src/main/java/org/sonar/server/qualityprofile/ActiveRuleChange.java +++ b/server/sonar-server-common/src/main/java/org/sonar/server/qualityprofile/ActiveRuleChange.java @@ -42,6 +42,7 @@ public class ActiveRuleChange { private final ActiveRuleKey key; private final String ruleUuid; private String severity = null; + private Boolean prioritizedRule = null; private ActiveRuleInheritance inheritance = null; private final Map parameters = new HashMap<>(); @@ -80,6 +81,16 @@ public class ActiveRuleChange { return this; } + public ActiveRuleChange setPrioritizedRule(@Nullable Boolean prioritizedRule){ + this.prioritizedRule = prioritizedRule; + return this; + } + + @CheckForNull + public Boolean isPrioritizedRule(){ + return prioritizedRule; + } + public ActiveRuleChange setInheritance(@Nullable ActiveRuleInheritance i) { this.inheritance = i; return this; @@ -147,6 +158,7 @@ public class ActiveRuleChange { .add("severity", severity) .add("inheritance", inheritance) .add("parameters", parameters) + .add("prioritizedRule", prioritizedRule) .toString(); } } diff --git a/server/sonar-webserver-api/src/main/java/org/sonar/server/qualityprofile/QProfileRules.java b/server/sonar-webserver-api/src/main/java/org/sonar/server/qualityprofile/QProfileRules.java index 660574f1f27..48d0f2864a1 100644 --- a/server/sonar-webserver-api/src/main/java/org/sonar/server/qualityprofile/QProfileRules.java +++ b/server/sonar-webserver-api/src/main/java/org/sonar/server/qualityprofile/QProfileRules.java @@ -50,7 +50,8 @@ public interface QProfileRules { * - rules are activated with default parameters * - an activation failure does not break others. No exception is thrown. */ - BulkChangeResult bulkActivateAndCommit(DbSession dbSession, QProfileDto profile, RuleQuery ruleQuery, @Nullable String severity); + BulkChangeResult bulkActivateAndCommit(DbSession dbSession, QProfileDto profile, RuleQuery ruleQuery, @Nullable String severity, + @Nullable Boolean prioritizedRule); List deactivateAndCommit(DbSession dbSession, QProfileDto profile, Collection ruleUuids); diff --git a/server/sonar-webserver-api/src/main/java/org/sonar/server/qualityprofile/RuleActivation.java b/server/sonar-webserver-api/src/main/java/org/sonar/server/qualityprofile/RuleActivation.java index 75aef5fca71..46abd860e6a 100644 --- a/server/sonar-webserver-api/src/main/java/org/sonar/server/qualityprofile/RuleActivation.java +++ b/server/sonar-webserver-api/src/main/java/org/sonar/server/qualityprofile/RuleActivation.java @@ -36,12 +36,15 @@ public class RuleActivation { private final String ruleUuid; private final boolean reset; private final String severity; + private final Boolean prioritizedRule; private final Map parameters = new HashMap<>(); - private RuleActivation(String ruleUuid, boolean reset, @Nullable String severity, @Nullable Map parameters) { + private RuleActivation(String ruleUuid, boolean reset, @Nullable String severity, @Nullable Boolean prioritizedRule, @Nullable Map parameters) { this.ruleUuid = ruleUuid; this.reset = reset; this.severity = severity; + this.prioritizedRule = prioritizedRule; if (severity != null && !Severity.ALL.contains(severity)) { throw new IllegalArgumentException("Unknown severity: " + severity); } @@ -53,15 +56,20 @@ public class RuleActivation { } public static RuleActivation createReset(String ruleUuid) { - return new RuleActivation(ruleUuid, true, null, null); + return new RuleActivation(ruleUuid, true, null, null, null); + } + + public static RuleActivation create(String ruleUuid, @Nullable String severity, @Nullable Boolean prioritizedRule, + @Nullable Map parameters) { + return new RuleActivation(ruleUuid, false, severity, prioritizedRule, parameters); } public static RuleActivation create(String ruleUuid, @Nullable String severity, @Nullable Map parameters) { - return new RuleActivation(ruleUuid, false, severity, parameters); + return create(ruleUuid, severity, null, parameters); } public static RuleActivation create(String ruleUuid) { - return create(ruleUuid, null, null); + return create(ruleUuid, null, null, null); } /** @@ -88,4 +96,9 @@ public class RuleActivation { public boolean isReset() { return reset; } + + @CheckForNull + public Boolean isPrioritizedRule() { + return prioritizedRule; + } } diff --git a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/qualityprofile/QProfileRuleImplIT.java b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/qualityprofile/QProfileRuleImplIT.java index 4a7f1c31d4c..a35fe2ade7f 100644 --- a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/qualityprofile/QProfileRuleImplIT.java +++ b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/qualityprofile/QProfileRuleImplIT.java @@ -27,8 +27,8 @@ import java.util.Optional; import java.util.Random; import java.util.stream.IntStream; import javax.annotation.Nullable; -import org.junit.Rule; -import org.junit.Test; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; import org.mockito.Mockito; import org.sonar.api.PropertyType; import org.sonar.api.config.Configuration; @@ -59,11 +59,13 @@ import org.sonar.server.util.IntegerTypeValidation; import org.sonar.server.util.StringTypeValidation; import org.sonar.server.util.TypeValidations; -import static com.google.common.collect.ImmutableMap.of; import static java.util.Arrays.asList; import static java.util.Collections.emptyMap; import static java.util.Collections.singleton; import static java.util.Collections.singletonList; +import static java.util.Map.entry; +import static java.util.Map.of; +import static java.util.Map.ofEntries; import static org.apache.commons.lang3.RandomStringUtils.randomAlphanumeric; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; @@ -81,14 +83,14 @@ import static org.sonar.db.rule.RuleTesting.newCustomRule; import static org.sonar.server.qualityprofile.ActiveRuleInheritance.INHERITED; import static org.sonar.server.qualityprofile.ActiveRuleInheritance.OVERRIDES; -public class QProfileRuleImplIT { +class QProfileRuleImplIT { private System2 system2 = new AlwaysIncreasingSystem2(); - @Rule + @RegisterExtension public DbTester db = DbTester.create(system2); - @Rule + @RegisterExtension public EsTester es = EsTester.create(); - @Rule + @RegisterExtension public UserSessionRule userSession = UserSessionRule.standalone(); private RuleIndex ruleIndex = new RuleIndex(es.client(), system2); private ActiveRuleIndexer activeRuleIndexer = new ActiveRuleIndexer(db.getDbClient(), es.client()); @@ -98,11 +100,13 @@ public class QProfileRuleImplIT { private Configuration configuration = mock(Configuration.class); private final SonarQubeVersion sonarQubeVersion = new SonarQubeVersion(Version.create(10, 3)); - private RuleActivator ruleActivator = new RuleActivator(system2, db.getDbClient(), typeValidations, userSession, configuration, sonarQubeVersion); - private QProfileRules underTest = new QProfileRulesImpl(db.getDbClient(), ruleActivator, ruleIndex, activeRuleIndexer, qualityProfileChangeEventService); + private RuleActivator ruleActivator = new RuleActivator(system2, db.getDbClient(), typeValidations, userSession, configuration, + sonarQubeVersion); + private QProfileRules underTest = new QProfileRulesImpl(db.getDbClient(), ruleActivator, ruleIndex, activeRuleIndexer, + qualityProfileChangeEventService); @Test - public void system_activates_rule_without_parameters() { + void system_activates_rule_without_parameters() { RuleDto rule = createRule(); QProfileDto profile = createProfile(rule); RuleActivation activation = RuleActivation.create(rule.getUuid(), BLOCKER, null); @@ -114,7 +118,7 @@ public class QProfileRuleImplIT { } @Test - public void user_activates_rule_without_parameters() { + void user_activates_rule_without_parameters() { userSession.logIn(); RuleDto rule = createRule(); QProfileDto profile = createProfile(rule); @@ -127,7 +131,7 @@ public class QProfileRuleImplIT { } @Test - public void activate_rule_with_default_severity_and_parameters() { + void activate_rule_with_default_severity_and_parameters() { RuleDto rule = createRule(); RuleParamDto ruleParam = db.rules().insertRuleParam(rule, p -> p.setName("min").setDefaultValue("10")); QProfileDto profile = createProfile(rule); @@ -135,13 +139,13 @@ public class QProfileRuleImplIT { RuleActivation activation = RuleActivation.create(rule.getUuid()); List changes = activate(profile, activation); - assertThatRuleIsActivated(profile, rule, changes, rule.getSeverityString(), null, of("min", "10")); + assertThatRuleIsActivated(profile, rule, changes, rule.getSeverityString(), null, ofEntries(entry("min", "10"))); assertThatProfileIsUpdatedBySystem(profile); verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), any(), eq(profile.getLanguage())); } @Test - public void activate_rule_with_parameters() { + void activate_rule_with_parameters() { RuleDto rule = createRule(); RuleParamDto ruleParam = db.rules().insertRuleParam(rule, p -> p.setName("min").setDefaultValue("10")); QProfileDto profile = createProfile(rule); @@ -155,7 +159,7 @@ public class QProfileRuleImplIT { } @Test - public void activate_rule_with_default_severity() { + void activate_rule_with_default_severity() { RuleDto rule = createRule(); QProfileDto profile = createProfile(rule); @@ -171,7 +175,7 @@ public class QProfileRuleImplIT { * SONAR-5841 */ @Test - public void activate_rule_with_empty_parameter_having_no_default_value() { + void activate_rule_with_empty_parameter_having_no_default_value() { RuleDto rule = createRule(); RuleParamDto ruleParam = db.rules().insertRuleParam(rule, p -> p.setName("min").setDefaultValue("10")); QProfileDto profile = createProfile(rule); @@ -189,7 +193,7 @@ public class QProfileRuleImplIT { * // */ @Test - public void activate_rule_with_negative_integer_value_on_parameter_having_no_default_value() { + void activate_rule_with_negative_integer_value_on_parameter_having_no_default_value() { RuleDto rule = createRule(); RuleParamDto paramWithoutDefault = db.rules().insertRuleParam(rule, p -> p.setName("min").setDefaultValue(null)); RuleParamDto paramWithDefault = db.rules().insertRuleParam(rule, p -> p.setName("max").setDefaultValue("10")); @@ -205,7 +209,7 @@ public class QProfileRuleImplIT { } @Test - public void activation_ignores_unsupported_parameters() { + void activation_ignores_unsupported_parameters() { RuleDto rule = createRule(); RuleParamDto param = db.rules().insertRuleParam(rule, p -> p.setName("max").setDefaultValue("10")); QProfileDto profile = createProfile(rule); @@ -219,7 +223,7 @@ public class QProfileRuleImplIT { } @Test - public void update_an_already_activated_rule() { + void update_an_already_activated_rule() { RuleDto rule = createRule(); RuleParamDto param = db.rules().insertRuleParam(rule, p -> p.setName("max").setDefaultValue("10")); QProfileDto profile = createProfile(rule); @@ -239,7 +243,7 @@ public class QProfileRuleImplIT { } @Test - public void update_activation_with_parameter_without_default_value() { + void update_activation_with_parameter_without_default_value() { RuleDto rule = createRule(); RuleParamDto paramWithoutDefault = db.rules().insertRuleParam(rule, p -> p.setName("min").setDefaultValue(null)); RuleParamDto paramWithDefault = db.rules().insertRuleParam(rule, p -> p.setName("max").setDefaultValue("10")); @@ -260,7 +264,7 @@ public class QProfileRuleImplIT { } @Test - public void reset_parameter_to_default_value() { + void reset_parameter_to_default_value() { RuleDto rule = createRule(); RuleParamDto paramWithDefault = db.rules().insertRuleParam(rule, p -> p.setName("max").setDefaultValue("10")); QProfileDto profile = createProfile(rule); @@ -280,7 +284,7 @@ public class QProfileRuleImplIT { } @Test - public void update_activation_removes_parameter_without_default_value() { + void update_activation_removes_parameter_without_default_value() { RuleDto rule = createRule(); RuleParamDto paramWithoutDefault = db.rules().insertRuleParam(rule, p -> p.setName("min").setDefaultValue(null)); RuleParamDto paramWithDefault = db.rules().insertRuleParam(rule, p -> p.setName("max").setDefaultValue("10")); @@ -295,13 +299,14 @@ public class QProfileRuleImplIT { RuleActivation updateActivation = RuleActivation.create(rule.getUuid(), null, of(paramWithoutDefault.getName(), "")); changes = activate(profile, updateActivation); - assertThatRuleIsUpdated(profile, rule, rule.getSeverityString(), null, of(paramWithDefault.getName(), paramWithDefault.getDefaultValue())); + assertThatRuleIsUpdated(profile, rule, rule.getSeverityString(), null, of(paramWithDefault.getName(), + paramWithDefault.getDefaultValue())); assertThat(changes).hasSize(1); verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), eq(changes), eq(profile.getLanguage())); } @Test - public void update_activation_with_new_parameter() { + void update_activation_with_new_parameter() { RuleDto rule = createRule(); RuleParamDto param = db.rules().insertRuleParam(rule, p -> p.setName("max").setDefaultValue("10")); QProfileDto profile = createProfile(rule); @@ -323,7 +328,7 @@ public class QProfileRuleImplIT { } @Test - public void ignore_activation_without_changes() { + void ignore_activation_without_changes() { RuleDto rule = createRule(); QProfileDto profile = createProfile(rule); @@ -341,7 +346,7 @@ public class QProfileRuleImplIT { } @Test - public void do_not_change_severity_and_params_if_unset_and_already_activated() { + void do_not_change_severity_and_params_if_unset_and_already_activated() { RuleDto rule = createRule(); RuleParamDto param = db.rules().insertRuleParam(rule, p -> p.setName("max").setDefaultValue("10")); QProfileDto profile = createProfile(rule); @@ -361,17 +366,18 @@ public class QProfileRuleImplIT { } @Test - public void fail_to_activate_rule_if_profile_is_on_different_languages() { + void fail_to_activate_rule_if_profile_is_on_different_languages() { RuleDto rule = createJavaRule(); QProfileDto profile = db.qualityProfiles().insert(p -> p.setLanguage("js")); RuleActivation activation = RuleActivation.create(rule.getUuid()); - expectFailure("java rule " + rule.getKey() + " cannot be activated on js profile " + profile.getKee(), () -> activate(profile, activation)); + expectFailure("java rule " + rule.getKey() + " cannot be activated on js profile " + profile.getKee(), () -> activate(profile, + activation)); verifyNoInteractions(qualityProfileChangeEventService); } @Test - public void fail_to_activate_rule_if_rule_has_REMOVED_status() { + void fail_to_activate_rule_if_rule_has_REMOVED_status() { RuleDto rule = db.rules().insert(r -> r.setStatus(RuleStatus.REMOVED)); QProfileDto profile = createProfile(rule); RuleActivation activation = RuleActivation.create(rule.getUuid()); @@ -381,7 +387,7 @@ public class QProfileRuleImplIT { } @Test - public void fail_to_activate_if_template() { + void fail_to_activate_if_template() { RuleDto rule = db.rules().insert(r -> r.setIsTemplate(true)); QProfileDto profile = createProfile(rule); RuleActivation activation = RuleActivation.create(rule.getUuid()); @@ -391,7 +397,7 @@ public class QProfileRuleImplIT { } @Test - public void fail_to_activate_if_invalid_parameter() { + void fail_to_activate_if_invalid_parameter() { RuleDto rule = createRule(); RuleParamDto param = db.rules().insertRuleParam(rule, p -> p.setName("max").setDefaultValue("10").setType(PropertyType.INTEGER.name())); QProfileDto profile = createProfile(rule); @@ -402,7 +408,7 @@ public class QProfileRuleImplIT { } @Test - public void ignore_parameters_when_activating_custom_rule() { + void ignore_parameters_when_activating_custom_rule() { RuleDto templateRule = db.rules().insert(r -> r.setIsTemplate(true)); RuleParamDto templateParam = db.rules().insertRuleParam(templateRule, p -> p.setName("format")); RuleDto customRule = db.rules().insert(newCustomRule(templateRule)); @@ -423,7 +429,7 @@ public class QProfileRuleImplIT { } @Test - public void user_deactivates_a_rule() { + void user_deactivates_a_rule() { userSession.logIn(); RuleDto rule = createRule(); QProfileDto profile = createProfile(rule); @@ -440,7 +446,7 @@ public class QProfileRuleImplIT { } @Test - public void system_deactivates_a_rule() { + void system_deactivates_a_rule() { RuleDto rule = createRule(); QProfileDto profile = createProfile(rule); RuleActivation activation = RuleActivation.create(rule.getUuid()); @@ -462,7 +468,7 @@ public class QProfileRuleImplIT { } @Test - public void ignore_deactivation_if_rule_is_not_activated() { + void ignore_deactivation_if_rule_is_not_activated() { RuleDto rule = createRule(); QProfileDto profile = createProfile(rule); @@ -473,7 +479,7 @@ public class QProfileRuleImplIT { } @Test - public void deactivate_rule_that_has_REMOVED_status() { + void deactivate_rule_that_has_REMOVED_status() { RuleDto rule = createRule(); QProfileDto profile = createProfile(rule); RuleActivation activation = RuleActivation.create(rule.getUuid()); @@ -490,7 +496,7 @@ public class QProfileRuleImplIT { } @Test - public void activate_shouldPropagateActivationOnChildren() { + void activate_shouldPropagateActivationOnChildren() { RuleDto rule = createRule(); QProfileDto parentProfile = createProfile(rule); QProfileDto childProfile = createChildProfile(parentProfile); @@ -504,7 +510,7 @@ public class QProfileRuleImplIT { } @Test - public void activate_whenChildProfileAlreadyActivatedRule_shouldNotStopPropagating() { + void activate_whenChildProfileAlreadyActivatedRule_shouldNotStopPropagating() { RuleDto rule = createRule(); QProfileDto parentProfile = createProfile(rule); QProfileDto childProfile = createChildProfile(parentProfile); @@ -530,7 +536,7 @@ public class QProfileRuleImplIT { } @Test - public void activate_whenChildAlreadyActivatedRuleWithOverriddenValues_shouldNotOverrideValues() { + void activate_whenChildAlreadyActivatedRuleWithOverriddenValues_shouldNotOverrideValues() { RuleDto rule = createRule(); QProfileDto parentProfile = createProfile(rule); QProfileDto childProfile = createChildProfile(parentProfile); @@ -552,7 +558,7 @@ public class QProfileRuleImplIT { } @Test - public void activate_whenParentHasRuleWithSameValues_shouldMarkInherited() { + void activate_whenParentHasRuleWithSameValues_shouldMarkInherited() { RuleDto rule = createRule(); QProfileDto parentProfile = createProfile(rule); QProfileDto childProfile = createChildProfile(parentProfile); @@ -568,7 +574,7 @@ public class QProfileRuleImplIT { } @Test - public void activate_whenParentHasRuleWithDifferentValues_shouldMarkOverridden() { + void activate_whenParentHasRuleWithDifferentValues_shouldMarkOverridden() { RuleDto rule = createRule(); QProfileDto parentProfile = createProfile(rule); QProfileDto childProfile = createChildProfile(parentProfile); @@ -584,7 +590,7 @@ public class QProfileRuleImplIT { } @Test - public void update_on_child_profile_is_propagated_to_descendants() { + void update_on_child_profile_is_propagated_to_descendants() { RuleDto rule = createRule(); RuleParamDto param = db.rules().insertRuleParam(rule); QProfileDto parentProfile = createProfile(rule); @@ -610,7 +616,7 @@ public class QProfileRuleImplIT { } @Test - public void override_activation_of_inherited_profile() { + void override_activation_of_inherited_profile() { RuleDto rule = createRule(); RuleParamDto param = db.rules().insertRuleParam(rule); QProfileDto parentProfile = createProfile(rule); @@ -632,7 +638,7 @@ public class QProfileRuleImplIT { } @Test - public void updated_activation_on_parent_is_not_propagated_to_overridden_profiles() { + void updated_activation_on_parent_is_not_propagated_to_overridden_profiles() { RuleDto rule = createRule(); RuleParamDto param = db.rules().insertRuleParam(rule); QProfileDto parentProfile = createProfile(rule); @@ -659,7 +665,7 @@ public class QProfileRuleImplIT { } @Test - public void reset_on_parent_is_not_propagated_to_overridden_profiles() { + void reset_on_parent_is_not_propagated_to_overridden_profiles() { RuleDto rule = createRule(); RuleParamDto param = db.rules().insertRuleParam(rule); QProfileDto parentProfile = createProfile(rule); @@ -688,7 +694,7 @@ public class QProfileRuleImplIT { } @Test - public void activate_whenRuleAlreadyActiveOnChildWithDifferentValues_shouldMarkOverridden() { + void activate_whenRuleAlreadyActiveOnChildWithDifferentValues_shouldMarkOverridden() { RuleDto rule = createRule(); RuleParamDto param = db.rules().insertRuleParam(rule); QProfileDto parentProfile = createProfile(rule); @@ -708,7 +714,7 @@ public class QProfileRuleImplIT { } @Test - public void activate_whenRuleAlreadyActiveOnChildWithSameValues_shouldMarkInherited() { + void activate_whenRuleAlreadyActiveOnChildWithSameValues_shouldMarkInherited() { RuleDto rule = createRule(); RuleParamDto param = db.rules().insertRuleParam(rule); QProfileDto parentProfile = createProfile(rule); @@ -728,7 +734,7 @@ public class QProfileRuleImplIT { } @Test - public void activate_whenSettingValuesOnChildAndParentHasSameValues_shouldMarkInherited() { + void activate_whenSettingValuesOnChildAndParentHasSameValues_shouldMarkInherited() { RuleDto rule = createRule(); RuleParamDto param = db.rules().insertRuleParam(rule); QProfileDto parentProfile = createProfile(rule); @@ -747,7 +753,7 @@ public class QProfileRuleImplIT { } @Test - public void activate_whenSettingValuesOnChildAndParentHasDifferentValues_shouldMarkOverridden() { + void activate_whenSettingValuesOnChildAndParentHasDifferentValues_shouldMarkOverridden() { RuleDto rule = createRule(); RuleParamDto param = db.rules().insertRuleParam(rule); QProfileDto parentProfile = createProfile(rule); @@ -766,7 +772,7 @@ public class QProfileRuleImplIT { } @Test - public void deactivate_shouldPropagateDeactivationOnChildren() { + void deactivate_shouldPropagateDeactivationOnChildren() { RuleDto rule = createRule(); QProfileDto parentProfile = createProfile(rule); QProfileDto childProfile = createChildProfile(parentProfile); @@ -785,7 +791,7 @@ public class QProfileRuleImplIT { } @Test - public void deactivate_whenChildAlreadyDeactivatedRule_shouldNotStopPropagating() { + void deactivate_whenChildAlreadyDeactivatedRule_shouldNotStopPropagating() { RuleDto rule = createRule(); QProfileDto parentProfile = createProfile(rule); QProfileDto childProfile = createChildProfile(parentProfile); @@ -816,7 +822,7 @@ public class QProfileRuleImplIT { } @Test - public void deactivate_whenChildOverridesRule_shouldPropagateDeactivation() { + void deactivate_whenChildOverridesRule_shouldPropagateDeactivation() { RuleDto rule = createRule(); QProfileDto parentProfile = createProfile(rule); QProfileDto childProfile = createChildProfile(parentProfile); @@ -840,7 +846,7 @@ public class QProfileRuleImplIT { } @Test - public void deactivate_whenRuleInherited_canBeDeactivated() { + void deactivate_whenRuleInherited_canBeDeactivated() { RuleDto rule = createRule(); QProfileDto parentProfile = createProfile(rule); QProfileDto childProfile = createChildProfile(parentProfile); @@ -857,7 +863,7 @@ public class QProfileRuleImplIT { } @Test - public void deactivate_whenRuleInheritedAndPropertyDisabled_cannotBeDeactivated() { + void deactivate_whenRuleInheritedAndPropertyDisabled_cannotBeDeactivated() { Mockito.when(configuration.getBoolean(CorePropertyDefinitions.ALLOW_DISABLE_INHERITED_RULES)).thenReturn(Optional.of(false)); RuleDto rule = createRule(); @@ -876,7 +882,7 @@ public class QProfileRuleImplIT { } @Test - public void reset_child_profile_do_not_change_parent() { + void reset_child_profile_do_not_change_parent() { RuleDto rule = createRule(); QProfileDto parentProfile = createProfile(rule); QProfileDto childProfile = createChildProfile(parentProfile); @@ -901,7 +907,7 @@ public class QProfileRuleImplIT { } @Test - public void reset_parent_is_not_propagated_when_child_overrides() { + void reset_parent_is_not_propagated_when_child_overrides() { RuleDto rule = createRule(); QProfileDto baseProfile = createProfile(rule); QProfileDto childProfile = createChildProfile(baseProfile); @@ -938,7 +944,7 @@ public class QProfileRuleImplIT { } @Test - public void ignore_reset_if_not_activated() { + void ignore_reset_if_not_activated() { RuleDto rule = createRule(); QProfileDto parentProfile = createProfile(rule); createChildProfile(parentProfile); @@ -950,7 +956,7 @@ public class QProfileRuleImplIT { } @Test - public void bulk_activation() { + void bulk_activation() { int bulkSize = SearchOptions.MAX_PAGE_SIZE + 10 + new Random().nextInt(100); String language = randomAlphanumeric(10); String repositoryKey = randomAlphanumeric(10); @@ -966,17 +972,17 @@ public class QProfileRuleImplIT { RuleQuery ruleQuery = new RuleQuery() .setRepositories(singletonList(repositoryKey)); - BulkChangeResult bulkChangeResult = underTest.bulkActivateAndCommit(db.getSession(), profile, ruleQuery, MINOR); + BulkChangeResult bulkChangeResult = underTest.bulkActivateAndCommit(db.getSession(), profile, ruleQuery, MINOR, true); assertThat(bulkChangeResult.countFailed()).isZero(); assertThat(bulkChangeResult.countSucceeded()).isEqualTo(bulkSize); assertThat(bulkChangeResult.getChanges()).hasSize(bulkSize); assertThat(db.getDbClient().activeRuleDao().selectByProfile(db.getSession(), profile)).hasSize(bulkSize); - rules.forEach(r -> assertThatRuleIsActivated(profile, r, null, MINOR, null, emptyMap())); + rules.forEach(r -> assertThatRuleIsActivated(profile, r, null, MINOR, true, null, emptyMap())); } @Test - public void bulk_deactivation() { + void bulk_deactivation() { int bulkSize = SearchOptions.MAX_PAGE_SIZE + 10 + new Random().nextInt(100); String language = randomAlphanumeric(10); String repositoryKey = randomAlphanumeric(10); @@ -992,7 +998,7 @@ public class QProfileRuleImplIT { RuleQuery ruleQuery = new RuleQuery() .setRepositories(singletonList(repositoryKey)); - BulkChangeResult bulkChangeResult = underTest.bulkActivateAndCommit(db.getSession(), profile, ruleQuery, MINOR); + BulkChangeResult bulkChangeResult = underTest.bulkActivateAndCommit(db.getSession(), profile, ruleQuery, MINOR, null); assertThat(bulkChangeResult.countFailed()).isZero(); assertThat(bulkChangeResult.countSucceeded()).isEqualTo(bulkSize); @@ -1010,7 +1016,7 @@ public class QProfileRuleImplIT { } @Test - public void bulkDeactivateAndCommit_whenRuleInherited_canBeDeactivated() { + void bulkDeactivateAndCommit_whenRuleInherited_canBeDeactivated() { RuleDto rule = createRule(); QProfileDto parentProfile = createProfile(rule); QProfileDto childProfile = createChildProfile(parentProfile); @@ -1032,7 +1038,7 @@ public class QProfileRuleImplIT { } @Test - public void bulk_change_severity() { + void bulk_change_severity_and_prioritized_rule() { RuleDto rule1 = createJavaRule(); RuleDto rule2 = createJavaRule(); QProfileDto parentProfile = createProfile(rule1); @@ -1047,16 +1053,16 @@ public class QProfileRuleImplIT { RuleQuery query = new RuleQuery() .setRuleKey(rule1.getRuleKey()) .setQProfile(parentProfile); - BulkChangeResult result = underTest.bulkActivateAndCommit(db.getSession(), parentProfile, query, "BLOCKER"); + BulkChangeResult result = underTest.bulkActivateAndCommit(db.getSession(), parentProfile, query, "BLOCKER", true); assertThat(result.getChanges()).hasSize(3); assertThat(result.countSucceeded()).isOne(); assertThat(result.countFailed()).isZero(); // Rule1 must be activated with BLOCKER on all profiles - assertThatRuleIsActivated(parentProfile, rule1, null, BLOCKER, null, emptyMap()); - assertThatRuleIsActivated(childProfile, rule1, null, BLOCKER, INHERITED, emptyMap()); - assertThatRuleIsActivated(grandchildProfile, rule1, null, BLOCKER, INHERITED, emptyMap()); + assertThatRuleIsActivated(parentProfile, rule1, null, BLOCKER, true, null, emptyMap()); + assertThatRuleIsActivated(childProfile, rule1, null, BLOCKER, true, INHERITED, emptyMap()); + assertThatRuleIsActivated(grandchildProfile, rule1, null, BLOCKER, true, INHERITED, emptyMap()); // Rule2 did not changed assertThatRuleIsActivated(parentProfile, rule2, null, rule2.getSeverityString(), null, emptyMap()); @@ -1065,7 +1071,7 @@ public class QProfileRuleImplIT { } @Test - public void delete_rule_from_all_profiles() { + void delete_rule_from_all_profiles() { RuleDto rule = createRule(); QProfileDto parentProfile = createProfile(rule); QProfileDto childProfile = createChildProfile(parentProfile); @@ -1090,7 +1096,7 @@ public class QProfileRuleImplIT { } @Test - public void activation_fails_when_profile_is_built_in() { + void activation_fails_when_profile_is_built_in() { RuleDto rule = createRule(); QProfileDto builtInProfile = db.qualityProfiles().insert(p -> p.setLanguage(rule.getLanguage()).setIsBuiltIn(true)); @@ -1138,7 +1144,8 @@ public class QProfileRuleImplIT { } private void assertThatRuleIsActivated(QProfileDto profile, RuleDto rule, @Nullable List changes, - String expectedSeverity, @Nullable ActiveRuleInheritance expectedInheritance, Map expectedParams) { + String expectedSeverity, boolean expectedPrioritizedRule, @Nullable ActiveRuleInheritance expectedInheritance, + Map expectedParams) { OrgActiveRuleDto activeRule = db.getDbClient().activeRuleDao().selectByProfile(db.getSession(), profile) .stream() .filter(ar -> ar.getRuleKey().equals(rule.getKey())) @@ -1146,6 +1153,7 @@ public class QProfileRuleImplIT { .orElseThrow(IllegalStateException::new); assertThat(activeRule.getSeverityString()).isEqualTo(expectedSeverity); + assertThat(activeRule.isPrioritizedRule()).isEqualTo(expectedPrioritizedRule); assertThat(activeRule.getInheritance()).isEqualTo(expectedInheritance != null ? expectedInheritance.name() : null); List params = db.getDbClient().activeRuleDao().selectParamsByActiveRuleUuid(db.getSession(), activeRule.getUuid()); @@ -1157,10 +1165,16 @@ public class QProfileRuleImplIT { .findFirst().orElseThrow(IllegalStateException::new); assertThat(change.getInheritance()).isEqualTo(expectedInheritance); assertThat(change.getSeverity()).isEqualTo(expectedSeverity); + assertThat(change.isPrioritizedRule()).isEqualTo(expectedPrioritizedRule); assertThat(change.getType()).isEqualTo(ActiveRuleChange.Type.ACTIVATED); } } + private void assertThatRuleIsActivated(QProfileDto profile, RuleDto rule, @Nullable List changes, + String expectedSeverity, @Nullable ActiveRuleInheritance expectedInheritance, Map expectedParams) { + assertThatRuleIsActivated(profile, rule, changes, expectedSeverity, false, expectedInheritance, expectedParams); + } + private void assertThatRuleIsNotPresent(QProfileDto profile, RuleDto rule) { Optional activeRule = db.getDbClient().activeRuleDao().selectByProfile(db.getSession(), profile) .stream() diff --git a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/qualityprofile/QProfileRulesImplIT.java b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/qualityprofile/QProfileRulesImplIT.java index fb356c6a4a3..5e20312caef 100644 --- a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/qualityprofile/QProfileRulesImplIT.java +++ b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/qualityprofile/QProfileRulesImplIT.java @@ -21,8 +21,8 @@ package org.sonar.server.qualityprofile; import com.google.common.collect.ImmutableMap; import java.util.Collections; -import org.junit.Rule; -import org.junit.Test; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; import org.sonar.api.config.Configuration; import org.sonar.api.rule.Severity; import org.sonar.api.utils.System2; @@ -53,40 +53,42 @@ import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; -public class QProfileRulesImplIT { +class QProfileRulesImplIT { - @Rule + @RegisterExtension public UserSessionRule userSession = UserSessionRule.standalone(); - @Rule + @RegisterExtension public DbTester db = DbTester.create(); - @Rule + @RegisterExtension public EsTester es = EsTester.create(); private RuleIndex ruleIndex = new RuleIndex(es.client(), System2.INSTANCE); private ActiveRuleIndexer activeRuleIndexer = new ActiveRuleIndexer(db.getDbClient(), es.client()); private final SonarQubeVersion sonarQubeVersion = new SonarQubeVersion(Version.create(10, 3)); - private RuleActivator ruleActivator = new RuleActivator(System2.INSTANCE, db.getDbClient(), new TypeValidations(singletonList(new IntegerTypeValidation())), + private RuleActivator ruleActivator = new RuleActivator(System2.INSTANCE, db.getDbClient(), + new TypeValidations(singletonList(new IntegerTypeValidation())), userSession, mock(Configuration.class), sonarQubeVersion); private QualityProfileChangeEventService qualityProfileChangeEventService = mock(QualityProfileChangeEventService.class); - private QProfileRules qProfileRules = new QProfileRulesImpl(db.getDbClient(), ruleActivator, ruleIndex, activeRuleIndexer, qualityProfileChangeEventService); + private QProfileRules qProfileRules = new QProfileRulesImpl(db.getDbClient(), ruleActivator, ruleIndex, activeRuleIndexer, + qualityProfileChangeEventService); @Test - public void activate_one_rule() { + void activate_one_rule() { QProfileDto qProfile = db.qualityProfiles().insert(); RuleDto rule = db.rules().insert(r -> r.setLanguage(qProfile.getLanguage())); - RuleActivation ruleActivation = RuleActivation.create(rule.getUuid(), Severity.CRITICAL, Collections.emptyMap()); + RuleActivation ruleActivation = RuleActivation.create(rule.getUuid(), Severity.CRITICAL, true, Collections.emptyMap()); qProfileRules.activateAndCommit(db.getSession(), qProfile, singleton(ruleActivation)); assertThat(db.getDbClient().activeRuleDao().selectByProfile(db.getSession(), qProfile)) - .extracting(ActiveRuleDto::getRuleKey, ActiveRuleDto::getSeverityString) - .containsExactlyInAnyOrder(tuple(rule.getKey(), Severity.CRITICAL)); + .extracting(ActiveRuleDto::getRuleKey, ActiveRuleDto::getSeverityString, ActiveRuleDto::isPrioritizedRule) + .containsExactlyInAnyOrder(tuple(rule.getKey(), Severity.CRITICAL, true)); verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), any(), eq(qProfile.getLanguage())); } @Test - public void active_rule_change() { + void active_rule_change() { UserDto user = db.users().insertUser(); userSession.logIn(user); QProfileDto qProfile = db.qualityProfiles().insert(); diff --git a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/qualityprofile/builtin/RuleActivatorIT.java b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/qualityprofile/builtin/RuleActivatorIT.java index 91523d86ed5..01020319405 100644 --- a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/qualityprofile/builtin/RuleActivatorIT.java +++ b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/qualityprofile/builtin/RuleActivatorIT.java @@ -19,11 +19,10 @@ */ package org.sonar.server.qualityprofile.builtin; -import com.google.common.collect.ImmutableMap; import java.util.List; import javax.annotation.Nullable; -import org.junit.Rule; -import org.junit.Test; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; import org.sonar.api.config.Configuration; import org.sonar.api.impl.utils.TestSystem2; import org.sonar.api.rule.RuleKey; @@ -52,9 +51,11 @@ import org.sonar.server.util.IntegerTypeValidation; import org.sonar.server.util.StringTypeValidation; import org.sonar.server.util.TypeValidations; +import static java.lang.Boolean.TRUE; import static java.util.Arrays.asList; import static java.util.Collections.emptyList; import static java.util.Collections.singletonList; +import static java.util.Map.of; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.Assert.assertThrows; import static org.mockito.Mockito.mock; @@ -65,11 +66,11 @@ import static org.sonar.server.qualityprofile.ActiveRuleInheritance.OVERRIDES; * Class org.sonar.server.qualityprofile.builtin.RuleActivator is mostly covered in * org.sonar.server.qualityprofile.builtin.BuiltInQProfileUpdateImplTest */ -public class RuleActivatorIT { - @Rule +class RuleActivatorIT { + @RegisterExtension public final DbTester db = DbTester.create(); - @Rule + @RegisterExtension public final UserSessionRule userSession = UserSessionRule.standalone(); private static final long NOW = 1_000; @@ -79,21 +80,22 @@ public class RuleActivatorIT { private final QualityProfileChangeEventService qualityProfileChangeEventService = mock(QualityProfileChangeEventService.class); private final SonarQubeVersion sonarQubeVersion = new SonarQubeVersion(Version.create(10, 3)); - private final RuleActivator underTest = new RuleActivator(system2, db.getDbClient(), typeValidations, userSession, mock(Configuration.class), sonarQubeVersion); + private final RuleActivator underTest = new RuleActivator(system2, db.getDbClient(), typeValidations, userSession, + mock(Configuration.class), sonarQubeVersion); @Test - public void reset_overridden_active_rule() { + void reset_overridden_active_rule() { RuleDto rule = db.rules().insert(r -> r.setLanguage("xoo").setSeverity(Severity.BLOCKER)); RuleParamDto ruleParam = db.rules().insertRuleParam(rule, p -> p.setName("min").setDefaultValue("10")); QProfileDto parentProfile = db.qualityProfiles().insert(p -> p.setLanguage(rule.getLanguage()).setIsBuiltIn(true)); ActiveRuleDto parentActiveRuleDto = activateRuleInDb(RulesProfileDto.from(parentProfile), rule, - RulePriority.valueOf(Severity.BLOCKER), null); + RulePriority.valueOf(Severity.BLOCKER), false, null); ActiveRuleParamDto parentActiveRuleParam = activateRuleParamInDb(parentActiveRuleDto, ruleParam, "10"); QProfileDto childProfile = createChildProfile(parentProfile); ActiveRuleDto childActiveRuleDto = activateRuleInDb(RulesProfileDto.from(childProfile), rule, - RulePriority.valueOf(Severity.MINOR), OVERRIDES); + RulePriority.valueOf(Severity.MINOR), true, OVERRIDES); ActiveRuleParamDto childActiveRuleParam = activateRuleParamInDb(childActiveRuleDto, ruleParam, "15"); DbSession session = db.getSession(); @@ -112,45 +114,49 @@ public class RuleActivatorIT { List result = underTest.activate(session, resetRequest, context); assertThat(result).hasSize(1); - assertThat(result.get(0).getParameters()).containsEntry("min", "10"); - assertThat(result.get(0).getSeverity()).isEqualTo(Severity.BLOCKER); - assertThat(result.get(0).getInheritance()).isEqualTo(ActiveRuleInheritance.INHERITED); + ActiveRuleChange activeRuleResult = result.get(0); + assertThat(activeRuleResult.getParameters()).containsEntry("min", "10"); + assertThat(activeRuleResult.getSeverity()).isEqualTo(Severity.BLOCKER); + assertThat(activeRuleResult.isPrioritizedRule()).isFalse(); + assertThat(activeRuleResult.getInheritance()).isEqualTo(ActiveRuleInheritance.INHERITED); } @Test - public void request_new_severity_and_param_for_child_rule() { + void request_new_severity_and_prioritized_rule_and_param_for_child_rule() { RuleDto rule = db.rules().insert(r -> r.setLanguage("xoo").setSeverity(Severity.BLOCKER)); RuleParamDto ruleParam = db.rules().insertRuleParam(rule, p -> p.setName("min").setDefaultValue("10")); QProfileDto parentProfile = db.qualityProfiles().insert(p -> p.setLanguage(rule.getLanguage()).setIsBuiltIn(true)); ActiveRuleDto parentActiveRuleDto = activateRuleInDb(RulesProfileDto.from(parentProfile), rule, - RulePriority.valueOf(Severity.BLOCKER), null); + RulePriority.valueOf(Severity.BLOCKER), null, null); ActiveRuleParamDto parentActiveRuleParam = activateRuleParamInDb(parentActiveRuleDto, ruleParam, "10"); QProfileDto childProfile = createChildProfile(parentProfile); ActiveRuleDto childActiveRuleDto = activateRuleInDb(RulesProfileDto.from(childProfile), rule, - RulePriority.valueOf(Severity.BLOCKER), INHERITED); + RulePriority.valueOf(Severity.BLOCKER), null, INHERITED); ActiveRuleParamDto childActiveRuleParam = activateRuleParamInDb(childActiveRuleDto, ruleParam, "10"); DbSession session = db.getSession(); - RuleActivation resetRequest = RuleActivation.create(rule.getUuid(), Severity.MINOR, ImmutableMap.of("min", "15")); + RuleActivation resetRequest = RuleActivation.create(rule.getUuid(), Severity.MINOR, true, of("min", "15")); RuleActivationContext context = new RuleActivationContext.Builder() - .setProfiles(asList(parentProfile, childProfile)) - .setBaseProfile(RulesProfileDto.from(childProfile)) - .setDate(NOW) - .setDescendantProfilesSupplier((profiles, ruleUuids) -> new Result(emptyList(), emptyList(), emptyList())) - .setRules(singletonList(rule)) - .setRuleParams(singletonList(ruleParam)) - .setActiveRules(asList(parentActiveRuleDto, childActiveRuleDto)) - .setActiveRuleParams(asList(parentActiveRuleParam, childActiveRuleParam)) - .build(); + .setProfiles(asList(parentProfile, childProfile)) + .setBaseProfile(RulesProfileDto.from(childProfile)) + .setDate(NOW) + .setDescendantProfilesSupplier((profiles, ruleUuids) -> new Result(emptyList(), emptyList(), emptyList())) + .setRules(singletonList(rule)) + .setRuleParams(singletonList(ruleParam)) + .setActiveRules(asList(parentActiveRuleDto, childActiveRuleDto)) + .setActiveRuleParams(asList(parentActiveRuleParam, childActiveRuleParam)) + .build(); List result = underTest.activate(session, resetRequest, context); assertThat(result).hasSize(1); - assertThat(result.get(0).getParameters()).containsEntry("min", "15"); - assertThat(result.get(0).getSeverity()).isEqualTo(Severity.MINOR); - assertThat(result.get(0).getInheritance()).isEqualTo(OVERRIDES); + ActiveRuleChange activeRuleResult = result.get(0); + assertThat(activeRuleResult.getParameters()).containsEntry("min", "15"); + assertThat(activeRuleResult.getSeverity()).isEqualTo(Severity.MINOR); + assertThat(activeRuleResult.isPrioritizedRule()).isTrue(); + assertThat(activeRuleResult.getInheritance()).isEqualTo(OVERRIDES); } @Test @@ -165,15 +171,15 @@ public class RuleActivatorIT { DbSession session = db.getSession(); RuleActivation resetRequest = RuleActivation.create(rule.getUuid()); RuleActivationContext context = new RuleActivationContext.Builder() - .setProfiles(asList(parentProfile, childProfile)) - .setBaseProfile(RulesProfileDto.from(childProfile)) - .setDate(NOW) - .setDescendantProfilesSupplier((profiles, ruleUuids) -> new Result(emptyList(), emptyList(), emptyList())) - .setRules(singletonList(rule)) - .setRuleParams(singletonList(ruleParam)) - .setActiveRules(emptyList()) - .setActiveRuleParams(emptyList()) - .build(); + .setProfiles(asList(parentProfile, childProfile)) + .setBaseProfile(RulesProfileDto.from(childProfile)) + .setDate(NOW) + .setDescendantProfilesSupplier((profiles, ruleUuids) -> new Result(emptyList(), emptyList(), emptyList())) + .setRules(singletonList(rule)) + .setRuleParams(singletonList(ruleParam)) + .setActiveRules(emptyList()) + .setActiveRuleParams(emptyList()) + .build(); List result = underTest.activate(session, resetRequest, context); @@ -184,7 +190,7 @@ public class RuleActivatorIT { } @Test - public void fail_if_rule_language_doesnt_match_qp() { + void fail_if_rule_language_doesnt_match_qp() { RuleDto rule = db.rules().insert(r -> r.setLanguage("xoo") .setRepositoryKey("repo") .setRuleKey("rule") @@ -210,11 +216,13 @@ public class RuleActivatorIT { } - private ActiveRuleDto activateRuleInDb(RulesProfileDto ruleProfile, RuleDto rule, RulePriority severity, @Nullable ActiveRuleInheritance inheritance) { + private ActiveRuleDto activateRuleInDb(RulesProfileDto ruleProfile, RuleDto rule, RulePriority severity, + @Nullable Boolean prioritizedRule, @Nullable ActiveRuleInheritance inheritance) { ActiveRuleDto dto = new ActiveRuleDto() .setKey(ActiveRuleKey.of(ruleProfile, RuleKey.of(rule.getRepositoryKey(), rule.getRuleKey()))) .setProfileUuid(ruleProfile.getUuid()) .setSeverity(severity.name()) + .setPrioritizedRule(TRUE.equals(prioritizedRule)) .setRuleUuid(rule.getUuid()) .setInheritance(inheritance != null ? inheritance.name() : null) .setCreatedAt(PAST) @@ -237,9 +245,9 @@ public class RuleActivatorIT { private QProfileDto createChildProfile(QProfileDto parent) { return db.qualityProfiles().insert(p -> p - .setLanguage(parent.getLanguage()) - .setParentKee(parent.getKee()) - .setName("Child of " + parent.getName())) + .setLanguage(parent.getLanguage()) + .setParentKee(parent.getKee()) + .setName("Child of " + parent.getName())) .setIsBuiltIn(false); } } diff --git a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/qualityprofile/ws/ActivateRuleActionIT.java b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/qualityprofile/ws/ActivateRuleActionIT.java index 0cb0b6a809b..18e8d23386b 100644 --- a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/qualityprofile/ws/ActivateRuleActionIT.java +++ b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/qualityprofile/ws/ActivateRuleActionIT.java @@ -21,9 +21,9 @@ package org.sonar.server.qualityprofile.ws; import java.net.HttpURLConnection; import java.util.Collection; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; import org.mockito.ArgumentCaptor; import org.mockito.MockitoAnnotations; import org.sonar.api.rule.RuleKey; @@ -56,13 +56,14 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.sonar.server.platform.db.migration.def.VarcharColumnDef.UUID_SIZE; import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_KEY; +import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_PRIORITIZED_RULE; import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_RULE; -public class ActivateRuleActionIT { +class ActivateRuleActionIT { - @Rule + @RegisterExtension public DbTester db = DbTester.create(); - @Rule + @RegisterExtension public UserSessionRule userSession = UserSessionRule.standalone(); private final ArgumentCaptor> ruleActivationCaptor = ArgumentCaptor.forClass(Collection.class); @@ -72,21 +73,22 @@ public class ActivateRuleActionIT { private final WsActionTester ws = new WsActionTester(new ActivateRuleAction(dbClient, qProfileRules, userSession, wsSupport)); - @Before - public void before() { + @BeforeEach + void before() { MockitoAnnotations.initMocks(this); } @Test - public void define_activate_rule_action() { + void define_activate_rule_action() { WebService.Action definition = ws.getDef(); assertThat(definition).isNotNull(); assertThat(definition.isPost()).isTrue(); - assertThat(definition.params()).extracting(WebService.Param::key).containsExactlyInAnyOrder("severity", "key", "reset", "rule", "params"); + assertThat(definition.params()).extracting(WebService.Param::key).containsExactlyInAnyOrder("severity", "prioritizedRule", "key", + "reset", "rule", "params"); } @Test - public void fail_if_not_logged_in() { + void fail_if_not_logged_in() { TestRequest request = ws.newRequest() .setMethod("POST") .setParam(PARAM_RULE, RuleTesting.newRule().getKey().toString()) @@ -97,7 +99,7 @@ public class ActivateRuleActionIT { } @Test - public void fail_if_not_global_quality_profile_administrator() { + void fail_if_not_global_quality_profile_administrator() { userSession.logIn(db.users().insertUser()); QProfileDto qualityProfile = db.qualityProfiles().insert(); TestRequest request = ws.newRequest() @@ -110,10 +112,11 @@ public class ActivateRuleActionIT { } @Test - public void fail_activate_if_built_in_profile() { + void fail_activate_if_built_in_profile() { userSession.logIn(db.users().insertUser()).addPermission(GlobalPermission.ADMINISTER_QUALITY_PROFILES); - QProfileDto qualityProfile = db.qualityProfiles().insert(profile -> profile.setIsBuiltIn(true).setName("Xoo profile").setLanguage("xoo")); + QProfileDto qualityProfile = db.qualityProfiles().insert(profile -> profile.setIsBuiltIn(true).setName("Xoo profile").setLanguage( + "xoo")); TestRequest request = ws.newRequest() .setMethod("POST") .setParam(PARAM_RULE, RuleTesting.newRule().getKey().toString()) @@ -125,7 +128,7 @@ public class ActivateRuleActionIT { } @Test - public void fail_activate_external_rule() { + void fail_activate_external_rule() { userSession.logIn(db.users().insertUser()).addPermission(GlobalPermission.ADMINISTER_QUALITY_PROFILES); QProfileDto qualityProfile = db.qualityProfiles().insert(); RuleDto rule = db.rules().insert(r -> r.setIsExternal(true)); @@ -141,7 +144,7 @@ public class ActivateRuleActionIT { } @Test - public void activate_rule() { + void activate_rule() { userSession.logIn().addPermission(GlobalPermission.ADMINISTER_QUALITY_PROFILES); QProfileDto qualityProfile = db.qualityProfiles().insert(); RuleDto rule = db.rules().insert(RuleTesting.randomRuleKey()); @@ -150,6 +153,7 @@ public class ActivateRuleActionIT { .setParam(PARAM_RULE, rule.getKey().toString()) .setParam(PARAM_KEY, qualityProfile.getKee()) .setParam("severity", "BLOCKER") + .setParam(PARAM_PRIORITIZED_RULE, "true") .setParam("params", "key1=v1;key2=v2") .setParam("reset", "false"); @@ -164,11 +168,12 @@ public class ActivateRuleActionIT { RuleActivation activation = activations.iterator().next(); assertThat(activation.getRuleUuid()).isEqualTo(rule.getUuid()); assertThat(activation.getSeverity()).isEqualTo(Severity.BLOCKER); + assertThat(activation.isPrioritizedRule()).isTrue(); assertThat(activation.isReset()).isFalse(); } @Test - public void as_qprofile_editor() { + void as_qprofile_editor() { UserDto user = db.users().insertUser(); QProfileDto qualityProfile = db.qualityProfiles().insert(); db.qualityProfiles().addUserPermission(qualityProfile, user); diff --git a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/qualityprofile/ws/ActivateRulesActionIT.java b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/qualityprofile/ws/ActivateRulesActionIT.java index 0eb7b35b42b..3c3ffc6d4aa 100644 --- a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/qualityprofile/ws/ActivateRulesActionIT.java +++ b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/qualityprofile/ws/ActivateRulesActionIT.java @@ -19,8 +19,9 @@ */ package org.sonar.server.qualityprofile.ws; -import org.junit.Rule; -import org.junit.Test; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; import org.mockito.Mockito; import org.sonar.api.server.ws.WebService; import org.sonar.db.DbClient; @@ -47,11 +48,11 @@ import static org.sonar.db.permission.GlobalPermission.ADMINISTER_QUALITY_PROFIL import static org.sonar.server.platform.db.migration.def.VarcharColumnDef.UUID_SIZE; import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_TARGET_KEY; -public class ActivateRulesActionIT { +class ActivateRulesActionIT { - @Rule + @RegisterExtension public DbTester db = DbTester.create(); - @Rule + @RegisterExtension public UserSessionRule userSession = UserSessionRule.standalone(); private DbClient dbClient = db.getDbClient(); @@ -59,10 +60,11 @@ public class ActivateRulesActionIT { private RuleQueryFactory ruleQueryFactory = mock(RuleQueryFactory.class, Mockito.RETURNS_MOCKS); private QProfileRules qProfileRules = mock(QProfileRules.class, Mockito.RETURNS_DEEP_STUBS); - private WsActionTester ws = new WsActionTester(new ActivateRulesAction(ruleQueryFactory, userSession, qProfileRules, wsSupport, dbClient)); + private WsActionTester ws = new WsActionTester(new ActivateRulesAction(ruleQueryFactory, userSession, qProfileRules, wsSupport, + dbClient)); @Test - public void define_bulk_activate_rule_action() { + void define_bulk_activate_rule_action() { WebService.Action definition = ws.getDef(); assertThat(definition).isNotNull(); assertThat(definition.isPost()).isTrue(); @@ -79,6 +81,7 @@ public class ActivateRulesActionIT { "asc", "q", "active_severities", + "prioritizedRule", "s", "repositories", "targetKey", @@ -98,7 +101,7 @@ public class ActivateRulesActionIT { } @Test - public void as_global_qprofile_admin() { + void as_global_qprofile_admin() { userSession.logIn(db.users().insertUser()).addPermission(ADMINISTER_QUALITY_PROFILES); QProfileDto qualityProfile = db.qualityProfiles().insert(); @@ -107,11 +110,11 @@ public class ActivateRulesActionIT { .setParam(PARAM_TARGET_KEY, qualityProfile.getKee()) .execute(); - verify(qProfileRules).bulkActivateAndCommit(any(), any(), any(), any()); + verify(qProfileRules).bulkActivateAndCommit(any(), any(), any(), any(), any()); } @Test - public void as_qprofile_editor() { + void as_qprofile_editor() { UserDto user = db.users().insertUser(); GroupDto group = db.users().insertGroup(); QProfileDto qualityProfile = db.qualityProfiles().insert(); @@ -123,11 +126,11 @@ public class ActivateRulesActionIT { .setParam(PARAM_TARGET_KEY, qualityProfile.getKee()) .execute(); - verify(qProfileRules).bulkActivateAndCommit(any(), any(), any(), any()); + verify(qProfileRules).bulkActivateAndCommit(any(), any(), any(), any(), any()); } @Test - public void fail_if_not_logged_in() { + void fail_if_not_logged_in() { TestRequest request = ws.newRequest() .setMethod("POST") .setParam(PARAM_TARGET_KEY, randomAlphanumeric(UUID_SIZE)); @@ -137,7 +140,7 @@ public class ActivateRulesActionIT { } @Test - public void fail_if_built_in_profile() { + void fail_if_built_in_profile() { userSession.logIn().addPermission(ADMINISTER_QUALITY_PROFILES); QProfileDto qualityProfile = db.qualityProfiles().insert(p -> p.setIsBuiltIn(true)); TestRequest request = ws.newRequest() @@ -149,7 +152,7 @@ public class ActivateRulesActionIT { } @Test - public void fail_if_not_enough_permission() { + void fail_if_not_enough_permission() { userSession.logIn(db.users().insertUser()); QProfileDto qualityProfile = db.qualityProfiles().insert(); diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/QProfileRulesImpl.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/QProfileRulesImpl.java index 03de7f45e8c..794cd7be265 100644 --- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/QProfileRulesImpl.java +++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/QProfileRulesImpl.java @@ -75,10 +75,11 @@ public class QProfileRulesImpl implements QProfileRules { } @Override - public BulkChangeResult bulkActivateAndCommit(DbSession dbSession, QProfileDto profile, RuleQuery ruleQuery, @Nullable String severity) { + public BulkChangeResult bulkActivateAndCommit(DbSession dbSession, QProfileDto profile, RuleQuery ruleQuery, @Nullable String severity, + @Nullable Boolean prioritizedRule) { verifyNotBuiltIn(profile); BulkChangeResult bulkChangeResult = doBulk(dbSession, profile, ruleQuery, (context, ruleDto) -> { - RuleActivation activation = RuleActivation.create(ruleDto.getUuid(), severity, null); + RuleActivation activation = RuleActivation.create(ruleDto.getUuid(), severity, prioritizedRule, null); return ruleActivator.activate(dbSession, activation, context); }); qualityProfileChangeEventService.distributeRuleChangeEvent(List.of(profile), bulkChangeResult.getChanges(), profile.getLanguage()); diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/builtin/RuleActivator.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/builtin/RuleActivator.java index 065422beca8..f2f8db8ed15 100644 --- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/builtin/RuleActivator.java +++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/builtin/RuleActivator.java @@ -59,6 +59,7 @@ import org.sonar.server.user.UserSession; import org.sonar.server.util.TypeValidations; import static com.google.common.base.Preconditions.checkArgument; +import static java.lang.Boolean.TRUE; import static org.sonar.server.exceptions.BadRequestException.checkRequest; /** @@ -74,7 +75,8 @@ public class RuleActivator { private final Configuration configuration; private final SonarQubeVersion sonarQubeVersion; - public RuleActivator(System2 system2, DbClient db, TypeValidations typeValidations, UserSession userSession, Configuration configuration, SonarQubeVersion sonarQubeVersion) { + public RuleActivator(System2 system2, DbClient db, TypeValidations typeValidations, UserSession userSession, + Configuration configuration, SonarQubeVersion sonarQubeVersion) { this.system2 = system2; this.db = db; this.typeValidations = typeValidations; @@ -120,7 +122,8 @@ public class RuleActivator { change = new ActiveRuleChange(ActiveRuleChange.Type.UPDATED, activeRuleKey, rule); handleUpdatedRuleActivation(activation, context, change, activeRule); - if (isSame(change, activeRule) || (context.isCascading() && activeRule.get().getInheritance() != null && !isSameAsParent(change, context))) { + if (isSame(change, activeRule) || (context.isCascading() && activeRule.get().getInheritance() != null && !isSameAsParent(change, + context))) { // The rule config hasn't changed; or the rule is being propagated but the parent has a different config, // which means the rule was overridden by a profile in the inheritance chain change = null; @@ -156,7 +159,7 @@ public class RuleActivator { } change.setInheritance(isSameAsParent(change, context) ? ActiveRuleInheritance.INHERITED : ActiveRuleInheritance.OVERRIDES); } else { - applySeverityAndParamToChange(activation, context, change); + applySeverityAndPrioritizedRuleAndParamToChange(activation, context, change); if (!context.isCascading() && context.getParentActiveRule() != null) { // override rule which is already declared on parents change.setInheritance(isSameAsParent(change, context) ? ActiveRuleInheritance.INHERITED : ActiveRuleInheritance.OVERRIDES); @@ -164,9 +167,10 @@ public class RuleActivator { } } - private ActiveRuleChange handleNewRuleActivation(RuleActivation activation, RuleActivationContext context, RuleDto rule, ActiveRuleKey activeRuleKey) { + private ActiveRuleChange handleNewRuleActivation(RuleActivation activation, RuleActivationContext context, RuleDto rule, + ActiveRuleKey activeRuleKey) { ActiveRuleChange change = new ActiveRuleChange(ActiveRuleChange.Type.ACTIVATED, activeRuleKey, rule); - applySeverityAndParamToChange(activation, context, change); + applySeverityAndPrioritizedRuleAndParamToChange(activation, context, change); if (context.isCascading() || context.getParentActiveRule() != null) { change.setInheritance(isSameAsParent(change, context) ? ActiveRuleInheritance.INHERITED : ActiveRuleInheritance.OVERRIDES); } @@ -179,32 +183,35 @@ public class RuleActivator { db.qualityProfileDao().update(dbSession, ruleProfile); if (userSession.isLoggedIn()) { - context.getProfiles().forEach(p -> db.qualityProfileDao().update(dbSession, OrgQProfileDto.from(p).setUserUpdatedAt(context.getDate()))); + context.getProfiles().forEach(p -> db.qualityProfileDao().update(dbSession, + OrgQProfileDto.from(p).setUserUpdatedAt(context.getDate()))); } } /** - * Update severity and params + * Update severity, prioritizedRule and params */ - private void applySeverityAndParamToChange(RuleActivation request, RuleActivationContext context, ActiveRuleChange change) { + private void applySeverityAndPrioritizedRuleAndParamToChange(RuleActivation request, RuleActivationContext context, ActiveRuleChange change) { RuleWrapper rule = context.getRule(); ActiveRuleWrapper activeRule = context.getActiveRule(); ActiveRuleWrapper parentActiveRule = context.getParentActiveRule(); if (request.isReset()) { - applySeverityAndParamsWhenResetRequested(change, rule, parentActiveRule); + applySeverityAndPrioritizedRuleAndParamsWhenResetRequested(change, rule, parentActiveRule); } else if (context.getRulesProfile().isBuiltIn()) { - applySeverityAndParamsWhenBuiltInProfile(request, context, change, rule); + applySeverityAndPrioritizedRuleAndParamsWhenBuiltInProfile(request, context, change, rule); } else { - applySeverityAndParamsWhenNonBuiltInProfile(request, context, change, rule, activeRule, parentActiveRule); + applySeverityAndPrioritizedRuleAndParamsWhenNonBuiltInProfile(request, context, change, rule, activeRule, parentActiveRule); } } - private void applySeverityAndParamsWhenResetRequested(ActiveRuleChange change, RuleWrapper rule, @Nullable ActiveRuleWrapper parentActiveRule) { + private void applySeverityAndPrioritizedRuleAndParamsWhenResetRequested(ActiveRuleChange change, RuleWrapper rule, + @Nullable ActiveRuleWrapper parentActiveRule) { String severity = firstNonNull( parentActiveRule != null ? parentActiveRule.get().getSeverityString() : null, rule.get().getSeverityString()); change.setSeverity(severity); + change.setPrioritizedRule(parentActiveRule != null && parentActiveRule.get().isPrioritizedRule()); for (RuleParamDto ruleParamDto : rule.getParams()) { String paramKey = ruleParamDto.getName(); @@ -217,12 +224,15 @@ public class RuleActivator { } } - private void applySeverityAndParamsWhenBuiltInProfile(RuleActivation request, RuleActivationContext context, ActiveRuleChange change, - RuleWrapper rule) { + private void applySeverityAndPrioritizedRuleAndParamsWhenBuiltInProfile(RuleActivation request, RuleActivationContext context, + ActiveRuleChange change, RuleWrapper rule) { // for builtin quality profiles, the severity from profile, when null use the default severity of the rule String severity = firstNonNull(request.getSeverity(), rule.get().getSeverityString()); change.setSeverity(severity); + boolean prioritizedRule = TRUE.equals(request.isPrioritizedRule()); + change.setPrioritizedRule(prioritizedRule); + for (RuleParamDto ruleParamDto : rule.getParams()) { String paramKey = ruleParamDto.getName(); // use the value defined in the profile definition, else the rule default value @@ -239,10 +249,13 @@ public class RuleActivator { * 3. apply parent value * 4. apply defaults */ - private void applySeverityAndParamsWhenNonBuiltInProfile(RuleActivation request, RuleActivationContext context, ActiveRuleChange change, + private void applySeverityAndPrioritizedRuleAndParamsWhenNonBuiltInProfile(RuleActivation request, RuleActivationContext context, + ActiveRuleChange change, RuleWrapper rule, @Nullable ActiveRuleWrapper activeRule, @Nullable ActiveRuleWrapper parentActiveRule) { String severity = getSeverityForNonBuiltInProfile(request, rule, activeRule, parentActiveRule); + boolean prioritizedRule = getPrioritizedRuleForNonBuiltInProfile(request, activeRule, parentActiveRule); change.setSeverity(severity); + change.setPrioritizedRule(prioritizedRule); for (RuleParamDto ruleParamDto : rule.getParams()) { String paramKey = ruleParamDto.getName(); @@ -255,8 +268,8 @@ public class RuleActivator { parentValue, rule.getParamDefaultValue(paramKey)); } else if (activeRule != null) { - // If the request doesn't contain the parameter, then we're using either user value from db, or parent value if rule inherited, or default - // value + // If the request doesn't contain the parameter, then we're using either user value from db, or parent value if rule inherited, + // or default value paramValue = firstNonNull( activeRule.get().doesOverride() ? activeRule.getParamValue(paramKey) : null, parentValue == null ? activeRule.getParamValue(paramKey) : parentValue, @@ -291,6 +304,25 @@ public class RuleActivator { return severity; } + private static boolean getPrioritizedRuleForNonBuiltInProfile(RuleActivation request, @Nullable ActiveRuleWrapper activeRule, + @Nullable ActiveRuleWrapper parentActiveRule) { + boolean prioritizedRule; + if (activeRule != null) { + ActiveRuleDto activeRuleDto = activeRule.get(); + // load prioritizedRule from request, else keep existing one (if overridden), else from parent if rule inherited, else 'false' + prioritizedRule = firstNonNull( + request.isPrioritizedRule(), + activeRuleDto.doesOverride() ? activeRuleDto.isPrioritizedRule() : null, + parentActiveRule != null && parentActiveRule.get().isPrioritizedRule()); + } else { + // load prioritizedRule from request, else from parent, else 'false' + prioritizedRule = firstNonNull( + request.isPrioritizedRule(), + parentActiveRule != null && parentActiveRule.get().isPrioritizedRule()); + } + return prioritizedRule; + } + private void persist(ActiveRuleChange change, RuleActivationContext context, DbSession dbSession) { ActiveRuleDto activeRule = null; if (change.getType() == ActiveRuleChange.Type.ACTIVATED) { @@ -322,6 +354,7 @@ public class RuleActivator { if (severity != null) { activeRule.setSeverity(severity); } + activeRule.setPrioritizedRule(TRUE.equals(change.isPrioritizedRule())); ActiveRuleInheritance inheritance = change.getInheritance(); if (inheritance != null) { activeRule.setInheritance(inheritance.name()); @@ -349,15 +382,20 @@ public class RuleActivator { } ActiveRuleDao dao = db.activeRuleDao(); String severity = change.getSeverity(); + ActiveRuleDto ruleDto = activeRule.get(); if (severity != null) { - activeRule.get().setSeverity(severity); + ruleDto.setSeverity(severity); + } + Boolean prioritizedRule = change.isPrioritizedRule(); + if (prioritizedRule != null) { + ruleDto.setPrioritizedRule(prioritizedRule); } ActiveRuleInheritance inheritance = change.getInheritance(); if (inheritance != null) { - activeRule.get().setInheritance(inheritance.name()); + ruleDto.setInheritance(inheritance.name()); } - activeRule.get().setUpdatedAt(system2.now()); - dao.update(dbSession, activeRule.get()); + ruleDto.setUpdatedAt(system2.now()); + dao.update(dbSession, ruleDto); for (Map.Entry param : change.getParameters().entrySet()) { ActiveRuleParamDto activeRuleParamDto = activeRule.getParam(param.getKey()); @@ -366,7 +404,7 @@ public class RuleActivator { if (param.getValue() != null) { activeRuleParamDto = ActiveRuleParamDto.createFor(context.getRule().getParam(param.getKey())); activeRuleParamDto.setValue(param.getValue()); - dao.insertParam(dbSession, activeRule.get(), activeRuleParamDto); + dao.insertParam(dbSession, ruleDto, activeRuleParamDto); } } else { if (param.getValue() != null) { @@ -377,7 +415,7 @@ public class RuleActivator { } } } - return activeRule.get(); + return ruleDto; } public List deactivate(DbSession dbSession, RuleActivationContext context, String ruleUuid, boolean force) { @@ -428,7 +466,8 @@ public class RuleActivator { return value; } - public RuleActivationContext createContextForBuiltInProfile(DbSession dbSession, RulesProfileDto builtInProfile, Collection ruleUuids) { + public RuleActivationContext createContextForBuiltInProfile(DbSession dbSession, RulesProfileDto builtInProfile, + Collection ruleUuids) { checkArgument(builtInProfile.isBuiltIn(), "Rules profile with UUID %s is not built-in", builtInProfile.getUuid()); RuleActivationContext.Builder builder = new RuleActivationContext.Builder(); @@ -495,7 +534,8 @@ public class RuleActivator { builder.setRuleParams(db.ruleDao().selectRuleParamsByRuleUuids(dbSession, ruleUuids)); } - private void completeWithActiveRules(DbSession dbSession, RuleActivationContext.Builder builder, Collection ruleUuids, Collection ruleProfileUuids) { + private void completeWithActiveRules(DbSession dbSession, RuleActivationContext.Builder builder, Collection ruleUuids, + Collection ruleProfileUuids) { Collection activeRules = db.activeRuleDao().selectByRulesAndRuleProfileUuids(dbSession, ruleUuids, ruleProfileUuids); builder.setActiveRules(activeRules); List activeRuleUuids = activeRules.stream().map(ActiveRuleDto::getUuid).toList(); @@ -511,6 +551,10 @@ public class RuleActivator { if (severity != null && !severity.equals(activeRule.get().getSeverityString())) { return false; } + Boolean prioritizedRule = change.isPrioritizedRule(); + if (prioritizedRule != null && prioritizedRule != activeRule.get().isPrioritizedRule()) { + return false; + } for (Map.Entry changeParam : change.getParameters().entrySet()) { String activeParamValue = activeRule.getParamValue(changeParam.getKey()); if (changeParam.getValue() == null && activeParamValue != null) { @@ -548,4 +592,13 @@ public class RuleActivator { } return null; } + + private static boolean firstNonNull(Boolean... booleans) { + for (Boolean b : booleans) { + if (b != null) { + return b; + } + } + return false; + } } diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/ws/ActivateRuleAction.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/ws/ActivateRuleAction.java index 7472aa90de8..93b149595cb 100644 --- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/ws/ActivateRuleAction.java +++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/ws/ActivateRuleAction.java @@ -35,12 +35,14 @@ import org.sonar.server.qualityprofile.QProfileRules; import org.sonar.server.qualityprofile.RuleActivation; import org.sonar.server.user.UserSession; +import static java.lang.Boolean.TRUE; import static java.lang.String.format; import static java.util.Collections.singletonList; import static org.sonar.core.util.Uuids.UUID_EXAMPLE_01; import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.ACTION_ACTIVATE_RULE; import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_KEY; import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_PARAMS; +import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_PRIORITIZED_RULE; import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_RESET; import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_RULE; import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_SEVERITY; @@ -69,6 +71,7 @@ public class ActivateRuleAction implements QProfileWsAction { "
  • Edit right on the specified quality profile
  • " + "") .setChangelog( + new Change("10.6", format("Add parameter '%s'.", PARAM_PRIORITIZED_RULE)), new Change("10.2", format("Parameter '%s' is now deprecated.", PARAM_SEVERITY))) .setHandler(this) .setPost(true) @@ -94,8 +97,14 @@ public class ActivateRuleAction implements QProfileWsAction { .setExampleValue("params=key1=v1;key2=v2"); activate.createParam(PARAM_RESET) - .setDescription("Reset severity and parameters of activated rule. Set the values defined on parent profile or from rule default values.") + .setDescription("Reset severity and parameters of activated rule. Set the values defined on parent profile or from rule default " + + "values.") .setBooleanPossibleValues(); + + activate.createParam(PARAM_PRIORITIZED_RULE) + .setDescription("Mark activated rule as prioritized, so all corresponding Issues will have to be fixed.") + .setBooleanPossibleValues() + .setSince("10.6"); } @Override @@ -115,17 +124,18 @@ public class ActivateRuleAction implements QProfileWsAction { private RuleActivation readActivation(DbSession dbSession, Request request) { RuleKey ruleKey = RuleKey.parse(request.mandatoryParam(PARAM_RULE)); RuleDto ruleDto = wsSupport.getRule(dbSession, ruleKey); - boolean reset = Boolean.TRUE.equals(request.paramAsBoolean(PARAM_RESET)); + boolean reset = TRUE.equals(request.paramAsBoolean(PARAM_RESET)); if (reset) { return RuleActivation.createReset(ruleDto.getUuid()); } String severity = request.param(PARAM_SEVERITY); + Boolean prioritizedRule = request.paramAsBoolean(PARAM_PRIORITIZED_RULE); Map params = null; String paramsAsString = request.param(PARAM_PARAMS); if (paramsAsString != null) { params = KeyValueFormat.parse(paramsAsString); } - return RuleActivation.create(ruleDto.getUuid(), severity, params); + return RuleActivation.create(ruleDto.getUuid(), severity, prioritizedRule, params); } } diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/ws/ActivateRulesAction.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/ws/ActivateRulesAction.java index 6904f6ceda1..d16e257e486 100644 --- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/ws/ActivateRulesAction.java +++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/ws/ActivateRulesAction.java @@ -33,6 +33,7 @@ import org.sonar.server.rule.index.RuleQuery; import org.sonar.server.rule.ws.RuleQueryFactory; import org.sonar.server.user.UserSession; +import static java.lang.Boolean.TRUE; import static java.lang.String.format; import static org.sonar.core.util.Uuids.UUID_EXAMPLE_03; import static org.sonar.server.qualityprofile.ws.BulkChangeWsResponse.writeResponse; @@ -42,6 +43,7 @@ import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_ACTIVE_SEVERITIES import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_SEVERITIES; import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_TYPES; import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.ACTION_ACTIVATE_RULES; +import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_PRIORITIZED_RULE; import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_TARGET_KEY; import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_TARGET_SEVERITY; @@ -73,6 +75,7 @@ public class ActivateRulesAction implements QProfileWsAction { .setPost(true) .setSince("4.4") .setChangelog( + new Change("10.6", format("Add parameter '%s'.", PARAM_PRIORITIZED_RULE)), new Change("10.2", format("Parameters '%s', '%s', '%s', and '%s' are now deprecated.", PARAM_SEVERITIES, PARAM_TARGET_SEVERITY, PARAM_ACTIVE_SEVERITIES, PARAM_TYPES)), new Change("10.0", "Parameter 'sansTop25' is deprecated")) .setHandler(this); @@ -88,6 +91,11 @@ public class ActivateRulesAction implements QProfileWsAction { .setDescription("Severity to set on the activated rules") .setDeprecatedSince("10.2") .setPossibleValues(Severity.ALL); + + activate.createParam(PARAM_PRIORITIZED_RULE) + .setDescription("Mark activated rules as prioritized, so all corresponding Issues will have to be fixed.") + .setBooleanPossibleValues() + .setSince("10.6"); } @Override @@ -101,7 +109,7 @@ public class ActivateRulesAction implements QProfileWsAction { wsSupport.checkNotBuiltIn(profile); RuleQuery ruleQuery = ruleQueryFactory.createRuleQuery(dbSession, request); ruleQuery.setIncludeExternal(false); - result = qProfileRules.bulkActivateAndCommit(dbSession, profile, ruleQuery, request.param(PARAM_TARGET_SEVERITY)); + result = qProfileRules.bulkActivateAndCommit(dbSession, profile, ruleQuery, request.param(PARAM_TARGET_SEVERITY), request.paramAsBoolean(PARAM_PRIORITIZED_RULE)); } writeResponse(result, response); diff --git a/sonar-ws/src/main/java/org/sonarqube/ws/client/qualityprofile/QualityProfileWsParameters.java b/sonar-ws/src/main/java/org/sonarqube/ws/client/qualityprofile/QualityProfileWsParameters.java index 48dc3e3fc57..ae9a36ba880 100644 --- a/sonar-ws/src/main/java/org/sonarqube/ws/client/qualityprofile/QualityProfileWsParameters.java +++ b/sonar-ws/src/main/java/org/sonarqube/ws/client/qualityprofile/QualityProfileWsParameters.java @@ -69,6 +69,7 @@ public class QualityProfileWsParameters { public static final String PARAM_TARGET_SEVERITY = "targetSeverity"; public static final String PARAM_TO = "to"; public static final String PARAM_TO_NAME = "toName"; + public static final String PARAM_PRIORITIZED_RULE = "prioritizedRule"; private QualityProfileWsParameters() { // Only static stuff -- 2.39.5