diff options
author | Benjamin Campomenosi <benjamin.campomenosi@sonarsource.com> | 2023-10-19 23:03:56 +0200 |
---|---|---|
committer | sonartech <sonartech@sonarsource.com> | 2023-10-23 20:02:43 +0000 |
commit | 9ff5b8d083d36c4b413632da7ad5b76c08a9f622 (patch) | |
tree | cc3758d156f420dc51a19fb6fbeba7ef59c18a47 /server/sonar-db-dao | |
parent | 564d295d94911eeea1e5ef192bd675c3ff1c406e (diff) | |
download | sonarqube-9ff5b8d083d36c4b413632da7ad5b76c08a9f622.tar.gz sonarqube-9ff5b8d083d36c4b413632da7ad5b76c08a9f622.zip |
SONAR-20664 - Add ProjectExportDao for all Export steps
Diffstat (limited to 'server/sonar-db-dao')
4 files changed, 294 insertions, 0 deletions
diff --git a/server/sonar-db-dao/src/it/java/org/sonar/db/project/ProjectExportDaoIT.java b/server/sonar-db-dao/src/it/java/org/sonar/db/project/ProjectExportDaoIT.java new file mode 100644 index 00000000000..cc2ea367217 --- /dev/null +++ b/server/sonar-db-dao/src/it/java/org/sonar/db/project/ProjectExportDaoIT.java @@ -0,0 +1,222 @@ +/* + * SonarQube + * Copyright (C) 2009-2023 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.db.project; + +import java.util.Iterator; +import java.util.List; +import java.util.Set; +import java.util.function.Consumer; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import org.apache.commons.lang.RandomStringUtils; +import org.apache.ibatis.cursor.Cursor; +import org.junit.Rule; +import org.junit.Test; +import org.sonar.api.impl.utils.AlwaysIncreasingSystem2; +import org.sonar.api.issue.Issue; +import org.sonar.api.rule.RuleKey; +import org.sonar.api.rule.RuleStatus; +import org.sonar.api.rule.Severity; +import org.sonar.api.rules.RuleType; +import org.sonar.api.utils.System2; +import org.sonar.db.DbTester; +import org.sonar.db.component.BranchDto; +import org.sonar.db.component.BranchType; +import org.sonar.db.component.ComponentDto; +import org.sonar.db.component.ProjectData; +import org.sonar.db.component.ProjectLinkDto; +import org.sonar.db.issue.IssueDto; +import org.sonar.db.newcodeperiod.NewCodePeriodDto; +import org.sonar.db.newcodeperiod.NewCodePeriodType; +import org.sonar.db.property.PropertyDto; +import org.sonar.db.rule.RuleDto; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.tuple; + +public class ProjectExportDaoIT { + + private final System2 system2 = new AlwaysIncreasingSystem2(1000L); + + @Rule + public DbTester db = DbTester.create(system2); + + private final ProjectExportDao projectExportDao = new ProjectExportDao(); + + @Test + public void selectBranchesForExport_shouldOnlyReturnBranchExcludedFromPurge() { + ProjectData projectData = db.components().insertPrivateProject("project-uuid"); + BranchDto branchExcludedFromPurge = db.components().insertProjectBranch(projectData.getProjectDto(), + branch -> branch.setExcludeFromPurge(true)); + db.components().insertProjectBranch(projectData.getProjectDto(), + branch -> branch.setBranchType(BranchType.PULL_REQUEST).setExcludeFromPurge(true)); + db.components().insertProjectBranch(projectData.getProjectDto(), + branch -> branch.setBranchType(BranchType.PULL_REQUEST)); + db.components().insertProjectBranch(projectData.getProjectDto()); + + List<BranchDto> exportedBranch = projectExportDao.selectBranchesForExport(db.getSession(), "project-uuid"); + + assertThat(exportedBranch) + .hasSize(2) + .containsOnly(projectData.getMainBranchDto(), branchExcludedFromPurge); + } + + @Test + public void selectPropertiesForExport_shouldOnlyReturnProjectPropertiesNotLinkedToUser() { + db.components().insertPrivateProject("project-uuid"); + PropertyDto userProjectProperty = new PropertyDto().setKey("userProjectProperty").setEntityUuid("project-uuid").setUserUuid("user-uuid"); + PropertyDto globalProperty = new PropertyDto().setKey("globalProperty"); + PropertyDto projectProperty = new PropertyDto().setKey("projectProperty").setEntityUuid("project-uuid"); + db.properties().insertProperties(List.of(userProjectProperty, globalProperty, projectProperty), null, null, null, null); + + List<PropertyDto> exportedProperties = projectExportDao.selectPropertiesForExport(db.getSession(), "project-uuid"); + + assertThat(exportedProperties) + .hasSize(1) + .extracting(PropertyDto::getKey).containsOnly("projectProperty"); + } + + @Test + public void selectLinksForExport_shouldReturnLinkOfProject() { + ProjectDto project = db.components().insertPrivateProject("project-uuid").getProjectDto(); + db.projectLinks().insertCustomLink(project, link -> link.setName("customLink").setHref("www.customLink.com")); + db.projectLinks().insertProvidedLink(project, link -> link.setName("providedLink").setHref("www.providedLink.com")); + ProjectDto otherProject = db.components().insertPrivateProject("another-project").getProjectDto(); + db.projectLinks().insertCustomLink(otherProject, link -> link.setName("customLink")); + + List<ProjectLinkDto> exportedLinks = projectExportDao.selectLinksForExport(db.getSession(), "project-uuid"); + + assertThat(exportedLinks) + .hasSize(2) + .extracting("name", "href") + .containsOnly(tuple("customLink", "www.customLink.com"), tuple("providedLink", "www.providedLink.com")); + } + + @Test + public void selectNewCodePeriodsForExport_shouldOnlyReturnGlobalNewCodePeriodOrNewCodePeriodOnBranchExcludedFromPurge() { + ProjectDto project = db.components().insertPrivateProject("project-uuid").getProjectDto(); + BranchDto branchExcludedFromPurge = db.components().insertProjectBranch(project, branch -> branch.setExcludeFromPurge(true)); + BranchDto branchNotExcludedFromPurge = db.components().insertProjectBranch(project); + db.newCodePeriods().insert(project.getUuid(), NewCodePeriodType.REFERENCE_BRANCH, "main"); + db.newCodePeriods().insert(project.getUuid(), branchExcludedFromPurge.getUuid(), NewCodePeriodType.PREVIOUS_VERSION, null); + db.newCodePeriods().insert(project.getUuid(), branchNotExcludedFromPurge.getUuid(), NewCodePeriodType.NUMBER_OF_DAYS, "10"); + db.newCodePeriods().insert(NewCodePeriodType.SPECIFIC_ANALYSIS, "uuid"); + + List<NewCodePeriodDto> exportedNewCodePeriods = projectExportDao.selectNewCodePeriodsForExport(db.getSession(), "project-uuid"); + + assertThat(exportedNewCodePeriods) + .hasSize(2) + .extracting("type", "value") + .containsOnly(tuple(NewCodePeriodType.REFERENCE_BRANCH, "main"), tuple(NewCodePeriodType.PREVIOUS_VERSION, null)); + } + + @Test + public void scrollAdhocRulesForExport_shouldOnlyReturnAdHocRulesNotRemovedAndActiveOnProjectBranchesExcludedFromPurge() { + ProjectData projectData = db.components().insertPrivateProject("project-uuid"); + ComponentDto file = db.components().insertFile(projectData.getMainBranchDto()); + ComponentDto mainBranchComponent = projectData.getMainBranchComponent(); + ComponentDto branchNotExcludedFromPurge = db.components().insertProjectBranch(mainBranchComponent); + + RuleDto externalRule = insertRule("externalRule", true, false); + db.issues().insertIssue(externalRule, mainBranchComponent, file, issueDto -> issueDto.setKee("issue-externalRule")); + RuleDto adHocRule1 = insertRule("adHocRule1", false, true); + db.issues().insertIssue(adHocRule1, mainBranchComponent, file, issueDto -> issueDto.setKee("issue-adHocRule1")); + RuleDto adHocRule2 = insertRule("adHocRule2", false, true); + db.issues().insertIssue(adHocRule2, branchNotExcludedFromPurge, file, issueDto -> issueDto.setKee("issue-adHocRule2")); + RuleDto adHocRule3 = insertRule("adHocRule3", false, true, RuleStatus.REMOVED); + db.issues().insertIssue(adHocRule3, mainBranchComponent, file, issueDto -> issueDto.setKee("issue-adHocRule3")); + RuleDto adHocRule4 = insertRule("adHocRule4", false, true); + db.issues().insertIssue(adHocRule4, mainBranchComponent, file, issueDto -> issueDto.setKee("issue-adHocRule4").setStatus(Issue.STATUS_CLOSED)); + RuleDto standardRule = insertRule("standardRule", false, false); + db.issues().insertIssue(standardRule, mainBranchComponent, file, issueDto -> issueDto.setKee("issue-standardRule")); + + Cursor<RuleDto> ruleDtos = projectExportDao.scrollAdhocRulesForExport(db.getSession(), "project-uuid"); + Set<RuleDto> ruleDtoSet = toSet(ruleDtos); + + assertThat(ruleDtoSet) + .hasSize(1) + .extracting("uuid") + .containsOnly(adHocRule1.getUuid()); + + } + + @Test + public void scrollIssueForExport_shouldOnlyReturnIssueWithRulesNotRemovedAndActiveOnProjectBranchesExcludedFromPurge() { + ProjectData projectData = db.components().insertPrivateProject("project-uuid"); + ComponentDto file = db.components().insertFile(projectData.getMainBranchDto()); + ComponentDto mainBranchComponent = projectData.getMainBranchComponent(); + ComponentDto branchNotExcludedFromPurge = db.components().insertProjectBranch(mainBranchComponent); + + RuleDto rule1 = db.rules().insertRule(ruleDto -> ruleDto.setUuid("rule1")); + db.issues().insertIssue(rule1, mainBranchComponent, file, issueDto -> issueDto.setKee("issue1")); + db.issues().insertIssue(rule1, branchNotExcludedFromPurge, file, issueDto -> issueDto.setKee("issue2")); + RuleDto rule2 = db.rules().insertRule(ruleDto -> ruleDto.setUuid("rule2").setStatus(RuleStatus.REMOVED)); + db.issues().insertIssue(rule2, mainBranchComponent, file, issueDto -> issueDto.setKee("issue3")); + db.rules().insertRule(ruleDto -> ruleDto.setUuid("rule3")); + db.issues().insertIssue(rule2, mainBranchComponent, file, issueDto -> issueDto.setKee("issue5").setStatus(Issue.STATUS_CLOSED)); + + Cursor<IssueDto> issueDtos = projectExportDao.scrollIssueForExport(db.getSession(), "project-uuid"); + Set<IssueDto> issuesSet = toSet(issueDtos); + + assertThat(issuesSet) + .hasSize(1) + .extracting("kee") + .containsOnly("issue1"); + + } + + private RuleDto insertRule(String ruleName, boolean isExternal, boolean isAdHoc) { + return insertRule(ruleName, isExternal, isAdHoc, RuleStatus.READY); + } + + private RuleDto insertRule(String ruleName, boolean isExternal, boolean isAdHoc, RuleStatus ruleStatus) { + RuleKey ruleKey = RuleKey.of("plugin1", ruleName); + db.rules().insertIssueRule(ProjectExportDaoIT.initRuleConsumer(ruleKey, isExternal, isAdHoc, ruleStatus)); + return db.getDbClient().ruleDao().selectByKey(db.getSession(), ruleKey) + .orElseThrow(() -> new RuntimeException("insertAdHocRule failed")); + } + + private static Consumer<RuleDto> initRuleConsumer(RuleKey ruleKey, boolean isExternal, boolean isAdHoc, RuleStatus ruleStatus) { + return rule -> { + rule + .setName(ruleKey.rule()) + .setIsExternal(isExternal) + .setIsAdHoc(isAdHoc) + .setRuleKey(ruleKey) + .setPluginKey("pluginKey" + RandomStringUtils.randomAlphanumeric(10)) + .setStatus(ruleStatus); + if (isAdHoc) { + rule.setAdHocName("ad_hoc_rule" + RandomStringUtils.randomAlphabetic(10)) + .setAdHocType(RuleType.VULNERABILITY) + .setAdHocSeverity(Severity.CRITICAL) + .setAdHocDescription("ad hoc description: " + RandomStringUtils.randomAlphanumeric(100)); + } + }; + } + + private static <T> Set<T> toSet(Cursor<T> ruleDtos) { + Iterator<T> ruleIterator = ruleDtos.iterator(); + return Stream.generate(() -> null) + .takeWhile(x -> ruleIterator.hasNext()) + .map(n -> ruleIterator.next()) + .collect(Collectors.toSet()); + } + +} diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/DaoModule.java b/server/sonar-db-dao/src/main/java/org/sonar/db/DaoModule.java index cd454bd0d64..9186324b27a 100644 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/DaoModule.java +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/DaoModule.java @@ -60,6 +60,7 @@ import org.sonar.db.plugin.PluginDao; import org.sonar.db.portfolio.PortfolioDao; import org.sonar.db.project.ProjectBadgeTokenDao; import org.sonar.db.project.ProjectDao; +import org.sonar.db.project.ProjectExportDao; import org.sonar.db.property.InternalComponentPropertiesDao; import org.sonar.db.property.InternalPropertiesDao; import org.sonar.db.property.PropertiesDao; @@ -153,6 +154,7 @@ public class DaoModule extends Module { PluginDao.class, ProjectDao.class, ProjectBadgeTokenDao.class, + ProjectExportDao.class, PortfolioDao.class, ProjectLinkDao.class, ProjectQgateAssociationDao.class, diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/DbClient.java b/server/sonar-db-dao/src/main/java/org/sonar/db/DbClient.java index f4f30d4e406..f9a93c4e0ba 100644 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/DbClient.java +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/DbClient.java @@ -60,6 +60,7 @@ import org.sonar.db.plugin.PluginDao; import org.sonar.db.portfolio.PortfolioDao; import org.sonar.db.project.ProjectBadgeTokenDao; import org.sonar.db.project.ProjectDao; +import org.sonar.db.project.ProjectExportDao; import org.sonar.db.property.InternalComponentPropertiesDao; import org.sonar.db.property.InternalPropertiesDao; import org.sonar.db.property.PropertiesDao; @@ -191,6 +192,7 @@ public class DbClient { private final GithubOrganizationGroupDao githubOrganizationGroupDao; private final GithubPermissionsMappingDao githubPermissionsMappingDao; private final RuleChangeDao ruleChangeDao; + private final ProjectExportDao projectExportDao; public DbClient(Database database, MyBatis myBatis, DBSessions dbSessions, Dao... daos) { this.database = database; @@ -282,6 +284,7 @@ public class DbClient { reportSubscriptionDao = getDao(map, ReportSubscriptionDao.class); anticipatedTransitionDao = getDao(map, AnticipatedTransitionDao.class); ruleChangeDao = getDao(map, RuleChangeDao.class); + projectExportDao = getDao(map, ProjectExportDao.class); } public DbSession openSession(boolean batch) { @@ -625,5 +628,9 @@ public class DbClient { public RuleChangeDao ruleChangeDao() { return ruleChangeDao; } + + public ProjectExportDao projectExportDao() { + return projectExportDao; + } } diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/project/ProjectExportDao.java b/server/sonar-db-dao/src/main/java/org/sonar/db/project/ProjectExportDao.java new file mode 100644 index 00000000000..3e6aa5cedbc --- /dev/null +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/project/ProjectExportDao.java @@ -0,0 +1,63 @@ +/* + * SonarQube + * Copyright (C) 2009-2023 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.db.project; + +import java.util.List; +import org.apache.ibatis.cursor.Cursor; +import org.sonar.db.Dao; +import org.sonar.db.DbSession; +import org.sonar.db.component.BranchDto; +import org.sonar.db.component.ProjectLinkDto; +import org.sonar.db.issue.IssueDto; +import org.sonar.db.newcodeperiod.NewCodePeriodDto; +import org.sonar.db.property.PropertyDto; +import org.sonar.db.rule.RuleDto; + +public class ProjectExportDao implements Dao { + + public List<BranchDto> selectBranchesForExport(DbSession dbSession, String projectUuid) { + return mapper(dbSession).selectBranchesForExport(projectUuid); + } + + public List<PropertyDto> selectPropertiesForExport(DbSession dbSession, String projectUuid) { + return mapper(dbSession).selectPropertiesForExport(projectUuid); + } + + public List<ProjectLinkDto> selectLinksForExport(DbSession dbSession, String projectUuid) { + return mapper(dbSession).selectLinksForExport(projectUuid); + } + + public List<NewCodePeriodDto> selectNewCodePeriodsForExport(DbSession dbSession, String projectUuid) { + return mapper(dbSession).selectNewCodePeriodsForExport(projectUuid); + } + + public Cursor<RuleDto> scrollAdhocRulesForExport(DbSession dbSession, String projectUuid) { + return mapper(dbSession).scrollAdhocRulesForExport(projectUuid); + } + + public Cursor<IssueDto> scrollIssueForExport(DbSession dbSession, String projectUuid) { + return mapper(dbSession).scrollIssueForExport(projectUuid); + } + + private static ProjectExportMapper mapper(DbSession session) { + return session.getMapper(ProjectExportMapper.class); + } + +} |