Browse Source

SONAR-21819 Add projectKey to project-bindings endpoint responses.

tags/10.5.0.89998
Wojtek Wajerowicz 1 month ago
parent
commit
fe9ee0e473

+ 36
- 0
server/sonar-webserver-common/src/main/java/org/sonar/server/common/projectbindings/service/ProjectBindingInformation.java View File

@@ -0,0 +1,36 @@
/*
* SonarQube
* Copyright (C) 2009-2024 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.server.common.projectbindings.service;

import javax.annotation.Nullable;

public record ProjectBindingInformation(
String id,

String devOpsPlatformSettingId,

String projectId,

String projectKey,

@Nullable String repository,

@Nullable String slug) {
}

+ 24
- 4
server/sonar-webserver-common/src/main/java/org/sonar/server/common/projectbindings/service/ProjectBindingsService.java View File

@@ -20,7 +20,11 @@
package org.sonar.server.common.projectbindings.service;

import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.alm.setting.ProjectAlmSettingDto;
@@ -28,6 +32,8 @@ import org.sonar.db.alm.setting.ProjectAlmSettingQuery;
import org.sonar.db.project.ProjectDto;
import org.sonar.server.common.SearchResults;

import static java.util.function.Function.identity;

public class ProjectBindingsService {

private final DbClient dbClient;
@@ -42,14 +48,14 @@ public class ProjectBindingsService {
}
}

public SearchResults<ProjectAlmSettingDto> findProjectBindingsByRequest(ProjectBindingsSearchRequest request) {
public SearchResults<ProjectBindingInformation> findProjectBindingsByRequest(ProjectBindingsSearchRequest request) {
ProjectAlmSettingQuery query = buildProjectAlmSettingQuery(request);
try (DbSession session = dbClient.openSession(false)) {
int total = dbClient.projectAlmSettingDao().countProjectAlmSettings(session, query);
if (request.pageSize() == 0) {
return new SearchResults<>(List.of(), total);
}
List<ProjectAlmSettingDto> searchResults = performSearch(session, query, request.page(), request.pageSize());
List<ProjectBindingInformation> searchResults = performSearch(session, query, request.page(), request.pageSize());
return new SearchResults<>(searchResults, total);
}
}
@@ -58,10 +64,24 @@ public class ProjectBindingsService {
return new ProjectAlmSettingQuery(request.repository(), request.dopSettingId());
}

private List<ProjectAlmSettingDto> performSearch(DbSession dbSession, ProjectAlmSettingQuery query, int page, int pageSize) {
return dbClient.projectAlmSettingDao().selectProjectAlmSettings(dbSession, query, page, pageSize)
private List<ProjectBindingInformation> performSearch(DbSession dbSession, ProjectAlmSettingQuery query, int page, int pageSize) {
List<ProjectAlmSettingDto> projectAlmSettings = dbClient.projectAlmSettingDao().selectProjectAlmSettings(dbSession, query, page, pageSize)
.stream()
.toList();
Set<String> projectUuids = projectAlmSettings.stream().map(ProjectAlmSettingDto::getProjectUuid).collect(Collectors.toSet());

List<ProjectDto> projectDtos = dbClient.projectDao().selectByUuids(dbSession, projectUuids);
Map<String, ProjectDto> projectUuidsToProject = projectDtos.stream().collect(Collectors.toMap(ProjectDto::getUuid, identity()));

return projectAlmSettings.stream().map(projectAlmSettingDtoToProjectBindingInformation(projectUuidsToProject)).toList();
}

private static Function<ProjectAlmSettingDto, ProjectBindingInformation> projectAlmSettingDtoToProjectBindingInformation(Map<String, ProjectDto> projectUuidToProject) {
return projectAlmSettingDto -> {
ProjectDto projectDto = projectUuidToProject.get(projectAlmSettingDto.getProjectUuid());
return new ProjectBindingInformation(projectAlmSettingDto.getUuid(), projectAlmSettingDto.getAlmSettingUuid(), projectAlmSettingDto.getProjectUuid(), projectDto.getKey(),
projectAlmSettingDto.getAlmRepo(), projectAlmSettingDto.getAlmSlug());
};
}

public Optional<ProjectDto> findProjectFromBinding(ProjectAlmSettingDto projectAlmSettingDto) {

+ 47
- 12
server/sonar-webserver-common/src/test/java/org/sonar/server/common/projectbindings/service/ProjectBindingsServiceTest.java View File

@@ -19,12 +19,13 @@
*/
package org.sonar.server.common.projectbindings.service;


import java.util.List;
import java.util.Optional;
import java.util.Set;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Answers;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.InjectMocks;
@@ -32,9 +33,9 @@ import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.alm.setting.ProjectAlmSettingDao;
import org.sonar.db.alm.setting.ProjectAlmSettingDto;
import org.sonar.db.alm.setting.ProjectAlmSettingQuery;
import org.sonar.db.project.ProjectDto;
import org.sonar.server.common.SearchResults;

import static org.assertj.core.api.Assertions.assertThat;
@@ -55,7 +56,7 @@ public class ProjectBindingsServiceTest {

@Mock
private DbSession dbSession;
@Mock
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private DbClient dbClient;

@InjectMocks
@@ -67,7 +68,6 @@ public class ProjectBindingsServiceTest {
@BeforeEach
void setup() {
when(dbClient.openSession(false)).thenReturn(dbSession);
when(dbClient.projectAlmSettingDao()).thenReturn(mock(ProjectAlmSettingDao.class));
}

@Test
@@ -87,21 +87,30 @@ public class ProjectBindingsServiceTest {

@Test
void findProjectBindingsByRequest_whenResults_returnsThem() {
ProjectAlmSettingDto dto1 = mock();
ProjectAlmSettingDto dto2 = mock();
List<ProjectAlmSettingDto> expectedResults = List.of(dto1, dto2);
ProjectAlmSettingDto projectAlmSettingDto1 = mockProjectAlmSettingDto("1");
ProjectAlmSettingDto projectAlmSettingDto2 = mockProjectAlmSettingDto("2");
List<ProjectAlmSettingDto> projectAlmSettings = List.of(projectAlmSettingDto1, projectAlmSettingDto2);

when(dbClient.projectAlmSettingDao().selectProjectAlmSettings(eq(dbSession), daoQueryCaptor.capture(), eq(12), eq(42)))
.thenReturn(expectedResults);
.thenReturn(projectAlmSettings);
when(dbClient.projectAlmSettingDao().countProjectAlmSettings(eq(dbSession), any()))
.thenReturn(expectedResults.size());
.thenReturn(projectAlmSettings.size());

ProjectDto mockProjectDto1 = mockProjectDto("1");
ProjectDto mockProjectDto2 = mockProjectDto("2");

when(dbClient.projectDao().selectByUuids(dbSession, Set.of("projectUuid_1", "projectUuid_2")))
.thenReturn(List.of(mockProjectDto1, mockProjectDto2));

ProjectBindingsSearchRequest request = new ProjectBindingsSearchRequest(REPO_QUERY, ALM_SETTING_UUID_QUERY, 12, 42);
SearchResults<ProjectAlmSettingDto> actualResults = underTest.findProjectBindingsByRequest(request);

List<ProjectBindingInformation> expectedResults = List.of(projectBindingInformation("1"), projectBindingInformation("2"));

SearchResults<ProjectBindingInformation> actualResults = underTest.findProjectBindingsByRequest(request);

assertThat(daoQueryCaptor.getValue().repository()).isEqualTo(REPO_QUERY);
assertThat(daoQueryCaptor.getValue().almSettingUuid()).isEqualTo(ALM_SETTING_UUID_QUERY);
assertThat(actualResults.total()).isEqualTo(expectedResults.size());
assertThat(actualResults.total()).isEqualTo(projectAlmSettings.size());
assertThat(actualResults.searchResults()).containsExactlyInAnyOrderElementsOf(expectedResults);
}

@@ -111,7 +120,7 @@ public class ProjectBindingsServiceTest {
.thenReturn(12);

ProjectBindingsSearchRequest request = new ProjectBindingsSearchRequest(null, null, 42, 0);
SearchResults<ProjectAlmSettingDto> actualResults = underTest.findProjectBindingsByRequest(request);
SearchResults<ProjectBindingInformation> actualResults = underTest.findProjectBindingsByRequest(request);

assertThat(actualResults.total()).isEqualTo(12);
assertThat(actualResults.searchResults()).isEmpty();
@@ -119,4 +128,30 @@ public class ProjectBindingsServiceTest {
verify(dbClient.projectAlmSettingDao(), never()).selectProjectAlmSettings(eq(dbSession), any(), anyInt(), anyInt());
}

private static ProjectAlmSettingDto mockProjectAlmSettingDto(String i) {
ProjectAlmSettingDto dto = mock();
when(dto.getUuid()).thenReturn("uuid_" + i);
when(dto.getAlmSettingUuid()).thenReturn("almSettingUuid_" + i);
when(dto.getProjectUuid()).thenReturn("projectUuid_" + i);
when(dto.getAlmRepo()).thenReturn("almRepo_" + i);
when(dto.getAlmSlug()).thenReturn("almSlug_" + i);
return dto;
}

private static ProjectDto mockProjectDto(String i) {
ProjectDto dto = mock();
when(dto.getUuid()).thenReturn("projectUuid_" + i);
when(dto.getKey()).thenReturn("projectKey_" + i);
return dto;
}

private static ProjectBindingInformation projectBindingInformation(String i) {
return new ProjectBindingInformation("uuid_" + i,
"almSettingUuid_" + i,
"projectUuid_" + i,
"projectKey_" + i,
"almRepo_" + i,
"almSlug_" + i);
}

}

+ 21
- 10
server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/api/projectbindings/controller/DefaultProjectBindingsController.java View File

@@ -24,6 +24,7 @@ import java.util.Optional;
import org.sonar.db.alm.setting.ProjectAlmSettingDto;
import org.sonar.db.project.ProjectDto;
import org.sonar.server.common.SearchResults;
import org.sonar.server.common.projectbindings.service.ProjectBindingInformation;
import org.sonar.server.common.projectbindings.service.ProjectBindingsSearchRequest;
import org.sonar.server.common.projectbindings.service.ProjectBindingsService;
import org.sonar.server.exceptions.NotFoundException;
@@ -54,34 +55,44 @@ public class DefaultProjectBindingsController implements ProjectBindingsControll
ProjectDto projectDto = projectBindingsService.findProjectFromBinding(projectAlmSettingDto.get())
.orElseThrow(() -> new IllegalStateException(String.format("Project (uuid '%s') not found for binding '%s'", projectAlmSettingDto.get().getProjectUuid(), id)));
userSession.checkEntityPermission(USER, projectDto);
return toProjectBinding(projectAlmSettingDto.get());
return toProjectBinding(projectDto, projectAlmSettingDto.get());
} else {
throw new NotFoundException(String.format("Project binding '%s' not found", id));
}
}

private static ProjectBinding toProjectBinding(ProjectDto projectDto, ProjectAlmSettingDto projectAlmSettingDto) {
return new ProjectBinding(
projectAlmSettingDto.getUuid(),
projectAlmSettingDto.getAlmSettingUuid(),
projectAlmSettingDto.getProjectUuid(),
projectDto.getKey(),
projectAlmSettingDto.getAlmRepo(),
projectAlmSettingDto.getAlmSlug());
}

@Override
public ProjectBindingsSearchRestResponse searchProjectBindings(ProjectBindingsSearchRestRequest restRequest, RestPage restPage) {
userSession.checkLoggedIn().checkPermission(PROVISION_PROJECTS);
ProjectBindingsSearchRequest serviceRequest = new ProjectBindingsSearchRequest(restRequest.repository(), restRequest.dopSettingId(), restPage.pageIndex(), restPage.pageSize());
SearchResults<ProjectAlmSettingDto> searchResults = projectBindingsService.findProjectBindingsByRequest(serviceRequest);
SearchResults<ProjectBindingInformation> searchResults = projectBindingsService.findProjectBindingsByRequest(serviceRequest);
List<ProjectBinding> projectBindings = toProjectBindings(searchResults);
return new ProjectBindingsSearchRestResponse(projectBindings, new PageRestResponse(restPage.pageIndex(), restPage.pageSize(), searchResults.total()));
}

private static List<ProjectBinding> toProjectBindings(SearchResults<ProjectAlmSettingDto> searchResults) {
private static List<ProjectBinding> toProjectBindings(SearchResults<ProjectBindingInformation> searchResults) {
return searchResults.searchResults().stream()
.map(DefaultProjectBindingsController::toProjectBinding)
.toList();
}

private static ProjectBinding toProjectBinding(ProjectAlmSettingDto dto) {
private static ProjectBinding toProjectBinding(ProjectBindingInformation projectBindingInformation) {
return new ProjectBinding(
dto.getUuid(),
dto.getAlmSettingUuid(),
dto.getProjectUuid(),
dto.getAlmRepo(),
dto.getAlmSlug()
);
projectBindingInformation.id(),
projectBindingInformation.devOpsPlatformSettingId(),
projectBindingInformation.projectId(),
projectBindingInformation.projectKey(),
projectBindingInformation.repository(),
projectBindingInformation.slug());
}
}

+ 4
- 1
server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/api/projectbindings/model/ProjectBinding.java View File

@@ -28,11 +28,14 @@ public record ProjectBinding (
String id,

@NotNull
String dopSettings,
String devOpsPlatformSettingId,

@NotNull
String projectId,

@NotNull
String projectKey,

@Nullable
String repository,


+ 44
- 28
server/sonar-webserver-webapi-v2/src/test/java/org/sonar/server/v2/api/projectbindings/controller/DefaultProjectBindingsControllerTest.java View File

@@ -27,6 +27,7 @@ import org.mockito.ArgumentCaptor;
import org.sonar.db.alm.setting.ProjectAlmSettingDto;
import org.sonar.db.project.ProjectDto;
import org.sonar.server.common.SearchResults;
import org.sonar.server.common.projectbindings.service.ProjectBindingInformation;
import org.sonar.server.common.projectbindings.service.ProjectBindingsSearchRequest;
import org.sonar.server.common.projectbindings.service.ProjectBindingsService;
import org.sonar.server.tester.UserSessionRule;
@@ -112,7 +113,10 @@ class DefaultProjectBindingsControllerTest {
@Test
void getProjectBinding_whenProjectBindingAndPermissions_returnsIt() throws Exception {
ProjectAlmSettingDto projectAlmSettingDto = mockProjectAlmSettingDto("1");

ProjectDto projectDto = mock();
when(projectDto.getKey()).thenReturn("projectKey_1");

userSession.logIn().addProjectPermission(ADMIN, projectDto);
when(projectBindingsService.findProjectBindingByUuid(UUID)).thenReturn(Optional.of(projectAlmSettingDto));
when(projectBindingsService.findProjectFromBinding(projectAlmSettingDto)).thenReturn(Optional.ofNullable(projectDto));
@@ -124,8 +128,9 @@ class DefaultProjectBindingsControllerTest {
content().json("""
{
"id": "uuid_1",
"dopSettings": "almSettingUuid_1",
"devOpsPlatformSettingId": "almSettingUuid_1",
"projectId": "projectUuid_1",
"projectKey": "projectKey_1",
"repository": "almRepo_1",
"slug": "almSlug_1"
}
@@ -175,10 +180,10 @@ class DefaultProjectBindingsControllerTest {
void searchProjectBindings_whenResultsFound_shouldReturnsThem() throws Exception {
userSession.logIn().addPermission(PROVISION_PROJECTS);

ProjectAlmSettingDto dto1 = mockProjectAlmSettingDto("1");
ProjectAlmSettingDto dto2 = mockProjectAlmSettingDto("2");
ProjectBindingInformation dto1 = projectBindingInformation("1");
ProjectBindingInformation dto2 = projectBindingInformation("2");

List<ProjectAlmSettingDto> expectedResults = List.of(dto1, dto2);
List<ProjectBindingInformation> expectedResults = List.of(dto1, dto2);
when(projectBindingsService.findProjectBindingsByRequest(any())).thenReturn(new SearchResults<>(expectedResults, expectedResults.size()));

mockMvc
@@ -190,33 +195,35 @@ class DefaultProjectBindingsControllerTest {
.andExpectAll(
status().isOk(),
content().json("""
{
"projectBindings": [
{
"id": "uuid_1",
"dopSettings": "almSettingUuid_1",
"projectId": "projectUuid_1",
"repository": "almRepo_1",
"slug": "almSlug_1"
},
{
"id": "uuid_2",
"dopSettings": "almSettingUuid_2",
"projectId": "projectUuid_2",
"repository": "almRepo_2",
"slug": "almSlug_2"
{
"projectBindings": [
{
"id": "uuid_1",
"devOpsPlatformSettingId": "almSettingUuid_1",
"projectId": "projectUuid_1",
"projectKey": "projectKey_1",
"repository": "almRepo_1",
"slug": "almSlug_1"
},
{
"id": "uuid_2",
"devOpsPlatformSettingId": "almSettingUuid_2",
"projectId": "projectUuid_2",
"projectKey": "projectKey_2",
"repository": "almRepo_2",
"slug": "almSlug_2"
}
],
"page": {
"pageIndex": 1,
"pageSize": 100,
"total": 2
}
],
"page": {
"pageIndex": 1,
"pageSize": 100,
"total": 2
}
}
"""));
"""));
}

private ProjectAlmSettingDto mockProjectAlmSettingDto(String i) {
private static ProjectAlmSettingDto mockProjectAlmSettingDto(String i) {
ProjectAlmSettingDto dto = mock();
when(dto.getUuid()).thenReturn("uuid_" + i);
when(dto.getAlmSettingUuid()).thenReturn("almSettingUuid_" + i);
@@ -226,4 +233,13 @@ class DefaultProjectBindingsControllerTest {
return dto;
}

}
private static ProjectBindingInformation projectBindingInformation(String i) {
return new ProjectBindingInformation("uuid_" + i,
"almSettingUuid_" + i,
"projectUuid_" + i,
"projectKey_" + i,
"almRepo_" + i,
"almSlug_" + i);
}

}

Loading…
Cancel
Save