-
-
Save arunsathiya/3aa25480319df50566bf95b4629baef8 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# (c) 2020 Humu | |
# MIT License | |
from typing import Any | |
import github | |
AUTOMERGE_LABEL_NAME = 'automerge' | |
class Automerge: | |
def __init__(self, githubClient: github.Github) -> None: | |
self._github = githubClient | |
def _hasAutomergeLabel(self, pr: github.PullRequest.PullRequest) -> bool: | |
return any(label.name == AUTOMERGE_LABEL_NAME for label in pr.labels) | |
def processWebhookEvent(self, eventType: str, eventJson: Any) -> None: | |
# If a PR becomes green, merge it. | |
# If new commits are pushed, a PR check fails, or the PR is closed, remove the label. | |
if eventType == 'status': | |
# https://developer.github.com/v3/activity/events/types/#statusevent | |
repo = self._github.create_from_raw_data( | |
github.Repository.Repository, eventJson['repository'] | |
) | |
commit = self._github.create_from_raw_data(github.Commit.Commit, eventJson['commit']) | |
# Shockingly, GitHub gives no way to get the PR associated with a 'status' event. You | |
# need to search the list of PRs. | |
matchingPr = next( | |
(pr for pr in repo.get_pulls(sort='updated') if pr.head.sha == commit.sha), None | |
) | |
if matchingPr and self._hasAutomergeLabel(matchingPr): | |
# Clean means green, unstable means yellow, which happens often with Reviewable, | |
# for whatever reason. (If the PR is not accepted or one of our required checks is | |
# failing, it'll be 'blocked'.) | |
# https://developer.github.com/v4/enum/mergestatestatus/ | |
if matchingPr.mergeable_state in ('clean', 'unstable'): | |
matchingPr.merge(merge_method='squash') | |
# If a check fails, we leave the label so that if it's a flaky test it can be rerun. | |
# (If a test fails due to a code issue and new commits are pushed as a fix, the | |
# label will be removed due to the 'synchronize' below.) | |
elif eventType == 'pull_request': | |
# https://developer.github.com/v3/activity/events/types/#pullrequestevent | |
pr = self._github.create_from_raw_data( | |
github.PullRequest.PullRequest, eventJson['pull_request'] | |
) | |
if self._hasAutomergeLabel(pr): | |
# 'synchonize' means new commits were pushed | |
if eventJson['action'] == 'synchronize' or ( | |
eventJson['action'] == 'closed' and not pr.merged | |
): | |
pr.remove_from_labels(AUTOMERGE_LABEL_NAME) | |
elif eventType == 'pull_request_review': | |
# https://developer.github.com/v3/activity/events/types/#pullrequestreviewevent | |
pr = self._github.create_from_raw_data( | |
github.PullRequest.PullRequest, eventJson['pull_request'] | |
) | |
review = self._github.create_from_raw_data( | |
github.PullRequestReview.PullRequestReview, eventJson['review'] | |
) | |
# Some API docs have 'state' values capitalized, some lowercase. Why? Don't know. | |
if eventJson['action'] == 'submitted' and review.state.lower() == 'changes_requested': | |
if self._hasAutomergeLabel(pr): | |
pr.remove_from_labels(AUTOMERGE_LABEL_NAME) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment