]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-18852 Refactor 'portfolio_projects'
authorDuarte Meneses <duarte.meneses@sonarsource.com>
Mon, 8 May 2023 21:08:34 +0000 (16:08 -0500)
committersonartech <sonartech@sonarsource.com>
Fri, 12 May 2023 20:02:41 +0000 (20:02 +0000)
server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/analysis/AnalysisMetadataHolder.java
server/sonar-db-dao/src/it/java/org/sonar/db/portfolio/PortfolioDaoIT.java
server/sonar-db-dao/src/main/java/org/sonar/db/component/BranchDao.java
server/sonar-db-dao/src/main/java/org/sonar/db/component/BranchMapper.java
server/sonar-db-dao/src/main/java/org/sonar/db/portfolio/PortfolioProjectDto.java
server/sonar-db-dao/src/main/resources/org/sonar/db/component/BranchMapper.xml
server/sonar-db-dao/src/main/resources/org/sonar/db/portfolio/PortfolioMapper.xml
server/sonar-db-dao/src/testFixtures/java/org/sonar/db/component/ComponentDbTester.java
server/sonar-server-common/src/main/java/org/sonar/server/project/Project.java

index b43943642fc40c42b1804c1659c3030b5343c4d9..9b712c6a430f2e3c89bfa725d6a549148c1d19e1 100644 (file)
@@ -93,16 +93,8 @@ public interface AnalysisMetadataHolder {
   String getPullRequestKey();
 
   /**
-   * The project as represented by the main branch. It is used to load settings
-   * like Quality gates, webhooks and configuration.
-   *
-   * In case of analysis of main branch, the returned value is the main branch,
-   * so its uuid and key are the same in
-   * {@link org.sonar.ce.task.projectanalysis.component.TreeRootHolder#getRoot().
-   *
-   * In case of analysis of non-main branch or pull request, the returned value
-   * is the main branch. Its uuid and key are different than
-   * {@link org.sonar.ce.task.projectanalysis.component.TreeRootHolder#getRoot().
+   * The project being analyzed. It can be a project, application or portfolio.
+   * It is used to load settings like Quality gates, webhooks and configuration.
    *
    * @throws IllegalStateException if project has not been set
    */
index e89907dd86b37501220939ea1ccfc6c8b647e2db..70865740051eb51b87410b8b2f9cba86f849b58f 100644 (file)
@@ -29,6 +29,7 @@ import org.sonar.db.DbSession;
 import org.sonar.db.DbTester;
 import org.sonar.db.audit.AuditPersister;
 import org.sonar.db.component.BranchDto;
+import org.sonar.db.component.ProjectData;
 import org.sonar.db.project.ApplicationProjectDto;
 import org.sonar.db.project.ProjectDto;
 
@@ -46,7 +47,7 @@ import static org.mockito.Mockito.verify;
 public class PortfolioDaoIT {
   private final System2 system2 = new AlwaysIncreasingSystem2(1L, 1);
   @Rule
-  public DbTester db = DbTester.create(system2);
+  public DbTester db = DbTester.create(system2, true);
   private final AuditPersister audit = mock(AuditPersister.class);
   private final PortfolioDao portfolioDao = new PortfolioDao(system2, UuidFactoryFast.getInstance(), audit);
   private final DbSession session = db.getSession();
@@ -443,7 +444,7 @@ public class PortfolioDaoIT {
     PortfolioDto portfolio1 = db.components().insertPrivatePortfolioDto("portfolio1");
     PortfolioDto portfolio2 = db.components().insertPrivatePortfolioDto("portfolio2");
 
-    ProjectDto app1 = db.components().insertPrivateApplication(c -> c.setUuid("app1")).getProjectDto();
+    ProjectDto app1 = db.components().insertPrivateApplication("app1").getProjectDto();
     portfolioDao.addReference(session, "portfolio1", "portfolio2");
     portfolioDao.addReference(session, "portfolio1", app1.getUuid());
     portfolioDao.addReference(session, "portfolio2", app1.getUuid());
@@ -649,27 +650,30 @@ public class PortfolioDaoIT {
 
   @Test
   public void selectAllProjectsInHierarchy() {
-    ProjectDto p1 = db.components().insertPrivateProject("p1").getProjectDto();
-    ProjectDto p2 = db.components().insertPrivateProject("p2").getProjectDto();
-    ProjectDto p3 = db.components().insertPrivateProject("p3").getProjectDto();
-    ProjectDto p4 = db.components().insertPrivateProject("p4").getProjectDto();
+    ProjectData p1 = db.components().insertPrivateProject("p1");
+    ProjectData p2 = db.components().insertPrivateProject("p2");
+    ProjectData p3 = db.components().insertPrivateProject("p3");
+    ProjectData p4 = db.components().insertPrivateProject("p4");
 
     PortfolioDto root = db.components().insertPrivatePortfolioDto("root");
     PortfolioDto child1 = addPortfolio(root, "child1");
     PortfolioDto child11 = addPortfolio(child1, "child11");
     PortfolioDto root2 = db.components().insertPrivatePortfolioDto("root2");
 
-    db.components().addPortfolioProject(root, p1);
-    db.components().addPortfolioProject(child1, p2);
-    db.components().addPortfolioProject(child11, p3);
-    db.components().addPortfolioProject(root2, p4);
+    db.components().addPortfolioProject(root, p1.getProjectDto());
+    db.components().addPortfolioProject(child1, p2.getProjectDto());
+    db.components().addPortfolioProject(child11, p3.getProjectDto());
+    db.components().addPortfolioProject(root2, p4.getProjectDto());
 
-    db.components().addPortfolioProjectBranch(root, p1, "branch1");
+    db.components().addPortfolioProjectBranch(root, p1.getProjectDto(), "branch1");
     session.commit();
 
     assertThat(portfolioDao.selectAllProjectsInHierarchy(session, root.getUuid()))
-      .extracting(PortfolioProjectDto::getProjectUuid, PortfolioProjectDto::getBranchUuids)
-      .containsExactlyInAnyOrder(tuple("p1", Set.of("branch1")), tuple("p2", emptySet()), tuple("p3", emptySet()));
+      .extracting(PortfolioProjectDto::getProjectUuid, PortfolioProjectDto::getBranchUuids, PortfolioProjectDto::getMainBranchUuid)
+      .containsExactlyInAnyOrder(
+        tuple("p1", Set.of("branch1"), p1.getMainBranchDto().getUuid()),
+        tuple("p2", emptySet(), p2.getMainBranchDto().getUuid()),
+        tuple("p3", emptySet(), p3.getMainBranchDto().getUuid()));
     assertThat(portfolioDao.selectAllProjectsInHierarchy(session, "nonexisting")).isEmpty();
   }
 
index e884c269e4ef472fd2887790477a5390537a3694..337a3ec94238a2ab230fc091168450b256b54670 100644 (file)
@@ -87,7 +87,7 @@ public class BranchDao implements Dao {
     if (branchKeys.isEmpty()) {
       return emptyList();
     }
-    return executeLargeInputs(branchKeys, partition -> mapper(dbSession).selectByKeys(projectUuid, branchKeys));
+    return executeLargeInputs(branchKeys, partition -> mapper(dbSession).selectByKeys(projectUuid, partition));
   }
 
   /*
@@ -113,7 +113,7 @@ public class BranchDao implements Dao {
     if (projectUuids.isEmpty()) {
       return List.of();
     }
-    return mapper(dbSession).selectMainBranchesByProjectUuids(projectUuids);
+    return executeLargeInputs(projectUuids, partition -> mapper(dbSession).selectMainBranchesByProjectUuids(partition));
   }
 
   public List<PrBranchAnalyzedLanguageCountByProjectDto> countPrBranchAnalyzedLanguageByProjectUuid(DbSession dbSession) {
index 803cae647d2ca485edd11f279aa9f7ff94cf389f..57bd3acd77e7050cd0f4545fde9657c24fa4311a 100644 (file)
@@ -39,7 +39,7 @@ public interface BranchMapper {
 
   BranchDto selectByKey(@Param("projectUuid") String projectUuid, @Param("key") String key, @Param("branchType") BranchType branchType);
 
-  List<BranchDto> selectByKeys(@Param("projectUuid") String projectUuid, @Param("keys") Set<String> branchKeys);
+  List<BranchDto> selectByKeys(@Param("projectUuid") String projectUuid, @Param("keys") Collection<String> branchKeys);
 
   BranchDto selectByUuid(@Param("uuid") String uuid);
 
@@ -75,5 +75,5 @@ public interface BranchMapper {
 
   Optional<BranchDto> selectMainBranchByProjectUuid(String projectUuid);
 
-  List<BranchDto> selectMainBranchesByProjectUuids(@Param("projectUuids") Set<String> projectUuids);
+  List<BranchDto> selectMainBranchesByProjectUuids(@Param("projectUuids") Collection<String> projectUuids);
 }
index 31976446c2f09e702668a8817b659f4a77c5e453..2fd5b1e69476aabcdcde25f368af6f7f5a1ccdfc 100644 (file)
@@ -28,6 +28,7 @@ public class PortfolioProjectDto {
   private String projectUuid;
   private String projectKey;
   private Set<String> branchUuids;
+  private String mainBranchUuid;
   private long createdAt;
 
   public String getUuid() {
@@ -39,6 +40,14 @@ public class PortfolioProjectDto {
     return this;
   }
 
+  public String getMainBranchUuid() {
+    return mainBranchUuid;
+  }
+
+  public void setMainBranchUuid(String mainBranchUuid) {
+    this.mainBranchUuid = mainBranchUuid;
+  }
+
   public String getPortfolioUuid() {
     return portfolioUuid;
   }
index 0ce062f2ee52bb3d244dd8e1515f77fb5749f7d9..56d6036d4b0968baea4c17e4b0d54d11a3561c8d 100644 (file)
     pb.project_uuid = #{projectUuid, jdbcType=VARCHAR}
   </select>
 
-  <select id="selectMainBranchByProjectUuid" parameterType="string" resultType="org.sonar.db.component.BranchDto">
+  <select id="selectMainBranchByProjectUuid" resultType="org.sonar.db.component.BranchDto">
     select <include refid="columns"/>
     from project_branches pb
     where
index be38d220f1b3e2fdfddf91dddc425f65b1ca8060..ea2c9dcb7356948e6b644ec44b621b98730bb751 100644 (file)
@@ -36,7 +36,8 @@
     pf.kee as portfolioKey,
     p.kee as projectKey,
     pp.created_at as createdAt,
-    ppb.branch_uuid as branchUuid
+    ppb.branch_uuid as branchUuid,
+    pb.uuid as mainBranchUuid
   </sql>
 
   <sql id="portfolioReferenceColumns">
       <include refid="portfolioProjectColumns"/>
      FROM portfolio_projects pp
      INNER JOIN projects p on p.uuid = pp.project_uuid
+     INNER JOIN project_branches pb on pb.project_uuid = p.uuid and pb.is_main = ${_true}
      INNER JOIN portfolios pf on pf.uuid = pp.portfolio_uuid
      LEFT OUTER JOIN portfolio_proj_branches ppb on pp.uuid = ppb.portfolio_project_uuid
      WHERE
       <include refid="portfolioProjectColumns"/>
      FROM portfolio_projects pp
      INNER JOIN projects p on p.uuid = pp.project_uuid
+     INNER JOIN project_branches pb on pb.project_uuid = p.uuid and pb.is_main = ${_true}
      INNER JOIN portfolios pf on pf.uuid = pp.portfolio_uuid
      LEFT OUTER JOIN portfolio_proj_branches ppb on pp.uuid = ppb.portfolio_project_uuid
      WHERE
       <include refid="portfolioProjectColumns"/>
     FROM portfolio_projects pp
     INNER JOIN projects p on p.uuid = pp.project_uuid
+    INNER JOIN project_branches pb on pb.project_uuid = p.uuid and pb.is_main = ${_true}
     INNER JOIN portfolios pf on pf.uuid = pp.portfolio_uuid
     LEFT OUTER JOIN portfolio_proj_branches ppb on pp.uuid = ppb.portfolio_project_uuid
   </select>
       <include refid="portfolioProjectColumns"/>
     FROM portfolio_projects pp
        INNER JOIN projects p on p.uuid = pp.project_uuid
+       INNER JOIN project_branches pb on pb.project_uuid = p.uuid and pb.is_main = ${_true}
        INNER JOIN portfolios pf on pp.portfolio_uuid = pf.uuid
        LEFT OUTER JOIN portfolio_proj_branches ppb on pp.uuid = ppb.portfolio_project_uuid
     where
index 55acac3b05d56449030726412197ea214fbbf7a7..de72ef83db388e6441e991470408824d053da76f 100644 (file)
@@ -21,7 +21,6 @@ package org.sonar.db.component;
 
 import java.util.Arrays;
 import java.util.List;
-import java.util.Optional;
 import java.util.function.Consumer;
 import javax.annotation.Nullable;
 import org.sonar.api.resources.Qualifiers;
@@ -105,11 +104,19 @@ public class ComponentDbTester {
   }
 
   public ProjectData insertPublicProject(String uuid) {
-    return insertComponentAndBranchAndProject(ComponentTesting.newPublicProjectDto(uuid), false);
+    if (useDifferentUuids) {
+      return insertComponentAndBranchAndProject(ComponentTesting.newPublicProjectDto(), false, defaults(), defaults(), p -> p.setUuid(uuid));
+    } else {
+      return insertComponentAndBranchAndProject(ComponentTesting.newPublicProjectDto(uuid), false);
+    }
   }
 
   public ProjectData insertPublicProject(String uuid, Consumer<ComponentDto> dtoPopulator) {
-    return insertComponentAndBranchAndProject(ComponentTesting.newPublicProjectDto(uuid), false, defaults(), dtoPopulator);
+    if (useDifferentUuids) {
+      return insertComponentAndBranchAndProject(ComponentTesting.newPublicProjectDto(), false, defaults(), dtoPopulator, p -> p.setUuid(uuid));
+    } else {
+      return insertComponentAndBranchAndProject(ComponentTesting.newPublicProjectDto(uuid), false, defaults(), dtoPopulator);
+    }
   }
 
   public ProjectData insertPublicProject(ComponentDto componentDto) {
@@ -117,7 +124,11 @@ public class ComponentDbTester {
   }
 
   public ProjectData insertPrivateProject(String uuid) {
-    return insertComponentAndBranchAndProject(ComponentTesting.newPrivateProjectDto(uuid), true);
+    if (useDifferentUuids) {
+      return insertComponentAndBranchAndProject(ComponentTesting.newPrivateProjectDto(), true, defaults(), defaults(), p -> p.setUuid(uuid));
+    } else {
+      return insertComponentAndBranchAndProject(ComponentTesting.newPrivateProjectDto(uuid), true);
+    }
   }
 
   public final ProjectData insertPrivateProject(Consumer<ComponentDto> dtoPopulator) {
@@ -338,6 +349,14 @@ public class ComponentDbTester {
     return insertComponentAndBranchAndProject(ComponentTesting.newApplication().setPrivate(false), false, defaults(), dtoPopulator);
   }
 
+  public final ProjectData insertPrivateApplication(String uuid, Consumer<ComponentDto> dtoPopulator) {
+    return insertPrivateApplication(dtoPopulator, p -> p.setUuid(uuid));
+  }
+
+  public final ProjectData insertPrivateApplication(String uuid) {
+    return insertPrivateApplication(defaults(), p -> p.setUuid(uuid));
+  }
+
   public final ProjectData insertPrivateApplication(Consumer<ComponentDto> dtoPopulator) {
     return insertPrivateApplication(dtoPopulator, defaults());
   }
index bfbcad3444df642046d6408a7e7eccf25b3d36b3..f09b33178acb59b169e408eb08a181cb63ad255a 100644 (file)
@@ -24,6 +24,7 @@ import java.util.Objects;
 import javax.annotation.Nullable;
 import javax.annotation.concurrent.Immutable;
 import org.sonar.db.component.ComponentDto;
+import org.sonar.db.portfolio.PortfolioDto;
 import org.sonar.db.project.ProjectDto;
 
 import static java.util.Collections.emptyList;
@@ -53,6 +54,10 @@ public class Project {
     return new Project(project.getUuid(), project.getKey(), project.getName(), project.getDescription(), project.getTags());
   }
 
+  public static Project from(PortfolioDto portfolio) {
+    return new Project(portfolio.getUuid(), portfolio.getKey(), portfolio.getName(), portfolio.getDescription(), emptyList());
+  }
+
   /**
    * Always links to a row that exists in database.
    */