From 2b456da715b2650a1519a4d273119b01388396df Mon Sep 17 00:00:00 2001 From: =?utf8?q?L=C3=A9o=20Geoffroy?= Date: Tue, 15 Aug 2023 10:58:11 +0200 Subject: [PATCH] SONAR-20169 Create custom rules with default impacts --- .../org/sonar/server/rule/RuleCreatorIT.java | 22 ++++++++++++++++--- .../org/sonar/server/rule/RuleUpdaterIT.java | 11 ++++++++++ .../org/sonar/server/rule/RuleCreator.java | 16 ++++++++++++-- .../org/sonar/server/rule/RuleUpdater.java | 10 +++++++++ 4 files changed, 54 insertions(+), 5 deletions(-) diff --git a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/rule/RuleCreatorIT.java b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/rule/RuleCreatorIT.java index 5cc1717306c..6956212b195 100644 --- a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/rule/RuleCreatorIT.java +++ b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/rule/RuleCreatorIT.java @@ -27,12 +27,16 @@ import java.util.Date; import java.util.List; import java.util.concurrent.atomic.AtomicReference; import org.assertj.core.api.Fail; +import org.assertj.core.groups.Tuple; import org.junit.Rule; import org.junit.Test; import org.sonar.api.impl.utils.TestSystem2; +import org.sonar.api.issue.impact.SoftwareQuality; import org.sonar.api.rule.RuleKey; import org.sonar.api.rule.RuleStatus; import org.sonar.api.rule.Severity; +import org.sonar.api.rules.CleanCodeAttribute; +import org.sonar.api.rules.RuleType; import org.sonar.api.server.debt.DebtRemediationFunction; import org.sonar.api.utils.System2; import org.sonar.core.util.SequenceUuidFactory; @@ -96,13 +100,13 @@ public class RuleCreatorIT { assertThat(rule.getTemplateUuid()).isEqualTo(templateRule.getUuid()); assertThat(rule.getName()).isEqualTo("My custom"); assertThat(rule.getDefaultRuleDescriptionSection().getContent()).isEqualTo("Some description"); + assertThat(rule.getEnumType()).isEqualTo(RuleType.CODE_SMELL); + assertCleanCodeInformation(rule); assertThat(rule.getSeverityString()).isEqualTo("MAJOR"); assertThat(rule.getStatus()).isEqualTo(RuleStatus.READY); assertThat(rule.getLanguage()).isEqualTo("java"); assertThat(rule.getConfigKey()).isEqualTo("S001"); - assertThat(rule.getDefRemediationFunction()).isEqualTo("LINEAR_OFFSET"); - assertThat(rule.getDefRemediationGapMultiplier()).isEqualTo("1h"); - assertThat(rule.getDefRemediationBaseEffort()).isEqualTo("5min"); + assertDefRemediation(rule); assertThat(rule.getGapDescription()).isEqualTo("desc"); assertThat(rule.getTags()).containsOnly("usertag1", "usertag2"); assertThat(rule.getSystemTags()).containsOnly("tag1", "tag4"); @@ -124,6 +128,18 @@ public class RuleCreatorIT { assertThat(ruleIndex.search(new RuleQuery(), new SearchOptions()).getUuids()).containsOnly(rule.getUuid(), templateRule.getUuid()); } + private static void assertCleanCodeInformation(RuleDto rule) { + assertThat(rule.getCleanCodeAttribute()).isEqualTo(CleanCodeAttribute.CONVENTIONAL); + assertThat(rule.getDefaultImpacts()).extracting(i -> i.getSoftwareQuality(), i -> i.getSeverity()) + .containsExactly(Tuple.tuple(SoftwareQuality.MAINTAINABILITY, org.sonar.api.issue.impact.Severity.MEDIUM)); + } + + private static void assertDefRemediation(RuleDto rule) { + assertThat(rule.getDefRemediationFunction()).isEqualTo("LINEAR_OFFSET"); + assertThat(rule.getDefRemediationGapMultiplier()).isEqualTo("1h"); + assertThat(rule.getDefRemediationBaseEffort()).isEqualTo("5min"); + } + @Test public void create_custom_rule_with_empty_parameter_value() { // insert template rule diff --git a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/rule/RuleUpdaterIT.java b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/rule/RuleUpdaterIT.java index 587fb83ac2a..46de88eb530 100644 --- a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/rule/RuleUpdaterIT.java +++ b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/rule/RuleUpdaterIT.java @@ -29,15 +29,19 @@ import java.util.stream.Collectors; import org.junit.Rule; import org.junit.Test; import org.sonar.api.impl.utils.TestSystem2; +import org.sonar.api.issue.impact.SoftwareQuality; import org.sonar.api.rule.RuleKey; import org.sonar.api.rule.RuleStatus; import org.sonar.api.rule.Severity; +import org.sonar.api.rules.RuleType; import org.sonar.api.server.debt.DebtRemediationFunction; import org.sonar.api.server.debt.internal.DefaultDebtRemediationFunction; import org.sonar.api.utils.System2; import org.sonar.core.util.UuidFactoryFast; +import org.sonar.core.util.Uuids; import org.sonar.db.DbSession; import org.sonar.db.DbTester; +import org.sonar.db.issue.ImpactDto; import org.sonar.db.qualityprofile.ActiveRuleDto; import org.sonar.db.qualityprofile.ActiveRuleKey; import org.sonar.db.qualityprofile.ActiveRuleParamDto; @@ -56,6 +60,7 @@ import org.sonar.server.tester.UserSessionRule; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.assertj.core.api.Assertions.tuple; import static org.sonar.api.rule.Severity.CRITICAL; import static org.sonar.db.rule.RuleTesting.newCustomRule; import static org.sonar.db.rule.RuleTesting.newRule; @@ -336,6 +341,10 @@ public class RuleUpdaterIT { RuleDto customRule = newCustomRule(templateRule, "Old description") .setName("Old name") + .setType(RuleType.CODE_SMELL) + .replaceAllDefaultImpacts(List.of(new ImpactDto().setUuid(Uuids.createFast()) + .setSoftwareQuality(SoftwareQuality.MAINTAINABILITY) + .setSeverity(org.sonar.api.issue.impact.Severity.LOW))) .setSeverity(Severity.MINOR) .setStatus(RuleStatus.BETA); db.rules().insert(customRule); @@ -358,6 +367,8 @@ public class RuleUpdaterIT { assertThat(customRuleReloaded).isNotNull(); assertThat(customRuleReloaded.getName()).isEqualTo("New name"); assertThat(customRuleReloaded.getDefaultRuleDescriptionSection().getContent()).isEqualTo("New description"); + assertThat(customRuleReloaded.getDefaultImpacts()).extracting(ImpactDto::getSoftwareQuality, ImpactDto::getSeverity) + .containsExactlyInAnyOrder(tuple(SoftwareQuality.MAINTAINABILITY, org.sonar.api.issue.impact.Severity.MEDIUM)); assertThat(customRuleReloaded.getSeverityString()).isEqualTo("MAJOR"); assertThat(customRuleReloaded.getStatus()).isEqualTo(RuleStatus.READY); diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/rule/RuleCreator.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/rule/RuleCreator.java index cb115044593..d0cd5bca426 100644 --- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/rule/RuleCreator.java +++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/rule/RuleCreator.java @@ -29,15 +29,20 @@ import java.util.Set; import java.util.function.Function; import java.util.stream.Collectors; import javax.annotation.Nullable; +import org.sonar.api.issue.impact.SoftwareQuality; import org.sonar.api.rule.RuleKey; import org.sonar.api.rule.RuleStatus; import org.sonar.api.rule.Severity; +import org.sonar.api.rules.CleanCodeAttribute; +import org.sonar.api.rules.RuleType; import org.sonar.api.server.ServerSide; import org.sonar.api.server.rule.RuleParamType; +import org.sonar.api.server.rule.internal.ImpactMapper; import org.sonar.api.utils.System2; import org.sonar.core.util.UuidFactory; import org.sonar.db.DbClient; import org.sonar.db.DbSession; +import org.sonar.db.issue.ImpactDto; import org.sonar.db.rule.RuleDescriptionSectionDto; import org.sonar.db.rule.RuleDto; import org.sonar.db.rule.RuleDto.Format; @@ -183,6 +188,11 @@ public class RuleCreator { private String createCustomRule(RuleKey ruleKey, NewCustomRule newRule, RuleDto templateRuleDto, DbSession dbSession) { RuleDescriptionSectionDto ruleDescriptionSectionDto = createDefaultRuleDescriptionSection(uuidFactory.create(), requireNonNull(newRule.markdownDescription())); + int type = newRule.type() == null ? templateRuleDto.getType() : newRule.type().getDbConstant(); + String severity = newRule.severity(); + SoftwareQuality softwareQuality = ImpactMapper.convertToSoftwareQuality(RuleType.valueOf(type)); + org.sonar.api.issue.impact.Severity impactSeverity = ImpactMapper.convertToImpactSeverity(severity); + RuleDto ruleDto = new RuleDto() .setUuid(uuidFactory.create()) .setRuleKey(ruleKey) @@ -190,9 +200,11 @@ public class RuleCreator { .setTemplateUuid(templateRuleDto.getUuid()) .setConfigKey(templateRuleDto.getConfigKey()) .setName(newRule.name()) - .setSeverity(newRule.severity()) + .setSeverity(severity) .setStatus(newRule.status()) - .setType(newRule.type() == null ? templateRuleDto.getType() : newRule.type().getDbConstant()) + .setType(type) + .addDefaultImpact(new ImpactDto().setUuid(uuidFactory.create()).setSoftwareQuality(softwareQuality).setSeverity(impactSeverity)) + .setCleanCodeAttribute(CleanCodeAttribute.CONVENTIONAL) .setLanguage(templateRuleDto.getLanguage()) .setDefRemediationFunction(templateRuleDto.getDefRemediationFunction()) .setDefRemediationGapMultiplier(templateRuleDto.getDefRemediationGapMultiplier()) diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/rule/RuleUpdater.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/rule/RuleUpdater.java index 98a9eadaa69..1d0d4a14464 100644 --- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/rule/RuleUpdater.java +++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/rule/RuleUpdater.java @@ -36,6 +36,7 @@ import org.sonar.api.rule.RuleStatus; import org.sonar.api.rule.Severity; import org.sonar.api.server.ServerSide; import org.sonar.api.server.debt.DebtRemediationFunction; +import org.sonar.api.server.rule.internal.ImpactMapper; import org.sonar.api.utils.System2; import org.sonar.core.util.UuidFactory; import org.sonar.db.DbClient; @@ -127,6 +128,14 @@ public class RuleUpdater { } } + private static void updateImpactSeverity(RuleDto rule, String severity) { + rule.getDefaultImpacts() + .stream() + .filter(i -> i.getSoftwareQuality().equals(ImpactMapper.convertToSoftwareQuality(rule.getEnumType()))) + .findFirst() + .ifPresent(i -> i.setSeverity(ImpactMapper.convertToImpactSeverity(severity))); + } + private static void updateName(RuleUpdate update, RuleDto rule) { String name = update.getName(); if (isNullOrEmpty(name)) { @@ -151,6 +160,7 @@ public class RuleUpdater { throw new IllegalArgumentException("The severity is invalid"); } rule.setSeverity(severity); + updateImpactSeverity(rule, severity); } private static void updateStatus(RuleUpdate update, RuleDto rule) { -- 2.39.5