// creates a new pr to the target branch after the old pr is merged public async Task CreateNewPR(MergeData data) { var client = await GetInstallationClientAsync(data.InstallationId); // check that the pr went through first var mergedPR = await client.PullRequest.Get(data.RepositoryOwner, data.RepositoryName, data.PullRequestNumber); if (!mergedPR.Merged) { log.LogError("The pull request was not merged yet."); return; } var sourceBranch = mergedPR.Base.Ref; // this could? be a commit hash too var pr = new NewPullRequest($"AutoMerge: {sourceBranch} to {data.BranchName} by @{data.MergeIssuer}", sourceBranch, data.BranchName); log.LogInformation($"Creating new PR: {sourceBranch} to {data.BranchName}"); var result = await client.PullRequest.Create(data.RepositoryOwner, data.RepositoryName, pr); // assign ownership log.LogInformation($"Created PR {result.Number}. Assigning ownership to {data.MergeIssuer}"); var reviewReq = new PullRequestReviewRequest(new List <string> { data.MergeIssuer }); await client.PullRequest.ReviewRequest.Create(data.RepositoryOwner, data.RepositoryName, result.Number, reviewReq); // TODO handle invalid BranchName log.LogInformation("Leaving a comment on closed PR."); // leave a comment on the merged PR var comment = $"Ok @{data.MergeIssuer}, I've created Pull Request #{result.Number} for you that merges `{sourceBranch}` into `{data.BranchName}`."; await client.Issue.Comment.Create(data.RepositoryOwner, data.RepositoryName, data.PullRequestNumber, comment); }
public static async Task Run([QueueTrigger("scheduledprsqueue", Connection = "AzureWebJobsStorage")] string myQueueItem, ILogger log) { MergeData mdQueueObject = Newtonsoft.Json.JsonConvert.DeserializeObject <MergeData>(myQueueItem); log.LogInformation($"Queue trigger function processed: Merge time " + mdQueueObject.MergeTime + " and branch name " + mdQueueObject.BranchName); // this env var should have an xml body containing an RSA key var xmlGHPrivateKey = Environment.GetEnvironmentVariable("GitHubPrivateKey"); var handler = new GitHubEventHandlers(log, xmlGHPrivateKey, GitHubWebhook.AppId); try { await handler.PassMergeAsync(mdQueueObject); await handler.MergePRAsync(mdQueueObject); if (!string.IsNullOrWhiteSpace(mdQueueObject.BranchName)) { // branchname specified, then create new PR from this PR's dest to the specified dest await handler.CreateNewPR(mdQueueObject); } } catch (Exception e) { log.LogInformation(e, "Caught exception when handling queue item."); } }
public async Task AckAddToQueueAsync(MergeData data) { var client = await GetInstallationClientAsync(data.InstallationId); log.LogInformation($"ACKing to PR comment {data.RepositoryOwner}/{data.RepositoryName}#{data.PullRequestNumber}"); var message = $"Ok @{data.MergeIssuer} , I'll merge this Pull Request at `{data.MergeTime}` UTC + about 5 minutes. (Currently it's `{DateTime.UtcNow}` UTC.)"; await client.Issue.Comment.Create(data.RepositoryOwner, data.RepositoryName, data.PullRequestNumber, message); }
// gets the rest of merge data from one that was created from a tag or PR comment/body private static MergeData GetMergeData(this MergeData fromBody, WebhookPayload payload) { if (fromBody == null) { return(null); // silently fail } fromBody.RepositoryOwner = payload.Repository.Owner.Login; fromBody.RepositoryName = payload.Repository.Name; fromBody.PullRequestNumber = payload.PullRequest?.Number ?? payload.Issue?.Number ?? -1; fromBody.PullRequestAuthor = payload.PullRequest?.User?.Login; fromBody.MergeIssuer = payload.Sender?.Login; fromBody.InstallationId = payload.Installation?.Id ?? 0; return(fromBody); }
public async Task PassMergeAsync(MergeData data) { var client = await GetInstallationClientAsync(data.InstallationId); var pr = await client.PullRequest.Get(data.RepositoryOwner, data.RepositoryName, data.PullRequestNumber); var prHead = pr.Head; var checkRun = new NewCheckRun($"PublishingScheduler Auto-Merge", prHead.Ref); checkRun.Status = CheckStatus.Completed; checkRun.Conclusion = CheckConclusion.Success; checkRun.Output = new NewCheckRunOutput($"{data.MergeTime} UTC", $"An auto-merge is scheduled for {data.MergeTime} UTC."); await client.Check.Run.Create(data.RepositoryOwner, data.RepositoryName, checkRun); }
private static string InsertMessageToQueue(CloudQueue cQueueToInsert, MergeData mdMessageData, TimeSpan tsTimeToExecute) { // AddMessage has no return value, so failure will only show as exception try { // prep object and add to queue string sMessageDataJson = JsonConvert.SerializeObject(mdMessageData); CloudQueueMessage cqMessage = new CloudQueueMessage(sMessageDataJson); cQueueToInsert.AddMessage(cqMessage, null, tsTimeToExecute, null, null); string sResult = "Message : " + Environment.NewLine + sMessageDataJson + Environment.NewLine + " ---- for " + cqMessage.Id + " inserted into queue."; return(sResult); } catch (Exception eThrownException) { return(eThrownException.Message); } }
public async Task MergePRAsync(MergeData data) { var client = await GetInstallationClientAsync(data.InstallationId); log.LogInformation($"Merging Pull Request: {data.RepositoryOwner}/{data.RepositoryName}#{data.PullRequestNumber}"); var x = await client.PullRequest.Get(data.RepositoryOwner, data.RepositoryName, data.PullRequestNumber); log.LogInformation($"PR #{data.PullRequestNumber} mergeable status {x.Mergeable} {x.State}"); // check requester association var valid = new List <string>() { "MEMBER", "COLLABORATOR", "OWNER" }; if (!valid.Contains(data.RequesterAssociation)) { // user is not allowed to do this await client.Issue.Comment.Create(data.RepositoryOwner, data.RepositoryName, data.PullRequestNumber, $"Auto-merge blocked, user @{data.MergeIssuer} ({data.RequesterAssociation}) does not have the association required to merge."); return; } if (x.Mergeable == false) { await client.Issue.Comment.Create(data.RepositoryOwner, data.RepositoryName, data.PullRequestNumber, $"Auto-merge blocked by unmergeable state. @{data.MergeIssuer}, please resolve this and merge manually."); } else { await client.PullRequest.Merge(data.RepositoryOwner, data.RepositoryName, data.PullRequestNumber, new MergePullRequest() { // AutoMerge #123 from Chris-Johnston: Implement the thing and solve world hunger CommitTitle = $"AutoMerge #{data.PullRequestNumber} from {data.MergeIssuer}: {x.Title}", MergeMethod = PullRequestMergeMethod.Squash, // HACK: need to check which merge methods are allowed by the repo and pick one that will work. }); } }