]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-23260 Publish impact changes to SonarQube IDE
authorDejan Milisavljevic <dejan.milisavljevic@sonarsource.com>
Fri, 11 Oct 2024 08:27:08 +0000 (10:27 +0200)
committersonartech <sonartech@sonarsource.com>
Wed, 16 Oct 2024 20:03:01 +0000 (20:03 +0000)
server/sonar-db-dao/src/main/java/org/sonar/db/qualityprofile/ActiveRuleDto.java
server/sonar-webserver-pushapi/src/main/java/org/sonar/server/pushapi/qualityprofile/QualityProfileChangeEventServiceImpl.java
server/sonar-webserver-pushapi/src/test/java/org/sonar/server/pushapi/qualityprofile/QualityProfileChangeEventServiceImplTest.java
sonar-core/src/main/java/org/sonar/core/util/rule/RuleChange.java
sonar-core/src/test/java/org/sonar/core/util/rule/RuleChangeTest.java [new file with mode: 0644]

index 8e08e754dc5ec3424bbccafba733ab8ebddbd09d..906cdb4a2c7ad4ac933707fd381d8c72eff05260 100644 (file)
@@ -214,6 +214,7 @@ public class ActiveRuleDto {
     dto.setProfileUuid(profile.getRulesProfileUuid());
     dto.setRuleUuid(ruleDto.getUuid());
     dto.setKey(ActiveRuleKey.of(profile, ruleDto.getKey()));
+    dto.setImpacts(ruleDto.getDefaultImpactsMap());
     return dto;
   }
 
index ddffddaab9954d841f3ee776cd6e2f6adbcd4725..a0dda22d239a6d9f0fbd1febdf03d5d7817476a3 100644 (file)
@@ -105,15 +105,17 @@ public class QualityProfileChangeEventServiceImpl implements QualityProfileChang
       Map<String, List<ActiveRuleParamDto>> paramsByActiveRuleUuid = dbClient.activeRuleDao().selectParamsByActiveRuleUuids(dbSession, activeRuleUuids)
         .stream().collect(Collectors.groupingBy(ActiveRuleParamDto::getActiveRuleUuid));
 
-      Map<String, String> activeRuleUuidByRuleUuid = activeRuleDtos.stream().collect(Collectors.toMap(ActiveRuleDto::getRuleUuid, ActiveRuleDto::getUuid));
+      Map<String, OrgActiveRuleDto> activeRuleByRuleUuid = activeRuleDtos.stream().collect(Collectors.toMap(ActiveRuleDto::getRuleUuid,
+        r -> r));
 
       List<String> ruleUuids = activeRuleDtos.stream().map(ActiveRuleDto::getRuleUuid).toList();
       List<RuleDto> ruleDtos = dbClient.ruleDao().selectByUuids(dbSession, ruleUuids);
 
       for (RuleDto ruleDto : ruleDtos) {
-        String activeRuleUuid = activeRuleUuidByRuleUuid.get(ruleDto.getUuid());
+        OrgActiveRuleDto activeRule = activeRuleByRuleUuid.get(ruleDto.getUuid());
+        String activeRuleUuid = activeRule.getUuid();
         List<ActiveRuleParamDto> params = paramsByActiveRuleUuid.getOrDefault(activeRuleUuid, new ArrayList<>());
-        RuleChange ruleChange = toRuleChange(ruleDto, params);
+        RuleChange ruleChange = toRuleChange(ruleDto, activeRule, params);
         ruleChanges.add(ruleChange);
       }
     }
@@ -137,11 +139,12 @@ public class QualityProfileChangeEventServiceImpl implements QualityProfileChang
   }
 
   @NotNull
-  private RuleChange toRuleChange(RuleDto ruleDto, List<ActiveRuleParamDto> activeRuleParamDtos) {
+  private RuleChange toRuleChange(RuleDto ruleDto, OrgActiveRuleDto activeRule, List<ActiveRuleParamDto> activeRuleParamDtos) {
     RuleChange ruleChange = new RuleChange();
     ruleChange.setKey(ruleDto.getKey().toString());
     ruleChange.setLanguage(ruleDto.getLanguage());
-    ruleChange.setSeverity(ruleDto.getSeverityString());
+    ruleChange.setSeverity(activeRule.getSeverityString());
+    activeRule.getImpacts().forEach(ruleChange::addImpact);
 
     List<ParamChange> paramChanges = new ArrayList<>();
     for (ActiveRuleParamDto activeRuleParam : activeRuleParamDtos) {
@@ -179,6 +182,8 @@ public class QualityProfileChangeEventServiceImpl implements QualityProfileChang
       ruleChange.setSeverity(arc.getSeverity());
       ruleChange.setLanguage(language);
 
+      arc.getImpactSeverities().forEach(ruleChange::addImpact);
+
       Optional<String> templateKey = templateKey(arc);
       templateKey.ifPresent(ruleChange::setTemplateKey);
 
@@ -313,9 +318,6 @@ public class QualityProfileChangeEventServiceImpl implements QualityProfileChang
       .collect(Collectors.toSet());
   }
 
-
-
-
   private static byte[] serializeIssueToPushEvent(RuleSetChangedEvent event) {
     return GSON.toJson(event).getBytes(UTF_8);
   }
index 0ba4583234bf5651f8193d39517e931776867f39..c6fee35dd7ddf2c92e641549c47661ed5adfa1e9 100644 (file)
@@ -24,10 +24,14 @@ import java.util.Collection;
 import java.util.Collections;
 import java.util.Deque;
 import java.util.List;
+import java.util.Map;
+import java.util.Random;
 import java.util.Set;
 import java.util.function.Consumer;
-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.issue.impact.Severity;
+import org.sonar.api.issue.impact.SoftwareQuality;
 import org.sonar.api.rule.RuleKey;
 import org.sonar.db.DbTester;
 import org.sonar.db.component.ComponentDto;
@@ -41,7 +45,6 @@ import org.sonar.db.qualityprofile.QualityProfileTesting;
 import org.sonar.db.rule.RuleDto;
 import org.sonar.db.rule.RuleParamDto;
 import org.sonar.server.qualityprofile.ActiveRuleChange;
-import org.sonarqube.ws.Common;
 
 import static java.util.List.of;
 import static org.apache.commons.lang3.RandomStringUtils.secure;
@@ -51,15 +54,14 @@ import static org.sonar.db.rule.RuleTesting.newCustomRule;
 import static org.sonar.db.rule.RuleTesting.newTemplateRule;
 import static org.sonar.server.qualityprofile.ActiveRuleChange.Type.ACTIVATED;
 
-public class QualityProfileChangeEventServiceImplTest {
+class QualityProfileChangeEventServiceImplTest {
 
-  @Rule
-  public DbTester db = DbTester.create();
-
-  public final QualityProfileChangeEventServiceImpl underTest = new QualityProfileChangeEventServiceImpl(db.getDbClient());
+  @RegisterExtension
+  private final DbTester db = DbTester.create();
+  private final QualityProfileChangeEventServiceImpl underTest = new QualityProfileChangeEventServiceImpl(db.getDbClient());
 
   @Test
-  public void distributeRuleChangeEvent() {
+  void distributeRuleChangeEvent() {
     QProfileDto qualityProfileDto = QualityProfileTesting.newQualityProfileDto();
 
     RuleDto templateRule = newTemplateRule(RuleKey.of("xoo", "template-key"));
@@ -73,6 +75,7 @@ public class QualityProfileChangeEventServiceImplTest {
     db.rules().insert(rule1);
 
     ActiveRuleChange activeRuleChange = changeActiveRule(qualityProfileDto, rule1, "paramChangeKey", "paramChangeValue");
+    activeRuleChange.setImpactSeverities(Map.of(SoftwareQuality.MAINTAINABILITY, Severity.LOW));
 
     Collection<QProfileDto> profiles = Collections.singleton(qualityProfileDto);
 
@@ -94,19 +97,21 @@ public class QualityProfileChangeEventServiceImplTest {
       .contains("\"activatedRules\":[{\"key\":\"repo:ruleKey\"," +
                 "\"language\":\"xoo\"," +
                 "\"templateKey\":\"xoo:template-key\"," +
-                "\"params\":[{\"key\":\"paramChangeKey\",\"value\":\"paramChangeValue\"}]}]," +
+                "\"params\":[{\"key\":\"paramChangeKey\",\"value\":\"paramChangeValue\"}]," +
+                "\"impacts\":[{\"softwareQuality\":\"MAINTAINABILITY\",\"severity\":\"LOW\"}]}]," +
                 "\"deactivatedRules\":[]");
   }
 
   @Test
-  public void distributeRuleChangeEvent_when_project_has_only_default_quality_profiles() {
+  void distributeRuleChangeEvent_when_project_has_only_default_quality_profiles() {
     String language = "xoo";
     ProjectData projectData = db.components().insertPrivateProject();
     ComponentDto mainBranch = projectData.getMainBranchComponent();
     RuleDto templateRule = insertTemplateRule();
     QProfileDto defaultQualityProfile = insertDefaultQualityProfile(language);
     RuleDto rule = insertCustomRule(templateRule, language, "<div>line1\nline2</div>");
-    ActiveRuleChange activeRuleChange = changeActiveRule(defaultQualityProfile, rule, "paramChangeKey", "paramChangeValue");
+    ActiveRuleChange activeRuleChange = changeActiveRule(defaultQualityProfile, rule, "paramChangeKey", "paramChangeValue")
+      .setImpactSeverities(Map.of(SoftwareQuality.RELIABILITY, Severity.MEDIUM));
     db.measures().insertMeasure(mainBranch, m -> m.addValue(NCLOC_LANGUAGE_DISTRIBUTION_KEY, language + "=100"));
 
     db.getSession().commit();
@@ -128,7 +133,8 @@ public class QualityProfileChangeEventServiceImplTest {
       .contains("\"activatedRules\":[{\"key\":\"repo:ruleKey\"," +
                 "\"language\":\"xoo\"," +
                 "\"templateKey\":\"xoo:template-key\"," +
-                "\"params\":[{\"key\":\"paramChangeKey\",\"value\":\"paramChangeValue\"}]}]," +
+                "\"params\":[{\"key\":\"paramChangeKey\",\"value\":\"paramChangeValue\"}]," +
+                "\"impacts\":[{\"softwareQuality\":\"RELIABILITY\",\"severity\":\"MEDIUM\"}]}]," +
                 "\"deactivatedRules\":[]");
   }
 
@@ -174,7 +180,7 @@ public class QualityProfileChangeEventServiceImplTest {
   }
 
   @Test
-  public void publishRuleActivationToSonarLintClients() {
+  void publishRuleActivationToSonarLintClients() {
     ProjectDto projectDto = new ProjectDto().setUuid("project-uuid");
     QProfileDto activatedQualityProfile = QualityProfileTesting.newQualityProfileDto();
     activatedQualityProfile.setLanguage("xoo");
@@ -182,7 +188,7 @@ public class QualityProfileChangeEventServiceImplTest {
     RuleDto rule1 = db.rules().insert(r -> r.setLanguage("xoo").setRepositoryKey("repo").setRuleKey("ruleKey"));
     RuleParamDto rule1Param = db.rules().insertRuleParam(rule1);
 
-    ActiveRuleDto activeRule1 = db.qualityProfiles().activateRule(activatedQualityProfile, rule1);
+    ActiveRuleDto activeRule1 = db.qualityProfiles().activateRule(activatedQualityProfile, rule1, ar -> ar.setImpacts(Map.of(SoftwareQuality.SECURITY, Severity.BLOCKER)));
     ActiveRuleParamDto activeRuleParam1 = ActiveRuleParamDto.createFor(rule1Param).setValue(secure().nextAlphanumeric(20));
     db.getDbClient().activeRuleDao().insertParam(db.getSession(), activeRule1, activeRuleParam1);
     db.getSession().commit();
@@ -210,8 +216,9 @@ public class QualityProfileChangeEventServiceImplTest {
 
     assertThat(ruleSetChangedEvent)
       .contains("\"activatedRules\":[{\"key\":\"repo:ruleKey\"," +
-                "\"language\":\"xoo\",\"severity\":\"" + Common.Severity.forNumber(rule1.getSeverity()).name() + "\"," +
-                "\"params\":[{\"key\":\"" + activeRuleParam1.getKey() + "\",\"value\":\"" + activeRuleParam1.getValue() + "\"}]}]," +
+                "\"language\":\"xoo\",\"severity\":\"" + activeRule1.getSeverityString() + "\"," +
+                "\"params\":[{\"key\":\"" + activeRuleParam1.getKey() + "\",\"value\":\"" + activeRuleParam1.getValue() + "\"}]," +
+                "\"impacts\":[{\"softwareQuality\":\"SECURITY\",\"severity\":\"BLOCKER\"}]}]," +
                 "\"deactivatedRules\":[\"repo2:ruleKey2\"]");
   }
 }
index a43b0716a6929e285caf996882665d651568058c..c3b99a2834c37b943bbfec4b127119e3f5e3f950 100644 (file)
 package org.sonar.core.util.rule;
 
 import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
 import javax.annotation.CheckForNull;
 import javax.annotation.Nullable;
+import org.sonar.api.issue.impact.Severity;
+import org.sonar.api.issue.impact.SoftwareQuality;
 import org.sonar.core.util.ParamChange;
 
 public class RuleChange implements Serializable {
@@ -30,6 +34,7 @@ public class RuleChange implements Serializable {
   private String templateKey;
   private String severity;
   private ParamChange[] params = new ParamChange[0];
+  private final List<Impact> impacts = new ArrayList<>();
 
   public String getKey() {
     return key;
@@ -77,4 +82,30 @@ public class RuleChange implements Serializable {
     this.params = params;
     return this;
   }
+
+  public List<Impact> getImpacts() {
+    return impacts;
+  }
+
+  public void addImpact(SoftwareQuality softwareQuality, Severity severity) {
+    impacts.add(new Impact(softwareQuality, severity));
+  }
+
+  static class Impact implements Serializable {
+    private final SoftwareQuality softwareQuality;
+    private final Severity severity;
+
+    Impact(SoftwareQuality softwareQuality, Severity severity) {
+      this.softwareQuality = softwareQuality;
+      this.severity = severity;
+    }
+
+    public SoftwareQuality getSoftwareQuality() {
+      return softwareQuality;
+    }
+
+    public Severity getSeverity() {
+      return severity;
+    }
+  }
 }
diff --git a/sonar-core/src/test/java/org/sonar/core/util/rule/RuleChangeTest.java b/sonar-core/src/test/java/org/sonar/core/util/rule/RuleChangeTest.java
new file mode 100644 (file)
index 0000000..a1f5c81
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2024 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.core.util.rule;
+
+import org.junit.jupiter.api.Test;
+import org.sonar.api.issue.impact.Severity;
+import org.sonar.api.issue.impact.SoftwareQuality;
+import org.sonar.core.util.ParamChange;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+class RuleChangeTest {
+
+  @Test
+  void valuesAreStoredAndReturnedCorrectly() {
+    RuleChange ruleChange = new RuleChange();
+
+    ruleChange.setKey("key");
+    ruleChange.setTemplateKey("templateKey");
+    ruleChange.setLanguage("language");
+    ruleChange.setSeverity("severity");
+    ruleChange.setParams(new ParamChange[]{new ParamChange("paramKey", "paramValue")});
+    ruleChange.addImpact(SoftwareQuality.MAINTAINABILITY, Severity.HIGH);
+
+    assertThat(ruleChange).extracting(
+        RuleChange::getKey,
+        RuleChange::getTemplateKey,
+        RuleChange::getLanguage,
+        RuleChange::getSeverity)
+      .containsExactly(
+        "key",
+        "templateKey",
+        "language",
+        "severity");
+
+    assertThat(ruleChange.getParams()).hasSize(1);
+    assertThat(ruleChange.getParams()[0])
+      .extracting(ParamChange::getKey, ParamChange::getValue)
+      .containsExactly("paramKey", "paramValue");
+
+    assertThat(ruleChange.getImpacts()).hasSize(1);
+    assertThat(ruleChange.getImpacts().get(0))
+      .extracting(RuleChange.Impact::getSoftwareQuality, RuleChange.Impact::getSeverity)
+      .containsExactly(SoftwareQuality.MAINTAINABILITY, Severity.HIGH);
+  }
+}