diff options
Diffstat (limited to 'server/sonar-webserver-core')
2 files changed, 94 insertions, 15 deletions
diff --git a/server/sonar-webserver-core/src/main/java/org/sonar/server/telemetry/TelemetryDataLoaderImpl.java b/server/sonar-webserver-core/src/main/java/org/sonar/server/telemetry/TelemetryDataLoaderImpl.java index 6382bef3174..b10220642d8 100644 --- a/server/sonar-webserver-core/src/main/java/org/sonar/server/telemetry/TelemetryDataLoaderImpl.java +++ b/server/sonar-webserver-core/src/main/java/org/sonar/server/telemetry/TelemetryDataLoaderImpl.java @@ -116,6 +116,8 @@ public class TelemetryDataLoaderImpl implements TelemetryDataLoader { private final Set<NewCodeDefinition> newCodeDefinitions = new HashSet<>(); private final Map<String, NewCodeDefinition> ncdByProject = new HashMap<>(); private final Map<String, NewCodeDefinition> ncdByBranch = new HashMap<>(); + private final Map<String, String> defaultQualityProfileByLanguage = new HashMap<>(); + private final Map<ProjectLanguageKey, String> qualityProfileByProjectAndLanguage = new HashMap<>(); private NewCodeDefinition instanceNcd = NewCodeDefinition.getInstanceDefault(); @Inject @@ -160,6 +162,7 @@ public class TelemetryDataLoaderImpl implements TelemetryDataLoader { try (DbSession dbSession = dbClient.openSession(false)) { var branchMeasuresDtos = dbClient.branchDao().selectBranchMeasuresWithCaycMetric(dbSession); loadNewCodeDefinitions(dbSession, branchMeasuresDtos); + loadQualityProfiles(dbSession); data.setDatabase(loadDatabaseMetadata(dbSession)); data.setNcdId(instanceNcd.hashCode()); @@ -211,6 +214,8 @@ public class TelemetryDataLoaderImpl implements TelemetryDataLoader { this.ncdByBranch.clear(); this.ncdByProject.clear(); this.instanceNcd = NewCodeDefinition.getInstanceDefault(); + this.defaultQualityProfileByLanguage.clear(); + this.qualityProfileByProjectAndLanguage.clear(); } private void loadNewCodeDefinitions(DbSession dbSession, List<BranchMeasuresDto> branchMeasuresDtos) { @@ -245,6 +250,16 @@ public class TelemetryDataLoaderImpl implements TelemetryDataLoader { } } + private void loadQualityProfiles(DbSession dbSession) { + dbClient.qualityProfileDao().selectAllDefaultProfiles(dbSession) + .forEach(defaultQualityProfile -> this.defaultQualityProfileByLanguage.put(defaultQualityProfile.getLanguage(), defaultQualityProfile.getKee())); + + dbClient.qualityProfileDao().selectAllProjectAssociations(dbSession) + .forEach(projectAssociation -> qualityProfileByProjectAndLanguage.put( + new ProjectLanguageKey(projectAssociation.projectUuid(), projectAssociation.language()), + projectAssociation.profileKey())); + } + private boolean isCommunityEdition() { var edition = editionProvider.get(); return edition.isPresent() && edition.get() == COMMUNITY; @@ -274,13 +289,12 @@ public class TelemetryDataLoaderImpl implements TelemetryDataLoader { Map<String, String> scmByProject = getAnalysisPropertyByProject(dbSession, SONAR_ANALYSIS_DETECTEDSCM); Map<String, String> ciByProject = getAnalysisPropertyByProject(dbSession, SONAR_ANALYSIS_DETECTEDCI); Map<String, ProjectAlmKeyAndProject> almAndUrlByProject = getAlmAndUrlByProject(dbSession); - Map<String, PrBranchAnalyzedLanguageCountByProjectDto> prAndBranchCountByProject = - dbClient.branchDao().countPrBranchAnalyzedLanguageByProjectUuid(dbSession) - .stream().collect(toMap(PrBranchAnalyzedLanguageCountByProjectDto::getProjectUuid, Function.identity())); + Map<String, PrBranchAnalyzedLanguageCountByProjectDto> prAndBranchCountByProject = dbClient.branchDao().countPrBranchAnalyzedLanguageByProjectUuid(dbSession) + .stream().collect(toMap(PrBranchAnalyzedLanguageCountByProjectDto::getProjectUuid, Function.identity())); Map<String, String> qgatesByProject = getProjectQgatesMap(dbSession); - Map<String, Map<String, Number>> metricsByProject = - getProjectMetricsByMetricKeys(dbSession, TECHNICAL_DEBT_KEY, DEVELOPMENT_COST_KEY, SECURITY_HOTSPOTS_KEY, VULNERABILITIES_KEY, - BUGS_KEY); + Map<String, Map<String, Number>> metricsByProject = getProjectMetricsByMetricKeys(dbSession, TECHNICAL_DEBT_KEY, DEVELOPMENT_COST_KEY, SECURITY_HOTSPOTS_KEY, + VULNERABILITIES_KEY, + BUGS_KEY); Map<String, Long> securityReportExportedAtByProjectUuid = getSecurityReportExportedAtDateByProjectUuid(dbSession); List<TelemetryData.ProjectStatistics> projectStatistics = new ArrayList<>(); @@ -336,7 +350,7 @@ public class TelemetryDataLoaderImpl implements TelemetryDataLoader { data.setProjects(buildProjectsList(branchesWithLargestNcloc, latestSnapshotMap)); } - private static List<TelemetryData.Project> buildProjectsList(List<ProjectLocDistributionDto> branchesWithLargestNcloc, + private List<TelemetryData.Project> buildProjectsList(List<ProjectLocDistributionDto> branchesWithLargestNcloc, Map<String, Long> latestSnapshotMap) { return branchesWithLargestNcloc.stream() .flatMap(measure -> Arrays.stream(measure.locDistribution().split(";")) @@ -345,9 +359,17 @@ public class TelemetryDataLoaderImpl implements TelemetryDataLoader { measure.projectUuid(), latestSnapshotMap.get(measure.branchUuid()), languageAndLoc[0], - Long.parseLong(languageAndLoc[1]) - )) - ).toList(); + getQualityProfile(measure.projectUuid(), languageAndLoc[0]), + Long.parseLong(languageAndLoc[1])))) + .toList(); + } + + private String getQualityProfile(String projectUuid, String language) { + String qualityProfile = this.qualityProfileByProjectAndLanguage.get(new ProjectLanguageKey(projectUuid, language)); + if (qualityProfile != null) { + return qualityProfile; + } + return this.defaultQualityProfileByLanguage.get(language); } private Map<String, String> getNclocMetricUuidMap(DbSession dbSession) { @@ -362,15 +384,12 @@ public class TelemetryDataLoaderImpl implements TelemetryDataLoader { for (QualityGateDto qualityGateDto : qualityGateDtos) { qualityGates.add( new TelemetryData.QualityGate(qualityGateDto.getUuid(), qualityGateCaycChecker.checkCaycCompliant(dbSession, - qualityGateDto.getUuid()).toString()) - ); + qualityGateDto.getUuid()).toString())); } data.setQualityGates(qualityGates); } - - private void resolveUsers(TelemetryData.Builder data, DbSession dbSession) { data.setUsers(dbClient.userDao().selectUsersForTelemetry(dbSession)); } @@ -465,4 +484,7 @@ public class TelemetryDataLoaderImpl implements TelemetryDataLoader { private TelemetryData.CloudUsage buildCloudUsage() { return cloudUsageDataProvider.getCloudUsage(); } + + private record ProjectLanguageKey(String projectKey, String language) { + } } diff --git a/server/sonar-webserver-core/src/test/java/org/sonar/server/telemetry/TelemetryDataLoaderImplTest.java b/server/sonar-webserver-core/src/test/java/org/sonar/server/telemetry/TelemetryDataLoaderImplTest.java index edf532d205e..d7494fa47cb 100644 --- a/server/sonar-webserver-core/src/test/java/org/sonar/server/telemetry/TelemetryDataLoaderImplTest.java +++ b/server/sonar-webserver-core/src/test/java/org/sonar/server/telemetry/TelemetryDataLoaderImplTest.java @@ -219,6 +219,12 @@ public class TelemetryDataLoaderImplTest { QualityGateDto qualityGate2 = db.qualityGates().insertQualityGate(qg -> qg.setName("QG2")); //quality profiles + QProfileDto javaQP = db.qualityProfiles().insert(qProfileDto -> qProfileDto.setLanguage("java")); + QProfileDto kotlinQP = db.qualityProfiles().insert(qProfileDto -> qProfileDto.setLanguage("kotlin")); + QProfileDto jsQP = db.qualityProfiles().insert(qProfileDto -> qProfileDto.setLanguage("js")); + db.qualityProfiles().associateWithProject(projectData1.getProjectDto(), javaQP, kotlinQP, jsQP); + db.qualityProfiles().associateWithProject(projectData2.getProjectDto(), javaQP, jsQP); + QProfileDto qualityProfile1 = db.qualityProfiles().insert(qp -> qp.setIsBuiltIn(true)); QProfileDto qualityProfile2 = db.qualityProfiles().insert(); db.qualityProfiles().setAsDefault(qualityProfile1, qualityProfile2); @@ -296,7 +302,13 @@ public class TelemetryDataLoaderImplTest { assertThat(data.getQualityProfiles()) .extracting(TelemetryData.QualityProfile::uuid, TelemetryData.QualityProfile::isBuiltIn) - .containsExactlyInAnyOrder(tuple(qualityProfile1.getKee(), qualityProfile1.isBuiltIn()), tuple(qualityProfile2.getKee(), qualityProfile2.isBuiltIn())); + .containsExactlyInAnyOrder( + tuple(qualityProfile1.getKee(), qualityProfile1.isBuiltIn()), + tuple(qualityProfile2.getKee(), qualityProfile2.isBuiltIn()), + tuple(jsQP.getKee(), jsQP.isBuiltIn()), + tuple(javaQP.getKee(), javaQP.isBuiltIn()), + tuple(kotlinQP.getKee(), kotlinQP.isBuiltIn()) + ); } @@ -372,6 +384,12 @@ public class TelemetryDataLoaderImplTest { MetricDto nclocDistrib = db.measures().insertMetric(m -> m.setKey(NCLOC_LANGUAGE_DISTRIBUTION_KEY)); ProjectData projectData = db.components().insertPublicProject(); + + QProfileDto javaQP = db.qualityProfiles().insert(qProfileDto -> qProfileDto.setLanguage("java")); + QProfileDto kotlinQP = db.qualityProfiles().insert(qProfileDto -> qProfileDto.setLanguage("kotlin")); + QProfileDto jsQP = db.qualityProfiles().insert(qProfileDto -> qProfileDto.setLanguage("js")); + db.qualityProfiles().associateWithProject(projectData.getProjectDto(), javaQP, kotlinQP, jsQP); + ComponentDto mainBranch = projectData.getMainBranchComponent(); db.measures().insertLiveMeasure(mainBranch, lines, m -> m.setValue(110d)); db.measures().insertLiveMeasure(mainBranch, ncloc, m -> m.setValue(110d)); @@ -404,6 +422,45 @@ public class TelemetryDataLoaderImplTest { } @Test + public void load_shouldProvideQualityProfileInProjectSection() { + server.setId("AU-TpxcB-iU5OvuD2FL7").setVersion("7.5.4"); + MetricDto ncloc = db.measures().insertMetric(m -> m.setKey(NCLOC_KEY)); + MetricDto nclocDistrib = db.measures().insertMetric(m -> m.setKey(NCLOC_LANGUAGE_DISTRIBUTION_KEY)); + + ProjectData projectData = db.components().insertPublicProject(); + + // default quality profile + QProfileDto javaQP = db.qualityProfiles().insert(qProfileDto -> qProfileDto.setLanguage("java")); + QProfileDto kotlinQP = db.qualityProfiles().insert(qProfileDto -> qProfileDto.setLanguage("kotlin")); + db.qualityProfiles().setAsDefault(javaQP,kotlinQP); + // selected quality profile + QProfileDto jsQP = db.qualityProfiles().insert(qProfileDto -> qProfileDto.setLanguage("js")); + db.qualityProfiles().associateWithProject(projectData.getProjectDto(), jsQP); + + + ComponentDto mainBranch = projectData.getMainBranchComponent(); + db.measures().insertLiveMeasure(mainBranch, ncloc, m -> m.setValue(110d)); + db.measures().insertLiveMeasure(mainBranch, nclocDistrib, m -> m.setValue(null).setData("java=70;js=30;kotlin=10")); + + ComponentDto branch = db.components().insertProjectBranch(mainBranch, b -> b.setBranchType(BRANCH)); + db.measures().insertLiveMeasure(branch, ncloc, m -> m.setValue(180d)); + db.measures().insertLiveMeasure(branch, nclocDistrib, m -> m.setValue(null).setData("java=100;js=50;kotlin=30")); + + SnapshotDto project1Analysis = db.components().insertSnapshot(mainBranch, t -> t.setLast(true)); + SnapshotDto project2Analysis = db.components().insertSnapshot(branch, t -> t.setLast(true)); + db.measures().insertMeasure(mainBranch, project1Analysis, nclocDistrib, m -> m.setData("java=70;js=30;kotlin=10")); + db.measures().insertMeasure(branch, project2Analysis, nclocDistrib, m -> m.setData("java=100;js=50;kotlin=30")); + + TelemetryData data = communityUnderTest.load(); + + assertThat(data.getProjects()).extracting(TelemetryData.Project::projectUuid, TelemetryData.Project::language, TelemetryData.Project::qualityProfile) + .containsExactlyInAnyOrder( + tuple(projectData.projectUuid(), "java", javaQP.getKee()), + tuple(projectData.projectUuid(), "js", jsQP.getKee()), + tuple(projectData.projectUuid(), "kotlin", kotlinQP.getKee())); + } + + @Test public void test_ncd_on_community_edition() { server.setId("AU-TpxcB-iU5OvuD2FL7").setVersion("7.5.4"); when(editionProvider.get()).thenReturn(Optional.of(COMMUNITY)); |