From a063c19e012fafa748fe8d3269482e758697c05b Mon Sep 17 00:00:00 2001 From: =?utf8?q?L=C3=A9o=20Geoffroy?= Date: Fri, 18 Oct 2024 17:41:03 +0200 Subject: [PATCH] SONAR-23259 add changelog management for impacts Co-authored-by: OrlovAlexander --- .../sonar/db/rule/RuleImpactChangeDto.java | 21 +++++- .../qualityprofile/ActiveRuleChange.java | 62 ++++++++++++++-- .../qualityprofile/ActiveRuleChangeTest.java | 74 ++++++++++++++++++- .../QualityProfileChangesUpdater.java | 11 ++- .../QualityProfileChangesUpdaterTest.java | 44 +++++++---- .../QualityProfileChangeEventServiceImpl.java | 5 +- ...lityProfileChangeEventServiceImplTest.java | 32 ++++---- .../qualityprofile/QProfileComparisonIT.java | 3 +- .../qualityprofile/QProfileResetImplIT.java | 4 +- .../qualityprofile/QProfileRuleImplIT.java | 3 +- .../qualityprofile/QProfileRulesImplIT.java | 3 +- .../qualityprofile/QProfileTreeImplIT.java | 4 +- ...RegisterQualityProfilesNotificationIT.java | 3 +- .../builtin/BuiltInQProfileInsertImplIT.java | 7 +- .../builtin/BuiltInQProfileUpdateImplIT.java | 4 +- .../builtin/RuleActivatorIT.java | 30 ++++++-- .../ws/ChangeParentActionIT.java | 4 +- .../qualityprofile/ws/CreateActionIT.java | 3 +- .../ws/InheritanceActionIT.java | 4 +- .../ws/QProfilesWsMediumIT.java | 6 +- .../sonar/server/rule/ws/SearchActionIT.java | 3 +- .../builtin/BuiltInQProfileInsertImpl.java | 1 - .../qualityprofile/builtin/RuleActivator.java | 57 +++++++++----- 23 files changed, 298 insertions(+), 90 deletions(-) diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/rule/RuleImpactChangeDto.java b/server/sonar-db-dao/src/main/java/org/sonar/db/rule/RuleImpactChangeDto.java index 2fa8d193e9d..2827495e6cb 100644 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/rule/RuleImpactChangeDto.java +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/rule/RuleImpactChangeDto.java @@ -19,6 +19,7 @@ */ package org.sonar.db.rule; +import java.util.Objects; import javax.annotation.Nullable; import org.sonar.api.issue.impact.Severity; import org.sonar.api.issue.impact.SoftwareQuality; @@ -37,7 +38,7 @@ public class RuleImpactChangeDto { } public RuleImpactChangeDto(@Nullable SoftwareQuality newSoftwareQuality, @Nullable SoftwareQuality oldSoftwareQuality, - @Nullable Severity newSeverity, @Nullable Severity oldSeverity) { + @Nullable Severity newSeverity, @Nullable Severity oldSeverity) { this.newSoftwareQuality = newSoftwareQuality; this.oldSoftwareQuality = oldSoftwareQuality; this.newSeverity = newSeverity; @@ -83,4 +84,22 @@ public class RuleImpactChangeDto { public void setRuleChangeUuid(String ruleChangeUuid) { this.ruleChangeUuid = ruleChangeUuid; } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + RuleImpactChangeDto that = (RuleImpactChangeDto) o; + return newSoftwareQuality == that.newSoftwareQuality && oldSoftwareQuality == that.oldSoftwareQuality && newSeverity == that.newSeverity && oldSeverity == that.oldSeverity + && Objects.equals(ruleChangeUuid, that.ruleChangeUuid); + } + + @Override + public int hashCode() { + return Objects.hash(newSoftwareQuality, oldSoftwareQuality, newSeverity, oldSeverity, ruleChangeUuid); + } } 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 eefcb5b8bd2..024fc814594 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 @@ -20,22 +20,30 @@ package org.sonar.server.qualityprofile; import com.google.common.base.MoreObjects; +import com.google.common.collect.MapDifference; +import com.google.common.collect.Maps; import java.util.EnumMap; import java.util.HashMap; import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; import javax.annotation.CheckForNull; import javax.annotation.Nullable; import org.apache.commons.lang3.StringUtils; +import org.jetbrains.annotations.NotNull; import org.sonar.api.issue.impact.Severity; import org.sonar.api.issue.impact.SoftwareQuality; import org.sonar.db.qualityprofile.ActiveRuleDto; import org.sonar.db.qualityprofile.ActiveRuleKey; import org.sonar.db.qualityprofile.QProfileChangeDto; +import org.sonar.db.rule.RuleChangeDto; import org.sonar.db.rule.RuleDto; +import org.sonar.db.rule.RuleImpactChangeDto; public class ActiveRuleChange { private ActiveRuleDto activeRule; + private RuleDto rule; public enum Type { ACTIVATED, DEACTIVATED, UPDATED @@ -45,7 +53,8 @@ public class ActiveRuleChange { private final ActiveRuleKey key; private final String ruleUuid; private String severity = null; - private final Map impactSeverities = new EnumMap<>(SoftwareQuality.class); + private final Map oldImpacts = new EnumMap<>(SoftwareQuality.class); + private final Map newImpacts = new EnumMap<>(SoftwareQuality.class); private Boolean prioritizedRule = null; private ActiveRuleInheritance inheritance = null; private final Map parameters = new HashMap<>(); @@ -60,6 +69,7 @@ public class ActiveRuleChange { public ActiveRuleChange(Type type, ActiveRuleKey key, RuleDto ruleDto) { this.type = type; this.key = key; + this.rule = ruleDto; this.ruleUuid = ruleDto.getUuid(); } @@ -85,13 +95,13 @@ public class ActiveRuleChange { return this; } - public Map getImpactSeverities() { - return impactSeverities; + public Map getNewImpacts() { + return newImpacts; } - public ActiveRuleChange setImpactSeverities(Map impactSeverities) { - this.impactSeverities.clear(); - this.impactSeverities.putAll(impactSeverities); + public ActiveRuleChange setNewImpacts(Map newImpacts) { + this.newImpacts.clear(); + this.newImpacts.putAll(newImpacts); return this; } @@ -100,6 +110,17 @@ public class ActiveRuleChange { return this; } + public ActiveRuleChange setOldImpacts(Map impactSeverities) { + this.oldImpacts.clear(); + this.oldImpacts.putAll(impactSeverities); + return this; + } + + public ActiveRuleChange setRule(RuleDto rule) { + this.rule = rule; + return this; + } + @CheckForNull public Boolean isPrioritizedRule() { return prioritizedRule; @@ -149,6 +170,12 @@ public class ActiveRuleChange { dto.setChangeType(type.name()); dto.setRulesProfileUuid(getKey().getRuleProfileUuid()); dto.setUserUuid(userUuid); + RuleChangeDto ruleChange = new RuleChangeDto(); + ruleChange.setRuleImpactChanges(createRuleImpactChanges()); + ruleChange.setRuleUuid(ruleUuid); + if (!ruleChange.getRuleImpactChanges().isEmpty()) { + dto.setRuleChange(ruleChange); + } Map data = new HashMap<>(); data.put("ruleUuid", getRuleUuid()); @@ -163,6 +190,27 @@ public class ActiveRuleChange { return dto; } + @NotNull + private Set createRuleImpactChanges() { + // We only compute ruleImpactChanges in case of the update or activate + if ((type == Type.UPDATED || type == Type.ACTIVATED) && rule != null) { + MapDifference difference = Maps.difference( + computeEffectiveImpactMap(rule, oldImpacts), + computeEffectiveImpactMap(rule, newImpacts)); + + return difference.entriesDiffering().entrySet().stream() + .map(e -> new RuleImpactChangeDto(e.getKey(), e.getKey(), e.getValue().rightValue(), e.getValue().leftValue())) + .collect(Collectors.toSet()); + } + return Set.of(); + } + + public static Map computeEffectiveImpactMap(RuleDto ruleDto, Map activeRuleImpacts) { + Map impacts = ruleDto.getDefaultImpactsMap(); + impacts.replaceAll(activeRuleImpacts::getOrDefault); + return impacts; + } + @Override public String toString() { return MoreObjects.toStringHelper(this) @@ -173,7 +221,7 @@ public class ActiveRuleChange { .add("inheritance", inheritance) .add("parameters", parameters) .add("prioritizedRule", prioritizedRule) - .add("impactSeverities", impactSeverities) + .add("impactSeverities", newImpacts) .toString(); } } diff --git a/server/sonar-server-common/src/test/java/org/sonar/server/qualityprofile/ActiveRuleChangeTest.java b/server/sonar-server-common/src/test/java/org/sonar/server/qualityprofile/ActiveRuleChangeTest.java index 48df809f5a6..ca26c5a48a7 100644 --- a/server/sonar-server-common/src/test/java/org/sonar/server/qualityprofile/ActiveRuleChangeTest.java +++ b/server/sonar-server-common/src/test/java/org/sonar/server/qualityprofile/ActiveRuleChangeTest.java @@ -19,17 +19,25 @@ */ package org.sonar.server.qualityprofile; +import java.util.List; +import java.util.Map; +import java.util.Set; import org.junit.Test; +import org.sonar.api.issue.impact.Severity; +import org.sonar.api.issue.impact.SoftwareQuality; import org.sonar.api.rule.RuleKey; import org.sonar.core.util.Uuids; +import org.sonar.db.issue.ImpactDto; import org.sonar.db.qualityprofile.ActiveRuleKey; import org.sonar.db.qualityprofile.QProfileChangeDto; import org.sonar.db.qualityprofile.QProfileDto; import org.sonar.db.rule.RuleDto; +import org.sonar.db.rule.RuleImpactChangeDto; import static org.assertj.core.api.Assertions.assertThat; import static org.sonar.db.qualityprofile.QualityProfileTesting.newQualityProfileDto; import static org.sonar.server.qualityprofile.ActiveRuleChange.Type.ACTIVATED; +import static org.sonar.server.qualityprofile.ActiveRuleChange.Type.UPDATED; public class ActiveRuleChangeTest { @@ -40,13 +48,75 @@ public class ActiveRuleChangeTest { QProfileDto profile = newQualityProfileDto(); ActiveRuleKey key = ActiveRuleKey.of(profile, RuleKey.of("P1", "R1")); String ruleUuid = Uuids.createFast(); - ActiveRuleChange underTest = new ActiveRuleChange(ACTIVATED, key, new RuleDto().setUuid(ruleUuid)); + ActiveRuleChange underTest = new ActiveRuleChange(UPDATED, key, new RuleDto().setUuid(ruleUuid)); + underTest.setRule( + new RuleDto().replaceAllDefaultImpacts(List.of(new ImpactDto(SoftwareQuality.RELIABILITY, Severity.LOW), new ImpactDto(SoftwareQuality.MAINTAINABILITY, Severity.HIGH)))); + underTest.setOldImpacts(Map.of(SoftwareQuality.SECURITY, Severity.LOW, SoftwareQuality.MAINTAINABILITY, Severity.HIGH)); + underTest.setNewImpacts(Map.of(SoftwareQuality.RELIABILITY, Severity.HIGH, SoftwareQuality.MAINTAINABILITY, Severity.BLOCKER)); QProfileChangeDto result = underTest.toDto(A_USER_UUID); - assertThat(result.getChangeType()).isEqualTo(ACTIVATED.name()); + assertThat(result.getChangeType()).isEqualTo(UPDATED.name()); assertThat(result.getRulesProfileUuid()).isEqualTo(profile.getRulesProfileUuid()); assertThat(result.getUserUuid()).isEqualTo(A_USER_UUID); assertThat(result.getDataAsMap()).containsEntry("ruleUuid", ruleUuid); + + Set ruleImpactChanges = result.getRuleChange().getRuleImpactChanges(); + + assertThat(ruleImpactChanges) + .hasSize(2) + .containsExactlyInAnyOrder( + new RuleImpactChangeDto(SoftwareQuality.MAINTAINABILITY, SoftwareQuality.MAINTAINABILITY, Severity.BLOCKER, Severity.HIGH), + new RuleImpactChangeDto(SoftwareQuality.RELIABILITY, SoftwareQuality.RELIABILITY, Severity.HIGH, Severity.LOW)); + } + + @Test + public void toDto_whenIdenticalImpacts_shouldNotReturnImpactChanges() { + QProfileDto profile = newQualityProfileDto(); + ActiveRuleKey key = ActiveRuleKey.of(profile, RuleKey.of("P1", "R1")); + String ruleUuid = Uuids.createFast(); + ActiveRuleChange underTest = new ActiveRuleChange(UPDATED, key, new RuleDto().setUuid(ruleUuid)); + underTest.setRule(new RuleDto().replaceAllDefaultImpacts(List.of(new ImpactDto(SoftwareQuality.MAINTAINABILITY, Severity.HIGH)))); + underTest.setOldImpacts(Map.of(SoftwareQuality.SECURITY, Severity.LOW, SoftwareQuality.MAINTAINABILITY, Severity.BLOCKER)); + underTest.setNewImpacts(Map.of(SoftwareQuality.SECURITY, Severity.LOW, SoftwareQuality.MAINTAINABILITY, Severity.BLOCKER)); + + QProfileChangeDto result = underTest.toDto(A_USER_UUID); + + assertThat(result.getRuleChange()).isNull(); + + } + + @Test + public void toDto_whenRuleChangeDtoIsActivated_shouldNotReturnImpactChanges() { + QProfileDto profile = newQualityProfileDto(); + ActiveRuleKey key = ActiveRuleKey.of(profile, RuleKey.of("P1", "R1")); + String ruleUuid = Uuids.createFast(); + ActiveRuleChange underTest = new ActiveRuleChange(ACTIVATED, key, new RuleDto().setUuid(ruleUuid)); + underTest.setRule(new RuleDto().replaceAllDefaultImpacts(List.of(new ImpactDto(SoftwareQuality.MAINTAINABILITY, Severity.HIGH)))); + underTest.setOldImpacts(Map.of(SoftwareQuality.SECURITY, Severity.LOW, SoftwareQuality.MAINTAINABILITY, Severity.BLOCKER)); + underTest.setNewImpacts(Map.of(SoftwareQuality.SECURITY, Severity.LOW, SoftwareQuality.MAINTAINABILITY, Severity.INFO)); + + QProfileChangeDto result = underTest.toDto(A_USER_UUID); + + assertThat(result.getRuleChange().getRuleImpactChanges()) + .hasSize(1) + .containsExactlyInAnyOrder( + new RuleImpactChangeDto(SoftwareQuality.MAINTAINABILITY, SoftwareQuality.MAINTAINABILITY, Severity.INFO, Severity.BLOCKER)); + } + + @Test + public void toDto_whenRuleChangeDtoIsActivatedAndSameImpacts_shouldNotReturnImpactChanges() { + QProfileDto profile = newQualityProfileDto(); + ActiveRuleKey key = ActiveRuleKey.of(profile, RuleKey.of("P1", "R1")); + String ruleUuid = Uuids.createFast(); + ActiveRuleChange underTest = new ActiveRuleChange(ACTIVATED, key, new RuleDto().setUuid(ruleUuid)); + underTest.setRule(new RuleDto().replaceAllDefaultImpacts(List.of(new ImpactDto(SoftwareQuality.MAINTAINABILITY, Severity.HIGH)))); + underTest.setOldImpacts(Map.of(SoftwareQuality.SECURITY, Severity.LOW, SoftwareQuality.MAINTAINABILITY, Severity.BLOCKER)); + underTest.setNewImpacts(Map.of(SoftwareQuality.SECURITY, Severity.LOW, SoftwareQuality.MAINTAINABILITY, Severity.BLOCKER)); + + QProfileChangeDto result = underTest.toDto(A_USER_UUID); + + assertThat(result.getRuleChange()).isNull(); + } } diff --git a/server/sonar-webserver-core/src/main/java/org/sonar/server/rule/registration/QualityProfileChangesUpdater.java b/server/sonar-webserver-core/src/main/java/org/sonar/server/rule/registration/QualityProfileChangesUpdater.java index 8f55e1962a8..1573c4a17c9 100644 --- a/server/sonar-webserver-core/src/main/java/org/sonar/server/rule/registration/QualityProfileChangesUpdater.java +++ b/server/sonar-webserver-core/src/main/java/org/sonar/server/rule/registration/QualityProfileChangesUpdater.java @@ -25,6 +25,7 @@ import java.util.Iterator; import java.util.List; import java.util.Set; import java.util.stream.Collectors; +import java.util.stream.Stream; import org.jetbrains.annotations.NotNull; import org.sonar.api.issue.impact.SoftwareQuality; import org.sonar.core.platform.SonarQubeVersion; @@ -53,8 +54,11 @@ public class QualityProfileChangesUpdater { List changesToPersist = pluginRuleUpdates.stream() .flatMap(pluginRuleUpdate -> { RuleChangeDto ruleChangeDto = createNewRuleChange(pluginRuleUpdate); - insertRuleChange(dbSession, ruleChangeDto); + if (!hasChanges(ruleChangeDto)) { + return Stream.empty(); + } + insertRuleChange(dbSession, ruleChangeDto); return findQualityProfilesForRule(dbSession, pluginRuleUpdate.getRuleUuid()).stream() .map(qualityProfileUuid -> buildQprofileChangeDtoForRuleChange(qualityProfileUuid, ruleChangeDto)); }).toList(); @@ -64,6 +68,10 @@ public class QualityProfileChangesUpdater { } } + private static boolean hasChanges(RuleChangeDto ruleChangeDto) { + return ruleChangeDto.getNewCleanCodeAttribute() != ruleChangeDto.getOldCleanCodeAttribute() || !ruleChangeDto.getRuleImpactChanges().isEmpty(); + } + private RuleChangeDto createNewRuleChange(PluginRuleUpdate pluginRuleUpdate) { RuleChangeDto ruleChangeDto = new RuleChangeDto(); ruleChangeDto.setUuid(uuidFactory.create()); @@ -81,6 +89,7 @@ public class QualityProfileChangesUpdater { .map(ActiveRuleDto::getProfileUuid) .collect(Collectors.toSet()); } + private void insertRuleChange(DbSession dbSession, RuleChangeDto ruleChangeDto) { dbClient.ruleChangeDao().insert(dbSession, ruleChangeDto); } diff --git a/server/sonar-webserver-core/src/test/java/org/sonar/server/rule/registration/QualityProfileChangesUpdaterTest.java b/server/sonar-webserver-core/src/test/java/org/sonar/server/rule/registration/QualityProfileChangesUpdaterTest.java index 91cf442389e..e319bb8c7e4 100644 --- a/server/sonar-webserver-core/src/test/java/org/sonar/server/rule/registration/QualityProfileChangesUpdaterTest.java +++ b/server/sonar-webserver-core/src/test/java/org/sonar/server/rule/registration/QualityProfileChangesUpdaterTest.java @@ -50,7 +50,7 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoInteractions; import static org.mockito.Mockito.when; -public class QualityProfileChangesUpdaterTest { +class QualityProfileChangesUpdaterTest { public static final String RULE_UUID = "ruleUuid"; private final DbClient dbClient = mock(); @@ -70,14 +70,14 @@ public class QualityProfileChangesUpdaterTest { } @Test - public void updateWithoutCommit_whenNoRuleChanges_thenDontInteractWithDatabase() { + void updateWithoutCommit_whenNoRuleChanges_thenDontInteractWithDatabase() { underTest.createQprofileChangesForRuleUpdates(mock(), Set.of()); verifyNoInteractions(dbClient); } @Test - public void updateWithoutCommit_whenOneRuleChangedItsAttribute_thenInsertRuleChangeButNotImpactChange() { + void updateWithoutCommit_whenOneRuleChangedItsAttribute_thenInsertRuleChangeButNotImpactChange() { PluginRuleUpdate pluginRuleUpdate = new PluginRuleUpdate(); pluginRuleUpdate.setNewCleanCodeAttribute(CleanCodeAttribute.CLEAR); pluginRuleUpdate.setOldCleanCodeAttribute(CleanCodeAttribute.TESTED); @@ -85,21 +85,20 @@ public class QualityProfileChangesUpdaterTest { underTest.createQprofileChangesForRuleUpdates(dbSession, Set.of(pluginRuleUpdate)); - verify(ruleChangeDao).insert(argThat(dbSession::equals), argThat(ruleChangeDto -> - ruleChangeDto.getNewCleanCodeAttribute() == CleanCodeAttribute.CLEAR - && ruleChangeDto.getOldCleanCodeAttribute() == CleanCodeAttribute.TESTED - && ruleChangeDto.getRuleUuid().equals(RULE_UUID) - && ruleChangeDto.getRuleImpactChanges().isEmpty())); + verify(ruleChangeDao).insert(argThat(dbSession::equals), argThat(ruleChangeDto -> ruleChangeDto.getNewCleanCodeAttribute() == CleanCodeAttribute.CLEAR + && ruleChangeDto.getOldCleanCodeAttribute() == CleanCodeAttribute.TESTED + && ruleChangeDto.getRuleUuid().equals(RULE_UUID) + && ruleChangeDto.getRuleImpactChanges().isEmpty())); } @Test - public void updateWithoutCommit_whenTwoRulesChangedTheirImpactsAndAttributes_thenInsertRuleChangeAndImpactChange() { + void updateWithoutCommit_whenTwoRulesChangedTheirImpactsAndAttributes_thenInsertRuleChangeAndImpactChange() { PluginRuleUpdate pluginRuleUpdate = new PluginRuleUpdate(); pluginRuleUpdate.setNewCleanCodeAttribute(CleanCodeAttribute.CLEAR); pluginRuleUpdate.setOldCleanCodeAttribute(CleanCodeAttribute.TESTED); pluginRuleUpdate.setRuleUuid(RULE_UUID); - //testing here detecting the change with 2 the same software qualities + // testing here detecting the change with 2 the same software qualities pluginRuleUpdate.addNewImpact(SoftwareQuality.RELIABILITY, Severity.LOW); pluginRuleUpdate.addOldImpact(SoftwareQuality.RELIABILITY, Severity.MEDIUM); @@ -108,7 +107,7 @@ public class QualityProfileChangesUpdaterTest { pluginRuleUpdate2.setOldCleanCodeAttribute(CleanCodeAttribute.DISTINCT); pluginRuleUpdate2.setRuleUuid("ruleUuid2"); - //testing here detecting the change with 2 the different software qualities + // testing here detecting the change with 2 the different software qualities pluginRuleUpdate2.addNewImpact(SoftwareQuality.SECURITY, Severity.HIGH); pluginRuleUpdate2.addOldImpact(SoftwareQuality.RELIABILITY, Severity.MEDIUM); @@ -130,12 +129,26 @@ public class QualityProfileChangesUpdaterTest { assertThat(secondChange.getRuleUuid()).isEqualTo("ruleUuid2"); assertThat(secondChange.getRuleImpactChanges()).hasSize(1); assertThat(secondChange.getRuleImpactChanges()).extracting(RuleImpactChangeDto::getNewSoftwareQuality, - RuleImpactChangeDto::getOldSoftwareQuality, RuleImpactChangeDto::getOldSeverity, RuleImpactChangeDto::getNewSeverity) + RuleImpactChangeDto::getOldSoftwareQuality, RuleImpactChangeDto::getOldSeverity, RuleImpactChangeDto::getNewSeverity) .containsExactly(tuple(SoftwareQuality.SECURITY, SoftwareQuality.RELIABILITY, Severity.MEDIUM, Severity.HIGH)); } @Test - public void updateWithoutCommit_whenOneRuleBelongingToTwoQualityProfilesChanged_thenInsertOneRuleChangeAndTwoQualityProfileChanges() { + void updateWithoutCommit_whenImpactsSeverityIsChanged_shouldNotCreateRuleChange() { + PluginRuleUpdate pluginRuleUpdate = new PluginRuleUpdate(); + pluginRuleUpdate.setRuleUuid(RULE_UUID); + + // testing here detecting the change with 2 the same software qualities + pluginRuleUpdate.addNewImpact(SoftwareQuality.RELIABILITY, Severity.LOW); + pluginRuleUpdate.addOldImpact(SoftwareQuality.RELIABILITY, Severity.MEDIUM); + + underTest.createQprofileChangesForRuleUpdates(dbSession, Set.of(pluginRuleUpdate)); + + verifyNoInteractions(ruleChangeDao); + } + + @Test + void updateWithoutCommit_whenOneRuleBelongingToTwoQualityProfilesChanged_thenInsertOneRuleChangeAndTwoQualityProfileChanges() { List activeRuleDtos = List.of( new ActiveRuleDto().setProfileUuid("profileUuid1").setRuleUuid(RULE_UUID), new ActiveRuleDto().setProfileUuid("profileUuid2").setRuleUuid(RULE_UUID)); @@ -149,8 +162,7 @@ public class QualityProfileChangesUpdaterTest { underTest.createQprofileChangesForRuleUpdates(dbSession, Set.of(pluginRuleUpdate)); verify(qualityProfileChangeDao, times(1)).bulkInsert(argThat(dbSession::equals), - argThat(qProfileChangeDtos -> - qProfileChangeDtos.stream() - .allMatch(dto -> "UPDATED".equals(dto.getChangeType()) && dto.getRuleChange() != null))); + argThat(qProfileChangeDtos -> qProfileChangeDtos.stream() + .allMatch(dto -> "UPDATED".equals(dto.getChangeType()) && dto.getRuleChange() != null))); } } diff --git a/server/sonar-webserver-pushapi/src/main/java/org/sonar/server/pushapi/qualityprofile/QualityProfileChangeEventServiceImpl.java b/server/sonar-webserver-pushapi/src/main/java/org/sonar/server/pushapi/qualityprofile/QualityProfileChangeEventServiceImpl.java index a0dda22d239..49ef88e5f0b 100644 --- a/server/sonar-webserver-pushapi/src/main/java/org/sonar/server/pushapi/qualityprofile/QualityProfileChangeEventServiceImpl.java +++ b/server/sonar-webserver-pushapi/src/main/java/org/sonar/server/pushapi/qualityprofile/QualityProfileChangeEventServiceImpl.java @@ -182,7 +182,7 @@ public class QualityProfileChangeEventServiceImpl implements QualityProfileChang ruleChange.setSeverity(arc.getSeverity()); ruleChange.setLanguage(language); - arc.getImpactSeverities().forEach(ruleChange::addImpact); + arc.getNewImpacts().forEach(ruleChange::addImpact); Optional templateKey = templateKey(arc); templateKey.ifPresent(ruleChange::setTemplateKey); @@ -280,8 +280,7 @@ public class QualityProfileChangeEventServiceImpl implements QualityProfileChang private List getDefaultQualityProfileAssociatedProjects(DbSession dbSession, String language) { Set associatedProjectUuids = new HashSet<>(); - List measureDtos = - dbClient.measureDao().selectAllForProjectMainBranchesAssociatedToDefaultQualityProfile(dbSession); + List measureDtos = dbClient.measureDao().selectAllForProjectMainBranchesAssociatedToDefaultQualityProfile(dbSession); for (ProjectMainBranchMeasureDto measureDto : measureDtos) { String distribution = (String) measureDto.getMetricValues().get(CoreMetrics.NCLOC_LANGUAGE_DISTRIBUTION_KEY); if (distribution != null && distributionContainsLanguage(distribution, language)) { diff --git a/server/sonar-webserver-pushapi/src/test/java/org/sonar/server/pushapi/qualityprofile/QualityProfileChangeEventServiceImplTest.java b/server/sonar-webserver-pushapi/src/test/java/org/sonar/server/pushapi/qualityprofile/QualityProfileChangeEventServiceImplTest.java index 02619792635..6ddfbc28acb 100644 --- a/server/sonar-webserver-pushapi/src/test/java/org/sonar/server/pushapi/qualityprofile/QualityProfileChangeEventServiceImplTest.java +++ b/server/sonar-webserver-pushapi/src/test/java/org/sonar/server/pushapi/qualityprofile/QualityProfileChangeEventServiceImplTest.java @@ -74,7 +74,7 @@ class QualityProfileChangeEventServiceImplTest { db.rules().insert(rule1); ActiveRuleChange activeRuleChange = changeActiveRule(qualityProfileDto, rule1, "paramChangeKey", "paramChangeValue"); - activeRuleChange.setImpactSeverities(Map.of(SoftwareQuality.MAINTAINABILITY, Severity.LOW)); + activeRuleChange.setNewImpacts(Map.of(SoftwareQuality.MAINTAINABILITY, Severity.LOW)); Collection profiles = Collections.singleton(qualityProfileDto); @@ -94,11 +94,11 @@ class QualityProfileChangeEventServiceImplTest { assertThat(ruleSetChangedEvent) .contains("\"activatedRules\":[{\"key\":\"repo:ruleKey\"," + - "\"language\":\"xoo\"," + - "\"templateKey\":\"xoo:template-key\"," + - "\"params\":[{\"key\":\"paramChangeKey\",\"value\":\"paramChangeValue\"}]," + - "\"impacts\":[{\"softwareQuality\":\"MAINTAINABILITY\",\"severity\":\"LOW\"}]}]," + - "\"deactivatedRules\":[]"); + "\"language\":\"xoo\"," + + "\"templateKey\":\"xoo:template-key\"," + + "\"params\":[{\"key\":\"paramChangeKey\",\"value\":\"paramChangeValue\"}]," + + "\"impacts\":[{\"softwareQuality\":\"MAINTAINABILITY\",\"severity\":\"LOW\"}]}]," + + "\"deactivatedRules\":[]"); } @Test @@ -110,7 +110,7 @@ class QualityProfileChangeEventServiceImplTest { QProfileDto defaultQualityProfile = insertDefaultQualityProfile(language); RuleDto rule = insertCustomRule(templateRule, language, "
line1\nline2
"); ActiveRuleChange activeRuleChange = changeActiveRule(defaultQualityProfile, rule, "paramChangeKey", "paramChangeValue") - .setImpactSeverities(Map.of(SoftwareQuality.RELIABILITY, Severity.MEDIUM)); + .setNewImpacts(Map.of(SoftwareQuality.RELIABILITY, Severity.MEDIUM)); db.measures().insertMeasure(mainBranch, m -> m.addValue(NCLOC_LANGUAGE_DISTRIBUTION_KEY, language + "=100")); db.getSession().commit(); @@ -130,11 +130,11 @@ class QualityProfileChangeEventServiceImplTest { assertThat(ruleSetChangedEvent) .contains("\"activatedRules\":[{\"key\":\"repo:ruleKey\"," + - "\"language\":\"xoo\"," + - "\"templateKey\":\"xoo:template-key\"," + - "\"params\":[{\"key\":\"paramChangeKey\",\"value\":\"paramChangeValue\"}]," + - "\"impacts\":[{\"softwareQuality\":\"RELIABILITY\",\"severity\":\"MEDIUM\"}]}]," + - "\"deactivatedRules\":[]"); + "\"language\":\"xoo\"," + + "\"templateKey\":\"xoo:template-key\"," + + "\"params\":[{\"key\":\"paramChangeKey\",\"value\":\"paramChangeValue\"}]," + + "\"impacts\":[{\"softwareQuality\":\"RELIABILITY\",\"severity\":\"MEDIUM\"}]}]," + + "\"deactivatedRules\":[]"); } private Deque getProjectEvents(ProjectDto projectDto) { @@ -215,9 +215,9 @@ class QualityProfileChangeEventServiceImplTest { assertThat(ruleSetChangedEvent) .contains("\"activatedRules\":[{\"key\":\"repo:ruleKey\"," + - "\"language\":\"xoo\",\"severity\":\"" + activeRule1.getSeverityString() + "\"," + - "\"params\":[{\"key\":\"" + activeRuleParam1.getKey() + "\",\"value\":\"" + activeRuleParam1.getValue() + "\"}]," + - "\"impacts\":[{\"softwareQuality\":\"SECURITY\",\"severity\":\"BLOCKER\"}]}]," + - "\"deactivatedRules\":[\"repo2:ruleKey2\"]"); + "\"language\":\"xoo\",\"severity\":\"" + activeRule1.getSeverityString() + "\"," + + "\"params\":[{\"key\":\"" + activeRuleParam1.getKey() + "\",\"value\":\"" + activeRuleParam1.getValue() + "\"}]," + + "\"impacts\":[{\"softwareQuality\":\"SECURITY\",\"severity\":\"BLOCKER\"}]}]," + + "\"deactivatedRules\":[\"repo2:ruleKey2\"]"); } } diff --git a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/qualityprofile/QProfileComparisonIT.java b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/qualityprofile/QProfileComparisonIT.java index eb8750c96dc..c43f242f8c2 100644 --- a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/qualityprofile/QProfileComparisonIT.java +++ b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/qualityprofile/QProfileComparisonIT.java @@ -34,6 +34,7 @@ import org.sonar.api.server.rule.RuleParamType; import org.sonar.api.utils.System2; import org.sonar.api.utils.Version; import org.sonar.core.platform.SonarQubeVersion; +import org.sonar.core.util.UuidFactoryImpl; import org.sonar.db.DbClient; import org.sonar.db.DbSession; import org.sonar.db.DbTester; @@ -90,7 +91,7 @@ class QProfileComparisonIT { ActiveRuleIndexer activeRuleIndexer = new ActiveRuleIndexer(db, es.client()); QualityProfileChangeEventService qualityProfileChangeEventService = mock(QualityProfileChangeEventService.class); SonarQubeVersion sonarQubeVersion = new SonarQubeVersion(Version.create(10, 3)); - RuleActivator ruleActivator = new RuleActivator(System2.INSTANCE, db, new TypeValidations(singletonList(new IntegerTypeValidation())), + RuleActivator ruleActivator = new RuleActivator(System2.INSTANCE, db, UuidFactoryImpl.INSTANCE, new TypeValidations(singletonList(new IntegerTypeValidation())), userSession, mock(Configuration.class), sonarQubeVersion); qProfileRules = new QProfileRulesImpl(db, ruleActivator, ruleIndex, activeRuleIndexer, qualityProfileChangeEventService); comparison = new QProfileComparison(db); diff --git a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/qualityprofile/QProfileResetImplIT.java b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/qualityprofile/QProfileResetImplIT.java index 190482e918d..469bbad06dc 100644 --- a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/qualityprofile/QProfileResetImplIT.java +++ b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/qualityprofile/QProfileResetImplIT.java @@ -26,6 +26,7 @@ import org.sonar.api.impl.utils.AlwaysIncreasingSystem2; import org.sonar.api.utils.System2; import org.sonar.api.utils.Version; import org.sonar.core.platform.SonarQubeVersion; +import org.sonar.core.util.UuidFactoryImpl; import org.sonar.db.DbTester; import org.sonar.db.qualityprofile.ActiveRuleKey; import org.sonar.db.qualityprofile.OrgActiveRuleDto; @@ -68,7 +69,8 @@ public class QProfileResetImplIT { private QualityProfileChangeEventService qualityProfileChangeEventService = mock(QualityProfileChangeEventService.class); private TypeValidations typeValidations = new TypeValidations(asList(new StringTypeValidation(), new IntegerTypeValidation())); private final SonarQubeVersion sonarQubeVersion = new SonarQubeVersion(Version.create(10, 3)); - private RuleActivator ruleActivator = new RuleActivator(system2, db.getDbClient(), typeValidations, userSession, mock(Configuration.class), sonarQubeVersion); + private RuleActivator ruleActivator = new RuleActivator(system2, db.getDbClient(), UuidFactoryImpl.INSTANCE, typeValidations, userSession, mock(Configuration.class), + sonarQubeVersion); private QProfileTree qProfileTree = new QProfileTreeImpl(db.getDbClient(), ruleActivator, system2, activeRuleIndexer, mock(QualityProfileChangeEventService.class)); private QProfileRules qProfileRules = new QProfileRulesImpl(db.getDbClient(), ruleActivator, null, activeRuleIndexer, qualityProfileChangeEventService); private QProfileResetImpl underTest = new QProfileResetImpl(db.getDbClient(), ruleActivator, activeRuleIndexer, mock(QualityProfileChangeEventService.class)); 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 ed5407003cf..cb69acb5b83 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 @@ -40,6 +40,7 @@ import org.sonar.api.utils.System2; import org.sonar.api.utils.Version; import org.sonar.core.config.CorePropertyDefinitions; import org.sonar.core.platform.SonarQubeVersion; +import org.sonar.core.util.UuidFactoryImpl; import org.sonar.db.DbTester; import org.sonar.db.issue.ImpactDto; import org.sonar.db.qualityprofile.ActiveRuleParamDto; @@ -102,7 +103,7 @@ 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, + private RuleActivator ruleActivator = new RuleActivator(system2, db.getDbClient(), UuidFactoryImpl.INSTANCE, typeValidations, userSession, configuration, sonarQubeVersion); private QProfileRules underTest = new QProfileRulesImpl(db.getDbClient(), ruleActivator, ruleIndex, activeRuleIndexer, qualityProfileChangeEventService); 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 5e20312caef..5d2ca42bafd 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 @@ -28,6 +28,7 @@ import org.sonar.api.rule.Severity; import org.sonar.api.utils.System2; import org.sonar.api.utils.Version; import org.sonar.core.platform.SonarQubeVersion; +import org.sonar.core.util.UuidFactoryImpl; import org.sonar.db.DbTester; import org.sonar.db.qualityprofile.ActiveRuleDto; import org.sonar.db.qualityprofile.QProfileChangeDto; @@ -65,7 +66,7 @@ class QProfileRulesImplIT { 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(), + private RuleActivator ruleActivator = new RuleActivator(System2.INSTANCE, db.getDbClient(), UuidFactoryImpl.INSTANCE, new TypeValidations(singletonList(new IntegerTypeValidation())), userSession, mock(Configuration.class), sonarQubeVersion); private QualityProfileChangeEventService qualityProfileChangeEventService = mock(QualityProfileChangeEventService.class); diff --git a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/qualityprofile/QProfileTreeImplIT.java b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/qualityprofile/QProfileTreeImplIT.java index e237af12f99..b1f4be81cc5 100644 --- a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/qualityprofile/QProfileTreeImplIT.java +++ b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/qualityprofile/QProfileTreeImplIT.java @@ -32,6 +32,7 @@ import org.sonar.api.rule.Severity; import org.sonar.api.utils.System2; import org.sonar.api.utils.Version; import org.sonar.core.platform.SonarQubeVersion; +import org.sonar.core.util.UuidFactoryImpl; import org.sonar.db.DbTester; import org.sonar.db.qualityprofile.ActiveRuleParamDto; import org.sonar.db.qualityprofile.OrgActiveRuleDto; @@ -74,7 +75,8 @@ public class QProfileTreeImplIT { private TypeValidations typeValidations = new TypeValidations(asList(new StringTypeValidation(), new IntegerTypeValidation())); private QualityProfileChangeEventService qualityProfileChangeEventService = mock(QualityProfileChangeEventService.class); private final SonarQubeVersion sonarQubeVersion = new SonarQubeVersion(Version.create(10, 3)); - private RuleActivator ruleActivator = new RuleActivator(system2, db.getDbClient(), typeValidations, userSession, mock(Configuration.class), sonarQubeVersion); + private RuleActivator ruleActivator = new RuleActivator(system2, db.getDbClient(), UuidFactoryImpl.INSTANCE, typeValidations, userSession, mock(Configuration.class), + sonarQubeVersion); private QProfileRules qProfileRules = new QProfileRulesImpl(db.getDbClient(), ruleActivator, null, activeRuleIndexer, qualityProfileChangeEventService); private QProfileTree underTest = new QProfileTreeImpl(db.getDbClient(), ruleActivator, System2.INSTANCE, activeRuleIndexer, mock(QualityProfileChangeEventService.class)); diff --git a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/qualityprofile/RegisterQualityProfilesNotificationIT.java b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/qualityprofile/RegisterQualityProfilesNotificationIT.java index 9945ba828d1..2d243476d69 100644 --- a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/qualityprofile/RegisterQualityProfilesNotificationIT.java +++ b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/qualityprofile/RegisterQualityProfilesNotificationIT.java @@ -111,7 +111,8 @@ class RegisterQualityProfilesNotificationIT { private final SonarQubeVersion sonarQubeVersion = new SonarQubeVersion(Version.create(10, 3)); private final BuiltInQProfileInsert builtInQProfileInsert = new BuiltInQProfileInsertImpl(dbClient, ruleFinder, system2, UuidFactoryImpl.INSTANCE, typeValidations, activeRuleIndexer, sonarQubeVersion); - private final RuleActivator ruleActivator = new RuleActivator(system2, dbClient, typeValidations, userSessionRule, mock(Configuration.class), sonarQubeVersion); + private final RuleActivator ruleActivator = new RuleActivator(system2, dbClient, UuidFactoryImpl.INSTANCE, typeValidations, userSessionRule, mock(Configuration.class), + sonarQubeVersion); private final QProfileRules qProfileRules = new QProfileRulesImpl(dbClient, ruleActivator, mock(RuleIndex.class), activeRuleIndexer, qualityProfileChangeEventService); private final BuiltInQProfileUpdate builtInQProfileUpdate = new BuiltInQProfileUpdateImpl(dbClient, ruleActivator, activeRuleIndexer, qualityProfileChangeEventService); private final BuiltInQualityProfilesUpdateListener builtInQualityProfilesNotification = mock(BuiltInQualityProfilesUpdateListener.class); diff --git a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/qualityprofile/builtin/BuiltInQProfileInsertImplIT.java b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/qualityprofile/builtin/BuiltInQProfileInsertImplIT.java index ba2bc1f5984..e356cd7d838 100644 --- a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/qualityprofile/builtin/BuiltInQProfileInsertImplIT.java +++ b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/qualityprofile/builtin/BuiltInQProfileInsertImplIT.java @@ -36,8 +36,8 @@ import org.sonar.api.server.profile.BuiltInQualityProfilesDefinition.NewBuiltInQ import org.sonar.api.utils.System2; import org.sonar.api.utils.Version; import org.sonar.core.platform.SonarQubeVersion; -import org.sonar.core.util.SequenceUuidFactory; import org.sonar.core.util.UuidFactory; +import org.sonar.core.util.UuidFactoryImpl; import org.sonar.db.DbSession; import org.sonar.db.DbTester; import org.sonar.db.issue.ImpactDto; @@ -73,14 +73,15 @@ class BuiltInQProfileInsertImplIT { public static DbTester db = DbTester.create(); private final System2 system2 = new AlwaysIncreasingSystem2(); - private final UuidFactory uuidFactory = new SequenceUuidFactory(); + private final UuidFactory uuidFactory = UuidFactoryImpl.INSTANCE; private final TypeValidations typeValidations = new TypeValidations(singletonList(new StringTypeValidation())); private final DbSession dbSession = db.getSession(); private static final DbSession batchDbSession = db.getDbClient().openSession(true); private final ServerRuleFinder ruleFinder = new DefaultRuleFinder(db.getDbClient(), mock(RuleDescriptionFormatter.class)); private final ActiveRuleIndexer activeRuleIndexer = mock(ActiveRuleIndexer.class); private final SonarQubeVersion sonarQubeVersion = new SonarQubeVersion(Version.create(10, 3)); - private final BuiltInQProfileInsertImpl underTest = new BuiltInQProfileInsertImpl(db.getDbClient(), ruleFinder, system2, uuidFactory, typeValidations, activeRuleIndexer, sonarQubeVersion); + private final BuiltInQProfileInsertImpl underTest = new BuiltInQProfileInsertImpl(db.getDbClient(), ruleFinder, system2, uuidFactory, typeValidations, activeRuleIndexer, + sonarQubeVersion); @AfterAll public static void tearDown() { diff --git a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/qualityprofile/builtin/BuiltInQProfileUpdateImplIT.java b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/qualityprofile/builtin/BuiltInQProfileUpdateImplIT.java index 885ca6c4c46..56cba72c6e6 100644 --- a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/qualityprofile/builtin/BuiltInQProfileUpdateImplIT.java +++ b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/qualityprofile/builtin/BuiltInQProfileUpdateImplIT.java @@ -39,6 +39,7 @@ import org.sonar.api.server.profile.BuiltInQualityProfilesDefinition.NewBuiltInQ import org.sonar.api.utils.System2; import org.sonar.api.utils.Version; import org.sonar.core.platform.SonarQubeVersion; +import org.sonar.core.util.UuidFactoryImpl; import org.sonar.db.DbTester; import org.sonar.db.issue.ImpactDto; import org.sonar.db.qualityprofile.ActiveRuleDto; @@ -91,7 +92,8 @@ class BuiltInQProfileUpdateImplIT { private TypeValidations typeValidations = new TypeValidations(asList(new StringTypeValidation(), new IntegerTypeValidation())); private QualityProfileChangeEventService qualityProfileChangeEventService = mock(QualityProfileChangeEventService.class); private final SonarQubeVersion sonarQubeVersion = new SonarQubeVersion(Version.create(10, 3)); - private RuleActivator ruleActivator = new RuleActivator(system2, db.getDbClient(), typeValidations, userSession, mock(Configuration.class), sonarQubeVersion); + private RuleActivator ruleActivator = new RuleActivator(system2, db.getDbClient(), UuidFactoryImpl.INSTANCE, typeValidations, userSession, mock(Configuration.class), + sonarQubeVersion); private BuiltInQProfileUpdateImpl underTest = new BuiltInQProfileUpdateImpl(db.getDbClient(), ruleActivator, activeRuleIndexer, qualityProfileChangeEventService); 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 96bda676488..3f385c9e398 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 @@ -33,15 +33,20 @@ import org.sonar.api.rules.RulePriority; import org.sonar.api.utils.System2; import org.sonar.api.utils.Version; import org.sonar.core.platform.SonarQubeVersion; +import org.sonar.core.util.UuidFactoryImpl; 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; +import org.sonar.db.qualityprofile.QProfileChangeDto; +import org.sonar.db.qualityprofile.QProfileChangeQuery; import org.sonar.db.qualityprofile.QProfileDto; import org.sonar.db.qualityprofile.RulesProfileDto; +import org.sonar.db.rule.RuleChangeDto; import org.sonar.db.rule.RuleDto; +import org.sonar.db.rule.RuleImpactChangeDto; import org.sonar.db.rule.RuleParamDto; import org.sonar.server.exceptions.BadRequestException; import org.sonar.server.pushapi.qualityprofile.QualityProfileChangeEventService; @@ -70,7 +75,7 @@ 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 + * org.sonar.server.qualityprofile.builtin.BuiltInQProfileUpdateImplIT */ class RuleActivatorIT { @RegisterExtension @@ -86,7 +91,7 @@ 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, + private final RuleActivator underTest = new RuleActivator(system2, db.getDbClient(), UuidFactoryImpl.INSTANCE, typeValidations, userSession, mock(Configuration.class), sonarQubeVersion); @Test @@ -123,7 +128,7 @@ class RuleActivatorIT { ActiveRuleChange activeRuleResult = result.get(0); assertThat(activeRuleResult.getParameters()).containsEntry("min", "10"); assertThat(activeRuleResult.getSeverity()).isEqualTo(Severity.BLOCKER); - assertThat(activeRuleResult.getImpactSeverities()).isEqualTo(Map.of(MAINTAINABILITY, org.sonar.api.issue.impact.Severity.HIGH)); + assertThat(activeRuleResult.getNewImpacts()).isEqualTo(Map.of(MAINTAINABILITY, org.sonar.api.issue.impact.Severity.HIGH)); assertThat(activeRuleResult.isPrioritizedRule()).isFalse(); assertThat(activeRuleResult.getInheritance()).isEqualTo(ActiveRuleInheritance.INHERITED); } @@ -163,7 +168,7 @@ class RuleActivatorIT { ActiveRuleChange activeRuleResult = result.get(0); assertThat(activeRuleResult.getParameters()).containsEntry("min", "15"); assertThat(activeRuleResult.getSeverity()).isEqualTo(Severity.MINOR); - assertThat(activeRuleResult.getImpactSeverities()).containsExactlyEntriesOf(Map.of(MAINTAINABILITY, org.sonar.api.issue.impact.Severity.LOW)); + assertThat(activeRuleResult.getNewImpacts()).containsExactlyEntriesOf(Map.of(MAINTAINABILITY, org.sonar.api.issue.impact.Severity.LOW)); assertThat(activeRuleResult.isPrioritizedRule()).isTrue(); assertThat(activeRuleResult.getInheritance()).isEqualTo(OVERRIDES); } @@ -202,7 +207,7 @@ class RuleActivatorIT { assertThat(result).hasSize(1); ActiveRuleChange activeRuleResult = result.get(0); assertThat(activeRuleResult.getSeverity()).isEqualTo(Severity.MINOR); - assertThat(activeRuleResult.getImpactSeverities()).containsExactlyEntriesOf(Map.of(SECURITY, org.sonar.api.issue.impact.Severity.LOW)); + assertThat(activeRuleResult.getNewImpacts()).containsExactlyEntriesOf(Map.of(SECURITY, org.sonar.api.issue.impact.Severity.LOW)); assertThat(activeRuleResult.getInheritance()).isEqualTo(OVERRIDES); } @@ -243,7 +248,7 @@ class RuleActivatorIT { assertThat(result).hasSize(1); ActiveRuleChange activeRuleResult = result.get(0); assertThat(activeRuleResult.getSeverity()).isEqualTo(Severity.BLOCKER); - assertThat(activeRuleResult.getImpactSeverities()) + assertThat(activeRuleResult.getNewImpacts()) .containsExactlyInAnyOrderEntriesOf(Map.of(SECURITY, org.sonar.api.issue.impact.Severity.LOW, RELIABILITY, org.sonar.api.issue.impact.Severity.LOW)); assertThat(activeRuleResult.getInheritance()).isEqualTo(OVERRIDES); } @@ -286,8 +291,17 @@ class RuleActivatorIT { assertThat(result).hasSize(1); ActiveRuleChange activeRuleResult = result.get(0); assertThat(activeRuleResult.getSeverity()).isEqualTo(Severity.MINOR); - assertThat(activeRuleResult.getImpactSeverities()).containsExactlyEntriesOf(Map.of(MAINTAINABILITY, org.sonar.api.issue.impact.Severity.LOW)); + assertThat(activeRuleResult.getNewImpacts()).containsExactlyEntriesOf(Map.of(MAINTAINABILITY, org.sonar.api.issue.impact.Severity.LOW)); assertThat(activeRuleResult.getInheritance()).isEqualTo(OVERRIDES); + + List qProfileChangeDtos = db.getDbClient().qProfileChangeDao().selectByQuery(session, new QProfileChangeQuery(childProfile.getKee())); + assertThat(qProfileChangeDtos).hasSize(1); + assertThat(qProfileChangeDtos.get(0).getChangeType()).isEqualTo("UPDATED"); + assertThat(qProfileChangeDtos.get(0).getDataAsMap()).containsEntry("severity", Severity.MINOR); + RuleChangeDto ruleChange = qProfileChangeDtos.get(0).getRuleChange(); + RuleImpactChangeDto expected = new RuleImpactChangeDto(MAINTAINABILITY, MAINTAINABILITY, org.sonar.api.issue.impact.Severity.LOW, org.sonar.api.issue.impact.Severity.BLOCKER); + expected.setRuleChangeUuid(ruleChange.getUuid()); + assertThat(ruleChange.getRuleImpactChanges()).containsExactly(expected); } @Test @@ -317,7 +331,7 @@ class RuleActivatorIT { assertThat(result).hasSize(1); assertThat(result.get(0).getParameters()).containsEntry("min", "10"); assertThat(result.get(0).getSeverity()).isEqualTo(Severity.BLOCKER); - assertThat(result.get(0).getImpactSeverities()).containsExactlyEntriesOf(Map.of(MAINTAINABILITY, org.sonar.api.issue.impact.Severity.HIGH)); + assertThat(result.get(0).getNewImpacts()).containsExactlyEntriesOf(Map.of(MAINTAINABILITY, org.sonar.api.issue.impact.Severity.HIGH)); assertThat(result.get(0).getInheritance()).isNull(); } diff --git a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/qualityprofile/ws/ChangeParentActionIT.java b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/qualityprofile/ws/ChangeParentActionIT.java index 1a29b094687..09918db2335 100644 --- a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/qualityprofile/ws/ChangeParentActionIT.java +++ b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/qualityprofile/ws/ChangeParentActionIT.java @@ -35,6 +35,7 @@ import org.sonar.api.server.ws.WebService.Param; import org.sonar.api.utils.System2; import org.sonar.api.utils.Version; import org.sonar.core.platform.SonarQubeVersion; +import org.sonar.core.util.UuidFactoryImpl; import org.sonar.db.DbClient; import org.sonar.db.DbSession; import org.sonar.db.DbTester; @@ -104,7 +105,8 @@ public class ChangeParentActionIT { activeRuleIndexer = new ActiveRuleIndexer(dbClient, esClient); TypeValidations typeValidations = new TypeValidations(Collections.emptyList()); sonarQubeVersion = new SonarQubeVersion(Version.create(10, 3)); - RuleActivator ruleActivator = new RuleActivator(System2.INSTANCE, dbClient, typeValidations, userSession, mock(Configuration.class), sonarQubeVersion); + RuleActivator ruleActivator = new RuleActivator(System2.INSTANCE, dbClient, UuidFactoryImpl.INSTANCE, typeValidations, userSession, mock(Configuration.class), + sonarQubeVersion); qProfileTree = new QProfileTreeImpl(dbClient, ruleActivator, System2.INSTANCE, activeRuleIndexer, mock(QualityProfileChangeEventService.class)); ChangeParentAction underTest = new ChangeParentAction( dbClient, diff --git a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/qualityprofile/ws/CreateActionIT.java b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/qualityprofile/ws/CreateActionIT.java index 0a2b71bca57..5791cfb7d5d 100644 --- a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/qualityprofile/ws/CreateActionIT.java +++ b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/qualityprofile/ws/CreateActionIT.java @@ -36,6 +36,7 @@ import org.sonar.api.utils.ValidationMessages; import org.sonar.api.utils.Version; import org.sonar.core.platform.SonarQubeVersion; import org.sonar.core.util.UuidFactoryFast; +import org.sonar.core.util.UuidFactoryImpl; import org.sonar.db.DbClient; import org.sonar.db.DbSession; import org.sonar.db.DbTester; @@ -93,7 +94,7 @@ public class CreateActionIT { private ProfileImporter[] profileImporters = createImporters(); private QualityProfileChangeEventService qualityProfileChangeEventService = mock(QualityProfileChangeEventService.class); private final SonarQubeVersion sonarQubeVersion = new SonarQubeVersion(Version.create(10, 3)); - private RuleActivator ruleActivator = new RuleActivator(System2.INSTANCE, dbClient, null, userSession, mock(Configuration.class), sonarQubeVersion); + private RuleActivator ruleActivator = new RuleActivator(System2.INSTANCE, dbClient, UuidFactoryImpl.INSTANCE, null, userSession, mock(Configuration.class), sonarQubeVersion); private QProfileRules qProfileRules = new QProfileRulesImpl(dbClient, ruleActivator, ruleIndex, activeRuleIndexer, qualityProfileChangeEventService); private QProfileExporters qProfileExporters = new QProfileExporters(dbClient, null, qProfileRules, profileImporters); diff --git a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/qualityprofile/ws/InheritanceActionIT.java b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/qualityprofile/ws/InheritanceActionIT.java index 724e193ccab..0beec33b7b6 100644 --- a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/qualityprofile/ws/InheritanceActionIT.java +++ b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/qualityprofile/ws/InheritanceActionIT.java @@ -35,6 +35,7 @@ import org.sonar.api.server.ws.WebService.Param; import org.sonar.api.utils.System2; import org.sonar.api.utils.Version; import org.sonar.core.platform.SonarQubeVersion; +import org.sonar.core.util.UuidFactoryImpl; import org.sonar.db.DbClient; import org.sonar.db.DbSession; import org.sonar.db.DbTester; @@ -88,7 +89,8 @@ public class InheritanceActionIT { private RuleIndex ruleIndex = new RuleIndex(esClient, System2.INSTANCE); private QualityProfileChangeEventService qualityProfileChangeEventService = mock(QualityProfileChangeEventService.class); private final SonarQubeVersion sonarQubeVersion = new SonarQubeVersion(Version.create(10, 3)); - private RuleActivator ruleActivator = new RuleActivator(System2.INSTANCE, dbClient, new TypeValidations(new ArrayList<>()), userSession, mock(Configuration.class), sonarQubeVersion); + private RuleActivator ruleActivator = new RuleActivator(System2.INSTANCE, dbClient, UuidFactoryImpl.INSTANCE, new TypeValidations(new ArrayList<>()), userSession, + mock(Configuration.class), sonarQubeVersion); private QProfileRules qProfileRules = new QProfileRulesImpl(dbClient, ruleActivator, ruleIndex, activeRuleIndexer, qualityProfileChangeEventService); private QProfileTree qProfileTree = new QProfileTreeImpl(dbClient, ruleActivator, System2.INSTANCE, activeRuleIndexer, mock(QualityProfileChangeEventService.class)); diff --git a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/qualityprofile/ws/QProfilesWsMediumIT.java b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/qualityprofile/ws/QProfilesWsMediumIT.java index d0aa20e69c4..eda3f7012da 100644 --- a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/qualityprofile/ws/QProfilesWsMediumIT.java +++ b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/qualityprofile/ws/QProfilesWsMediumIT.java @@ -33,6 +33,7 @@ import org.sonar.api.server.ws.WebService.Param; import org.sonar.api.utils.System2; import org.sonar.api.utils.Version; import org.sonar.core.platform.SonarQubeVersion; +import org.sonar.core.util.UuidFactoryImpl; import org.sonar.db.DbClient; import org.sonar.db.DbSession; import org.sonar.db.DbTester; @@ -89,7 +90,8 @@ public class QProfilesWsMediumIT { private final TypeValidations typeValidations = new TypeValidations(emptyList()); private final QualityProfileChangeEventService qualityProfileChangeEventService = mock(QualityProfileChangeEventService.class); private final SonarQubeVersion sonarQubeVersion = new SonarQubeVersion(Version.create(10, 3)); - private final RuleActivator ruleActivator = new RuleActivator(System2.INSTANCE, dbClient, typeValidations, userSessionRule, mock(Configuration.class), sonarQubeVersion); + private final RuleActivator ruleActivator = new RuleActivator(System2.INSTANCE, dbClient, UuidFactoryImpl.INSTANCE, typeValidations, userSessionRule, mock(Configuration.class), + sonarQubeVersion); private final QProfileRules qProfileRules = new QProfileRulesImpl(dbClient, ruleActivator, ruleIndex, activeRuleIndexer, qualityProfileChangeEventService); private final QProfileWsSupport qProfileWsSupport = new QProfileWsSupport(dbClient, userSessionRule); private final RuleQueryFactory ruleQueryFactory = new RuleQueryFactory(dbClient); @@ -100,7 +102,7 @@ public class QProfilesWsMediumIT { private final WsActionTester wsActivateRules = new WsActionTester(new ActivateRulesAction(ruleQueryFactory, userSessionRule, qProfileRules, qProfileWsSupport, dbClient)); @Before - public void before(){ + public void before() { userSessionRule.logIn().setSystemAdministrator(); userSessionRule.addPermission(GlobalPermission.ADMINISTER); userSessionRule.addPermission(GlobalPermission.ADMINISTER_QUALITY_PROFILES); diff --git a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/rule/ws/SearchActionIT.java b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/rule/ws/SearchActionIT.java index 85fcf9ce615..ae0c5d36c9c 100644 --- a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/rule/ws/SearchActionIT.java +++ b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/rule/ws/SearchActionIT.java @@ -51,6 +51,7 @@ import org.sonar.api.utils.Version; import org.sonar.core.platform.SonarQubeVersion; import org.sonar.core.util.UuidFactory; import org.sonar.core.util.UuidFactoryFast; +import org.sonar.core.util.UuidFactoryImpl; import org.sonar.db.DbTester; import org.sonar.db.issue.ImpactDto; import org.sonar.db.qualityprofile.ActiveRuleParamDto; @@ -138,7 +139,7 @@ class SearchActionIT { new RulesResponseFormatter(db.getDbClient(), new RuleWsSupport(db.getDbClient(), userSession), ruleMapper, languages)); private final TypeValidations typeValidations = new TypeValidations(asList(new StringTypeValidation(), new IntegerTypeValidation())); private final SonarQubeVersion sonarQubeVersion = new SonarQubeVersion(Version.create(10, 3)); - private final RuleActivator ruleActivator = new RuleActivator(System2.INSTANCE, db.getDbClient(), typeValidations, userSession, + private final RuleActivator ruleActivator = new RuleActivator(System2.INSTANCE, db.getDbClient(), UuidFactoryImpl.INSTANCE, typeValidations, userSession, mock(Configuration.class), sonarQubeVersion); private final QProfileRules qProfileRules = new QProfileRulesImpl(db.getDbClient(), ruleActivator, ruleIndex, activeRuleIndexer, qualityProfileChangeEventService); diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/builtin/BuiltInQProfileInsertImpl.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/builtin/BuiltInQProfileInsertImpl.java index e6bdc955983..e88535791c4 100644 --- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/builtin/BuiltInQProfileInsertImpl.java +++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/builtin/BuiltInQProfileInsertImpl.java @@ -102,7 +102,6 @@ public class BuiltInQProfileInsertImpl implements BuiltInQProfileInsert { activeRuleIndexer.commitAndIndex(batchDbSession, changes); } - private void createDefaultAndOrgQProfiles(DbSession batchDbSession, BuiltInQProfile builtIn, RulesProfileDto rulesProfileDto) { Optional qProfileUuid = dbClient.defaultQProfileDao().selectDefaultQProfileUuid(batchDbSession, builtIn.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 146b0d5c69c..380203c5d7e 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 @@ -41,6 +41,7 @@ import org.sonar.api.server.rule.RuleParamType; import org.sonar.api.utils.System2; import org.sonar.core.config.CorePropertyDefinitions; import org.sonar.core.platform.SonarQubeVersion; +import org.sonar.core.util.UuidFactory; import org.sonar.db.DbClient; import org.sonar.db.DbSession; import org.sonar.db.qualityprofile.ActiveRuleDao; @@ -74,15 +75,17 @@ public class RuleActivator { private final System2 system2; private final DbClient db; + private final UuidFactory uuidFactory; private final TypeValidations typeValidations; private final UserSession userSession; private final Configuration configuration; private final SonarQubeVersion sonarQubeVersion; - public RuleActivator(System2 system2, DbClient db, TypeValidations typeValidations, UserSession userSession, + public RuleActivator(System2 system2, DbClient db, UuidFactory uuidFactory, TypeValidations typeValidations, UserSession userSession, Configuration configuration, SonarQubeVersion sonarQubeVersion) { this.system2 = system2; this.db = db; + this.uuidFactory = uuidFactory; this.typeValidations = typeValidations; this.userSession = userSession; this.configuration = configuration; @@ -124,6 +127,7 @@ public class RuleActivator { // No change if propagating to descendants, but child profile already overrides rule if (!context.isCascading() || !activeRule.get().doesOverride()) { change = new ActiveRuleChange(ActiveRuleChange.Type.UPDATED, activeRuleKey, rule); + change.setRule(context.getRule().get()); handleUpdatedRuleActivation(activation, context, change, activeRule); if (isSame(change, activeRule) || (context.isCascading() && activeRule.get().getInheritance() != null && !isSameAsParent(change, @@ -158,7 +162,7 @@ public class RuleActivator { if (context.isCascading() && activeRule.get().getInheritance() == null) { // The rule is being propagated, but it was activated directly on this profile before change.setSeverity(activeRule.get().getSeverityString()); - change.setImpactSeverities(activeRule.get().getImpacts()); + change.setNewImpacts(activeRule.get().getImpacts()); for (ActiveRuleParamDto activeParam : activeRule.getParams()) { change.setParameter(activeParam.getKey(), activeParam.getValue()); } @@ -203,24 +207,26 @@ public class RuleActivator { ActiveRuleWrapper parentActiveRule = context.getParentActiveRule(); if (request.isReset()) { - applySeverityAndPrioritizedRuleAndParamsWhenResetRequested(change, rule, parentActiveRule); + applySeverityAndPrioritizedRuleAndParamsWhenResetRequested(change, rule, activeRule, parentActiveRule); } else if (context.getRulesProfile().isBuiltIn()) { - applySeverityAndPrioritizedRuleAndParamsWhenBuiltInProfile(request, context, change, rule); + applySeverityAndPrioritizedRuleAndParamsWhenBuiltInProfile(request, context, change, rule, activeRule); } else { applySeverityAndPrioritizedRuleAndParamsWhenNonBuiltInProfile(request, context, change, rule, activeRule, parentActiveRule); } } - private void applySeverityAndPrioritizedRuleAndParamsWhenResetRequested(ActiveRuleChange change, RuleWrapper rule, + private void applySeverityAndPrioritizedRuleAndParamsWhenResetRequested(ActiveRuleChange change, RuleWrapper rule, @Nullable ActiveRuleWrapper currentActiveRule, @Nullable ActiveRuleWrapper parentActiveRule) { String severity = firstNonNull( parentActiveRule != null ? parentActiveRule.get().getSeverityString() : null, rule.get().getSeverityString()); change.setSeverity(severity); + Map oldImpactSeverities = currentActiveRule != null ? currentActiveRule.get().getImpacts() : Map.of(); Map impactsSeverities = parentActiveRule != null ? parentActiveRule.get().getImpacts() : rule.get().getDefaultImpactsMap(); - change.setImpactSeverities(impactsSeverities); + change.setOldImpacts(oldImpactSeverities); + change.setNewImpacts(impactsSeverities); change.setPrioritizedRule(parentActiveRule != null && parentActiveRule.get().isPrioritizedRule()); @@ -236,11 +242,14 @@ public class RuleActivator { } private void applySeverityAndPrioritizedRuleAndParamsWhenBuiltInProfile(RuleActivation request, RuleActivationContext context, - ActiveRuleChange change, RuleWrapper rule) { + ActiveRuleChange change, RuleWrapper rule, @Nullable ActiveRuleWrapper currentActiveRule) { // for builtin quality profiles, the severity from profile, when null use the default severity of the rule SeverityConfiguration severityConfiguration = determineSeverityConfiguration(request, rule.get(), null, null); change.setSeverity(severityConfiguration.severity()); - change.setImpactSeverities(severityConfiguration.impacts()); + + Map oldImpactSeverities = currentActiveRule != null ? currentActiveRule.get().getImpacts() : Map.of(); + change.setOldImpacts(oldImpactSeverities); + change.setNewImpacts(severityConfiguration.impacts()); boolean prioritizedRule = TRUE.equals(request.isPrioritizedRule()); change.setPrioritizedRule(prioritizedRule); @@ -290,11 +299,14 @@ public class RuleActivator { */ private void applySeverityAndPrioritizedRuleAndParamsWhenNonBuiltInProfile(RuleActivation request, RuleActivationContext context, ActiveRuleChange change, - RuleWrapper rule, @Nullable ActiveRuleWrapper activeRule, @Nullable ActiveRuleWrapper parentActiveRule) { - SeverityConfiguration severityConfiguration = getSeverityConfigurationForNonBuiltInProfile(request, rule, activeRule, parentActiveRule); - boolean prioritizedRule = getPrioritizedRuleForNonBuiltInProfile(request, activeRule, parentActiveRule); + RuleWrapper rule, @Nullable ActiveRuleWrapper currentActiveRule, @Nullable ActiveRuleWrapper parentActiveRule) { + SeverityConfiguration severityConfiguration = getSeverityConfigurationForNonBuiltInProfile(request, rule, currentActiveRule, parentActiveRule); + boolean prioritizedRule = getPrioritizedRuleForNonBuiltInProfile(request, currentActiveRule, parentActiveRule); change.setSeverity(severityConfiguration.severity()); - change.setImpactSeverities(severityConfiguration.impacts()); + + Map oldImpactSeverities = currentActiveRule != null ? currentActiveRule.get().getImpacts() : Map.of(); + change.setOldImpacts(oldImpactSeverities); + change.setNewImpacts(severityConfiguration.impacts()); change.setPrioritizedRule(prioritizedRule); for (RuleParamDto ruleParamDto : rule.getParams()) { @@ -307,12 +319,12 @@ public class RuleActivator { context.getRequestedParamValue(request, paramKey), parentValue, rule.getParamDefaultValue(paramKey)); - } else if (activeRule != null) { + } else if (currentActiveRule != 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 paramValue = firstNonNull( - activeRule.get().doesOverride() ? activeRule.getParamValue(paramKey) : null, - parentValue == null ? activeRule.getParamValue(paramKey) : parentValue, + currentActiveRule.get().doesOverride() ? currentActiveRule.getParamValue(paramKey) : null, + parentValue == null ? currentActiveRule.getParamValue(paramKey) : parentValue, rule.getParamDefaultValue(paramKey)); } else { paramValue = firstNonNull( @@ -364,6 +376,13 @@ public class RuleActivator { change.setActiveRule(activeRule); QProfileChangeDto dto = change.toDto(userSession.getUuid()); + + if (dto.getRuleChange() != null) { + dto.getRuleChange().setUuid(uuidFactory.create()); + dto.getRuleChange().getRuleImpactChanges().forEach(e -> e.setRuleChangeUuid(dto.getRuleChange().getUuid())); + db.ruleChangeDao().insert(dbSession, dto.getRuleChange()); + } + dto.setSqVersion(sonarQubeVersion.toString()); db.qProfileChangeDao().insert(dbSession, dto); @@ -381,7 +400,7 @@ public class RuleActivator { if (severity != null) { activeRule.setSeverity(severity); } - activeRule.setImpacts(change.getImpactSeverities()); + activeRule.setImpacts(change.getNewImpacts()); activeRule.setPrioritizedRule(TRUE.equals(change.isPrioritizedRule())); ActiveRuleInheritance inheritance = change.getInheritance(); if (inheritance != null) { @@ -414,7 +433,7 @@ public class RuleActivator { if (severity != null) { ruleDto.setSeverity(severity); } - ruleDto.setImpacts(change.getImpactSeverities()); + ruleDto.setImpacts(change.getNewImpacts()); Boolean prioritizedRule = change.isPrioritizedRule(); if (prioritizedRule != null) { ruleDto.setPrioritizedRule(prioritizedRule); @@ -580,7 +599,7 @@ public class RuleActivator { if (severity != null && !severity.equals(activeRule.get().getSeverityString())) { return false; } - Map impactSeverities = change.getImpactSeverities(); + Map impactSeverities = change.getNewImpacts(); if (!impactSeverities.equals(activeRule.get().getImpacts())) { return false; } @@ -608,7 +627,7 @@ public class RuleActivator { if (!StringUtils.equals(change.getSeverity(), parentActiveRule.get().getSeverityString())) { return false; } - if (!change.getImpactSeverities().equals(parentActiveRule.get().getImpacts())) { + if (!change.getNewImpacts().equals(parentActiveRule.get().getImpacts())) { return false; } if (change.isPrioritizedRule() != null && !Objects.equals(change.isPrioritizedRule(), parentActiveRule.get().isPrioritizedRule())) { -- 2.39.5