use of org.finos.legend.sdlc.server.error.LegendSDLCServerException in project legend-sdlc by finos.
the class GitLabVersionApi method getVersions.
@Override
public List<Version> getVersions(String projectId, Integer minMajorVersion, Integer maxMajorVersion, Integer minMinorVersion, Integer maxMinorVersion, Integer minPatchVersion, Integer maxPatchVersion) {
LegendSDLCServerException.validateNonNull(projectId, "projectId may not be null");
GitLabProjectId gitLabProjectId = parseProjectId(projectId);
switch(getProjectTypeFromMode(gitLabProjectId.getGitLabMode())) {
case PROTOTYPE:
{
return Collections.emptyList();
}
case PRODUCTION:
{
List<Version> versions = getVersions(gitLabProjectId, minMajorVersion, maxMajorVersion, minMinorVersion, maxMinorVersion, minPatchVersion, maxPatchVersion).collect(Collectors.toList());
versions.sort(Comparator.comparing(Version::getId).reversed());
return versions;
}
default:
{
throw new LegendSDLCServerException("Unknown project: " + projectId, Status.BAD_REQUEST);
}
}
}
use of org.finos.legend.sdlc.server.error.LegendSDLCServerException in project legend-sdlc by finos.
the class GitLabVersionApi method newVersion.
@Override
public Version newVersion(String projectId, NewVersionType type, String revisionId, String notes) {
LegendSDLCServerException.validateNonNull(projectId, "projectId may not be null");
LegendSDLCServerException.validateNonNull(type, "type may not be null");
GitLabProjectId gitLabProjectId = parseProjectId(projectId);
switch(getProjectTypeFromMode(gitLabProjectId.getGitLabMode())) {
case PROTOTYPE:
{
throw new LegendSDLCServerException("Cannot create versions for prototype projects", Status.BAD_REQUEST);
}
case PRODUCTION:
{
Version latestVersion = getLatestVersion(gitLabProjectId);
VersionId latestVersionId = (latestVersion == null) ? NULL_VERSION : latestVersion.getId();
VersionId nextVersionId;
switch(type) {
case MAJOR:
{
nextVersionId = latestVersionId.nextMajorVersion();
break;
}
case MINOR:
{
nextVersionId = latestVersionId.nextMinorVersion();
break;
}
case PATCH:
{
nextVersionId = latestVersionId.nextPatchVersion();
break;
}
default:
{
throw new LegendSDLCServerException("Unknown new version type: " + type, Status.BAD_REQUEST);
}
}
return newVersion(gitLabProjectId, revisionId, nextVersionId, notes);
}
default:
{
throw new LegendSDLCServerException("Unknown project: " + projectId, Status.BAD_REQUEST);
}
}
}
use of org.finos.legend.sdlc.server.error.LegendSDLCServerException in project legend-sdlc by finos.
the class GitLabVersionApi method newVersion.
private Version newVersion(GitLabProjectId projectId, String revisionId, VersionId versionId, String notes) {
String tagName = buildVersionTagName(versionId);
String message = "Release tag for version " + versionId.toVersionIdString();
try {
GitLabApi gitLabApi = getGitLabApi(projectId.getGitLabMode());
CommitsApi commitsApi = gitLabApi.getCommitsApi();
Commit referenceCommit;
if (revisionId == null) {
referenceCommit = commitsApi.getCommit(projectId.getGitLabId(), MASTER_BRANCH);
if (referenceCommit == null) {
throw new LegendSDLCServerException("Cannot create version " + versionId.toVersionIdString() + " of project " + projectId + ": cannot find current revision (project may be corrupt)", Status.INTERNAL_SERVER_ERROR);
}
} else {
try {
referenceCommit = commitsApi.getCommit(projectId.getGitLabId(), revisionId);
} catch (GitLabApiException e) {
if (GitLabApiTools.isNotFoundGitLabApiException(e)) {
throw new LegendSDLCServerException("Revision " + revisionId + " is unknown in project " + projectId, Status.BAD_REQUEST);
}
throw e;
}
Pager<CommitRef> referenceCommitBranchPager = withRetries(() -> commitsApi.getCommitRefs(projectId.getGitLabId(), referenceCommit.getId(), RefType.BRANCH, ITEMS_PER_PAGE));
Stream<CommitRef> referenceCommitBranches = PagerTools.stream(referenceCommitBranchPager);
if (referenceCommitBranches.noneMatch(ref -> MASTER_BRANCH.equals(ref.getName()))) {
throw new LegendSDLCServerException("Revision " + revisionId + " is unknown in project " + projectId, Status.BAD_REQUEST);
}
}
String referenceRevisionId = referenceCommit.getId();
Pager<CommitRef> referenceCommitTagPager = withRetries(() -> commitsApi.getCommitRefs(projectId.getGitLabId(), referenceRevisionId, RefType.TAG, ITEMS_PER_PAGE));
List<CommitRef> referenceCommitTags = PagerTools.stream(referenceCommitTagPager).collect(Collectors.toList());
if (referenceCommitTags.stream().map(CommitRef::getName).anyMatch(GitLabVersionApi::isVersionTagName)) {
StringBuilder builder = new StringBuilder("Revision ").append(referenceRevisionId).append(" has already been released in ");
List<VersionId> revisionVersionIds = referenceCommitTags.stream().map(CommitRef::getName).filter(GitLabVersionApi::isVersionTagName).map(GitLabVersionApi::parseVersionTagName).collect(Collectors.toList());
if (revisionVersionIds.size() == 1) {
builder.append("version ");
revisionVersionIds.get(0).appendVersionIdString(builder);
} else {
builder.append("versions ");
revisionVersionIds.sort(Comparator.naturalOrder());
boolean first = true;
for (VersionId revisionVersionId : revisionVersionIds) {
if (first) {
first = false;
} else {
builder.append(", ");
}
revisionVersionId.appendVersionIdString(builder);
}
}
throw new LegendSDLCServerException(builder.toString());
}
Tag tag = getGitLabApi(projectId.getGitLabMode()).getTagsApi().createTag(projectId.getGitLabId(), tagName, referenceRevisionId, message, notes);
return fromGitLabTag(projectId.toString(), tag);
} catch (Exception e) {
throw buildException(e, () -> "User " + getCurrentUser() + " is not allowed to create version " + versionId.toVersionIdString() + " of project " + projectId, () -> "Unknown project: " + projectId, () -> "Error creating version " + versionId.toVersionIdString() + " of project " + projectId);
}
}
use of org.finos.legend.sdlc.server.error.LegendSDLCServerException 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.finos.legend.sdlc.server.error.LegendSDLCServerException in project legend-sdlc by finos.
the class GitLabWorkspaceApi method deleteWorkspace.
/**
* When we delete a workspace, we also need to remember to delete the conflict resolution and backup workspaces
*/
@Override
public void deleteWorkspace(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();
// Delete workspace
boolean workspaceDeleted;
ProjectFileAccessProvider.WorkspaceAccessType workspaceAccessType = ProjectFileAccessProvider.WorkspaceAccessType.WORKSPACE;
try {
workspaceDeleted = GitLabApiTools.deleteBranchAndVerify(repositoryApi, gitLabProjectId.getGitLabId(), getWorkspaceBranchName(workspaceId, workspaceType, workspaceAccessType), 20, 1_000);
} catch (Exception e) {
throw buildException(e, () -> "User " + getCurrentUser() + " is not allowed to delete " + workspaceType.getLabel() + " " + workspaceAccessType.getLabel() + " " + workspaceId + " in project " + projectId, () -> "Unknown " + workspaceType.getLabel() + " " + workspaceAccessType.getLabel() + " (" + workspaceId + ") or project (" + projectId + ")", () -> "Error deleting " + workspaceType.getLabel() + " " + workspaceAccessType.getLabel() + " " + workspaceId + " in project " + projectId);
}
if (!workspaceDeleted) {
throw new LegendSDLCServerException("Failed to delete " + workspaceType.getLabel() + " " + workspaceAccessType.getLabel() + " " + workspaceId + " in project " + projectId);
}
// Delete conflict resolution workspace
ProjectFileAccessProvider.WorkspaceAccessType conflictResolutionWorkspaceType = ProjectFileAccessProvider.WorkspaceAccessType.CONFLICT_RESOLUTION;
try {
boolean deleted = GitLabApiTools.deleteBranchAndVerify(repositoryApi, gitLabProjectId.getGitLabId(), getWorkspaceBranchName(workspaceId, workspaceType, conflictResolutionWorkspaceType), 20, 1_000);
if (!deleted) {
LOGGER.error("Failed to delete {} {} in project {}", workspaceType.getLabel() + " " + conflictResolutionWorkspaceType.getLabel(), workspaceId, projectId);
}
} catch (Exception e) {
// unfortunate, but this should not throw error
LOGGER.error("Error deleting {} {} in project {}", workspaceType.getLabel() + " " + conflictResolutionWorkspaceType.getLabel(), workspaceId, projectId, e);
}
// Delete backup workspace
ProjectFileAccessProvider.WorkspaceAccessType backupWorkspaceType = ProjectFileAccessProvider.WorkspaceAccessType.BACKUP;
try {
boolean deleted = GitLabApiTools.deleteBranchAndVerify(repositoryApi, gitLabProjectId.getGitLabId(), getWorkspaceBranchName(workspaceId, workspaceType, backupWorkspaceType), 20, 1_000);
if (!deleted) {
LOGGER.error("Failed to delete {} {} in project {}", workspaceType.getLabel() + " " + backupWorkspaceType.getLabel(), workspaceId, projectId);
}
} catch (Exception e) {
// unfortunate, but this should not throw error
LOGGER.error("Error deleting {} {} in project {}", workspaceType.getLabel() + " " + backupWorkspaceType.getLabel(), workspaceId, projectId, e);
}
}
Aggregations