From 333d9bce74015255e99c7bce8b4664c5bb9ddff4 Mon Sep 17 00:00:00 2001 From: Simon Brandhof Date: Tue, 21 Mar 2017 22:17:57 +0100 Subject: [PATCH] SONAR-8971 check consistency of Quality profiles in Compute Engine --- .../LoadReportAnalysisMetadataHolderStep.java | 25 +++++++ ...dReportAnalysisMetadataHolderStepTest.java | 67 ++++++++++++++++--- 2 files changed, 83 insertions(+), 9 deletions(-) diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/step/LoadReportAnalysisMetadataHolderStep.java b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/step/LoadReportAnalysisMetadataHolderStep.java index 754f992225a..c106f554eb5 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/step/LoadReportAnalysisMetadataHolderStep.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/step/LoadReportAnalysisMetadataHolderStep.java @@ -20,14 +20,18 @@ package org.sonar.server.computation.task.projectanalysis.step; import com.google.common.base.Function; +import com.google.common.base.Joiner; import java.util.Date; +import java.util.List; import java.util.Optional; import javax.annotation.Nullable; import org.sonar.api.utils.MessageException; import org.sonar.ce.queue.CeTask; +import org.sonar.core.util.stream.Collectors; import org.sonar.db.DbClient; import org.sonar.db.DbSession; import org.sonar.db.organization.OrganizationDto; +import org.sonar.db.qualityprofile.QualityProfileDto; import org.sonar.scanner.protocol.output.ScannerReport; import org.sonar.scanner.protocol.output.ScannerReport.Metadata.QProfile; import org.sonar.server.computation.task.projectanalysis.analysis.MutableAnalysisMetadataHolder; @@ -41,6 +45,7 @@ import static com.google.common.base.Preconditions.checkState; import static com.google.common.collect.Maps.transformValues; import static java.lang.String.format; import static org.apache.commons.lang.StringUtils.isNotEmpty; +import static org.sonar.core.util.stream.Collectors.toList; /** * Feed analysis metadata holder with metadata from the analysis report. @@ -79,6 +84,7 @@ public class LoadReportAnalysisMetadataHolderStep implements ComputationStep { checkProjectKeyConsistency(reportMetadata); Organization organization = toOrganization(ceTask.getOrganizationUuid()); checkOrganizationKeyConsistency(reportMetadata, organization); + checkQualityProfilesConsistency(reportMetadata, organization); mutableAnalysisMetadataHolder.setRootComponentRef(reportMetadata.getRootComponentRef()); mutableAnalysisMetadataHolder.setBranch(isNotEmpty(reportMetadata.getBranch()) ? reportMetadata.getBranch() : null); @@ -87,6 +93,25 @@ public class LoadReportAnalysisMetadataHolderStep implements ComputationStep { mutableAnalysisMetadataHolder.setOrganization(organization); } + /** + * Check that the Quality profiles sent by scanner correctly relate to the project organization. + */ + private void checkQualityProfilesConsistency(ScannerReport.Metadata metadata, Organization organization) { + List profileKeys = metadata.getQprofilesPerLanguage().values().stream() + .map(QProfile::getKey) + .collect(toList(metadata.getQprofilesPerLanguage().size())); + try (DbSession dbSession = dbClient.openSession(false)) { + List profiles = dbClient.qualityProfileDao().selectByKeys(dbSession, profileKeys); + String badKeys = profiles.stream() + .filter(p -> !p.getOrganizationUuid().equals(organization.getUuid())) + .map(p -> p.getKey()) + .collect(Collectors.join(Joiner.on(", "))); + if (!badKeys.isEmpty()) { + throw MessageException.of(format("Quality profiles with following keys don't exist in organization [%s]: %s", organization.getKey(), badKeys)); + } + } + } + private void checkProjectKeyConsistency(ScannerReport.Metadata reportMetadata) { String reportProjectKey = projectKeyFromReport(reportMetadata); String componentKey = ceTask.getComponentKey(); diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/step/LoadReportAnalysisMetadataHolderStepTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/step/LoadReportAnalysisMetadataHolderStepTest.java index 0ead8bd64b2..8ae21842cc7 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/step/LoadReportAnalysisMetadataHolderStepTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/step/LoadReportAnalysisMetadataHolderStepTest.java @@ -61,13 +61,13 @@ public class LoadReportAnalysisMetadataHolderStepTest { private ComputationStep underTest; @Before - public void setUp() throws Exception { + public void setUp() { CeTask defaultOrgCeTask = createCeTask(PROJECT_KEY, dbTester.getDefaultOrganization().getUuid()); underTest = createStep(defaultOrgCeTask); } @Test - public void set_root_component_ref() throws Exception { + public void set_root_component_ref() { reportReader.setMetadata( newBatchReportBuilder() .setRootComponentRef(1) @@ -79,7 +79,7 @@ public class LoadReportAnalysisMetadataHolderStepTest { } @Test - public void set_analysis_date() throws Exception { + public void set_analysis_date() { reportReader.setMetadata( newBatchReportBuilder() .setAnalysisDate(ANALYSIS_DATE) @@ -91,7 +91,7 @@ public class LoadReportAnalysisMetadataHolderStepTest { } @Test - public void set_branch() throws Exception { + public void set_branch() { reportReader.setMetadata( newBatchReportBuilder() .setBranch(BRANCH) @@ -106,7 +106,7 @@ public class LoadReportAnalysisMetadataHolderStepTest { } @Test - public void set_null_branch_when_nothing_in_the_report() throws Exception { + public void set_null_branch_when_nothing_in_the_report() { reportReader.setMetadata( newBatchReportBuilder() .build()); @@ -117,7 +117,7 @@ public class LoadReportAnalysisMetadataHolderStepTest { } @Test - public void set_cross_project_duplication_to_true() throws Exception { + public void set_cross_project_duplication_to_true() { reportReader.setMetadata( newBatchReportBuilder() .setCrossProjectDuplicationActivated(true) @@ -129,7 +129,7 @@ public class LoadReportAnalysisMetadataHolderStepTest { } @Test - public void set_cross_project_duplication_to_false() throws Exception { + public void set_cross_project_duplication_to_false() { reportReader.setMetadata( newBatchReportBuilder() .setCrossProjectDuplicationActivated(false) @@ -141,7 +141,7 @@ public class LoadReportAnalysisMetadataHolderStepTest { } @Test - public void set_cross_project_duplication_to_false_when_nothing_in_the_report() throws Exception { + public void set_cross_project_duplication_to_false_when_nothing_in_the_report() { reportReader.setMetadata( newBatchReportBuilder() .build()); @@ -207,7 +207,6 @@ public class LoadReportAnalysisMetadataHolderStepTest { nonDefaultOrganizationDto.getKey() + ") than the default one (" + dbTester.getDefaultOrganization().getKey() + ")"); underTest.execute(); - } @Test @@ -259,6 +258,56 @@ public class LoadReportAnalysisMetadataHolderStepTest { assertThat(organization.getName()).isEqualTo(nonDefaultOrganizationDto.getName()); } + @Test + public void execute_ensures_that_report_has_quality_profiles_matching_the_project_organization() { + OrganizationDto organization = dbTester.organizations().insert(); + ScannerReport.Metadata.Builder metadataBuilder = newBatchReportBuilder(); + metadataBuilder.setOrganizationKey(organization.getKey()); + metadataBuilder.getMutableQprofilesPerLanguage().put("js", ScannerReport.Metadata.QProfile.newBuilder().setKey("p1").setName("Sonar way").setLanguage("js").build()); + reportReader.setMetadata(metadataBuilder.build()); + + dbTester.qualityProfiles().insert(organization, p -> p.setLanguage("js"), p -> p.setKey("p1")); + + ComputationStep underTest = createStep(createCeTask(PROJECT_KEY, organization.getUuid())); + + // no errors + underTest.execute(); + } + + @Test + public void execute_fails_with_MessageException_when_report_has_quality_profiles_on_other_organizations() { + OrganizationDto organization1 = dbTester.organizations().insert(); + OrganizationDto organization2 = dbTester.organizations().insert(); + ScannerReport.Metadata.Builder metadataBuilder = newBatchReportBuilder(); + metadataBuilder.setOrganizationKey(organization1.getKey()); + metadataBuilder.getMutableQprofilesPerLanguage().put("js", ScannerReport.Metadata.QProfile.newBuilder().setKey("jsInOrg1").setName("Sonar way").setLanguage("js").build()); + metadataBuilder.getMutableQprofilesPerLanguage().put("php", ScannerReport.Metadata.QProfile.newBuilder().setKey("phpInOrg2").setName("PHP way").setLanguage("php").build()); + reportReader.setMetadata(metadataBuilder.build()); + + dbTester.qualityProfiles().insert(organization1, p -> p.setLanguage("js"), p -> p.setKey("jsInOrg1")); + dbTester.qualityProfiles().insert(organization2, p -> p.setLanguage("php"), p -> p.setKey("phpInOrg2")); + + ComputationStep underTest = createStep(createCeTask(PROJECT_KEY, organization1.getUuid())); + + expectedException.expect(MessageException.class); + expectedException.expectMessage("Quality profiles with following keys don't exist in organization [" + organization1.getKey() + "]: phpInOrg2"); + + underTest.execute(); + } + + @Test + public void execute_does_not_fail_when_report_has_a_quality_profile_that_does_not_exist_anymore() { + OrganizationDto organization = dbTester.organizations().insert(); + ScannerReport.Metadata.Builder metadataBuilder = newBatchReportBuilder(); + metadataBuilder.setOrganizationKey(organization.getKey()); + metadataBuilder.getMutableQprofilesPerLanguage().put("js", ScannerReport.Metadata.QProfile.newBuilder().setKey("p1").setName("Sonar way").setLanguage("js").build()); + reportReader.setMetadata(metadataBuilder.build()); + + ComputationStep underTest = createStep(createCeTask(PROJECT_KEY, organization.getUuid())); + + underTest.execute(); + } + private LoadReportAnalysisMetadataHolderStep createStep(CeTask ceTask) { return new LoadReportAnalysisMetadataHolderStep(ceTask, reportReader, analysisMetadataHolder, defaultOrganizationProvider, dbClient); } -- 2.39.5