]> source.dussan.org Git - sonarqube.git/blob
7e945bc0589d502c323c3bc4f038956b24744ef6
[sonarqube.git] /
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
22 import java.util.List;
23 import java.util.Optional;
24 import org.junit.jupiter.api.BeforeEach;
25 import org.junit.jupiter.api.Test;
26 import org.junit.jupiter.api.extension.ExtendWith;
27 import org.mockito.Answers;
28 import org.mockito.ArgumentCaptor;
29 import org.mockito.InjectMocks;
30 import org.mockito.Mock;
31 import org.mockito.junit.jupiter.MockitoExtension;
32 import org.sonar.alm.client.gitlab.GitLabBranch;
33 import org.sonar.alm.client.gitlab.GitlabApplicationClient;
34 import org.sonar.alm.client.gitlab.GitlabServerException;
35 import org.sonar.alm.client.gitlab.Project;
36 import org.sonar.db.DbClient;
37 import org.sonar.db.DbSession;
38 import org.sonar.db.alm.pat.AlmPatDto;
39 import org.sonar.db.alm.setting.ALM;
40 import org.sonar.db.alm.setting.AlmSettingDto;
41 import org.sonar.db.alm.setting.ProjectAlmSettingDto;
42 import org.sonar.db.project.CreationMethod;
43 import org.sonar.db.project.ProjectDto;
44 import org.sonar.server.common.almintegration.ProjectKeyGenerator;
45 import org.sonar.server.common.almsettings.DevOpsProjectDescriptor;
46 import org.sonar.server.common.project.ProjectCreator;
47 import org.sonar.server.component.ComponentCreationData;
48 import org.sonar.server.user.UserSession;
49
50 import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
51 import static org.assertj.core.api.AssertionsForClassTypes.assertThatExceptionOfType;
52 import static org.mockito.ArgumentMatchers.any;
53 import static org.mockito.ArgumentMatchers.eq;
54 import static org.mockito.Mockito.lenient;
55 import static org.mockito.Mockito.mock;
56 import static org.mockito.Mockito.verify;
57 import static org.mockito.Mockito.when;
58
59 @ExtendWith(MockitoExtension.class)
60 class GitlabProjectCreatorTest {
61
62   private static final String PROJECT_UUID = "projectUuid";
63
64   private static final String USER_LOGIN = "userLogin";
65   private static final String USER_UUID = "userUuid";
66
67   private static final String REPOSITORY_PATH_WITH_NAMESPACE = "pathWith/namespace";
68
69   private static final String GITLAB_PROJECT_NAME = "gitlabProjectName";
70
71   private static final String REPOSITORY_ID = "1234";
72
73   private static final String MAIN_BRANCH_NAME = "defaultBranch";
74
75   private static final String ALM_SETTING_KEY = "gitlab_config_1";
76   private static final String ALM_SETTING_UUID = "almSettingUuid";
77
78   private static final String USER_PAT = "1234";
79
80   public static final String GITLAB_URL = "http://api.com";
81   @Mock(answer = Answers.RETURNS_DEEP_STUBS)
82   private DbClient dbClient;
83
84   @Mock
85   private ProjectKeyGenerator projectKeyGenerator;
86
87   @Mock
88   private ProjectCreator projectCreator;
89
90   @Mock
91   private AlmSettingDto almSettingDto;
92   @Mock
93   private DevOpsProjectDescriptor devOpsProjectDescriptor;
94   @Mock
95   private GitlabApplicationClient gitlabApplicationClient;
96   @Mock
97   private UserSession userSession;
98
99   @InjectMocks
100   private GitlabProjectCreator underTest;
101
102   @BeforeEach
103   void setup() {
104     lenient().when(userSession.getLogin()).thenReturn(USER_LOGIN);
105     lenient().when(userSession.getUuid()).thenReturn(USER_UUID);
106
107     lenient().when(almSettingDto.getUrl()).thenReturn(GITLAB_URL);
108     lenient().when(almSettingDto.getKey()).thenReturn(ALM_SETTING_KEY);
109     lenient().when(almSettingDto.getUuid()).thenReturn(ALM_SETTING_UUID);
110
111     lenient().when(devOpsProjectDescriptor.projectIdentifier()).thenReturn(REPOSITORY_ID);
112     lenient().when(devOpsProjectDescriptor.url()).thenReturn(GITLAB_URL);
113     lenient().when(devOpsProjectDescriptor.alm()).thenReturn(ALM.GITLAB);
114   }
115
116   @Test
117   void isScanAllowedUsingPermissionsFromDevopsPlatform_shouldThrowUnsupportedOperationException() {
118     assertThatExceptionOfType(UnsupportedOperationException.class)
119       .isThrownBy(() -> underTest.isScanAllowedUsingPermissionsFromDevopsPlatform())
120       .withMessage("Not Implemented");
121   }
122
123   @Test
124   void createProjectAndBindToDevOpsPlatform_whenUserHasNoPat_throws() {
125     assertThatExceptionOfType(IllegalArgumentException.class)
126       .isThrownBy(() -> underTest.createProjectAndBindToDevOpsPlatform(mock(DbSession.class), CreationMethod.ALM_IMPORT_API, false, null, null))
127       .withMessage("personal access token for 'gitlab_config_1' is missing");
128   }
129
130   @Test
131   void createProjectAndBindToDevOpsPlatform_whenRepoNotFound_throws() {
132     mockPatForUser();
133     when(gitlabApplicationClient.getProject(GITLAB_URL, USER_PAT, Long.valueOf(REPOSITORY_ID))).thenThrow(new GitlabServerException(404, "Not found"));
134     assertThatExceptionOfType(IllegalStateException.class)
135       .isThrownBy(() -> underTest.createProjectAndBindToDevOpsPlatform(mock(DbSession.class), CreationMethod.ALM_IMPORT_API, false, null, null))
136       .withMessage("Failed to fetch GitLab project with ID '1234' from 'http://api.com'");
137
138   }
139
140   @Test
141   void createProjectAndBindToDevOpsPlatform_whenRepoFoundOnGitlab_successfullyCreatesProject() {
142     mockPatForUser();
143     mockGitlabProject();
144     mockMainBranch();
145     mockProjectCreation("projectKey", "projectName");
146
147     underTest.createProjectAndBindToDevOpsPlatform(mock(DbSession.class), CreationMethod.ALM_IMPORT_API, true, "projectKey", "projectName");
148
149     ArgumentCaptor<ProjectAlmSettingDto> projectAlmSettingCaptor = ArgumentCaptor.forClass(ProjectAlmSettingDto.class);
150
151     verify(dbClient.projectAlmSettingDao()).insertOrUpdate(any(), projectAlmSettingCaptor.capture(), eq(ALM_SETTING_KEY), eq("projectName"), eq("projectKey"));
152
153     ProjectAlmSettingDto createdProjectAlmSettingDto = projectAlmSettingCaptor.getValue();
154
155     assertThat(createdProjectAlmSettingDto.getAlmSettingUuid()).isEqualTo(ALM_SETTING_UUID);
156     assertThat(createdProjectAlmSettingDto.getAlmRepo()).isEqualTo(REPOSITORY_ID);
157     assertThat(createdProjectAlmSettingDto.getProjectUuid()).isEqualTo(PROJECT_UUID);
158     assertThat(createdProjectAlmSettingDto.getMonorepo()).isTrue();
159   }
160
161   @Test
162   void createProjectAndBindToDevOpsPlatform_whenNoKeyAndNameSpecified_generatesKeyAndUsersGitlabProjectName() {
163     mockPatForUser();
164     mockGitlabProject();
165     mockMainBranch();
166
167     String generatedProjectKey = "generatedProjectKey";
168     when(projectKeyGenerator.generateUniqueProjectKey(REPOSITORY_PATH_WITH_NAMESPACE)).thenReturn(generatedProjectKey);
169
170     mockProjectCreation(generatedProjectKey, GITLAB_PROJECT_NAME);
171
172     underTest.createProjectAndBindToDevOpsPlatform(mock(DbSession.class), CreationMethod.ALM_IMPORT_API, true, null, null);
173
174     ArgumentCaptor<ProjectAlmSettingDto> projectAlmSettingCaptor = ArgumentCaptor.forClass(ProjectAlmSettingDto.class);
175
176     verify(dbClient.projectAlmSettingDao()).insertOrUpdate(any(), projectAlmSettingCaptor.capture(), eq(ALM_SETTING_KEY), eq(GITLAB_PROJECT_NAME), eq(generatedProjectKey));
177
178     ProjectAlmSettingDto createdProjectAlmSettingDto = projectAlmSettingCaptor.getValue();
179
180     assertThat(createdProjectAlmSettingDto.getAlmSettingUuid()).isEqualTo(ALM_SETTING_UUID);
181     assertThat(createdProjectAlmSettingDto.getAlmRepo()).isEqualTo(REPOSITORY_ID);
182     assertThat(createdProjectAlmSettingDto.getProjectUuid()).isEqualTo(PROJECT_UUID);
183     assertThat(createdProjectAlmSettingDto.getMonorepo()).isTrue();
184   }
185
186   private void mockPatForUser() {
187     AlmPatDto almPatDto = mock();
188     when(almPatDto.getPersonalAccessToken()).thenReturn(USER_PAT);
189     when(dbClient.almPatDao().selectByUserAndAlmSetting(any(), eq(USER_UUID), eq(almSettingDto))).thenReturn(Optional.of(almPatDto));
190   }
191
192   private void mockGitlabProject() {
193     Project project = mock(Project.class);
194     lenient().when(project.getPathWithNamespace()).thenReturn(REPOSITORY_PATH_WITH_NAMESPACE);
195     when(project.getName()).thenReturn(GITLAB_PROJECT_NAME);
196     when(gitlabApplicationClient.getProject(GITLAB_URL, USER_PAT, Long.valueOf(REPOSITORY_ID))).thenReturn(project);
197
198   }
199
200   private void mockMainBranch() {
201     when(gitlabApplicationClient.getBranches(GITLAB_URL, USER_PAT, Long.valueOf(REPOSITORY_ID)))
202       .thenReturn(List.of(new GitLabBranch("notMain", false), new GitLabBranch(MAIN_BRANCH_NAME, true)));
203   }
204
205   private void mockProjectCreation(String projectKey, String projectName) {
206     ComponentCreationData componentCreationData = mock();
207     ProjectDto projectDto = mock();
208     when(componentCreationData.projectDto()).thenReturn(projectDto);
209     when(projectDto.getUuid()).thenReturn(PROJECT_UUID);
210     when(projectDto.getKey()).thenReturn(projectKey);
211     when(projectDto.getName()).thenReturn(projectName);
212     when(projectCreator.createProject(any(), eq(projectKey), eq(projectName), eq(MAIN_BRANCH_NAME), eq(CreationMethod.ALM_IMPORT_API)))
213       .thenReturn(componentCreationData);
214   }
215
216 }