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() {
return url;
}
+ public String getDefaultBranch() {
+ return defaultBranch;
+ }
+
@Override
public String toString() {
return "Repository{" +
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()));
}
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);
}
import com.google.gson.annotations.SerializedName;
import java.util.List;
+import static org.sonar.alm.client.github.GithubApplicationClient.*;
+
public class GithubBinding {
private 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);
+ }
}
}
.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() {
.setVisibility(Visibility.getLabel(componentDto.isPrivate())))
.build();
}
-
}
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;
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) {
.setSummaryCommentEnabled(true)
.setMonorepo(false);
dbClient.projectAlmSettingDao().insertOrUpdate(dbSession, projectAlmSettingDto);
- dbSession.commit();
}
}
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;
* 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;
&& 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);
--- /dev/null
+/*
+ * 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());
+ }
+}
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;
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));
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
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));
.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"));