use of org.gitlab4j.api.models.Branch in project legend-sdlc by finos.
the class GitLabProjectApi method importProject.
@Override
public ImportReport importProject(String id, ProjectType type, String groupId, String artifactId) {
LegendSDLCServerException.validateNonNull(id, "id may not be null");
LegendSDLCServerException.validateNonNull(type, "type may not be null");
LegendSDLCServerException.validate(groupId, ProjectStructure::isValidGroupId, g -> "Invalid groupId: " + g);
LegendSDLCServerException.validate(artifactId, ProjectStructure::isValidArtifactId, a -> "Invalid artifactId: " + a);
// Get project id
GitLabProjectId projectId;
if (id.chars().allMatch(Character::isDigit)) {
projectId = GitLabProjectId.newProjectId(getGitLabModeFromProjectType(type), Integer.parseInt(id));
} else {
projectId = parseProjectId(id);
if (projectId.getGitLabMode() != getGitLabModeFromProjectType(type)) {
throw new LegendSDLCServerException("Invalid project id \"" + id + "\" for project type " + type, Status.BAD_REQUEST);
}
}
// Find project
GitLabApi gitLabApi = getGitLabApi(projectId.getGitLabMode());
org.gitlab4j.api.ProjectApi gitLabProjectApi = gitLabApi.getProjectApi();
org.gitlab4j.api.models.Project currentProject;
try {
currentProject = withRetries(() -> gitLabProjectApi.getProject(projectId.getGitLabId()));
} catch (Exception e) {
throw buildException(e, () -> "User " + getCurrentUser() + " is not allowed to access project " + id + " of type " + type, () -> "Could not find project " + id + " of type " + type, () -> "Failed to access project " + id + " of type " + type);
}
// Create a workspace for project configuration
RepositoryApi repositoryApi = gitLabApi.getRepositoryApi();
String workspaceId = "ProjectConfiguration_" + getRandomIdString();
Branch workspaceBranch;
try {
workspaceBranch = GitLabApiTools.createBranchFromSourceBranchAndVerify(repositoryApi, projectId.getGitLabId(), getWorkspaceBranchName(workspaceId, WorkspaceType.USER, ProjectFileAccessProvider.WorkspaceAccessType.WORKSPACE), MASTER_BRANCH, 30, 1_000);
} catch (Exception e) {
throw buildException(e, () -> "User " + getCurrentUser() + " is not allowed to create a workspace for initial configuration of project " + id + " of type " + type, () -> "Could not find project " + id + " of type " + type, () -> "Failed to create workspace for initial configuration of project " + id + " of type " + type);
}
if (workspaceBranch == null) {
throw new LegendSDLCServerException("Failed to create workspace " + workspaceId + " in project " + projectId);
}
// Configure project in workspace
ProjectFileAccessProvider projectFileAccessProvider = getProjectFileAccessProvider();
Revision configRevision;
try {
ProjectConfiguration currentConfig = ProjectStructure.getProjectConfiguration(projectId.toString(), null, null, projectFileAccessProvider, WorkspaceType.USER, ProjectFileAccessProvider.WorkspaceAccessType.WORKSPACE);
ProjectConfigurationUpdateBuilder builder = ProjectConfigurationUpdateBuilder.newBuilder(projectFileAccessProvider, type, projectId.toString()).withWorkspace(workspaceId, WorkspaceType.USER, ProjectFileAccessProvider.WorkspaceAccessType.WORKSPACE).withGroupId(groupId).withArtifactId(artifactId).withProjectStructureExtensionProvider(this.projectStructureExtensionProvider).withProjectStructurePlatformExtensions(this.projectStructurePlatformExtensions);
int defaultProjectStructureVersion = getDefaultProjectStructureVersion();
if (currentConfig == null) {
// No current project structure: build a new one
configRevision = builder.withProjectStructureVersion(defaultProjectStructureVersion).withMessage("Build project structure").buildProjectStructure();
} else {
// Existing project structure: update
if (currentConfig.getProjectType() != type) {
throw new LegendSDLCServerException("Mismatch between requested project type (" + type + ") and found project type (" + currentConfig.getProjectType() + ")", Status.BAD_REQUEST);
}
ProjectStructureVersion currentVersion = currentConfig.getProjectStructureVersion();
if ((currentVersion == null) || (currentVersion.getVersion() < defaultProjectStructureVersion)) {
builder.withProjectStructureVersion(defaultProjectStructureVersion).withProjectStructureExtensionVersion(null);
}
configRevision = builder.withMessage("Update project structure").updateProjectConfiguration();
}
} catch (Exception e) {
// Try to delete the branch in case of exception
deleteWorkspace(projectId, repositoryApi, workspaceId);
throw e;
}
// Submit workspace changes, if any, for review
String reviewId;
if (configRevision == null) {
// No changes: nothing to submit
reviewId = null;
// Try to delete the branch
deleteWorkspace(projectId, repositoryApi, workspaceId);
} else {
MergeRequest mergeRequest;
try {
mergeRequest = gitLabApi.getMergeRequestApi().createMergeRequest(projectId.getGitLabId(), getWorkspaceBranchName(workspaceId, WorkspaceType.USER, ProjectFileAccessProvider.WorkspaceAccessType.WORKSPACE), MASTER_BRANCH, "Project structure", "Set up project structure", null, null, null, null, true, false);
} catch (Exception e) {
// Try to delete the branch in case of exception
deleteWorkspace(projectId, repositoryApi, workspaceId);
throw buildException(e, () -> "User " + getCurrentUser() + " is not allowed to submit project configuration changes create a workspace for initial configuration of project " + id + " of type " + type, () -> "Could not find workspace " + workspaceId + " project " + id + " of type " + type, () -> "Failed to create a review for configuration of project " + id + " of type " + type);
}
reviewId = toStringIfNotNull(mergeRequest.getIid());
}
// Add tags
Project finalProject;
List<String> currentTags = currentProject.getTagList();
if ((currentTags != null) && currentTags.stream().anyMatch(this::isLegendSDLCProjectTag)) {
// already has the necessary tag
finalProject = fromGitLabProject(currentProject, projectId.getGitLabMode());
} else {
List<String> updatedTags = Lists.mutable.ofInitialCapacity((currentTags == null) ? 1 : (currentTags.size() + 1));
if (currentTags != null) {
updatedTags.addAll(currentTags);
}
updatedTags.add(getLegendSDLCProjectTag());
org.gitlab4j.api.models.Project updatedProject;
try {
updatedProject = gitLabProjectApi.updateProject(new org.gitlab4j.api.models.Project().withId(currentProject.getId()).withTagList(updatedTags));
} catch (Exception e) {
// Try to delete the branch in case of exception
deleteWorkspace(projectId, repositoryApi, workspaceId);
throw buildException(e, () -> "User " + getCurrentUser() + " is not allowed to import project " + id + " of type " + type, () -> "Could not find project " + id + " of type " + type, () -> "Failed to import project " + id + " of type " + type);
}
finalProject = fromGitLabProject(updatedProject, projectId.getGitLabMode());
}
return new ImportReport() {
@Override
public Project getProject() {
return finalProject;
}
@Override
public String getReviewId() {
return reviewId;
}
};
}
use of org.gitlab4j.api.models.Branch in project legend-sdlc by finos.
the class GitLabReviewApi method getMergeRequestTargetRevision.
private String getMergeRequestTargetRevision(GitLabProjectId projectId, GitLabApi gitLabApi, MergeRequest mergeRequest) {
RepositoryApi repositoryApi = gitLabApi.getRepositoryApi();
Branch targetBranch;
try {
targetBranch = withRetries(() -> repositoryApi.getBranch(projectId.getGitLabId(), mergeRequest.getTargetBranch()));
} catch (Exception e) {
LOGGER.error("Error getting target branch head for merge request {} in project {} (target branch: {})", mergeRequest.getIid(), projectId, mergeRequest.getTargetBranch(), e);
StringBuilder builder = new StringBuilder("Error getting target revision for review ").append(mergeRequest.getIid()).append(" for project ").append(projectId);
StringTools.appendThrowableMessageIfPresent(builder, e);
throw new LegendSDLCServerException(builder.toString(), e);
}
Commit targetHead = targetBranch.getCommit();
if ((targetHead == null) || (targetHead.getId() == null)) {
LOGGER.error("Error getting target branch head for merge request {} in project {} (target branch: {}): {}", mergeRequest.getIid(), projectId, mergeRequest.getTargetBranch(), targetHead);
throw new LegendSDLCServerException("Error getting target revision for review " + mergeRequest.getIid() + " for project");
}
return targetHead.getId();
}
use of org.gitlab4j.api.models.Branch in project legend-sdlc by finos.
the class GitLabWorkspaceApi method attemptToRebaseWorkspaceUsingTemporaryBranch.
/**
* This method attempts to rebase the workspace branch on top of master by using a temp branch. Detailed procedure outlined below:
* 1. Create a new merge request (MR) that merges temp branch into master branch so that we can use gitlab rebase functionality
* 2. Call rebase.
* 3. Continuously check the rebase status of the merge request:
* - If failed -> return `false`
* - If succeeded, proceed
* 4. Re-create workspace branch on top of the rebased temp branch.
* 5. Cleanup: remove the temp branch and the MR
* 6. Return `true`
*
* @return a boolean flag indicating if the attempted rebase succeeded.
*/
private boolean attemptToRebaseWorkspaceUsingTemporaryBranch(String projectId, String workspaceId, WorkspaceType workspaceType, String tempBranchName, String masterRevisionId) {
GitLabProjectId gitLabProjectId = parseProjectId(projectId);
GitLabApi gitLabApi = getGitLabApi(gitLabProjectId.getGitLabMode());
RepositoryApi repositoryApi = gitLabApi.getRepositoryApi();
// Create merge request to rebase
MergeRequestApi mergeRequestApi = getGitLabApi(gitLabProjectId.getGitLabMode()).getMergeRequestApi();
String title = "Update workspace " + workspaceId;
String message = "Update workspace " + workspaceId + " up to revision " + masterRevisionId;
MergeRequest mergeRequest;
try {
mergeRequest = mergeRequestApi.createMergeRequest(gitLabProjectId.getGitLabId(), tempBranchName, MASTER_BRANCH, title, message, null, null, null, null, false, false);
} catch (Exception e) {
throw buildException(e, () -> "User " + getCurrentUser() + " is not allowed to create merge request in project " + projectId, () -> "Unknown branch in project " + projectId + ": " + tempBranchName, () -> "Error creating merge request in project " + projectId);
}
// Attempt to rebase the merge request
try {
mergeRequestApi.rebaseMergeRequest(gitLabProjectId.getGitLabId(), mergeRequest.getIid());
// Check rebase status
// This only throws when we have 403, so we need to keep polling till we know the result
// See https://docs.gitlab.com/ee/api/merge_requests.html#rebase-a-merge-request
CallUntil<MergeRequest, GitLabApiException> rebaseStatusCallUntil = CallUntil.callUntil(() -> withRetries(() -> mergeRequestApi.getRebaseStatus(gitLabProjectId.getGitLabId(), mergeRequest.getIid())), mr -> !mr.getRebaseInProgress(), 600, 1000L);
if (!rebaseStatusCallUntil.succeeded()) {
LOGGER.warn("Timeout waiting for merge request " + mergeRequest.getIid() + " in project " + projectId + " to finish rebasing");
return false;
}
// Check if there is merge conflict
if (rebaseStatusCallUntil.getResult().getMergeError() != null) {
return false;
} else // if there are no merge conflicts, proceed with the update
{
// Create backup branch
Branch backupBranch;
ProjectFileAccessProvider.WorkspaceAccessType backupWorkspaceAccessType = ProjectFileAccessProvider.WorkspaceAccessType.BACKUP;
ProjectFileAccessProvider.WorkspaceAccessType workspaceAccessType = ProjectFileAccessProvider.WorkspaceAccessType.WORKSPACE;
try {
backupBranch = GitLabApiTools.createBranchFromSourceBranchAndVerify(repositoryApi, gitLabProjectId.getGitLabId(), getWorkspaceBranchName(workspaceId, workspaceType, backupWorkspaceAccessType), getWorkspaceBranchName(workspaceId, workspaceType, workspaceAccessType), 30, 1_000);
} catch (Exception e) {
throw buildException(e, () -> "User " + getCurrentUser() + " is not allowed to create " + workspaceType.getLabel() + " " + backupWorkspaceAccessType.getLabel() + " " + workspaceAccessType.getLabel() + " " + workspaceId + " in project " + projectId, () -> "Unknown project: " + projectId, () -> "Error creating " + workspaceType.getLabel() + " " + backupWorkspaceAccessType.getLabel() + " " + workspaceAccessType.getLabel() + " " + workspaceId + " in project " + projectId);
}
if (backupBranch == null) {
throw new LegendSDLCServerException("Failed to create " + workspaceType.getLabel() + " " + backupWorkspaceAccessType.getLabel() + " " + workspaceAccessType.getLabel() + " " + workspaceId + " from " + workspaceType.getLabel() + " " + workspaceAccessType.getLabel() + " " + workspaceId + " in project " + projectId);
}
// Delete original branch
boolean originalBranchDeleted;
try {
originalBranchDeleted = GitLabApiTools.deleteBranchAndVerify(repositoryApi, gitLabProjectId.getGitLabId(), getWorkspaceBranchName(workspaceId, workspaceType, workspaceAccessType), 20, 1_000);
} catch (Exception e) {
throw buildException(e, () -> "Error while attempting to update the workspace " + workspaceId + " in project " + projectId + ": user " + getCurrentUser() + " is not allowed to delete workspace", () -> "Error while attempting to update the workspace " + workspaceId + " in project " + projectId + ": unknown workspace or project", () -> "Error while attempting to update the workspace " + workspaceId + " in project " + projectId + ": error deleting workspace");
}
if (!originalBranchDeleted) {
throw new LegendSDLCServerException("Failed to delete " + workspaceType.getLabel() + " " + workspaceAccessType.getLabel() + " " + workspaceId + " in project " + projectId);
}
// Create new workspace branch off the temp branch head
Branch newWorkspaceBranch;
try {
newWorkspaceBranch = GitLabApiTools.createBranchFromSourceBranchAndVerify(repositoryApi, gitLabProjectId.getGitLabId(), getWorkspaceBranchName(workspaceId, workspaceType, workspaceAccessType), tempBranchName, 30, 1_000);
} catch (Exception e) {
throw buildException(e, () -> "Error while attempting to update the workspace " + workspaceId + " in project " + projectId + ": user " + getCurrentUser() + " is not allowed to create workspace", () -> "Error while attempting to update the workspace " + workspaceId + " in project " + projectId + ": unknown project: " + projectId, () -> "Error while attempting to update the workspace " + workspaceId + " in project " + projectId + ": error creating workspace");
}
if (newWorkspaceBranch == null) {
throw new LegendSDLCServerException("Failed to create " + workspaceType.getLabel() + " " + workspaceAccessType.getLabel() + " " + workspaceId + " from temporary workspace " + tempBranchName + " in project " + projectId);
}
// Delete backup branch
try {
boolean deleted = GitLabApiTools.deleteBranchAndVerify(repositoryApi, gitLabProjectId.getGitLabId(), getWorkspaceBranchName(workspaceId, workspaceType, backupWorkspaceAccessType), 20, 1_000);
if (!deleted) {
LOGGER.error("Failed to delete {} {} in project {}", workspaceType.getLabel() + " " + backupWorkspaceAccessType.getLabel() + " " + workspaceAccessType.getLabel(), workspaceId, projectId);
}
} catch (Exception e) {
// unfortunate, but this should not throw error
LOGGER.error("Error deleting {} {} in project {}", workspaceType.getLabel() + " " + backupWorkspaceAccessType.getLabel() + " " + workspaceAccessType.getLabel(), workspaceId, projectId);
}
}
} catch (Exception e) {
throw buildException(e, () -> "User " + getCurrentUser() + " is not allowed to rebase merge request " + mergeRequest.getIid() + " in project " + projectId, () -> "Unknown merge request ( " + mergeRequest.getIid() + " ) or project ( " + projectId + " )", () -> "Error rebasing merge request " + mergeRequest.getIid() + " in project " + projectId);
} finally {
// Try to close merge request
try {
mergeRequestApi.updateMergeRequest(gitLabProjectId.getGitLabId(), mergeRequest.getIid(), null, title, null, null, StateEvent.CLOSE, null, null, null, null, null, null);
} catch (Exception closeEx) {
// if we fail, log the error but we don't throw it
LOGGER.error("Could not close merge request {} for project {}: {}", mergeRequest.getIid(), projectId, mergeRequest.getWebUrl(), closeEx);
}
// Delete temporary branch in the background
submitBackgroundRetryableTask(() -> waitForPipelinesDeleteBranchAndVerify(gitLabApi, gitLabProjectId, tempBranchName), 5000L, "delete " + tempBranchName);
}
return true;
}
use of org.gitlab4j.api.models.Branch in project legend-sdlc by finos.
the class GitLabWorkspaceApi method isWorkspaceInConflictResolutionMode.
@Override
public boolean isWorkspaceInConflictResolutionMode(String projectId, String workspaceId, WorkspaceType workspaceType) {
LegendSDLCServerException.validateNonNull(projectId, "projectId may not be null");
LegendSDLCServerException.validateNonNull(workspaceId, "workspaceId may not be null");
GitLabProjectId gitLabProjectId = parseProjectId(projectId);
RepositoryApi repositoryApi = getGitLabApi(gitLabProjectId.getGitLabMode()).getRepositoryApi();
ProjectFileAccessProvider.WorkspaceAccessType workspaceAccessType = ProjectFileAccessProvider.WorkspaceAccessType.WORKSPACE;
try {
withRetries(() -> repositoryApi.getBranch(gitLabProjectId.getGitLabId(), getWorkspaceBranchName(workspaceId, workspaceType, workspaceAccessType)));
} catch (Exception e) {
throw buildException(e, () -> "User " + getCurrentUser() + " is not allowed to get " + workspaceType.getLabel() + " " + workspaceAccessType.getLabel() + " " + workspaceId + " in project " + projectId, () -> "Unknown " + workspaceType.getLabel() + " " + workspaceAccessType.getLabel() + " (" + workspaceId + ") or project (" + projectId + ")", () -> "Error getting " + workspaceType.getLabel() + " " + workspaceAccessType.getLabel() + " is in conflict resolution mode for " + workspaceId + " in project " + projectId);
}
Branch conflictBranch;
ProjectFileAccessProvider.WorkspaceAccessType conflictResolutionWorkspaceType = ProjectFileAccessProvider.WorkspaceAccessType.CONFLICT_RESOLUTION;
try {
conflictBranch = repositoryApi.getBranch(gitLabProjectId.getGitLabId(), getWorkspaceBranchName(workspaceId, workspaceType, conflictResolutionWorkspaceType));
return conflictBranch != null;
} catch (Exception e) {
if (GitLabApiTools.isNotFoundGitLabApiException(e)) {
return false;
}
throw buildException(e, () -> "User " + getCurrentUser() + " is not allowed to check if " + workspaceType.getLabel() + " " + workspaceAccessType.getLabel() + " is in conflict resolution mode for " + workspaceType.getLabel() + " " + workspaceAccessType.getLabel() + " " + workspaceId + " in project " + projectId, () -> "Unknown " + workspaceType.getLabel() + " " + workspaceAccessType.getLabel() + " (" + workspaceId + ") or project (" + projectId + ")", () -> "Error checking if " + workspaceType.getLabel() + " " + workspaceAccessType.getLabel() + " is in conflict resolution mode for " + workspaceId + " in project " + projectId);
}
}
use of org.gitlab4j.api.models.Branch in project legend-sdlc by finos.
the class GitLabWorkspaceApi method getWorkspacesByAccessType.
private List<Workspace> getWorkspacesByAccessType(String projectId, WorkspaceType workspaceType, ProjectFileAccessProvider.WorkspaceAccessType workspaceAccessType) {
LegendSDLCServerException.validateNonNull(projectId, "projectId may not be null");
LegendSDLCServerException.validateNonNull(projectId, "workspaceAccessType may not be null");
try {
GitLabProjectId gitLabProjectId = parseProjectId(projectId);
Pager<Branch> pager = getGitLabApi(gitLabProjectId.getGitLabMode()).getRepositoryApi().getBranches(gitLabProjectId.getGitLabId(), ITEMS_PER_PAGE);
return PagerTools.stream(pager).filter(branch -> (branch != null) && isUserOrGroupWorkspaceBranchName(branch.getName(), workspaceType, workspaceAccessType)).map(branch -> workspaceBranchToWorkspace(projectId, branch, workspaceType, workspaceAccessType)).collect(Collectors.toList());
} catch (Exception e) {
throw buildException(e, () -> "User " + getCurrentUser() + " is not allowed to get " + workspaceType.getLabel() + " " + workspaceAccessType.getLabelPlural() + " for project " + projectId, () -> "Unknown project: " + projectId, () -> "Error getting " + workspaceType.getLabel() + " " + workspaceAccessType.getLabelPlural() + " for project " + projectId);
}
}
Aggregations