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;
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.
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);
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<String> profileKeys = metadata.getQprofilesPerLanguage().values().stream()
+ .map(QProfile::getKey)
+ .collect(toList(metadata.getQprofilesPerLanguage().size()));
+ try (DbSession dbSession = dbClient.openSession(false)) {
+ List<QualityProfileDto> 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();
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)
}
@Test
- public void set_analysis_date() throws Exception {
+ public void set_analysis_date() {
reportReader.setMetadata(
newBatchReportBuilder()
.setAnalysisDate(ANALYSIS_DATE)
}
@Test
- public void set_branch() throws Exception {
+ public void set_branch() {
reportReader.setMetadata(
newBatchReportBuilder()
.setBranch(BRANCH)
}
@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());
}
@Test
- public void set_cross_project_duplication_to_true() throws Exception {
+ public void set_cross_project_duplication_to_true() {
reportReader.setMetadata(
newBatchReportBuilder()
.setCrossProjectDuplicationActivated(true)
}
@Test
- public void set_cross_project_duplication_to_false() throws Exception {
+ public void set_cross_project_duplication_to_false() {
reportReader.setMetadata(
newBatchReportBuilder()
.setCrossProjectDuplicationActivated(false)
}
@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());
nonDefaultOrganizationDto.getKey() + ") than the default one (" + dbTester.getDefaultOrganization().getKey() + ")");
underTest.execute();
-
}
@Test
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);
}