Browse Source

SONAR-14566 Update SonarQube main branch name during Github project onboarding

tags/8.8.0.42792
Belen Pruvost 3 years ago
parent
commit
546ee77ee2

+ 7
- 1
server/sonar-alm-client/src/main/java/org/sonar/alm/client/github/GithubApplicationClient.java View File

@@ -102,13 +102,15 @@ public interface GithubApplicationClient {
private final boolean isPrivate;
private final String fullName;
private final String url;
private final String defaultBranch;

public Repository(long id, String name, boolean isPrivate, String fullName, String url) {
public Repository(long id, String name, boolean isPrivate, String fullName, String url, String defaultBranch) {
this.id = id;
this.name = name;
this.isPrivate = isPrivate;
this.fullName = fullName;
this.url = url;
this.defaultBranch = defaultBranch;
}

public long getId() {
@@ -131,6 +133,10 @@ public interface GithubApplicationClient {
return url;
}

public String getDefaultBranch() {
return defaultBranch;
}

@Override
public String toString() {
return "Repository{" +

+ 2
- 2
server/sonar-alm-client/src/main/java/org/sonar/alm/client/github/GithubApplicationClientImpl.java View File

@@ -183,7 +183,7 @@ public class GithubApplicationClientImpl implements GithubApplicationClient {

if (gsonRepositories.get().items != null) {
repositories.setRepositories(gsonRepositories.get().items.stream()
.map(gsonRepository -> new Repository(gsonRepository.id, gsonRepository.name, gsonRepository.isPrivate, gsonRepository.fullName, gsonRepository.url))
.map(GsonGithubRepository::toRepository)
.collect(toList()));
}

@@ -200,7 +200,7 @@ public class GithubApplicationClientImpl implements GithubApplicationClient {
GetResponse response = appHttpClient.get(appUrl, accessToken, String.format("/repos/%s", repositoryKey));
return response.getContent()
.map(content -> GSON.fromJson(content, GsonGithubRepository.class))
.map(repository -> new Repository(repository.id, repository.name, repository.isPrivate, repository.fullName, repository.url));
.map(GsonGithubRepository::toRepository);
} catch (Exception e) {
throw new IllegalStateException(format("Failed to get repository '%s' of '%s' accessible by user access token on '%s'", repositoryKey, organization, appUrl), e);
}

+ 9
- 0
server/sonar-alm-client/src/main/java/org/sonar/alm/client/github/GithubBinding.java View File

@@ -22,6 +22,8 @@ package org.sonar.alm.client.github;
import com.google.gson.annotations.SerializedName;
import java.util.List;

import static org.sonar.alm.client.github.GithubApplicationClient.*;

public class GithubBinding {

private GithubBinding() {
@@ -138,11 +140,18 @@ public class GithubBinding {
boolean isPrivate;
@SerializedName("url")
String url;
@SerializedName("default_branch")
String defaultBranch;

public GsonGithubRepository() {
// even if empty constructor is not required for Gson, it is strongly
// recommended:
// http://stackoverflow.com/a/18645370/229031
}

public Repository toRepository() {
return new Repository(this.id, this.name, this.isPrivate, this.fullName,
this.url, this.defaultBranch);
}
}
}

+ 2
- 2
server/sonar-alm-client/src/test/java/org/sonar/alm/client/github/GithubApplicationClientImplTest.java View File

@@ -793,8 +793,8 @@ public class GithubApplicationClientImplTest {
.isPresent()
.get()
.extracting(GithubApplicationClient.Repository::getId, GithubApplicationClient.Repository::getName, GithubApplicationClient.Repository::getFullName,
GithubApplicationClient.Repository::getUrl, GithubApplicationClient.Repository::isPrivate)
.containsOnly(1296269L, "Hello-World", "octocat/Hello-World", "https://github.sonarsource.com/api/v3/repos/octocat/Hello-World", false);
GithubApplicationClient.Repository::getUrl, GithubApplicationClient.Repository::isPrivate, GithubApplicationClient.Repository::getDefaultBranch)
.containsOnly(1296269L, "Hello-World", "octocat/Hello-World", "https://github.sonarsource.com/api/v3/repos/octocat/Hello-World", false, "master");
}

private AppToken mockAppToken() {

+ 0
- 1
server/sonar-webserver-webapi/src/main/java/org/sonar/server/almintegration/ws/ImportHelper.java View File

@@ -72,5 +72,4 @@ public class ImportHelper {
.setVisibility(Visibility.getLabel(componentDto.isPrivate())))
.build();
}

}

+ 6
- 6
server/sonar-webserver-webapi/src/main/java/org/sonar/server/almintegration/ws/github/ImportGithubProjectAction.java View File

@@ -61,7 +61,7 @@ public class ImportGithubProjectAction implements AlmIntegrationsWsAction {
private final ImportHelper importHelper;

public ImportGithubProjectAction(DbClient dbClient, UserSession userSession, ProjectDefaultVisibility projectDefaultVisibility,
GithubApplicationClientImpl githubApplicationClient, ComponentUpdater componentUpdater, ImportHelper importHelper) {
GithubApplicationClientImpl githubApplicationClient, ComponentUpdater componentUpdater, ImportHelper importHelper) {
this.dbClient = dbClient;
this.userSession = userSession;
this.projectDefaultVisibility = projectDefaultVisibility;
@@ -121,22 +121,23 @@ public class ImportGithubProjectAction implements AlmIntegrationsWsAction {
Repository repository = githubApplicationClient.getRepository(url, accessToken, githubOrganization, repositoryKey)
.orElseThrow(() -> new NotFoundException(String.format("GitHub repository '%s' not found", repositoryKey)));

ComponentDto componentDto = createProject(dbSession, repository);
ComponentDto componentDto = createProject(dbSession, repository, repository.getDefaultBranch());
populatePRSetting(dbSession, repository, componentDto, almSettingDto);
componentUpdater.commitAndIndex(dbSession, componentDto);

return toCreateResponse(componentDto);
}
}

private ComponentDto createProject(DbSession dbSession, Repository repo) {
private ComponentDto createProject(DbSession dbSession, Repository repo, String mainBranchName) {
boolean visibility = projectDefaultVisibility.get(dbSession).isPrivate();
return componentUpdater.create(dbSession, newComponentBuilder()
return componentUpdater.createWithoutCommit(dbSession, newComponentBuilder()
.setKey(getProjectKeyFromRepository(repo))
.setName(repo.getName())
.setPrivate(visibility)
.setQualifier(PROJECT)
.build(),
userSession.getUuid());
userSession.getUuid(), mainBranchName, s -> {});
}

static String getProjectKeyFromRepository(Repository repo) {
@@ -152,6 +153,5 @@ public class ImportGithubProjectAction implements AlmIntegrationsWsAction {
.setSummaryCommentEnabled(true)
.setMonorepo(false);
dbClient.projectAlmSettingDao().insertOrUpdate(dbSession, projectAlmSettingDto);
dbSession.commit();
}
}

+ 16
- 4
server/sonar-webserver-webapi/src/main/java/org/sonar/server/component/ComponentUpdater.java View File

@@ -22,6 +22,7 @@ package org.sonar.server.component;
import com.google.common.collect.ImmutableSet;
import java.util.Date;
import java.util.Locale;
import java.util.Optional;
import java.util.Set;
import java.util.function.Consumer;
import javax.annotation.Nullable;
@@ -88,11 +89,22 @@ public class ComponentUpdater {
* Create component without committing.
* Don't forget to call commitAndIndex(...) when ready to commit.
*/
public ComponentDto createWithoutCommit(DbSession dbSession, NewComponent newComponent, @Nullable String userUuid, Consumer<ComponentDto> componentModifier) {
public ComponentDto createWithoutCommit(DbSession dbSession, NewComponent newComponent,
@Nullable String userUuid, Consumer<ComponentDto> componentModifier) {
return createWithoutCommit(dbSession, newComponent, userUuid, null, componentModifier);
}

/**
* Create component without committing.
* Don't forget to call commitAndIndex(...) when ready to commit.
*/
public ComponentDto createWithoutCommit(DbSession dbSession, NewComponent newComponent,
@Nullable String userUuid, @Nullable String mainBranchName,
Consumer<ComponentDto> componentModifier) {
checkKeyFormat(newComponent.qualifier(), newComponent.key());
ComponentDto componentDto = createRootComponent(dbSession, newComponent, componentModifier);
if (isRootProject(componentDto)) {
createMainBranch(dbSession, componentDto.uuid());
createMainBranch(dbSession, componentDto.uuid(), mainBranchName);
}
handlePermissionTemplate(dbSession, componentDto, userUuid);
return componentDto;
@@ -152,11 +164,11 @@ public class ComponentUpdater {
&& MAIN_BRANCH_QUALIFIERS.contains(componentDto.qualifier());
}

private void createMainBranch(DbSession session, String componentUuid) {
private void createMainBranch(DbSession session, String componentUuid, @Nullable String mainBranch) {
BranchDto branch = new BranchDto()
.setBranchType(BranchType.BRANCH)
.setUuid(componentUuid)
.setKey(BranchDto.DEFAULT_MAIN_BRANCH_NAME)
.setKey(Optional.ofNullable(mainBranch).orElse(BranchDto.DEFAULT_MAIN_BRANCH_NAME))
.setMergeBranchUuid(null)
.setExcludeFromPurge(true)
.setProjectUuid(componentUuid);

+ 97
- 0
server/sonar-webserver-webapi/src/test/java/org/sonar/server/almintegration/ws/ImportHelperTest.java View File

@@ -0,0 +1,97 @@
/*
* SonarQube
* Copyright (C) 2009-2021 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.almintegration.ws;

import org.junit.Rule;
import org.junit.Test;
import org.sonar.api.server.ws.Request;
import org.sonar.api.utils.System2;
import org.sonar.db.DbTester;
import org.sonar.db.component.BranchDto;
import org.sonar.db.component.BranchType;
import org.sonar.db.component.ComponentDto;
import org.sonar.db.component.ComponentTesting;
import org.sonar.server.exceptions.NotFoundException;
import org.sonar.server.exceptions.UnauthorizedException;
import org.sonar.server.tester.UserSessionRule;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.sonarqube.ws.Projects.CreateWsResponse;

public class ImportHelperTest {

private final System2 system2 = System2.INSTANCE;
private final ComponentDto componentDto = ComponentTesting.newPublicProjectDto();
private final BranchDto branchDto = new BranchDto()
.setBranchType(BranchType.BRANCH)
.setKey("main")
.setUuid(componentDto.uuid())
.setProjectUuid(componentDto.uuid());
private final Request request = mock(Request.class);

@Rule
public final DbTester db = DbTester.create(system2);

@Rule
public UserSessionRule userSession = UserSessionRule.standalone();

private ImportHelper underTest = new ImportHelper(db.getDbClient(), userSession);

@Test
public void it_throws_exception_when_provisioning_project_without_permission() {
assertThatThrownBy(() -> underTest.checkProvisionProjectPermission())
.isInstanceOf(UnauthorizedException.class)
.hasMessage("Authentication is required");
}

@Test
public void it_throws_exception_on_get_alm_setting_when_key_is_empty() {
assertThatThrownBy(() -> underTest.getAlmSetting(request))
.isInstanceOf(NotFoundException.class);
}

@Test
public void it_throws_exception_on_get_alm_setting_when_key_is_not_found() {
when(request.mandatoryParam("almSetting")).thenReturn("key");
assertThatThrownBy(() -> underTest.getAlmSetting(request))
.isInstanceOf(NotFoundException.class)
.hasMessage("ALM Setting 'key' not found");
}

@Test
public void it_throws_exception_when_user_uuid_is_null() {
assertThatThrownBy(() -> underTest.getUserUuid())
.isInstanceOf(NullPointerException.class)
.hasMessage("User UUID cannot be null");
}

@Test
public void it_returns_create_response() {
CreateWsResponse response = ImportHelper.toCreateResponse(componentDto);
CreateWsResponse.Project project = response.getProject();

assertThat(project).extracting(CreateWsResponse.Project::getKey, CreateWsResponse.Project::getName,
CreateWsResponse.Project::getQualifier)
.containsExactly(componentDto.getDbKey(), componentDto.name(), componentDto.qualifier());
}
}

+ 6
- 2
server/sonar-webserver-webapi/src/test/java/org/sonar/server/almintegration/ws/github/ImportGithubProjectActionTest.java View File

@@ -31,6 +31,7 @@ import org.sonar.core.i18n.I18n;
import org.sonar.core.util.SequenceUuidFactory;
import org.sonar.db.DbTester;
import org.sonar.db.alm.setting.AlmSettingDto;
import org.sonar.db.component.BranchDto;
import org.sonar.db.permission.GlobalPermission;
import org.sonar.db.project.ProjectDto;
import org.sonar.db.user.UserDto;
@@ -90,7 +91,7 @@ public class ImportGithubProjectActionTest {
db.almPats().insert(p -> p.setAlmSettingUuid(githubAlmSetting.getUuid()).setUserUuid(userSession.getUuid()));

GithubApplicationClient.Repository repository = new GithubApplicationClient.Repository(1L, "Hello-World", false, "octocat/Hello-World",
"https://github.sonarsource.com/api/v3/repos/octocat/Hello-World");
"https://github.sonarsource.com/api/v3/repos/octocat/Hello-World", "default-branch");
when(appClient.getRepository(any(), any(), any(), any()))
.thenReturn(Optional.of(repository));

@@ -107,6 +108,9 @@ public class ImportGithubProjectActionTest {
Optional<ProjectDto> projectDto = db.getDbClient().projectDao().selectProjectByKey(db.getSession(), result.getKey());
assertThat(projectDto).isPresent();
assertThat(db.getDbClient().projectAlmSettingDao().selectByProject(db.getSession(), projectDto.get())).isPresent();
Optional<BranchDto> mainBranch = db.getDbClient().branchDao().selectByProject(db.getSession(), projectDto.get()).stream().filter(BranchDto::isMain).findAny();
assertThat(mainBranch).isPresent();
assertThat(mainBranch.get().getKey()).isEqualTo("default-branch");
}

@Test
@@ -116,7 +120,7 @@ public class ImportGithubProjectActionTest {
db.components().insertPublicProject(p -> p.setDbKey("octocat_Hello-World"));

GithubApplicationClient.Repository repository = new GithubApplicationClient.Repository(1L, "Hello-World", false, "octocat/Hello-World",
"https://github.sonarsource.com/api/v3/repos/octocat/Hello-World");
"https://github.sonarsource.com/api/v3/repos/octocat/Hello-World", "main");
when(appClient.getRepository(any(), any(), any(), any()))
.thenReturn(Optional.of(repository));


+ 2
- 1
server/sonar-webserver-webapi/src/test/java/org/sonar/server/almintegration/ws/github/ListGithubRepositoriesActionTest.java View File

@@ -107,7 +107,8 @@ public class ListGithubRepositoriesActionTest {
.thenReturn(new GithubApplicationClient.Repositories()
.setTotal(2)
.setRepositories(Stream.of("HelloWorld", "HelloUniverse")
.map(name -> new GithubApplicationClient.Repository(name.length(), name, false, "github/" + name, "https://github-enterprise.sonarqube.com/api/v3/github/HelloWorld"))
.map(name -> new GithubApplicationClient.Repository(name.length(), name, false, "github/" + name,
"https://github-enterprise.sonarqube.com/api/v3/github/HelloWorld", "main"))
.collect(Collectors.toList())));

ProjectDto project = db.components().insertPrivateProjectDto(componentDto -> componentDto.setDbKey("github_HelloWorld"));

Loading…
Cancel
Save