Created
April 15, 2020 19:51
-
-
Save sophiebits-humu/d38ec7508f89338e7ac45cb0f33f9217 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