Skip to content

Instantly share code, notes, and snippets.

@craigcabrey
Last active March 18, 2016 02:39
Show Gist options
  • Save craigcabrey/c3a4990d70f5d16deb76 to your computer and use it in GitHub Desktop.
Save craigcabrey/c3a4990d70f5d16deb76 to your computer and use it in GitHub Desktop.
#!/usr/bin/env python3
import functools
import git
import github
import tempfile
import textwrap
changes_requested_label = 'changes requested'
merge_label = 'ready to merge'
rebase_label = 'needs rebase'
review_label = 'needs review'
repo_url = ''
github_repo = ''
token = ''
def merge(target_branch, default_branch='develop'):
with tempfile.TemporaryDirectory() as temp_dir:
repo = git.Repo.clone_from(repo_url, temp_dir)
origin = repo.remotes[0]
try:
repo.git.rebase('{0}/{1}'.format(origin.name, target_branch))
origin.push('refs/heads/{0}:refs/heads/{0}'.format(default_branch))
origin.push(':refs/heads/{0}'.format(target_branch))
return True
except git.GitCommandError:
return False
def main():
gh = github.Github(token)
repo = gh.get_repo(github_repo)
HEAD = repo.get_branch(repo.default_branch).commit.sha
pulls = repo.get_pulls()
for pull in pulls:
commits = [commit for commit in pull.get_commits()]
# Check if the parent(s) of the first commit of the PR is HEAD
is_rebased = any(parent.sha == HEAD for parent in commits[0].parents)
issue = repo.get_issue(pull.number)
new_labels = [label.name for label in issue.labels]
if changes_requested_label not in new_labels:
for pr_commit in commits:
message_lines = pr_commit.commit.message.split()
if 50 < len(message_lines[0]):
pull.create_issue_comment(textwrap.dedent('''
Commit messages do not conform to best practices.
Please ensure your subject line (first line of the
message) is 50 characters or less. Each line of the
body should be 72 characters or less.
'''))
new_labels.append(changes_requested_label)
break
if not is_rebased:
new_labels.append(rebase_label)
else:
if rebase_label in new_labels:
new_labels.remove(rebase_label)
if len(new_labels) == 0 or new_labels == [rebase_label]:
new_labels.append(review_label)
new_labels = list(set(new_labels))
issue.edit(labels=new_labels)
statuses = functools.reduce(
lambda x, y: x + y,
[[s for s in c.get_statuses()] for c in commits]
)
failure = any(status.state == 'failure' for status in statuses)
if not failure and new_labels == [merge_label]:
print('Merging pull request #{0}'.format(pull.number))
if merge(pull.head.ref, repo.default_branch):
# Last commit of the merged PR becomes the new HEAD
HEAD = commits[-1].sha
else:
pull.create_issue_comment(
':warning: **Warning!** Failed to auto-merge.'
)
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment