private async Task <QuantifierResult> QuantifyPullRequest(PullRequestEventPayload payload) { var gitHubClientAdapter = await gitHubClientAdapterFactory.GetGitHubClientAdapterAsync( payload.Installation.Id, new Uri(payload.PullRequest.HtmlUrl).DnsSafeHost); var quantifierInput = await GetQuantifierInputFromPullRequest(payload, gitHubClientAdapter); var context = await GetContextFromRepoIfPresent(payload, gitHubClientAdapter); var quantifyClient = new QuantifyClient(context); var quantifierClientResult = await quantifyClient.Compute(quantifierInput); await ApplyLabelToPullRequest( payload, gitHubClientAdapter, quantifierClientResult, quantifyClient.Context.Thresholds.Select(t => t.Label)); var quantifierContextLink = !string.IsNullOrWhiteSpace(context) ? $"{payload.Repository.HtmlUrl}/blob/{payload.Repository.DefaultBranch}/prquantifier.yaml" : string.Empty; await UpdateCommentOnPullRequest( payload, gitHubClientAdapter, quantifierClientResult, quantifierContextLink); return(quantifierClientResult); }
public PullRequestContext(string repositoryName, PullRequestEventPayload payload, IConnection githubConnection, ILogger logger) { RepositoryName = repositoryName; Payload = payload; GithubConnection = githubConnection; Logger = logger; }
private async Task UpdateCommentOnPullRequest( PullRequestEventPayload payload, IGitHubClientAdapter gitHubClientAdapter, QuantifierResult quantifierClientResult, string quantifierContextLink) { // delete existing comments created by us var existingComments = await gitHubClientAdapter.GetIssueCommentsAsync(payload.Repository.Id, payload.PullRequest.Number); var existingCommentsCreatedByUs = existingComments.Where( ec => ec.User.Login.Equals($"{gitHubClientAdapter.GitHubAppSettings.Name}[bot]")); foreach (var existingComment in existingCommentsCreatedByUs) { await gitHubClientAdapter.DeleteIssueCommentAsync(payload.Repository.Id, existingComment.Id); } // create a new comment on the issue var comment = await quantifierClientResult.ToMarkdownCommentAsync( payload.Repository.HtmlUrl, quantifierContextLink, payload.PullRequest.HtmlUrl, payload.PullRequest.User.Login, ShouldPostAnonymousFeedbackLink(payload), new MarkdownCommentOptions { CollapsePullRequestQuantifiedSection = true }); await gitHubClientAdapter.CreateIssueCommentAsync( payload.Repository.Id, payload.PullRequest.Number, comment); }
/// <inheritdoc /> public void ProcessPayload(PullRequestEventPayload payload) { if ((payload.Action != "opened" && payload.Action != "synchronize") || payload.PullRequest.State.Value != ItemState.Open) { return; } backgroundJobClient.Enqueue(() => ScanPullRequest(payload.Repository.Id, payload.PullRequest.Number, payload.Installation.Id, JobCancellationToken.Null)); }
/// <inheritdoc /> public Task ProcessPayload(PullRequestEventPayload payload, CancellationToken cancellationToken) { if (payload == null) { throw new ArgumentNullException(nameof(payload)); } return(CheckMergePullRequest(payload.PullRequest.Number, cancellationToken)); }
/// <inheritdoc /> public async Task ProcessPayload(PullRequestEventPayload payload, CancellationToken cancellationToken) { if (payload == null) { throw new ArgumentNullException(nameof(payload)); } await CheckMergePullRequest(payload.PullRequest, cancellationToken).ConfigureAwait(false); }
public CheckSuiteRequestHandler(PullRequestEventPayload payload, IPrivateKeySource keySource, Guid requestId) { GithubInstallationId = payload.Installation.Id; CurrentRepository = payload.Repository; CommitSha = payload.PullRequest.Head.Sha; IsPullRequest = true; RequestId = requestId; Init(keySource); }
private async Task ApplyLabelToPullRequest( PullRequestEventPayload payload, IGitHubClientAdapter gitHubClientAdapter, QuantifierResult quantifierClientResult, IEnumerable <string> labelOptionsFromContext) { // create a new label in the repository if doesn't exist try { var existingLabel = await gitHubClientAdapter.GetLabelAsync( payload.Repository.Id, quantifierClientResult.Label); } catch (NotFoundException) { // create new label var color = Color.FromName(quantifierClientResult.Color); await gitHubClientAdapter.CreateLabelAsync( payload.Repository.Id, new NewLabel(quantifierClientResult.Label, ConvertToHex(color))); } // remove any previous labels applied if it's different // labels do not have the property of who applied them // so we use string matching against the label options present in the context // if label strings have changed in context since last PR update, this will break var existingLabels = await gitHubClientAdapter.GetIssueLabelsAsync(payload.Repository.Id, payload.PullRequest.Number); var existingLabelsByUs = existingLabels.Select(el => el.Name).Intersect(labelOptionsFromContext).ToList(); foreach (var existingLabel in existingLabelsByUs) { if (existingLabel == quantifierClientResult.Label) { continue; } await gitHubClientAdapter.RemoveLabelFromIssueAsync( payload.Repository.Id, payload.PullRequest.Number, existingLabel); } // apply new label to pull request await gitHubClientAdapter.ApplyLabelAsync( payload.Repository.Id, payload.PullRequest.Number, new[] { quantifierClientResult.Label }); }
private async Task <QuantifierInput> GetQuantifierInputFromPullRequest(PullRequestEventPayload payload, IGitHubClientAdapter gitHubClientAdapter) { // get pull request files var pullRequestFiles = await gitHubClientAdapter.GetPullRequestFilesAsync( payload.Repository.Id, payload.PullRequest.Number); // convert to quantifier input var quantifierInput = new QuantifierInput(); foreach (var pullRequestFile in pullRequestFiles) { if (pullRequestFile.Patch == null) { continue; } var changeType = GitChangeType.Modified; switch (pullRequestFile.Status) { case "modified": break; case "added": changeType = GitChangeType.Added; break; case "deleted": changeType = GitChangeType.Deleted; break; } var fileExtension = !string.IsNullOrWhiteSpace(pullRequestFile.FileName) ? new FileInfo(pullRequestFile.FileName).Extension : string.Empty; var gitFilePatch = new GitFilePatch( pullRequestFile.FileName, fileExtension) { ChangeType = changeType, AbsoluteLinesAdded = pullRequestFile.Additions, AbsoluteLinesDeleted = pullRequestFile.Deletions, DiffContent = pullRequestFile.Patch, }; quantifierInput.Changes.Add(gitFilePatch); } return(quantifierInput); }
private async Task <string> GetContextFromRepoIfPresent(PullRequestEventPayload payload, IGitHubClientAdapter gitHubClientAdapter) { // get context if present string context = null; try { var rawContext = await gitHubClientAdapter.GetRawFileAsync( payload.Repository.Owner.Login, payload.Repository.Name, "/prquantifier.yaml"); context = Encoding.UTF8.GetString(rawContext); } catch (NotFoundException) { } catch { // ignored } return(context); }
private async Task <QuantifierResult> QuantifyPullRequest(PullRequestEventPayload payload) { var gitHubClientAdapter = await gitHubClientAdapterFactory.GetGitHubClientAdapterAsync( payload.Installation.Id, new Uri(payload.PullRequest.HtmlUrl).DnsSafeHost); // get pull request var pullRequest = await gitHubClientAdapter.GetPullRequestAsync( payload.Repository.Id, payload.PullRequest.Number); // get pull request files var pullRequestFiles = await gitHubClientAdapter.GetPullRequestFilesAsync( payload.Repository.Id, payload.PullRequest.Number); // convert to quantifier input var quantifierInput = new QuantifierInput(); foreach (var pullRequestFile in pullRequestFiles) { if (pullRequestFile.Patch == null) { continue; } var changeType = GitChangeType.Modified; switch (pullRequestFile.Status) { case "modified": break; case "added": changeType = GitChangeType.Added; break; case "deleted": changeType = GitChangeType.Deleted; break; } var fileExtension = !string.IsNullOrWhiteSpace(pullRequestFile.FileName) ? new FileInfo(pullRequestFile.FileName).Extension : string.Empty; var gitFilePatch = new GitFilePatch( pullRequestFile.FileName, fileExtension) { ChangeType = changeType, AbsoluteLinesAdded = pullRequestFile.Additions, AbsoluteLinesDeleted = pullRequestFile.Deletions, DiffContent = pullRequestFile.Patch, }; quantifierInput.Changes.Add(gitFilePatch); } // get context if present string context = null; try { var rawContext = await gitHubClientAdapter.GetRawFileAsync( payload.Repository.Owner.Login, payload.Repository.Name, "/prquantifier.yaml"); context = Encoding.UTF8.GetString(rawContext); } catch (NotFoundException) { } catch { // ignored } var quantifyClient = new QuantifyClient(context); var quantifierClientResult = await quantifyClient.Compute(quantifierInput); // create a new label in the repository if doesn't exist try { var existingLabel = await gitHubClientAdapter.GetLabelAsync( payload.Repository.Id, quantifierClientResult.Label); } catch (NotFoundException) { // create new label var color = Color.FromName(quantifierClientResult.Color); await gitHubClientAdapter.CreateLabelAsync( payload.Repository.Id, new NewLabel(quantifierClientResult.Label, ConvertToHex(color))); } // apply label to pull request await gitHubClientAdapter.ApplyLabelAsync( payload.Repository.Id, payload.PullRequest.Number, new[] { quantifierClientResult.Label }); // create a comment on the issue var defaultBranch = payload.Repository.DefaultBranch; var quantifierContextLink = $"{payload.Repository.HtmlUrl}/blob/{defaultBranch}/prquantifier.yaml"; var comment = await quantifierClientResult.ToMarkdownCommentAsync( payload.Repository.HtmlUrl, quantifierContextLink, payload.PullRequest.HtmlUrl, payload.PullRequest.User.Login); await gitHubClientAdapter.CreateIssueCommentAsync( payload.Repository.Id, payload.PullRequest.Number, comment); return(quantifierClientResult); }
/// <summary> /// Page has been loaded - called by GitHub when a pull request is opened, merged or closed. /// </summary> /// <param name="sender"></param> /// <param name="e"></param> protected void Page_Load(object sender, EventArgs e) { string json = GetJsonFromInputStream(); if (string.IsNullOrWhiteSpace(json)) { Response.StatusCode = 200; return; } SimpleJsonSerializer octokitSerialiser = new SimpleJsonSerializer(); PullRequestEventPayload payload = octokitSerialiser.Deserialize <PullRequestEventPayload>(json); if (payload == null || payload.PullRequest == null) { ShowMessage("Cannot find pull request in GitHub JSON."); Response.StatusCode = 400; // Bad request } else if (!payload.PullRequest.Merged) { ShowMessage("Pull request not merged - ignored"); } else if (payload.PullRequest.GetIssueID() == -1) { ShowMessage("Pull request doesn't reference an issue."); } else if (payload.Repository.Owner.Login == "APSIMInitiative") { if (payload.Repository.Name == "ApsimX") { // If an ApsimX Pull Request has been merged, start a CreateInstallation job on Jenkins. string issueNumber = payload.PullRequest.GetIssueID().ToString(); string pullId = payload.PullRequest.Number.ToString(); string author = payload.PullRequest.User.Login; string token = GetJenkinsToken(); string issueTitle = payload.PullRequest.GetIssueTitle("APSIMInitiative", "ApsimX"); bool released = payload.PullRequest.FixesAnIssue(); string mergeCommit = payload.PullRequest.MergeCommitSha; string jenkinsUrl = $"https://jenkins.apsim.info/job/apsim-release/buildWithParameters?token={token}&ISSUE_NUMBER={issueNumber}&PULL_ID={pullId}&COMMIT_AUTHOR={author}&ISSUE_TITLE={issueTitle}&RELEASED={released}&MERGE_COMMIT={mergeCommit}"; if (released) { WebUtilities.CallRESTService <object>(jenkinsUrl); ShowMessage(string.Format("Triggered a deploy step for {0}'s pull request {1} - {2}", author, pullId, payload.PullRequest.Title)); } else { ShowMessage($"No release will be generated {author}'s pull request #{pullId} - {payload.PullRequest.Title} as it doesn't resolve an issue"); } } else if (payload.Repository.Name == "APSIMClassic") { // If an APSIM Classic Pull Request has been created, and it fixes an issue, start a ReleaseClassic job on Jenkins string pullId = payload.PullRequest.Number.ToString(); string author = payload.PullRequest.User.Login; if (payload.PullRequest.FixesAnIssue()) { string token = GetJenkinsReleaseClassicToken(); string sha = payload.PullRequest.MergeCommitSha; string jenkinsUrl = $"http://apsimdev.apsim.info:8080/jenkins/job/ReleaseClassic/buildWithParameters?token={token}&PULL_ID={pullId}&SHA1={sha}"; WebUtilities.CallRESTService <object>(jenkinsUrl); ShowMessage($"Triggered a deploy step for {author}'s pull request #{pullId} - {payload.PullRequest.Title}"); } else { ShowMessage($"No release will be generated {author}'s pull request #{pullId} - {payload.PullRequest.Title} as it doesn't resolve an issue"); } } } }
public ActionResult Default() { string actionName = Request.Headers.Get("X-GITHUB-EVENT"); // Only the below events will be handled if (!actionName.Equals("check_suite", StringComparison.InvariantCultureIgnoreCase) && !actionName.Equals("check_run", StringComparison.InvariantCultureIgnoreCase) && !actionName.Equals("pull_request", StringComparison.InvariantCultureIgnoreCase)) { return(new HttpStatusCodeResult(200)); } // Obtain the body signature string messageSignature = Request.Headers.Get("X-HUB-Signature"); if (string.IsNullOrEmpty(messageSignature)) { return(new HttpStatusCodeResult(400)); } // Read the body string body = GetRequestPostData(Request); // Validate message integrity if (!RequestPayloadHelper.ValidateSender(body, messageSignature, GitScanAppConfig.GetValue(Constants.GlobalSection, Constants.GitHubAppWebhookSecretKey))) { return(new HttpStatusCodeResult(400)); } Guid requestId = Guid.NewGuid(); if (actionName.Equals("check_run", StringComparison.InvariantCultureIgnoreCase)) { CheckRunEventPayload checkRunPayload = RequestPayloadHelper.Parse <CheckRunEventPayload>(body); if (checkRunPayload.Action.Equals("rerequested", StringComparison.InvariantCultureIgnoreCase)) { CheckSuiteRequestHandler handler = new CheckSuiteRequestHandler(checkRunPayload, PrivateKeySource.Value, requestId); handler.Go(); return(new HttpStatusCodeResult(200)); } else { return(new HttpStatusCodeResult(200)); } } if (actionName.Equals("pull_request", StringComparison.InvariantCultureIgnoreCase)) { PullRequestEventPayload pullPayload = RequestPayloadHelper.Parse <PullRequestEventPayload>(body); if (pullPayload.Action.Equals("opened", StringComparison.InvariantCultureIgnoreCase)) { CheckSuiteRequestHandler handler = new CheckSuiteRequestHandler(pullPayload, PrivateKeySource.Value, requestId); handler.Go().Wait(); return(new HttpStatusCodeResult(200)); } else { return(new HttpStatusCodeResult(200)); } } CheckSuiteEventPayload payload = RequestPayloadHelper.Parse(body); if (!payload.Action.Equals("rerequested", StringComparison.OrdinalIgnoreCase) && (payload.CheckSuite.PullRequests == null || payload.CheckSuite.PullRequests.Count == 0)) { return(new HttpStatusCodeResult(200)); } if (!payload.Action.Equals("completed", StringComparison.OrdinalIgnoreCase)) { CheckSuiteRequestHandler handler = new CheckSuiteRequestHandler(payload, PrivateKeySource.Value, requestId); handler.Go(); } return(new HttpStatusCodeResult(200)); }
public PullRequestContext(PullRequestEventPayload payload, IConnection githubConnection, ILogger logger) { Payload = payload; GithubConnection = githubConnection; Logger = logger; }
// only post anonymous feedback link in case of github.com flavor private bool ShouldPostAnonymousFeedbackLink(PullRequestEventPayload payload) { return(new Uri(payload.PullRequest.HtmlUrl).DnsSafeHost.Equals("github.com")); }