/// <inheritdoc /> public async Task ProcessPayload(PullRequestEventPayload payload, CancellationToken cancellationToken) { if (payload == null) { throw new ArgumentNullException(nameof(payload)); } if (payload.Action != "edited") { throw new NotSupportedException(); } var signOff = await dataStore.ReadData <PullRequestSignOffs>(SignOffDataKey, cancellationToken).ConfigureAwait(false); if (!signOff.Entries.Remove(payload.PullRequest.Number)) { return; } await dataStore.WriteData(SignOffDataKey, signOff, cancellationToken).ConfigureAwait(false); var botLoginTask = gitHubManager.GetUserLogin(null, cancellationToken); var reviews = await gitHubManager.GetPullRequestReviews(payload.PullRequest).ConfigureAwait(false); var botLogin = await botLoginTask.ConfigureAwait(false); await Task.WhenAll( reviews.Where( x => x.User.Id == botLogin.Id && x.State.Value == PullRequestReviewState.Approved ).Select( x => gitHubManager.DismissReview(payload.PullRequest, x, stringLocalizer["SignOffNulled"]) )); }
/// <summary> /// Erases the sign off and dismisses the 'approved' reviews /// </summary> /// <param name="pullRequest">The <see cref="PullRequest"/> to un-sign</param> /// <param name="message">The dismissal message</param> /// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation</param> /// <returns>A <see cref="Task"/> representing the running operation</returns> async Task EraseAndDismissReviews(PullRequest pullRequest, string message, CancellationToken cancellationToken) { var reviewsTask = gitHubManager.GetPullRequestReviews(pullRequest); var botLoginTask = gitHubManager.GetUserLogin(null, cancellationToken); await dataStore.WriteData(pullRequest.Number.ToString(CultureInfo.InvariantCulture), new PullRequestSignOff(), cancellationToken).ConfigureAwait(false); var reviews = await reviewsTask.ConfigureAwait(false); var botLogin = await botLoginTask.ConfigureAwait(false); await Task.WhenAll( reviews.Where( x => x.User.Id == botLogin.Id && x.State.Value == PullRequestReviewState.Approved ).Select( x => gitHubManager.DismissReview(pullRequest, x, message) )).ConfigureAwait(false); }
/// <inheritdoc /> public async Task <AutoMergeStatus> EvaluateFor(PullRequest pullRequest, CancellationToken cancellationToken) { if (gitHubManager == null) { throw new InvalidOperationException("Configure() wasn't called!"); } var reviews = await gitHubManager.GetPullRequestReviews(pullRequest).ConfigureAwait(false); var approvers = new List <User>(); var critics = new List <User>(); var userCheckups = new Dictionary <string, Task <bool> >(); foreach (var I in reviews) { void CheckupUser() { if (!userCheckups.ContainsKey(I.User.Login)) { userCheckups.Add(I.User.Login, gitHubManager.UserHasWriteAccess(I.User)); } } if (I.State.Value == PullRequestReviewState.Approved) { critics.RemoveAll(x => x.Id == I.User.Id); approvers.Add(I.User); CheckupUser(); } else if (I.State.Value == PullRequestReviewState.ChangesRequested) { approvers.RemoveAll(x => x.Id == I.User.Id); critics.Add(I.User); CheckupUser(); } } var result = new AutoMergeStatus(); await Task.WhenAll(userCheckups.Select(x => x.Value)).ConfigureAwait(false); foreach (var I in approvers) { if (!userCheckups[I.Login].Result) { continue; } ++result.Progress; result.Notes.Add(stringLocalizer["ApprovedBy", I.Login]); } if (result.Progress == 0) { result.Notes.Add(stringLocalizer["NoApproval"]); } result.RequiredProgress = result.Progress; foreach (var I in critics) { if (!userCheckups[I.Login].Result) { continue; } ++result.RequiredProgress; result.Notes.Add(stringLocalizer["RequestedChanges", I.Login]); } result.RequiredProgress = Math.Max(result.RequiredProgress, 1); return(result); }