protected override async Task <EventHandlerResult> execute(IssueCommentPayload webhookPayload, RepositorySettings repoSettings) { if (webhookPayload.Issue == null) { return(EventHandlerResult.PayloadError("no issue information in webhook payload")); } if (repoSettings.CommentProtection == null || !repoSettings.CommentProtection.Enabled) { return(EventHandlerResult.Disabled()); } if (webhookPayload.Action.Equals("edited", StringComparison.OrdinalIgnoreCase) || webhookPayload.Action.Equals("deleted", StringComparison.OrdinalIgnoreCase)) { if (webhookPayload.Sender != null && webhookPayload.Comment?.User != null && webhookPayload.Sender.Login == webhookPayload.Comment.User.Login) { return(EventHandlerResult.NoActionNeeded($"comment action {webhookPayload.Action} by {webhookPayload.Sender.Login} allowed, referencing own comment")); } else { await GitHubClient.Issue.Comment.Create(webhookPayload.Repository.Id, webhookPayload.Issue.Number, getWarningText(repoSettings.CommentProtection)); return(EventHandlerResult.ActionPerformed("comment action resulting in warning")); } } return(EventHandlerResult.EventNotOfInterest(webhookPayload.Action)); }
protected override async Task <EventHandlerResult> executeCore(WorkflowRunEventPayload webhookPayload) { if (webhookPayload.Action.Equals("completed", StringComparison.OrdinalIgnoreCase)) { if (string.IsNullOrEmpty(webhookPayload.Sender?.Login)) { return(EventHandlerResult.PayloadError("missing actor user")); } if (await isUserOrganizationMember(webhookPayload, webhookPayload.Sender.Login)) { return(EventHandlerResult.NoActionNeeded("workflow_run ok, not triggered by student")); } var workflowRuns = await GitHubClient.CountWorkflowRunsInRepository(webhookPayload.Repository.Owner.Login, webhookPayload.Repository.Name, webhookPayload.Sender.Login); if (workflowRuns <= WorkflowRunThreshold) { return(EventHandlerResult.NoActionNeeded("workflow_run ok, has less then threshold")); } var prNum = await getMostRecentPullRequest(webhookPayload); if (prNum.HasValue) { await GitHubClient.Issue.Comment.Create(webhookPayload.Repository.Id, prNum.Value, WarningText); } return(EventHandlerResult.ActionPerformed("workflow_run warning, threshold exceeded")); } return(EventHandlerResult.EventNotOfInterest(webhookPayload.Action)); }
protected override async Task <EventHandlerResult> execute(PullRequestEventPayload webhookPayload, RepositorySettings repoSettings) { if (webhookPayload.PullRequest == null) { return(EventHandlerResult.PayloadError("no pull request information in webhook payload")); } if (repoSettings.ReviewerToAssignee == null || !repoSettings.ReviewerToAssignee.Enabled) { return(EventHandlerResult.Disabled()); } if (webhookPayload.Action.Equals("review_requested", StringComparison.OrdinalIgnoreCase)) { if (webhookPayload.PullRequest.RequestedReviewers == null || webhookPayload.PullRequest.RequestedReviewers.Count == 0) { return(EventHandlerResult.PayloadError("no requested reviewer in webhook payload")); } else if (!isPrAssignedToReviewer(webhookPayload)) { await GitHubClient.Issue.Assignee.AddAssignees(webhookPayload.Repository.Owner.Login, webhookPayload.Repository.Name, webhookPayload.PullRequest.Number, getUsersToAssign(webhookPayload)); return(EventHandlerResult.ActionPerformed("pull request review_requested handled, assignee set")); } else { return(EventHandlerResult.NoActionNeeded("pull request review_requested is ok, assignee is present")); } } return(EventHandlerResult.EventNotOfInterest(webhookPayload.Action)); }
private async Task <(RepositorySettings, EventHandlerResult)> tryGetRepositorySettings(TPayload webhookPayload, string organizationLogin) { try { var contents = await GitHubClient.Repository.Content.GetAllContents(organizationLogin, "ahk-monitor-config", "ahk-monitor.yml") ?? await GitHubClient.Repository.Content.GetAllContentsByRef(webhookPayload.Repository.Id, ".github/ahk-monitor.yml", webhookPayload.Repository.DefaultBranch); var settingsString = contents?.FirstOrDefault()?.Content; if (settingsString == null) { return(null, EventHandlerResult.Disabled("repository has no ahk-monitor.yml")); } try { return(YamlDeserializer.Deserialize <RepositorySettings>(settingsString), null); } catch (Exception ex) { return(null, EventHandlerResult.PayloadError("Config yaml parse error: " + ex.Message)); } } catch (NotFoundException) { return(null, EventHandlerResult.Disabled("repository has no ahk-monitor.yml")); } }
protected override async Task <EventHandlerResult> executeCore(PullRequestEventPayload webhookPayload) { if (webhookPayload.PullRequest == null) { return(EventHandlerResult.PayloadError("no pull request information in webhook payload")); } if (webhookPayload.Action.Equals("opened", StringComparison.OrdinalIgnoreCase)) { var repositoryPrs = await getAllRepoPullRequests(webhookPayload); if (repositoryPrs.Count <= 1) { return(EventHandlerResult.NoActionNeeded("pull request open is ok, there are no other PRs")); } else { var(handledOpen, resultOpen) = await handleAnyOpenPrs(webhookPayload, repositoryPrs); var(handledClosed, resultClosed) = await handleAnyClosedPrs(webhookPayload, repositoryPrs); if (!handledOpen && !handledClosed) { return(EventHandlerResult.NoActionNeeded($"{resultOpen}; {resultClosed}")); } else { return(EventHandlerResult.ActionPerformed($"{resultOpen}; {resultClosed}")); } } } return(EventHandlerResult.EventNotOfInterest(webhookPayload.Action)); }
private async Task <EventHandlerResult> OkCommandExecute(string commentContents, IssueCommentPayload payload) { var merge = new MergePullRequest(); merge.CommitTitle = $"merged PR via +ok: #{payload.Issue.Number} {payload.Issue.Title}"; var result = await GitHubClient.PullRequest.Merge(payload.Repository.Id, payload.Issue.Number, merge); return(result.Merged ? EventHandlerResult.ActionPerformed( $"merged pull request #{payload.Issue.Number} {payload.Issue.Title}") : EventHandlerResult.PayloadError( $"failed to merge pull request ${payload.Issue.Number} {payload.Issue.Title}")); }
protected override async Task <EventHandlerResult> executeCore(PullRequestReviewEventPayload webhookPayload) { if (webhookPayload.Review == null) { return(EventHandlerResult.PayloadError("no review information in webhook payload")); } if (webhookPayload.Action.Equals("submitted", StringComparison.OrdinalIgnoreCase)) { return(await processComment(new ReviewCommentPayloadFacade(webhookPayload))); } return(EventHandlerResult.EventNotOfInterest(webhookPayload.Action)); }
protected override async Task <EventHandlerResult> executeCore(IssueCommentPayload webhookPayload) { if (webhookPayload.Issue == null) { return(EventHandlerResult.PayloadError("no issue information in webhook payload")); } if (webhookPayload.Action.Equals("created", StringComparison.OrdinalIgnoreCase)) { return(await processComment(new IssueCommentPayloadFacade(webhookPayload))); } return(EventHandlerResult.EventNotOfInterest(webhookPayload.Action)); }
protected bool tryParsePayload(string requestBody, out TPayload payload, out EventHandlerResult errorResult, out string organizationLogin) { payload = null; organizationLogin = null; if (string.IsNullOrEmpty(requestBody)) { errorResult = EventHandlerResult.PayloadError("request body was empty"); return(false); } try { payload = new SimpleJsonSerializer().Deserialize <TPayload>(requestBody); } catch (Exception ex) { errorResult = EventHandlerResult.PayloadError($"request body deserialization failed: {ex.Message}"); return(false); } if (payload == null) { errorResult = EventHandlerResult.PayloadError("parsed payload was null or empty"); return(false); } if (payload.Repository == null) { errorResult = EventHandlerResult.PayloadError("no repository information in webhook payload"); return(false); } try { var jsonobj = JsonDocument.Parse(requestBody); organizationLogin = jsonobj.RootElement.GetProperty("organization").GetProperty("login").GetString(); } catch (Exception) { errorResult = EventHandlerResult.PayloadError($"no organization info in webhook payload"); return(false); } errorResult = null; return(true); }
protected override async Task <EventHandlerResult> execute(IssueCommentPayload webhookPayload, RepositorySettings repoSettings) { if (webhookPayload.Issue == null) { return(EventHandlerResult.PayloadError("no issue information in webhook payload")); } if (repoSettings.PullRequestCommentCommand == null || !repoSettings.PullRequestCommentCommand.Enabled) { return(EventHandlerResult.Disabled()); } if (!webhookPayload.Action.Equals("created", StringComparison.OrdinalIgnoreCase)) { return(EventHandlerResult.EventNotOfInterest(webhookPayload.Action)); } var contents = webhookPayload.Comment.Body; if (!contents.StartsWith('+')) { return(EventHandlerResult.NoActionNeeded("comment is not a command")); } var endOfWord = contents.IndexOf(' '); var potentialCommand = endOfWord >= 0 ? contents.Substring(1, contents.IndexOf(' ') - 1) : contents.Substring(1); if (!commands.ContainsKey(potentialCommand)) { return(EventHandlerResult.NoActionNeeded($"invalid command: +{potentialCommand}")); } if (!await commands[potentialCommand].checkPermission(webhookPayload)) { return(EventHandlerResult.PayloadError($"{webhookPayload.Comment.User.Login} is not allowed to execute the command: {contents}")); } return(await commands[potentialCommand].execute(contents, webhookPayload)); }
protected bool tryParsePayload(string requestBody, out TPayload payload, out EventHandlerResult errorResult) { payload = null; if (string.IsNullOrEmpty(requestBody)) { errorResult = EventHandlerResult.PayloadError("request body was empty"); Logger.LogError("request body was empty"); return(false); } try { payload = new SimpleJsonSerializer().Deserialize <TPayload>(requestBody); } catch (Exception ex) { errorResult = EventHandlerResult.PayloadError($"request body deserialization failed: {ex.Message}"); Logger.LogError(ex, "request body deserialization failed"); return(false); } if (payload == null) { errorResult = EventHandlerResult.PayloadError("parsed payload was null or empty"); Logger.LogError("parsed payload was null or empty"); return(false); } if (payload.Repository == null) { errorResult = EventHandlerResult.PayloadError("no repository information in webhook payload"); Logger.LogError("no repository information in webhook payload"); return(false); } errorResult = null; return(true); }