]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-13645 Make github onboarding resiliant to project name/key change
authorMathieu Suen <59278745+mathieu-suen-sonarsource@users.noreply.github.com>
Mon, 26 Apr 2021 07:44:58 +0000 (09:44 +0200)
committersonartech <sonartech@sonarsource.com>
Mon, 26 Apr 2021 20:03:35 +0000 (20:03 +0000)
Co-authored-by: Pierre <pierre.guillot@sonarsource.com>
server/sonar-webserver-webapi/src/main/java/org/sonar/server/almintegration/ws/github/ListGithubRepositoriesAction.java
server/sonar-webserver-webapi/src/test/java/org/sonar/server/almintegration/ws/github/ListGithubRepositoriesActionTest.java

index a0872a6a4cb360a0bda42671449654b207bc6298..1451788e347c228e2a32d00bb29a58f4fc0772d8 100644 (file)
  */
 package org.sonar.server.almintegration.ws.github;
 
+import java.util.Comparator;
 import java.util.List;
+import java.util.Map;
 import java.util.Optional;
+import java.util.Set;
+import java.util.function.BinaryOperator;
+import java.util.function.Function;
+import java.util.stream.Collectors;
 import org.sonar.alm.client.github.GithubApplicationClient;
 import org.sonar.alm.client.github.GithubApplicationClient.Repository;
 import org.sonar.alm.client.github.GithubApplicationClientImpl;
@@ -33,6 +39,8 @@ import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.alm.pat.AlmPatDto;
 import org.sonar.db.alm.setting.AlmSettingDto;
+import org.sonar.db.alm.setting.ProjectAlmSettingDao;
+import org.sonar.db.alm.setting.ProjectAlmSettingDto;
 import org.sonar.db.project.ProjectDto;
 import org.sonar.server.almintegration.ws.AlmIntegrationsWsAction;
 import org.sonar.server.exceptions.NotFoundException;
@@ -45,7 +53,6 @@ import static org.sonar.api.server.ws.WebService.Param.PAGE;
 import static org.sonar.api.server.ws.WebService.Param.PAGE_SIZE;
 import static org.sonar.api.server.ws.WebService.Param.TEXT_QUERY;
 import static org.sonar.db.permission.GlobalPermission.PROVISION_PROJECTS;
-import static org.sonar.server.almintegration.ws.github.ImportGithubProjectAction.getProjectKeyFromRepository;
 import static org.sonar.server.ws.WsUtils.writeProtobuf;
 
 public class ListGithubRepositoriesAction implements AlmIntegrationsWsAction {
@@ -56,11 +63,13 @@ public class ListGithubRepositoriesAction implements AlmIntegrationsWsAction {
   private final DbClient dbClient;
   private final UserSession userSession;
   private final GithubApplicationClient githubApplicationClient;
+  private final ProjectAlmSettingDao projectAlmSettingDao;
 
-  public ListGithubRepositoriesAction(DbClient dbClient, UserSession userSession, GithubApplicationClientImpl githubApplicationClient) {
+  public ListGithubRepositoriesAction(DbClient dbClient, UserSession userSession, GithubApplicationClientImpl githubApplicationClient, ProjectAlmSettingDao projectAlmSettingDao) {
     this.dbClient = dbClient;
     this.userSession = userSession;
     this.githubApplicationClient = githubApplicationClient;
+    this.projectAlmSettingDao = projectAlmSettingDao;
   }
 
   @Override
@@ -131,20 +140,46 @@ public class ListGithubRepositoriesAction implements AlmIntegrationsWsAction {
 
       List<Repository> repositoryList = repositories.getRepositories();
       if (repositoryList != null) {
-        repositoryList.forEach(repository -> {
-              Optional<String> sonarQubeKey = dbClient.projectDao().selectProjectByKey(dbSession, getProjectKeyFromRepository(repository)).map(ProjectDto::getKey);
-              response.addRepositories(AlmIntegrations.GithubRepository.newBuilder()
-                .setId(repository.getId())
-                .setKey(repository.getFullName())
-                .setName(repository.getName())
-                .setUrl(repository.getUrl())
-                .setSqProjectKey(sonarQubeKey.orElse(""))
-                .build());
-            }
-          );
+
+        Set<String> repo = repositoryList.stream().map(Repository::getFullName).collect(Collectors.toSet());
+        List<ProjectAlmSettingDto> projectAlmSettingDtos = projectAlmSettingDao.selectByAlmSettingAndRepos(dbSession, almSettingDto, repo);
+
+        Map<String, ProjectDto> projectsDtoByAlmRepo = getProjectDtoByAlmRepo(dbSession, projectAlmSettingDtos);
+
+        for (Repository repository : repositoryList) {
+          AlmIntegrations.GithubRepository.Builder builder = AlmIntegrations.GithubRepository.newBuilder()
+            .setId(repository.getId())
+            .setKey(repository.getFullName())
+            .setName(repository.getName())
+            .setUrl(repository.getUrl());
+
+          if (projectsDtoByAlmRepo.containsKey(repository.getFullName())) {
+            Optional.ofNullable(projectsDtoByAlmRepo.get(repository.getFullName()))
+              .ifPresent(p -> builder.setSqProjectKey(p.getKey()));
+          }
+
+          response.addRepositories(builder.build());
+        }
       }
 
       return response.build();
     }
   }
+
+  private Map<String, ProjectDto> getProjectDtoByAlmRepo(DbSession dbSession, List<ProjectAlmSettingDto> projectAlmSettingDtos) {
+    Map<String, ProjectAlmSettingDto> projectAlmSettingDtoByProjectUuid = projectAlmSettingDtos.stream()
+      .collect(Collectors.toMap(ProjectAlmSettingDto::getProjectUuid, Function.identity()));
+
+    Set<String> projectUuids = projectAlmSettingDtos.stream().map(ProjectAlmSettingDto::getProjectUuid).collect(Collectors.toSet());
+
+    return dbClient.projectDao().selectByUuids(dbSession, projectUuids)
+      .stream()
+      .collect(Collectors.toMap(projectDto -> projectAlmSettingDtoByProjectUuid.get(projectDto.getUuid()).getAlmRepo(),
+        Function.identity(), resolveNameCollisionOperatorByNaturalOrder()));
+  }
+
+  private static BinaryOperator<ProjectDto> resolveNameCollisionOperatorByNaturalOrder() {
+    Comparator<ProjectDto> comparator = Comparator.comparing(ProjectDto::getKey);
+    return (a, b) -> comparator.compare(a, b) > 0 ? b : a;
+  }
 }
index 66fd47a2ad2208e8dbbb5a159d6f3df427977e28..9e73e35f6829ab63c1e35f5343c52ab3d4d4e589 100644 (file)
@@ -29,6 +29,7 @@ import org.sonar.api.utils.System2;
 import org.sonar.db.DbTester;
 import org.sonar.db.alm.pat.AlmPatDto;
 import org.sonar.db.alm.setting.AlmSettingDto;
+import org.sonar.db.alm.setting.ProjectAlmSettingDao;
 import org.sonar.db.permission.GlobalPermission;
 import org.sonar.db.project.ProjectDto;
 import org.sonar.db.user.UserDto;
@@ -63,7 +64,9 @@ public class ListGithubRepositoriesActionTest {
   @Rule
   public DbTester db = DbTester.create(system2);
 
-  private final WsActionTester ws = new WsActionTester(new ListGithubRepositoriesAction(db.getDbClient(), userSession, appClient));
+  private final ProjectAlmSettingDao projectAlmSettingDao = db.getDbClient().projectAlmSettingDao();
+
+  private final WsActionTester ws = new WsActionTester(new ListGithubRepositoriesAction(db.getDbClient(), userSession, appClient, projectAlmSettingDao));
 
   @Test
   public void fail_when_missing_create_project_permission() {
@@ -112,6 +115,10 @@ public class ListGithubRepositoriesActionTest {
             .collect(Collectors.toList())));
 
     ProjectDto project = db.components().insertPrivateProjectDto(componentDto -> componentDto.setDbKey("github_HelloWorld"));
+    db.almSettings().insertGitHubProjectAlmSetting(githubAlmSettings, project, projectAlmSettingDto -> projectAlmSettingDto.setAlmRepo("github/HelloWorld"));
+
+    ProjectDto project2 = db.components().insertPrivateProjectDto(componentDto -> componentDto.setDbKey("github_HelloWorld2"));
+    db.almSettings().insertGitHubProjectAlmSetting(githubAlmSettings, project2, projectAlmSettingDto -> projectAlmSettingDto.setAlmRepo("github/HelloWorld"));
 
     ListGithubRepositoriesWsResponse response = ws.newRequest()
       .setParam(ListGithubRepositoriesAction.PARAM_ALM_SETTING, githubAlmSettings.getKey())