Search in sources :

Example 6 with MergeRequestApi

use of org.gitlab4j.api.MergeRequestApi 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;
}
Also used : GitLabApi(org.gitlab4j.api.GitLabApi) GitLabApiException(org.gitlab4j.api.GitLabApiException) LegendSDLCServerException(org.finos.legend.sdlc.server.error.LegendSDLCServerException) GitLabApiException(org.gitlab4j.api.GitLabApiException) ProjectFileAccessProvider(org.finos.legend.sdlc.server.project.ProjectFileAccessProvider) LegendSDLCServerException(org.finos.legend.sdlc.server.error.LegendSDLCServerException) MergeRequest(org.gitlab4j.api.models.MergeRequest) GitLabProjectId(org.finos.legend.sdlc.server.gitlab.GitLabProjectId) Branch(org.gitlab4j.api.models.Branch) MergeRequestApi(org.gitlab4j.api.MergeRequestApi) RepositoryApi(org.gitlab4j.api.RepositoryApi)

Example 7 with MergeRequestApi

use of org.gitlab4j.api.MergeRequestApi in project legend-sdlc by finos.

the class GitLabEntityApiTestResource method runEntitiesInNormalGroupWorkspaceWorkflowTest.

public void runEntitiesInNormalGroupWorkspaceWorkflowTest() throws GitLabApiException {
    String projectName = "CommitFlowTestProjectTwo";
    String description = "A test project.";
    ProjectType projectType = ProjectType.PRODUCTION;
    String groupId = "org.finos.sdlc.test";
    String artifactId = "entitytestprojtwo";
    List<String> tags = Lists.mutable.with("doe", "moffitt", AbstractGitLabServerApiTest.INTEGRATION_TEST_PROJECT_TAG);
    String workspaceName = "entitytestworkspace";
    Project createdProject = gitLabProjectApi.createProject(projectName, description, projectType, groupId, artifactId, tags);
    String projectId = createdProject.getProjectId();
    Workspace createdWorkspace = gitLabWorkspaceApi.newGroupWorkspace(projectId, workspaceName);
    String workspaceId = createdWorkspace.getWorkspaceId();
    List<Entity> initialWorkspaceEntities = gitLabEntityApi.getGroupWorkspaceEntityAccessContext(projectId, workspaceId).getEntities(null, null, null);
    List<Entity> initialProjectEntities = gitLabEntityApi.getProjectEntityAccessContext(projectId).getEntities(null, null, null);
    Assert.assertEquals(Collections.emptyList(), initialWorkspaceEntities);
    Assert.assertEquals(Collections.emptyList(), initialProjectEntities);
    String entityPath = "test::entity";
    String classifierPath = "meta::test::mathematicsDepartment";
    Map<String, String> entityContentMap = Maps.mutable.with("package", "test", "name", "entity", "math-113", "abstract-algebra", "math-185", "complex-analysis");
    gitLabEntityApi.getGroupWorkspaceEntityModificationContext(projectId, workspaceId).createEntity(entityPath, classifierPath, entityContentMap, "initial entity");
    List<Entity> modifiedWorkspaceEntities = gitLabEntityApi.getGroupWorkspaceEntityAccessContext(projectId, workspaceId).getEntities(null, null, null);
    List<Entity> modifiedProjectEntities = gitLabEntityApi.getProjectEntityAccessContext(projectId).getEntities(null, null, null);
    Assert.assertNotNull(modifiedWorkspaceEntities);
    Assert.assertEquals(Collections.emptyList(), modifiedProjectEntities);
    Assert.assertEquals(1, modifiedWorkspaceEntities.size());
    Entity initalEntity = modifiedWorkspaceEntities.get(0);
    Assert.assertEquals(initalEntity.getPath(), entityPath);
    Assert.assertEquals(initalEntity.getClassifierPath(), classifierPath);
    Assert.assertEquals(initalEntity.getContent(), entityContentMap);
    Map<String, String> newEntityContentMap = Maps.mutable.with("package", "test", "name", "entity", "math-128", "numerical-analysis", "math-110", "linear-algebra");
    gitLabEntityApi.getGroupWorkspaceEntityModificationContext(projectId, workspaceId).updateEntity(entityPath, classifierPath, newEntityContentMap, "update entity");
    List<Entity> updatedWorkspaceEntities = gitLabEntityApi.getGroupWorkspaceEntityAccessContext(projectId, workspaceId).getEntities(null, null, null);
    Assert.assertNotNull(updatedWorkspaceEntities);
    Assert.assertEquals(1, updatedWorkspaceEntities.size());
    Entity updatedEntity = updatedWorkspaceEntities.get(0);
    Assert.assertEquals(updatedEntity.getPath(), entityPath);
    Assert.assertEquals(updatedEntity.getClassifierPath(), classifierPath);
    Assert.assertEquals(updatedEntity.getContent(), newEntityContentMap);
    String entityPathTwo = "testtwo::entitytwo";
    String classifierPathTwo = "meta::test::csDepartment";
    Map<String, String> newEntityContentMapTwo = Maps.mutable.with("package", "testtwo", "name", "entitytwo", "cs-194", "computational-imaging", "cs-189", "machine-learning");
    gitLabEntityApi.getGroupWorkspaceEntityModificationContext(projectId, workspaceId).createEntity(entityPathTwo, classifierPathTwo, newEntityContentMapTwo, "second entity");
    List<Entity> postAddWorkspaceEntities = gitLabEntityApi.getGroupWorkspaceEntityAccessContext(projectId, workspaceId).getEntities(null, null, null);
    Assert.assertNotNull(postAddWorkspaceEntities);
    Assert.assertEquals(2, postAddWorkspaceEntities.size());
    gitLabEntityApi.getGroupWorkspaceEntityModificationContext(projectId, workspaceId).deleteEntity(entityPath, classifierPath);
    List<Entity> postDeleteWorkspaceEntities = gitLabEntityApi.getGroupWorkspaceEntityAccessContext(projectId, workspaceId).getEntities(null, null, null);
    Assert.assertNotNull(postDeleteWorkspaceEntities);
    Assert.assertEquals(1, postDeleteWorkspaceEntities.size());
    Entity remainedEntity = postDeleteWorkspaceEntities.get(0);
    Assert.assertEquals(remainedEntity.getPath(), entityPathTwo);
    Assert.assertEquals(remainedEntity.getClassifierPath(), classifierPathTwo);
    Assert.assertEquals(remainedEntity.getContent(), newEntityContentMapTwo);
    List<String> paths = gitLabEntityApi.getGroupWorkspaceEntityAccessContext(projectId, workspaceId).getEntityPaths(null, null, null);
    Assert.assertNotNull(paths);
    Assert.assertEquals(1, paths.size());
    Assert.assertEquals(entityPathTwo, paths.get(0));
    List<String> labels = Collections.singletonList("default");
    Review testReview = gitLabCommitterReviewApi.createReview(projectId, workspaceId, WorkspaceType.GROUP, "Add Courses.", "add two courses", labels);
    String reviewId = testReview.getId();
    Review approvedReview = gitLabApproverReviewApi.approveReview(projectId, reviewId);
    Assert.assertNotNull(approvedReview);
    Assert.assertEquals(reviewId, approvedReview.getId());
    Assert.assertEquals(ReviewState.OPEN, approvedReview.getState());
    GitLabProjectId sdlcGitLabProjectId = GitLabProjectId.parseProjectId(projectId);
    MergeRequestApi mergeRequestApi = gitLabMemberUserContext.getGitLabAPI(sdlcGitLabProjectId.getGitLabMode()).getMergeRequestApi();
    int parsedMergeRequestId = Integer.parseInt(reviewId);
    int gitlabProjectId = sdlcGitLabProjectId.getGitLabId();
    String requiredStatus = "can_be_merged";
    CallUntil<MergeRequest, GitLabApiException> callUntil = CallUntil.callUntil(() -> mergeRequestApi.getMergeRequest(gitlabProjectId, parsedMergeRequestId), mr -> requiredStatus.equals(mr.getMergeStatus()), 20, 1000);
    if (!callUntil.succeeded()) {
        throw new RuntimeException("Merge request " + approvedReview.getId() + " still does not have status \"" + requiredStatus + "\" after " + callUntil.getTryCount() + " tries");
    }
    LOGGER.info("Waited {} times for merge to have status \"{}\"", callUntil.getTryCount(), requiredStatus);
    gitLabCommitterReviewApi.commitReview(projectId, reviewId, "add two math courses");
    String requiredMergedStatus = "merged";
    CallUntil<MergeRequest, GitLabApiException> callUntilMerged = CallUntil.callUntil(() -> mergeRequestApi.getMergeRequest(gitlabProjectId, parsedMergeRequestId), mr -> requiredMergedStatus.equals(mr.getState()), 10, 500);
    if (!callUntilMerged.succeeded()) {
        throw new RuntimeException("Merge request " + reviewId + " still does not have state \"" + requiredMergedStatus + "\" after " + callUntilMerged.getTryCount() + " tries");
    }
    LOGGER.info("Waited {} times for merge request to have state \"{}\"", callUntilMerged.getTryCount(), requiredMergedStatus);
    RepositoryApi repositoryApi = gitLabMemberUserContext.getGitLabAPI(sdlcGitLabProjectId.getGitLabMode()).getRepositoryApi();
    CallUntil<List<Branch>, GitLabApiException> callUntilBranchDeleted = CallUntil.callUntil(() -> repositoryApi.getBranches(sdlcGitLabProjectId.getGitLabId()), GitLabEntityApiTestResource::hasOnlyMasterBranch, 15, 1000);
    if (!callUntilBranchDeleted.succeeded()) {
        // Warn instead of throwing exception since we cannot manage time expectation on GitLab to reflect branch deletion.
        LOGGER.warn("Branch is still not deleted post merge after {} tries", callUntilBranchDeleted.getTryCount());
    }
    LOGGER.info("Waited {} times for branch to be deleted post merge", callUntilBranchDeleted.getTryCount());
    List<Entity> postCommitProjectEntities = gitLabEntityApi.getProjectEntityAccessContext(projectId).getEntities(null, null, null);
    Assert.assertNotNull(postCommitProjectEntities);
    Assert.assertEquals(1, postCommitProjectEntities.size());
    Entity projectEntity = postCommitProjectEntities.get(0);
    Assert.assertEquals(projectEntity.getPath(), entityPathTwo);
    Assert.assertEquals(projectEntity.getClassifierPath(), classifierPathTwo);
    Assert.assertEquals(projectEntity.getContent(), newEntityContentMapTwo);
}
Also used : Entity(org.finos.legend.sdlc.domain.model.entity.Entity) GitLabApiException(org.gitlab4j.api.GitLabApiException) Review(org.finos.legend.sdlc.domain.model.review.Review) Project(org.finos.legend.sdlc.domain.model.project.Project) MergeRequest(org.gitlab4j.api.models.MergeRequest) GitLabProjectId(org.finos.legend.sdlc.server.gitlab.GitLabProjectId) ProjectType(org.finos.legend.sdlc.domain.model.project.ProjectType) MergeRequestApi(org.gitlab4j.api.MergeRequestApi) RepositoryApi(org.gitlab4j.api.RepositoryApi) List(java.util.List) Workspace(org.finos.legend.sdlc.domain.model.project.workspace.Workspace)

Example 8 with MergeRequestApi

use of org.gitlab4j.api.MergeRequestApi in project legend-sdlc by finos.

the class GitLabWorkspaceApiTestResource method runUpdateGroupWorkspaceWithRebaseNoConflictTest.

public void runUpdateGroupWorkspaceWithRebaseNoConflictTest() throws GitLabApiException {
    // Create new workspace from previous HEAD
    String projectName = "WorkspaceTestProjectThree";
    String description = "A test project.";
    ProjectType projectType = ProjectType.PRODUCTION;
    String groupId = "org.finos.sdlc.test";
    String artifactId = "testworkprojthree";
    List<String> tags = Lists.mutable.with("doe", "moffitt", AbstractGitLabServerApiTest.INTEGRATION_TEST_PROJECT_TAG);
    String workspaceName = "workspaceone";
    Project createdProject = gitLabProjectApi.createProject(projectName, description, projectType, groupId, artifactId, tags);
    String projectId = createdProject.getProjectId();
    Workspace createdWorkspace = gitLabWorkspaceApi.newGroupWorkspace(projectId, workspaceName);
    String workspaceId = createdWorkspace.getWorkspaceId();
    List<Entity> initialWorkspaceEntities = gitLabEntityApi.getGroupWorkspaceEntityAccessContext(projectId, workspaceId).getEntities(null, null, null);
    List<Entity> initialProjectEntities = gitLabEntityApi.getProjectEntityAccessContext(projectId).getEntities(null, null, null);
    Assert.assertEquals(Collections.emptyList(), initialWorkspaceEntities);
    Assert.assertEquals(Collections.emptyList(), initialProjectEntities);
    // Create another workspace, commit, review, merge to move project HEAD forward -- use workspace two
    String workspaceTwoName = "workspacetwo";
    Workspace createdWorkspaceTwo = gitLabWorkspaceApi.newGroupWorkspace(projectId, workspaceTwoName);
    String workspaceTwoId = createdWorkspaceTwo.getWorkspaceId();
    List<Entity> initialWorkspaceTwoEntities = gitLabEntityApi.getGroupWorkspaceEntityAccessContext(projectId, workspaceTwoId).getEntities(null, null, null);
    Assert.assertEquals(Collections.emptyList(), initialWorkspaceTwoEntities);
    String entityPath = "test::entity";
    String classifierPath = "meta::test::mathematicsDepartment";
    Map<String, String> entityContentMap = Maps.mutable.with("package", "test", "name", "entity", "math-113", "abstract-algebra", "math-185", "complex-analysis");
    gitLabEntityApi.getGroupWorkspaceEntityModificationContext(projectId, workspaceTwoId).createEntity(entityPath, classifierPath, entityContentMap, "initial entity");
    List<Entity> modifiedWorkspaceEntities = gitLabEntityApi.getGroupWorkspaceEntityAccessContext(projectId, workspaceTwoId).getEntities(null, null, null);
    Assert.assertNotNull(modifiedWorkspaceEntities);
    Assert.assertEquals(1, modifiedWorkspaceEntities.size());
    Entity initalEntity = modifiedWorkspaceEntities.get(0);
    Assert.assertEquals(initalEntity.getPath(), entityPath);
    Assert.assertEquals(initalEntity.getClassifierPath(), classifierPath);
    Assert.assertEquals(initalEntity.getContent(), entityContentMap);
    List<String> labels = Collections.singletonList("default");
    Review testReview = gitLabCommitterReviewApi.createReview(projectId, workspaceTwoId, WorkspaceType.GROUP, "Add Courses.", "add two math courses", labels);
    String reviewId = testReview.getId();
    Review approvedReview = gitLabApproverReviewApi.approveReview(projectId, reviewId);
    Assert.assertNotNull(approvedReview);
    Assert.assertEquals(reviewId, approvedReview.getId());
    Assert.assertEquals(ReviewState.OPEN, approvedReview.getState());
    GitLabProjectId sdlcGitLabProjectId = GitLabProjectId.parseProjectId(projectId);
    MergeRequestApi mergeRequestApi = gitLabMemberUserContext.getGitLabAPI(sdlcGitLabProjectId.getGitLabMode()).getMergeRequestApi();
    Integer parsedMergeRequestId = Integer.parseInt(reviewId);
    Integer gitlabProjectId = sdlcGitLabProjectId.getGitLabId();
    String requiredStatus = "can_be_merged";
    CallUntil<MergeRequest, GitLabApiException> callUntil = CallUntil.callUntil(() -> mergeRequestApi.getMergeRequest(gitlabProjectId, parsedMergeRequestId), mr -> requiredStatus.equals(mr.getMergeStatus()), 20, 1000);
    if (!callUntil.succeeded()) {
        throw new RuntimeException("Merge request " + approvedReview.getId() + " still does not have status \"" + requiredStatus + "\" after " + callUntil.getTryCount() + " tries");
    }
    LOGGER.info("Waited {} times for merge to have status \"{}\"", callUntil.getTryCount(), requiredStatus);
    gitLabCommitterReviewApi.commitReview(projectId, reviewId, "add two math courses");
    String requiredMergedStatus = "merged";
    CallUntil<MergeRequest, GitLabApiException> callUntilMerged = CallUntil.callUntil(() -> mergeRequestApi.getMergeRequest(gitlabProjectId, parsedMergeRequestId), mr -> requiredMergedStatus.equals(mr.getState()), 10, 500);
    if (!callUntilMerged.succeeded()) {
        throw new RuntimeException("Merge request " + reviewId + " still does not have state \"" + requiredMergedStatus + "\" after " + callUntilMerged.getTryCount() + " tries");
    }
    LOGGER.info("Waited {} times for merge request to have state \"{}\"", callUntilMerged.getTryCount(), requiredMergedStatus);
    RepositoryApi repositoryApi = gitLabMemberUserContext.getGitLabAPI(sdlcGitLabProjectId.getGitLabMode()).getRepositoryApi();
    CallUntil<List<Branch>, GitLabApiException> callUntilBranchDeleted = CallUntil.callUntil(() -> repositoryApi.getBranches(sdlcGitLabProjectId.getGitLabId()), branches -> GitLabApiTestSetupUtil.hasOnlyBranchesWithNames(branches, Lists.mutable.of(workspaceName, "master")), 15, 1000);
    if (!callUntilBranchDeleted.succeeded()) {
        // Warn instead of throwing exception since we cannot manage time expectation on GitLab to reflect branch deletion.
        LOGGER.warn("Branch {} is still not deleted post merge after {} tries", workspaceTwoName, callUntilBranchDeleted.getTryCount());
    }
    LOGGER.info("Waited {} times for branch {} to be deleted post merge", callUntilBranchDeleted.getTryCount(), workspaceTwoName);
    List<Entity> postCommitProjectEntities = gitLabEntityApi.getProjectEntityAccessContext(projectId).getEntities(null, null, null);
    Assert.assertNotNull(postCommitProjectEntities);
    Assert.assertEquals(1, postCommitProjectEntities.size());
    Entity projectEntity = postCommitProjectEntities.get(0);
    Assert.assertEquals(projectEntity.getPath(), entityPath);
    Assert.assertEquals(projectEntity.getClassifierPath(), classifierPath);
    Assert.assertEquals(projectEntity.getContent(), entityContentMap);
    // Create changes and make change in workspace branch -- use workspace
    Map<String, String> currentEntityContentMap = Maps.mutable.with("package", "test", "name", "entity", "math-113", "abstract-algebra", "math-185", "complex-analysis");
    gitLabEntityApi.getGroupWorkspaceEntityModificationContext(projectId, workspaceId).createEntity(entityPath, classifierPath, currentEntityContentMap, "initial entity");
    List<Entity> modifiedWorkspaceEntitiesNew = gitLabEntityApi.getGroupWorkspaceEntityAccessContext(projectId, workspaceId).getEntities(null, null, null);
    Assert.assertNotNull(modifiedWorkspaceEntitiesNew);
    Assert.assertEquals(1, modifiedWorkspaceEntities.size());
    Entity initalEntityNew = modifiedWorkspaceEntitiesNew.get(0);
    Assert.assertEquals(initalEntityNew.getPath(), entityPath);
    Assert.assertEquals(initalEntityNew.getClassifierPath(), classifierPath);
    Assert.assertEquals(initalEntityNew.getContent(), currentEntityContentMap);
    // Update workspace branch and trigger rebase
    gitLabWorkspaceApi.updateGroupWorkspace(projectId, workspaceId);
    List<Entity> updatedWorkspaceEntities = gitLabEntityApi.getGroupWorkspaceEntityAccessContext(projectId, workspaceId).getEntities(null, null, null);
    Assert.assertNotNull(updatedWorkspaceEntities);
    Assert.assertEquals(1, updatedWorkspaceEntities.size());
    Entity updatedEntity = updatedWorkspaceEntities.get(0);
    Assert.assertEquals(updatedEntity.getPath(), entityPath);
    Assert.assertEquals(updatedEntity.getClassifierPath(), classifierPath);
    Assert.assertEquals(updatedEntity.getContent(), currentEntityContentMap);
}
Also used : Entity(org.finos.legend.sdlc.domain.model.entity.Entity) GitLabApiException(org.gitlab4j.api.GitLabApiException) Review(org.finos.legend.sdlc.domain.model.review.Review) Project(org.finos.legend.sdlc.domain.model.project.Project) MergeRequest(org.gitlab4j.api.models.MergeRequest) GitLabProjectId(org.finos.legend.sdlc.server.gitlab.GitLabProjectId) ProjectType(org.finos.legend.sdlc.domain.model.project.ProjectType) MergeRequestApi(org.gitlab4j.api.MergeRequestApi) RepositoryApi(org.gitlab4j.api.RepositoryApi) List(java.util.List) Workspace(org.finos.legend.sdlc.domain.model.project.workspace.Workspace)

Example 9 with MergeRequestApi

use of org.gitlab4j.api.MergeRequestApi in project legend-sdlc by finos.

the class GitLabReviewApi method commitReview.

@Override
public Review commitReview(String projectId, String reviewId, String message) {
    LegendSDLCServerException.validateNonNull(projectId, "projectId may not be null");
    LegendSDLCServerException.validateNonNull(reviewId, "reviewId may not be null");
    LegendSDLCServerException.validateNonNull(message, "message may not be null");
    GitLabProjectId gitLabProjectId = parseProjectId(projectId);
    MergeRequestApi mergeRequestApi = getGitLabApi(gitLabProjectId.getGitLabMode()).getMergeRequestApi();
    // Find the merge request
    MergeRequest mergeRequest = getReviewMergeRequest(mergeRequestApi, gitLabProjectId, reviewId);
    // Validate that the merge request is ready to be merged
    // Check that the state is open
    validateMergeRequestReviewState(mergeRequest, ReviewState.OPEN);
    // Check that there are no approvals still required
    Integer approvalsLeft = mergeRequest.getApprovalsLeft();
    if ((approvalsLeft != null) && (approvalsLeft > 0)) {
        throw new LegendSDLCServerException("Review " + reviewId + " in project " + projectId + " still requires " + approvalsLeft + " approvals", Status.CONFLICT);
    }
    // Accept
    try {
        return fromGitLabMergeRequest(projectId, mergeRequestApi.acceptMergeRequest(gitLabProjectId.getGitLabId(), mergeRequest.getIid(), message, true, null, null));
    } catch (GitLabApiException e) {
        switch(e.getHttpStatus()) {
            // Status 401 (Unauthorized) can indicate either that the user is not properly authenticated or that the user is not allowed to merge the request.
            case 401:
            case 403:
                {
                    // This shouldn't happen, but just in case ...
                    throw new LegendSDLCServerException("User " + getCurrentUser() + " is not allowed to commit changes from review " + reviewId + " in project " + projectId, Status.FORBIDDEN, e);
                }
            case 404:
                {
                    // This shouldn't happen, as we already verified the review exists
                    throw new LegendSDLCServerException("Unknown review in project " + projectId + ": " + reviewId, Status.NOT_FOUND, e);
                }
            case 405:
                {
                    // Status 405 (Method Not Allowed) indicates the merge request could not be accepted because it's not in an appropriate state (i.e., work in progress, closed, pipeline pending completion, or failed while requiring success)
                    throw new LegendSDLCServerException("Review " + reviewId + " in project " + projectId + " is not in a committable state; for more details, see: " + mergeRequest.getWebUrl(), Status.CONFLICT, e);
                }
            case 406:
                {
                    // Status 406 (Not Acceptable) indicates the merge could not occur because of a conflict
                    throw new LegendSDLCServerException("Could not commit review " + reviewId + " in project " + projectId + " because of a conflict; for more details, see: " + mergeRequest.getWebUrl(), Status.CONFLICT, e);
                }
            default:
                {
                    StringBuilder builder = new StringBuilder("Error committing changes from review ").append(reviewId).append(" to project ").append(projectId);
                    StringTools.appendThrowableMessageIfPresent(builder, e);
                    LOGGER.warn("Unexpected response status committing changes from review {} to project {}; status {}; message: {}", reviewId, projectId, e.getHttpStatus(), e.getMessage());
                    throw new LegendSDLCServerException(builder.toString(), e);
                }
        }
    } catch (LegendSDLCServerException e) {
        throw e;
    } catch (Exception e) {
        StringBuilder builder = new StringBuilder("Error committing changes from review ").append(reviewId).append(" to project ").append(projectId);
        StringTools.appendThrowableMessageIfPresent(builder, e);
        throw new LegendSDLCServerException(builder.toString(), e);
    }
}
Also used : LegendSDLCServerException(org.finos.legend.sdlc.server.error.LegendSDLCServerException) MergeRequest(org.gitlab4j.api.models.MergeRequest) GitLabProjectId(org.finos.legend.sdlc.server.gitlab.GitLabProjectId) MergeRequestApi(org.gitlab4j.api.MergeRequestApi) GitLabApiException(org.gitlab4j.api.GitLabApiException) LegendSDLCServerException(org.finos.legend.sdlc.server.error.LegendSDLCServerException) GitLabApiException(org.gitlab4j.api.GitLabApiException)

Example 10 with MergeRequestApi

use of org.gitlab4j.api.MergeRequestApi in project legend-sdlc by finos.

the class GitLabReviewApi method reopenReview.

@Override
public Review reopenReview(String projectId, String reviewId) {
    LegendSDLCServerException.validateNonNull(projectId, "projectId may not be null");
    LegendSDLCServerException.validateNonNull(reviewId, "reviewId may not be null");
    GitLabProjectId gitLabProjectId = parseProjectId(projectId);
    MergeRequestApi mergeRequestApi = getGitLabApi(gitLabProjectId.getGitLabMode()).getMergeRequestApi();
    MergeRequest mergeRequest = getReviewMergeRequest(mergeRequestApi, gitLabProjectId, reviewId);
    validateMergeRequestReviewState(mergeRequest, ReviewState.CLOSED);
    try {
        MergeRequest reopenMergeRequest = updateMergeRequestState(mergeRequestApi, gitLabProjectId, mergeRequest, StateEvent.REOPEN);
        return fromGitLabMergeRequest(projectId, reopenMergeRequest);
    } catch (Exception e) {
        throw buildException(e, () -> "User " + getCurrentUser() + " is not allowed to reopen review " + reviewId + " in project " + projectId, () -> "Unknown review in project " + projectId + ": " + reviewId, () -> "Error reopening review " + reviewId + " in project " + projectId);
    }
}
Also used : MergeRequest(org.gitlab4j.api.models.MergeRequest) GitLabProjectId(org.finos.legend.sdlc.server.gitlab.GitLabProjectId) MergeRequestApi(org.gitlab4j.api.MergeRequestApi) LegendSDLCServerException(org.finos.legend.sdlc.server.error.LegendSDLCServerException) GitLabApiException(org.gitlab4j.api.GitLabApiException)

Aggregations

GitLabProjectId (org.finos.legend.sdlc.server.gitlab.GitLabProjectId)14 MergeRequestApi (org.gitlab4j.api.MergeRequestApi)14 MergeRequest (org.gitlab4j.api.models.MergeRequest)14 GitLabApiException (org.gitlab4j.api.GitLabApiException)13 LegendSDLCServerException (org.finos.legend.sdlc.server.error.LegendSDLCServerException)10 RepositoryApi (org.gitlab4j.api.RepositoryApi)5 List (java.util.List)4 Entity (org.finos.legend.sdlc.domain.model.entity.Entity)4 Project (org.finos.legend.sdlc.domain.model.project.Project)4 ProjectType (org.finos.legend.sdlc.domain.model.project.ProjectType)4 Workspace (org.finos.legend.sdlc.domain.model.project.workspace.Workspace)4 Review (org.finos.legend.sdlc.domain.model.review.Review)4 GitLabApi (org.gitlab4j.api.GitLabApi)3 ProjectFileAccessProvider (org.finos.legend.sdlc.server.project.ProjectFileAccessProvider)2 Branch (org.gitlab4j.api.models.Branch)1 MergeRequestParams (org.gitlab4j.api.models.MergeRequestParams)1