aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorViktor Vorona <viktor.vorona@sonarsource.com>2024-12-12 16:43:03 +0100
committersonartech <sonartech@sonarsource.com>2024-12-24 13:31:10 +0000
commitc97f38af457c276d5a14022ba490cc412a952373 (patch)
tree8b3095414a398cacbef891158a190dece4e863c1
parentfaf152d6dec43d4909119f4b19509eced2c1d8dc (diff)
downloadsonarqube-c97f38af457c276d5a14022ba490cc412a952373.tar.gz
sonarqube-c97f38af457c276d5a14022ba490cc412a952373.zip
SONAR-23402 Back up/restore clean code attributes for custom rules
-rw-r--r--server/sonar-db-dao/src/main/java/org/sonar/db/qualityprofile/ExportRuleDto.java5
-rw-r--r--server/sonar-db-dao/src/main/resources/org/sonar/db/qualityprofile/QualityProfileExportMapper.xml2
-rw-r--r--server/sonar-webserver-webapi/src/it/java/org/sonar/server/qualityprofile/QProfileBackuperImplIT.java18
-rw-r--r--server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/ImportedRule.java9
-rw-r--r--server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/QProfileBackuperImpl.java3
-rw-r--r--server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/QProfileParser.java4
-rw-r--r--sonar-ws/src/main/java/org/sonarqube/ws/client/rules/CreateRequest.java29
-rw-r--r--sonar-ws/src/main/java/org/sonarqube/ws/client/rules/RulesService.java1
8 files changed, 69 insertions, 2 deletions
diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/qualityprofile/ExportRuleDto.java b/server/sonar-db-dao/src/main/java/org/sonar/db/qualityprofile/ExportRuleDto.java
index 09fd58daeaa..e005c6391bd 100644
--- a/server/sonar-db-dao/src/main/java/org/sonar/db/qualityprofile/ExportRuleDto.java
+++ b/server/sonar-db-dao/src/main/java/org/sonar/db/qualityprofile/ExportRuleDto.java
@@ -31,6 +31,7 @@ import org.sonar.db.rule.SeverityUtil;
public class ExportRuleDto {
private String activeRuleUuid = null;
+ private String cleanCodeAttribute = null;
private String description = null;
private String repository = null;
private String rule = null;
@@ -94,6 +95,10 @@ public class ExportRuleDto {
return Objects.requireNonNull(description, "description is expected to be set but it is null");
}
+ public String getCleanCodeAttribute() {
+ return cleanCodeAttribute;
+ }
+
public List<ExportRuleParamDto> getParams() {
if (params == null) {
params = new LinkedList<>();
diff --git a/server/sonar-db-dao/src/main/resources/org/sonar/db/qualityprofile/QualityProfileExportMapper.xml b/server/sonar-db-dao/src/main/resources/org/sonar/db/qualityprofile/QualityProfileExportMapper.xml
index 5406e85f3f1..b459ede2dc2 100644
--- a/server/sonar-db-dao/src/main/resources/org/sonar/db/qualityprofile/QualityProfileExportMapper.xml
+++ b/server/sonar-db-dao/src/main/resources/org/sonar/db/qualityprofile/QualityProfileExportMapper.xml
@@ -21,6 +21,7 @@
a.failure_level as "severity",
a.impacts as "impacts",
a.prioritized_rule as "prioritizedRule",
+ r.clean_code_attribute as "cleanCodeAttribute",
r.plugin_rule_key as "rule",
r.plugin_name as "repository",
r.priority as "defaultSeverity",
@@ -45,6 +46,7 @@
<result property="severity" column="severity"/>
<result property="impacts" column="impacts"/>
<result property="prioritizedRule" column="prioritizedRule"/>
+ <result property="cleanCodeAttribute" column="cleanCodeAttribute"/>
<result property="rule" column="rule"/>
<result property="repository" column="repository"/>
<result property="name" column="name"/>
diff --git a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/qualityprofile/QProfileBackuperImplIT.java b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/qualityprofile/QProfileBackuperImplIT.java
index 4204e3d1df0..87cc65c71d3 100644
--- a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/qualityprofile/QProfileBackuperImplIT.java
+++ b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/qualityprofile/QProfileBackuperImplIT.java
@@ -25,7 +25,6 @@ import java.io.StringReader;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Collection;
-import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
@@ -39,6 +38,7 @@ import org.junit.jupiter.params.provider.MethodSource;
import org.sonar.api.impl.utils.AlwaysIncreasingSystem2;
import org.sonar.api.rule.RuleKey;
import org.sonar.api.rule.RuleStatus;
+import org.sonar.api.rules.CleanCodeAttribute;
import org.sonar.api.rules.RuleType;
import org.sonar.api.utils.System2;
import org.sonar.core.util.UuidFactoryFast;
@@ -51,6 +51,7 @@ import org.sonar.db.qualityprofile.QualityProfileTesting;
import org.sonar.db.rule.RuleDto;
import org.sonar.db.rule.RuleParamDto;
import org.sonar.server.common.rule.RuleCreator;
+import org.sonar.server.common.rule.service.NewCustomRule;
import org.sonar.server.qualityprofile.builtin.QProfileName;
import static java.nio.charset.StandardCharsets.UTF_8;
@@ -227,6 +228,7 @@ class QProfileBackuperImplIT {
"<name>" + rule.getName() + "</name>" +
"<templateKey>" + templateRule.getKey().rule() + "</templateKey>" +
"<description>" + rule.getDefaultRuleDescriptionSection().getContent() + "</description>" +
+ "<cleanCodeAttribute>" + rule.getCleanCodeAttribute() + "</cleanCodeAttribute>" +
"<parameters><parameter>" +
"<key>" + param.getName() + "</key>" +
"<value>20</value>" +
@@ -430,7 +432,15 @@ class QProfileBackuperImplIT {
@Test
void restore_custom_rule() {
- when(ruleCreator.restore(any(), anyList())).then(invocation -> Collections.singletonList(db.rules().insert(RuleKey.of("sonarjs", "s001"))));
+ when(ruleCreator.restore(any(), anyList())).then(invocation -> {
+ List<NewCustomRule> newRuleList = invocation.getArgument(1);
+ return newRuleList.stream().map(newRule -> {
+ RuleDto rule = db.rules().insert(newRule.ruleKey())
+ .setCleanCodeAttribute(newRule.getCleanCodeAttribute())
+ .setName(newRule.name());
+ return db.rules().update(rule);
+ }).toList();
+ });
Reader backup = new StringReader("<?xml version='1.0' encoding='UTF-8'?>" +
"<profile>" +
@@ -444,6 +454,7 @@ class QProfileBackuperImplIT {
"<name>custom rule name</name>" +
"<templateKey>rule_mc8</templateKey>" +
"<description>custom rule description</description>" +
+ "<cleanCodeAttribute>MODULAR</cleanCodeAttribute>" +
"<parameters><parameter>" +
"<key>bar</key>" +
"<value>baz</value>" +
@@ -457,6 +468,9 @@ class QProfileBackuperImplIT {
RuleActivation activation = reset.calledActivations.get(0);
assertThat(activation.getSeverity()).isEqualTo("CRITICAL");
assertThat(activation.getParameter("bar")).isEqualTo("baz");
+ RuleDto rule = db.getDbClient().ruleDao().selectByKey( db.getSession(), RuleKey.of("sonarjs", "s001")).get();
+ assertThat(rule.getCleanCodeAttribute()).isEqualTo(CleanCodeAttribute.MODULAR);
+ assertThat(rule.getName()).isEqualTo("custom rule name");
}
@Test
diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/ImportedRule.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/ImportedRule.java
index 544a41022a4..eafa7aea183 100644
--- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/ImportedRule.java
+++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/ImportedRule.java
@@ -35,6 +35,7 @@ class ImportedRule {
private Map<SoftwareQuality, org.sonar.api.issue.impact.Severity> impacts = Map.of();
private Boolean prioritizedRule = false;
private String description = null;
+ private String cleanCodeAttribute = null;
private Map<String, String> parameters = null;
public Map<String, String> getParameters() {
@@ -73,6 +74,10 @@ class ImportedRule {
return description;
}
+ public String getCleanCodeAttribute() {
+ return cleanCodeAttribute;
+ }
+
ImportedRule setType(String type) {
this.type = type;
return this;
@@ -98,6 +103,10 @@ class ImportedRule {
return this;
}
+ public void setCleanCodeAttribute(String cleanCodeAttribute) {
+ this.cleanCodeAttribute = cleanCodeAttribute;
+ }
+
ImportedRule setParameters(Map<String, String> parameters) {
this.parameters = parameters;
return this;
diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/QProfileBackuperImpl.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/QProfileBackuperImpl.java
index 27345a95527..d81424294cf 100644
--- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/QProfileBackuperImpl.java
+++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/QProfileBackuperImpl.java
@@ -34,6 +34,7 @@ import javax.annotation.Nullable;
import org.apache.commons.lang3.builder.CompareToBuilder;
import org.sonar.api.rule.RuleKey;
import org.sonar.api.rule.RuleStatus;
+import org.sonar.api.rules.CleanCodeAttribute;
import org.sonar.api.rules.RuleType;
import org.sonar.api.server.ServerSide;
import org.sonar.db.DbClient;
@@ -100,6 +101,7 @@ public class QProfileBackuperImpl implements QProfileBackuper {
if (exportRuleDto.isCustomRule()) {
importedRule.setTemplate(exportRuleDto.getTemplateRuleKey().rule());
importedRule.setDescription(exportRuleDto.getDescriptionOrThrow());
+ importedRule.setCleanCodeAttribute(exportRuleDto.getCleanCodeAttribute());
}
importedRule.setType(exportRuleDto.getRuleType().name());
importedRule.setParameters(exportRuleDto.getParams().stream().collect(Collectors.toMap(ExportRuleParamDto::getKey, ExportRuleParamDto::getValue)));
@@ -220,6 +222,7 @@ public class QProfileBackuperImpl implements QProfileBackuper {
.setPreventReactivation(true)
.setType(RuleType.valueOf(r.getType()))
.setMarkdownDescription(r.getDescription())
+ .setCleanCodeAttribute(CleanCodeAttribute.valueOf(r.getCleanCodeAttribute()))
.setParameters(r.getParameters());
}
diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/QProfileParser.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/QProfileParser.java
index e29e02bf6ca..7f6f46039ee 100644
--- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/QProfileParser.java
+++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/QProfileParser.java
@@ -66,6 +66,7 @@ public class QProfileParser {
private static final String ATTRIBUTE_TEMPLATE_KEY = "templateKey";
private static final String ATTRIBUTE_TYPE = "type";
private static final String ATTRIBUTE_DESCRIPTION = "description";
+ private static final String ATTRIBUTE_CLEAN_CODE_ATTRIBUTE = "cleanCodeAttribute";
private static final String ATTRIBUTE_PARAMETERS = "parameters";
private static final String ATTRIBUTE_PARAMETER = "parameter";
@@ -103,6 +104,7 @@ public class QProfileParser {
xml.prop(ATTRIBUTE_NAME, ruleToExport.getName());
xml.prop(ATTRIBUTE_TEMPLATE_KEY, ruleToExport.getTemplateRuleKey().rule());
xml.prop(ATTRIBUTE_DESCRIPTION, ruleToExport.getDescriptionOrThrow());
+ xml.prop(ATTRIBUTE_CLEAN_CODE_ATTRIBUTE, ruleToExport.getCleanCodeAttribute());
}
xml.begin(ATTRIBUTE_PARAMETERS);
@@ -198,6 +200,8 @@ public class QProfileParser {
rule.setType(StringUtils.trim(ruleCursor.collectDescendantText(false)));
} else if (StringUtils.equals(ATTRIBUTE_DESCRIPTION, nodeName)) {
rule.setDescription(StringUtils.trim(ruleCursor.collectDescendantText(false)));
+ } else if (StringUtils.equals(ATTRIBUTE_CLEAN_CODE_ATTRIBUTE, nodeName)) {
+ rule.setCleanCodeAttribute(StringUtils.trim(ruleCursor.collectDescendantText(false)));
} else if (StringUtils.equals(ATTRIBUTE_PRIORITY, nodeName)) {
rule.setSeverity(StringUtils.trim(ruleCursor.collectDescendantText(false)));
} else if (StringUtils.equals(ATTRIBUTE_IMPACTS, nodeName)) {
diff --git a/sonar-ws/src/main/java/org/sonarqube/ws/client/rules/CreateRequest.java b/sonar-ws/src/main/java/org/sonarqube/ws/client/rules/CreateRequest.java
index aaaaf6b68e5..65e0691f454 100644
--- a/sonar-ws/src/main/java/org/sonarqube/ws/client/rules/CreateRequest.java
+++ b/sonar-ws/src/main/java/org/sonarqube/ws/client/rules/CreateRequest.java
@@ -39,6 +39,7 @@ public class CreateRequest {
private String severity;
private String status;
private String templateKey;
+ private String cleanCodeAttribute;
private String type;
/**
@@ -161,6 +162,34 @@ public class CreateRequest {
/**
* Possible values:
* <ul>
+ * <li>CONVENTIONAL</li>
+ * <li>FORMATTED</li>
+ * <li>IDENTIFIABLE</li>
+ * <li>CLEAR</li>
+ * <li>COMPLETE</li>
+ * <li>EFFICIENT</li>
+ * <li>LOGICAL</li>
+ * <li>DISTINCT</li>
+ * <li>FOCUSED</li>
+ * <li>MODULAR</li>
+ * <li>TESTED</li>
+ * <li>LAWFUL</li>
+ * <li>RESPECTFUL</li>
+ * <li>TRUSTWORTHY</li>
+ * </ul>
+ */
+ public CreateRequest setCleanCodeAttribute(String cleanCodeAttribute) {
+ this.cleanCodeAttribute = cleanCodeAttribute;
+ return this;
+ }
+
+ public String getCleanCodeAttribute() {
+ return cleanCodeAttribute;
+ }
+
+ /**
+ * Possible values:
+ * <ul>
* <li>"CODE_SMELL"</li>
* <li>"BUG"</li>
* <li>"VULNERABILITY"</li>
diff --git a/sonar-ws/src/main/java/org/sonarqube/ws/client/rules/RulesService.java b/sonar-ws/src/main/java/org/sonarqube/ws/client/rules/RulesService.java
index 01ac8197e2e..3dbe4c7d6ef 100644
--- a/sonar-ws/src/main/java/org/sonarqube/ws/client/rules/RulesService.java
+++ b/sonar-ws/src/main/java/org/sonarqube/ws/client/rules/RulesService.java
@@ -73,6 +73,7 @@ public class RulesService extends BaseService {
.setParam("severity", request.getSeverity())
.setParam("status", request.getStatus())
.setParam("templateKey", request.getTemplateKey())
+ .setParam("cleanCodeAttribute", request.getCleanCodeAttribute())
.setParam("type", request.getType()),
CreateResponse.parser());
}