You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

GitlabProjectCreatorTest.java 9.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. /*
  2. * SonarQube
  3. * Copyright (C) 2009-2024 SonarSource SA
  4. * mailto:info AT sonarsource DOT com
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public
  8. * License as published by the Free Software Foundation; either
  9. * version 3 of the License, or (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public License
  17. * along with this program; if not, write to the Free Software Foundation,
  18. * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  19. */
  20. package org.sonar.server.common.almsettings.gitlab;
  21. import java.util.List;
  22. import java.util.Optional;
  23. import org.junit.jupiter.api.BeforeEach;
  24. import org.junit.jupiter.api.Test;
  25. import org.junit.jupiter.api.extension.ExtendWith;
  26. import org.mockito.Answers;
  27. import org.mockito.ArgumentCaptor;
  28. import org.mockito.InjectMocks;
  29. import org.mockito.Mock;
  30. import org.mockito.junit.jupiter.MockitoExtension;
  31. import org.sonar.alm.client.gitlab.GitLabBranch;
  32. import org.sonar.alm.client.gitlab.GitlabApplicationClient;
  33. import org.sonar.alm.client.gitlab.GitlabServerException;
  34. import org.sonar.alm.client.gitlab.Project;
  35. import org.sonar.db.DbClient;
  36. import org.sonar.db.DbSession;
  37. import org.sonar.db.alm.pat.AlmPatDto;
  38. import org.sonar.db.alm.setting.ALM;
  39. import org.sonar.db.alm.setting.AlmSettingDto;
  40. import org.sonar.db.alm.setting.ProjectAlmSettingDto;
  41. import org.sonar.db.project.CreationMethod;
  42. import org.sonar.db.project.ProjectDto;
  43. import org.sonar.server.common.almintegration.ProjectKeyGenerator;
  44. import org.sonar.server.common.almsettings.DevOpsProjectDescriptor;
  45. import org.sonar.server.common.project.ProjectCreator;
  46. import org.sonar.server.component.ComponentCreationData;
  47. import org.sonar.server.user.UserSession;
  48. import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
  49. import static org.assertj.core.api.AssertionsForClassTypes.assertThatExceptionOfType;
  50. import static org.mockito.ArgumentMatchers.any;
  51. import static org.mockito.ArgumentMatchers.eq;
  52. import static org.mockito.Mockito.lenient;
  53. import static org.mockito.Mockito.mock;
  54. import static org.mockito.Mockito.verify;
  55. import static org.mockito.Mockito.when;
  56. @ExtendWith(MockitoExtension.class)
  57. class GitlabProjectCreatorTest {
  58. private static final String PROJECT_UUID = "projectUuid";
  59. @Mock(answer = Answers.RETURNS_DEEP_STUBS)
  60. private DbClient dbClient;
  61. @Mock
  62. private ProjectKeyGenerator projectKeyGenerator;
  63. @Mock
  64. private ProjectCreator projectCreator;
  65. @Mock
  66. private AlmSettingDto almSettingDto;
  67. @Mock
  68. private DevOpsProjectDescriptor devOpsProjectDescriptor;
  69. @Mock
  70. private GitlabApplicationClient gitlabApplicationClient;
  71. @Mock
  72. private UserSession userSession;
  73. @InjectMocks
  74. private GitlabProjectCreator underTest;
  75. private static final String USER_LOGIN = "userLogin";
  76. private static final String USER_UUID = "userUuid";
  77. private static final String GROUP_NAME = "group1";
  78. private static final String REPOSITORY_PATH_WITH_NAMESPACE = "pathWith/namespace";
  79. private static final String GITLAB_PROJECT_NAME = "gitlabProjectName";
  80. private static final String REPOSITORY_ID = "1234";
  81. private static final String MAIN_BRANCH_NAME = "defaultBranch";
  82. private static final String ALM_SETTING_KEY = "gitlab_config_1";
  83. private static final String ALM_SETTING_UUID = "almSettingUuid";
  84. private static final String USER_PAT = "1234";
  85. public static final String GITLAB_URL = "http://api.com";
  86. private static final DevOpsProjectDescriptor DEVOPS_PROJECT_DESCRIPTOR = new DevOpsProjectDescriptor(ALM.GITLAB, GITLAB_URL, REPOSITORY_ID);
  87. @BeforeEach
  88. void setup() {
  89. lenient().when(userSession.getLogin()).thenReturn(USER_LOGIN);
  90. lenient().when(userSession.getUuid()).thenReturn(USER_UUID);
  91. lenient().when(almSettingDto.getUrl()).thenReturn(GITLAB_URL);
  92. lenient().when(almSettingDto.getKey()).thenReturn(ALM_SETTING_KEY);
  93. lenient().when(almSettingDto.getUuid()).thenReturn(ALM_SETTING_UUID);
  94. lenient().when(devOpsProjectDescriptor.projectIdentifier()).thenReturn(REPOSITORY_ID);
  95. lenient().when(devOpsProjectDescriptor.url()).thenReturn(GITLAB_URL);
  96. lenient().when(devOpsProjectDescriptor.alm()).thenReturn(ALM.GITLAB);
  97. }
  98. @Test
  99. void isScanAllowedUsingPermissionsFromDevopsPlatform_shouldThrowUnsupportedOperationException() {
  100. assertThatExceptionOfType(UnsupportedOperationException.class)
  101. .isThrownBy(() -> underTest.isScanAllowedUsingPermissionsFromDevopsPlatform())
  102. .withMessage("Not Implemented");
  103. }
  104. @Test
  105. void createProjectAndBindToDevOpsPlatform_whenUserHasNoPat_throws() {
  106. assertThatExceptionOfType(IllegalArgumentException.class)
  107. .isThrownBy(() -> underTest.createProjectAndBindToDevOpsPlatform(mock(DbSession.class), CreationMethod.ALM_IMPORT_API, false, null, null))
  108. .withMessage("personal access token for 'gitlab_config_1' is missing");
  109. }
  110. @Test
  111. void createProjectAndBindToDevOpsPlatform_whenRepoNotFound_throws() {
  112. mockPatForUser();
  113. when(gitlabApplicationClient.getProject(DEVOPS_PROJECT_DESCRIPTOR.url(), USER_PAT, Long.valueOf(REPOSITORY_ID))).thenThrow(new GitlabServerException(404, "Not found"));
  114. assertThatExceptionOfType(IllegalStateException.class)
  115. .isThrownBy(() -> underTest.createProjectAndBindToDevOpsPlatform(mock(DbSession.class), CreationMethod.ALM_IMPORT_API, false, null, null))
  116. .withMessage("Failed to fetch GitLab project with ID '1234' from 'http://api.com'");
  117. }
  118. @Test
  119. void createProjectAndBindToDevOpsPlatform_whenRepoFoundOnGitlab_successfullyCreatesProject() {
  120. mockPatForUser();
  121. mockGitlabProject();
  122. mockMainBranch();
  123. mockProjectCreation("projectKey", "projectName");
  124. underTest.createProjectAndBindToDevOpsPlatform(mock(DbSession.class), CreationMethod.ALM_IMPORT_API, true, "projectKey", "projectName");
  125. ArgumentCaptor<ProjectAlmSettingDto> projectAlmSettingCaptor = ArgumentCaptor.forClass(ProjectAlmSettingDto.class);
  126. verify(dbClient.projectAlmSettingDao()).insertOrUpdate(any(), projectAlmSettingCaptor.capture(), eq(ALM_SETTING_KEY), eq("projectName"), eq("projectKey"));
  127. ProjectAlmSettingDto createdProjectAlmSettingDto = projectAlmSettingCaptor.getValue();
  128. assertThat(createdProjectAlmSettingDto.getAlmSettingUuid()).isEqualTo(ALM_SETTING_UUID);
  129. assertThat(createdProjectAlmSettingDto.getAlmRepo()).isEqualTo(REPOSITORY_ID);
  130. assertThat(createdProjectAlmSettingDto.getProjectUuid()).isEqualTo(PROJECT_UUID);
  131. assertThat(createdProjectAlmSettingDto.getMonorepo()).isTrue();
  132. }
  133. @Test
  134. void createProjectAndBindToDevOpsPlatform_whenNoKeyAndNameSpecified_generatesOneKeyAndUsersGitlabProjectName() {
  135. mockPatForUser();
  136. mockGitlabProject();
  137. mockMainBranch();
  138. String generatedProjectKey = "generatedProjectKey";
  139. when(projectKeyGenerator.generateUniqueProjectKey(REPOSITORY_PATH_WITH_NAMESPACE)).thenReturn(generatedProjectKey);
  140. mockProjectCreation(generatedProjectKey, GITLAB_PROJECT_NAME);
  141. underTest.createProjectAndBindToDevOpsPlatform(mock(DbSession.class), CreationMethod.ALM_IMPORT_API, true, null, null);
  142. ArgumentCaptor<ProjectAlmSettingDto> projectAlmSettingCaptor = ArgumentCaptor.forClass(ProjectAlmSettingDto.class);
  143. verify(dbClient.projectAlmSettingDao()).insertOrUpdate(any(), projectAlmSettingCaptor.capture(), eq(ALM_SETTING_KEY), eq(GITLAB_PROJECT_NAME), eq(generatedProjectKey));
  144. ProjectAlmSettingDto createdProjectAlmSettingDto = projectAlmSettingCaptor.getValue();
  145. assertThat(createdProjectAlmSettingDto.getAlmSettingUuid()).isEqualTo(ALM_SETTING_UUID);
  146. assertThat(createdProjectAlmSettingDto.getAlmRepo()).isEqualTo(REPOSITORY_ID);
  147. assertThat(createdProjectAlmSettingDto.getProjectUuid()).isEqualTo(PROJECT_UUID);
  148. assertThat(createdProjectAlmSettingDto.getMonorepo()).isTrue();
  149. }
  150. private void mockPatForUser() {
  151. AlmPatDto almPatDto = mock();
  152. when(almPatDto.getPersonalAccessToken()).thenReturn(USER_PAT);
  153. when(dbClient.almPatDao().selectByUserAndAlmSetting(any(), eq(USER_UUID), eq(almSettingDto))).thenReturn(Optional.of(almPatDto));
  154. }
  155. private void mockGitlabProject() {
  156. Project project = mock(Project.class);
  157. lenient().when(project.getPathWithNamespace()).thenReturn(REPOSITORY_PATH_WITH_NAMESPACE);
  158. when(project.getName()).thenReturn(GITLAB_PROJECT_NAME);
  159. when(gitlabApplicationClient.getProject(DEVOPS_PROJECT_DESCRIPTOR.url(), USER_PAT, Long.valueOf(REPOSITORY_ID))).thenReturn(project);
  160. }
  161. private void mockMainBranch() {
  162. when(gitlabApplicationClient.getBranches(DEVOPS_PROJECT_DESCRIPTOR.url(), USER_PAT, Long.valueOf(REPOSITORY_ID)))
  163. .thenReturn(List.of(new GitLabBranch("notMain", false), new GitLabBranch(MAIN_BRANCH_NAME, true)));
  164. }
  165. private void mockProjectCreation(String projectKey, String projectName) {
  166. ComponentCreationData componentCreationData = mock();
  167. ProjectDto projectDto = mock();
  168. when(componentCreationData.projectDto()).thenReturn(projectDto);
  169. when(projectDto.getUuid()).thenReturn(PROJECT_UUID);
  170. when(projectDto.getKey()).thenReturn(projectKey);
  171. when(projectDto.getName()).thenReturn(projectName);
  172. when(projectCreator.createProject(any(), eq(projectKey), eq(projectName), eq(MAIN_BRANCH_NAME), eq(CreationMethod.ALM_IMPORT_API)))
  173. .thenReturn(componentCreationData);
  174. }
  175. }