public void AbortBuild(MergeRequest mergeRequest, Build build) { var projectClient = client.GetRepository(mergeRequest.SourceProjectId); var actualBuild = build ?? projectClient.Builds.GetBuilds().FirstOrDefault(); if (actualBuild == null || (actualBuild.Status != BuildStatus.pending && actualBuild.Status != BuildStatus.running)) return; projectClient.Builds.Cancel(actualBuild); }
public MergeRequestViewModel(BranchViewModel branch, MergeRequest mergeRequest) { Branch = branch; MergeRequest = mergeRequest; Changes = branch.GetMergeRequestChanges(mergeRequest).Select(x => new MergeRequestFileDataViewModel(x)).ToList(); Commits = branch.GetCommits(mergeRequest) .Select(commit => new CommitViewModel(commit, sha => branch.GetBuilds(mergeRequest, sha), x => branch.DownloadArtifacts(mergeRequest, x), x => branch.DownloadTrace(mergeRequest, x))) .ToList(); Title = MergeRequest.Title; SourceBranch = MergeRequest.SourceBranch; TargetBranch = MergeRequest.TargetBranch; Author = MergeRequest.Author.Username; Assignee = MergeRequest.Assignee?.Username; AssigneeId = MergeRequest?.Assignee?.Id; }
public MergeRequest CloseMergeRequest(MergeRequest mergeRequest) { var mergeRequestsClient = client.GetMergeRequest(mergeRequest.ProjectId); try { return mergeRequestsClient.Update(mergeRequest.Id, new MergeRequestUpdate() { NewState = "close", AssigneeId = mergeRequest.Assignee?.Id, SourceBranch = mergeRequest.SourceBranch, TargetBranch = mergeRequest.TargetBranch, Title = mergeRequest.Title, Description = mergeRequest.Description, }); } catch { return mergeRequestsClient[mergeRequest.Id]; } }
public IEnumerable<Commit> GetCommits(MergeRequest mergeRequest) { return gitLabWrapper.GetMergeRequestCommits(mergeRequest); }
static bool ValidateMergeRequestChanges(GitLabWrapper gitLabWrapper, MergeRequest mergeRequest, bool ignoreValidation) { if (ignoreValidation) return true; bool result = true; var fileChanges = gitLabWrapper.GetFileChanges(mergeRequest); foreach (var fileChange in fileChanges) { if (!ValidateFileChange(fileChange)) { Log.Error($"File {fileChange.OldPath} has nonwindows line endings. Only windows line endings allowed."); result = false; } } return result; }
static MergeRequestResult ProcessMergeRequest(DXVcsWrapper vcsWrapper, GitWrapper gitWrapper, GitLabWrapper gitLabWrapper, RegisteredUsers users, User defaultUser, string localGitDir, TrackBranch branch, MergeRequest mergeRequest, SyncHistoryWrapper syncHistory) { switch (mergeRequest.State) { case "reopened": case "opened": return ProcessOpenedMergeRequest(vcsWrapper, gitWrapper, gitLabWrapper, users, defaultUser, localGitDir, branch, mergeRequest, syncHistory); } return MergeRequestResult.InvalidState; }
static bool ShouldForceSyncTask(MergeRequest mergeRequest, MergeRequestHookClient hook) { var assignee = mergeRequest.Assignee; if (assignee == null || !assignee.Name.StartsWith("dxvcs2git")) { Log.Message("Force sync rejected because assignee is not set or not sync task."); return false; } if (hook.Attributes.WorkInProcess) { Log.Message("Force sync rejected because merge request has work in process flag."); return false; } if (hook.Attributes.MergeStatus == "unchecked" || hook.Attributes.MergeStatus == "can_be_merged") return true; Log.Message("Force sync rejected because merge request can`t be merged automatically."); return false; }
static string CalcCommentForMergeRequest(MergeRequest mergeRequest) { StringBuilder sb = new StringBuilder(); if (!string.IsNullOrEmpty(mergeRequest.Title)) sb.AppendLine(mergeRequest.Title); if (!string.IsNullOrEmpty(mergeRequest.Description)) { sb.Append(mergeRequest.Description); sb.AppendLine(); } return sb.ToString(); }
public IEnumerable<Comment> GetComments(MergeRequest mergeRequest) { var mergeRequestsClient = client.GetMergeRequest(mergeRequest.ProjectId); var commentsClient = mergeRequestsClient.Comments(mergeRequest.Id); return commentsClient.All; }
public IEnumerable<Build> GetBuilds(MergeRequest mergeRequest, Sha1 sha) { var projectClient = client.GetRepository(mergeRequest.SourceProjectId); return projectClient.Builds.GetBuildsForCommit(sha); }
public void ForceBuild(MergeRequest mergeRequest, Build build = null) { var projectClient = client.GetRepository(mergeRequest.SourceProjectId); var actualBuild = build ?? projectClient.Builds.GetBuilds().FirstOrDefault(); if (actualBuild == null || actualBuild.Status == BuildStatus.success || actualBuild.Status == BuildStatus.pending || actualBuild.Status == BuildStatus.running) return; projectClient.Builds.Retry(actualBuild); }
public byte[] DownloadTrace(MergeRequest mergeRequest, Build build) { var projectClient = client.GetRepository(mergeRequest.SourceProjectId); byte[] result = null; projectClient.Builds.GetTraceFile(build, stream => { if (stream == null) return; using (MemoryStream ms = new MemoryStream()) { stream.CopyTo(ms); result = ms.ToArray(); } }); return result; }
public void AbortBuild(MergeRequest mergeRequest, Build build = null) { gitLabWrapper.AbortBuild(mergeRequest, build); }
public MergeRequestSyncAction GetSyncOptions(MergeRequest mergeRequest) { var comments = gitLabWrapper.GetComments(mergeRequest); var mergeRequestSyncOptions = comments.Where(x => IsXml(x.Note)).Where(x => { var mr = MergeRequestOptions.ConvertFromString(x.Note); return mr?.ActionType == MergeRequestActionType.sync; }).Select(x => (MergeRequestSyncAction)MergeRequestOptions.ConvertFromString(x.Note).Action).LastOrDefault(); return mergeRequestSyncOptions; }
public IEnumerable<MergeRequestFileData> GetMergeRequestChanges(MergeRequest mergeRequest) { return gitLabWrapper.GetMergeRequestChanges(mergeRequest); }
public IEnumerable<MergeRequestFileData> GetMergeRequestChanges(MergeRequest mergeRequest) { var mergeRequestsClient = client.GetMergeRequest(mergeRequest.ProjectId); var changesClient = mergeRequestsClient.Changes(mergeRequest.Id); return changesClient.Changes.Files; }
public Comment AddCommentToMergeRequest(MergeRequest mergeRequest, string comment) { var mergeRequestsClient = client.GetMergeRequest(mergeRequest.ProjectId); var commentsClient = mergeRequestsClient.Comments(mergeRequest.Id); return commentsClient.Add(new MergeRequestComment() { Note = comment }); }
public IEnumerable<Commit> GetMergeRequestCommits(MergeRequest mergeRequest) { var mergeRequestsClient = client.GetMergeRequest(mergeRequest.ProjectId); return mergeRequestsClient.Commits(mergeRequest.Id).All; }
public byte[] DownloadArtifacts(MergeRequest mergeRequest, Build build) { var projectClient = client.GetRepository(mergeRequest.SourceProjectId); return DownloadArtifactsCore(projectClient, build); }
public MergeRequest ProcessMergeRequest(MergeRequest mergeRequest, string comment) { var mergeRequestsClient = client.GetMergeRequest(mergeRequest.ProjectId); try { return mergeRequestsClient.Accept(mergeRequest.Id, new MergeCommitMessage() { Message = comment }); } catch (Exception ex) { Log.Error("Merging has thrown exception", ex); mergeRequest.State = "merging_failed"; return mergeRequest; } }
static CommentWrapper CalcComment(MergeRequest mergeRequest, TrackBranch branch, string autoSyncToken) { CommentWrapper comment = new CommentWrapper(); comment.Author = mergeRequest.Author.Username; comment.Branch = branch.Name; comment.Token = autoSyncToken; comment.Comment = CalcCommentForMergeRequest(mergeRequest); return comment; }
public MergeRequest ReopenMergeRequest(MergeRequest mergeRequest, string autoMergeFailedComment) { var mergeRequestsClient = client.GetMergeRequest(mergeRequest.ProjectId); try { return mergeRequestsClient.Update(mergeRequest.Id, new MergeRequestUpdate() {NewState = "reopen", Description = autoMergeFailedComment}); } catch { return mergeRequestsClient[mergeRequest.Id]; } }
static void ForceSyncBuild(GitLabWrapper gitLabWrapper, MergeRequest mergeRequest, Project targetProject, MergeRequestHookClient hook) { var xmlComments = gitLabWrapper.GetComments(mergeRequest).Where(x => IsXml(x.Note)); var options = xmlComments.Select(x => MergeRequestOptions.ConvertFromString(x.Note)).FirstOrDefault(); if (options != null && options.ActionType == MergeRequestActionType.sync) { var action = (MergeRequestSyncAction)options.Action; if (action.PerformTesting) { Log.Message("Check build status before force build."); var commit = gitLabWrapper.GetMergeRequestCommits(mergeRequest).FirstOrDefault(); var build = commit != null ? gitLabWrapper.GetBuilds(mergeRequest, commit.Id).FirstOrDefault() : null; var buildStatus = build?.Status ?? BuildStatus.undefined; Log.Message($"Build status = {buildStatus}."); if (buildStatus == BuildStatus.success) ForceBuild(action.SyncTask); return; } Log.Message("Build forces without checking tests status."); ForceBuild(action.SyncTask); return; } string task = FarmIntegrator.FindTask($"{mergeRequest.TargetBranch}@{targetProject.PathWithNamespace}"); if (!string.IsNullOrEmpty(task)) { Log.Message($"Sync task {task} found by heuristic."); ForceBuild(task); return; } Log.Message("Merge request can`t be merged because merge request notes has no farm config."); Log.Message(""); }
public bool ShouldIgnoreSharedFiles(MergeRequest mergeRequest) { var mergeRequestsClient = client.GetMergeRequest(mergeRequest.ProjectId); var commentsClient = mergeRequestsClient.Comments(mergeRequest.Id); var comment = commentsClient.All.LastOrDefault(); return comment?.Note == IgnoreValidation; }
static void AssignBackConflictedMergeRequest(GitLabWrapper gitLabWrapper, RegisteredUsers users, MergeRequest mergeRequest, string comment) { User author = users.GetUser(mergeRequest.Author.Username); var mr = gitLabWrapper.UpdateMergeRequestAssignee(mergeRequest, author.UserName); gitLabWrapper.AddCommentToMergeRequest(mr, comment); }
public MergeRequest UpdateMergeRequestAssignee(MergeRequest mergeRequest, string user) { var userInfo = GetUsers().FirstOrDefault(x => x.Username == user); if (mergeRequest.Assignee?.Username != userInfo?.Username) { var mergeRequestsClient = client.GetMergeRequest(mergeRequest.ProjectId); try { return mergeRequestsClient.Update(mergeRequest.Id, new MergeRequestUpdate() { AssigneeId = userInfo?.Id, Title = mergeRequest.Title, Description = mergeRequest.Description, SourceBranch = mergeRequest.SourceBranch, TargetBranch = mergeRequest.TargetBranch, }); } catch { return mergeRequestsClient[mergeRequest.Id]; } } return mergeRequest; }
static MergeRequestResult ProcessOpenedMergeRequest(DXVcsWrapper vcsWrapper, GitWrapper gitWrapper, GitLabWrapper gitLabWrapper, RegisteredUsers users, User defaultUser, string localGitDir, TrackBranch branch, MergeRequest mergeRequest, SyncHistoryWrapper syncHistory) { string autoSyncToken = syncHistory.CreateNewToken(); var lastHistoryItem = syncHistory.GetHead(); Log.Message($"Start merging mergerequest {mergeRequest.Title}"); Log.ResetErrorsAccumulator(); var changes = gitLabWrapper.GetMergeRequestChanges(mergeRequest).ToList(); if (changes.Count >= MaxChangesCount) { Log.Error($"Merge request contains more than {MaxChangesCount} changes and cannot be processed. Split it into smaller merge requests"); AssignBackConflictedMergeRequest(gitLabWrapper, users, mergeRequest, CalcCommentForFailedCheckoutMergeRequest(null)); return MergeRequestResult.Failed; } var genericChange = changes .Where(x => branch.TrackItems.FirstOrDefault(track => CheckItemForChangeSet(x, track)) != null) .Select(x => ProcessMergeRequestChanges(mergeRequest, x, localGitDir, branch, autoSyncToken)).ToList(); bool ignoreValidation = gitLabWrapper.ShouldIgnoreSharedFiles(mergeRequest); if (!ValidateMergeRequestChanges(gitLabWrapper, mergeRequest, ignoreValidation) || !vcsWrapper.ProcessCheckout(genericChange, ignoreValidation, branch)) { Log.Error("Merging merge request failed because failed validation."); AssignBackConflictedMergeRequest(gitLabWrapper, users, mergeRequest, CalcCommentForFailedCheckoutMergeRequest(genericChange)); vcsWrapper.ProcessUndoCheckout(genericChange); return MergeRequestResult.CheckoutFailed; } CommentWrapper comment = CalcComment(mergeRequest, branch, autoSyncToken); mergeRequest = gitLabWrapper.ProcessMergeRequest(mergeRequest, comment.ToString()); if (mergeRequest.State == "merged") { Log.Message("Merge request merged successfully."); gitWrapper.Pull(); gitWrapper.LFSPull(); var gitCommit = gitWrapper.FindCommit(x => CommentWrapper.Parse(x.Message).Token == autoSyncToken); long timeStamp = lastHistoryItem.VcsCommitTimeStamp; if (gitCommit != null && vcsWrapper.ProcessCheckIn(genericChange, comment.ToString())) { var checkinHistory = vcsWrapper.GenerateHistory(branch, new DateTime(timeStamp)).Where(x => x.ActionDate.Ticks > timeStamp); var lastCommit = checkinHistory.OrderBy(x => x.ActionDate).LastOrDefault(); long newTimeStamp = lastCommit?.ActionDate.Ticks ?? timeStamp; var mergeRequestResult = MergeRequestResult.Success; if (!ValidateMergeRequest(vcsWrapper, branch, lastHistoryItem, defaultUser)) mergeRequestResult = MergeRequestResult.Mixed; if (!ValidateChangeSet(genericChange)) mergeRequestResult = MergeRequestResult.Mixed; syncHistory.Add(gitCommit.Sha, newTimeStamp, autoSyncToken, mergeRequestResult == MergeRequestResult.Success ? SyncHistoryStatus.Success : SyncHistoryStatus.Mixed); syncHistory.Save(); Log.Message("Merge request checkin successfully."); return mergeRequestResult; } Log.Error("Merge request checkin failed."); if (gitCommit == null) Log.Error($"Can`t find git commit with token {autoSyncToken}"); var failedHistory = vcsWrapper.GenerateHistory(branch, new DateTime(timeStamp)); var lastFailedCommit = failedHistory.OrderBy(x => x.ActionDate).LastOrDefault(); syncHistory.Add(gitCommit.Sha, lastFailedCommit?.ActionDate.Ticks ?? timeStamp, autoSyncToken, SyncHistoryStatus.Failed); syncHistory.Save(); return MergeRequestResult.Failed; } Log.Message($"Merge request merging failed due conflicts. Resolve conflicts manually."); vcsWrapper.ProcessUndoCheckout(genericChange); AssignBackConflictedMergeRequest(gitLabWrapper, users, mergeRequest, CalcCommentForFailedCheckoutMergeRequest(genericChange)); return MergeRequestResult.Conflicts; }
public MergeRequest UpdateMergeRequestTitleAndDescription(MergeRequest mergeRequest, string title, string description) { var mergeRequestsClient = client.GetMergeRequest(mergeRequest.ProjectId); try { return mergeRequestsClient.Update(mergeRequest.Id, new MergeRequestUpdate() { Description = description, Title = title, AssigneeId = mergeRequest.Assignee?.Id, SourceBranch = mergeRequest.SourceBranch, TargetBranch = mergeRequest.TargetBranch, }); } catch { return mergeRequestsClient[mergeRequest.Id]; } }
static SyncItem ProcessMergeRequestChanges(MergeRequest mergeRequest, MergeRequestFileData fileData, string localGitDir, TrackBranch branch, string token) { string vcsRoot = branch.RepoRoot; var syncItem = new SyncItem(); if (fileData.IsNew) { syncItem.SyncAction = SyncAction.New; syncItem.LocalPath = CalcLocalPath(localGitDir, branch, fileData.OldPath); syncItem.VcsPath = CalcVcsPath(branch, fileData.OldPath); } else if (fileData.IsDeleted) { syncItem.SyncAction = SyncAction.Delete; syncItem.LocalPath = CalcLocalPath(localGitDir, branch, fileData.OldPath); syncItem.VcsPath = CalcVcsPath(branch, fileData.OldPath); } else if (fileData.IsRenamed) { syncItem.SyncAction = SyncAction.Move; syncItem.LocalPath = CalcLocalPath(localGitDir, branch, fileData.OldPath); syncItem.NewLocalPath = CalcLocalPath(localGitDir, branch, fileData.NewPath); syncItem.VcsPath = CalcVcsPath(branch, fileData.OldPath); syncItem.NewVcsPath = CalcVcsPath(branch, fileData.NewPath); } else { syncItem.SyncAction = SyncAction.Modify; syncItem.LocalPath = CalcLocalPath(localGitDir, branch, fileData.OldPath); syncItem.VcsPath = CalcVcsPath(branch, fileData.OldPath); } syncItem.Comment = CalcComment(mergeRequest, branch, token); return syncItem; }
public IEnumerable<Build> GetBuilds(MergeRequest mergeRequest, Sha1 sha) { return gitLabWrapper.GetBuilds(mergeRequest, sha); }