def acknowledge_merge_on_travis(data): """When a user comments on a pull request with one of the automerge triggers (e.g. merge on green), this hook will add the 'automerge' label. Issue comment data reference: https://developer.github.com/v3/activity/events/types/#issuecommentevent """ if data.get('action') != 'created': return # Make sure it's a PR. if not github_helper.is_pull_request(data): return # If comment has trigger text. comment = data['comment'] if not check_for_auto_merge_trigger(comment['body']): return # If user is a collaborator. gh = github_helper.get_client() repository = github_helper.get_repository(gh, data) if not repository.is_collaborator(data['sender']['login']): logging.info( '{} is not an owner and is trying to tell me what to do.'.format( data['sender']['login'])) # Write a comment about it. pr = github_helper.get_pull_request(gh, data) pr.create_comment('Okay! I\'ll merge when all statuses are green.') pr.issue().add_labels('automerge')
def pull_request_review_merge_on_travis(data): """When all approvers approve and statuses pass, this hook will automatically merge it if it's labeled with 'automerge'. Status data reference: https://developer.github.com/v3/activity/events/types/#pullrequestreviewevent """ # If it's not successful don't even bother. if data['review']['state'] != 'approved': logging.info('Not approved, returning.') return # If the PR is closed, don't bother if data['pull_request']['state'] != 'open': logging.info('Closed, returning.') return gh = github_helper.get_client() repo = gh.repository( data['repository']['owner']['login'], data['repository']['name']) pr = repo.pull_request(data['pull_request']['number']) merge_pull_request(repo, pr, commit_sha=pr.head.sha)
def pull_request_review_merge_on_travis(data): """When all approvers approve and statuses pass, this hook will automatically merge it if it's labeled with 'automerge'. Status data reference: https://developer.github.com/v3/activity/events/types/#pullrequestreviewevent """ # If it's not successful don't even bother. if data['review']['state'] != 'approved': logging.info('Not approved, returning.') return # If the PR is closed, don't bother if data['pull_request']['state'] != 'open': logging.info('Closed, returning.') return gh = github_helper.get_client() repo = gh.repository( data['repository']['owner']['login'], data['repository']['name']) pr = repo.pull_request(data['pull_request']['number']) merge_pull_request(repo, pr, commit_sha=pr.head.sha)
def complete_merge_on_travis(data): """When all statuses on a PR are green, this hook will automatically merge it if it's labeled with 'automerge'. Status data reference: https://developer.github.com/v3/activity/events/types/#statusevent """ # TODO: Idea - if automerge has been triggered and the status fails, # nag the committer to fix? # If it's not successful don't even bother. if data['state'] != 'success': logging.info('Status not successful, returning.') return # NOTE: I'm not sure if there's a better way to do this. But, it seems # the status change message doesn't tell you which PR the commit is # from. Indeed, it's possible for a commit to actually be in multiple # PRs. Anyways, the idea here is to get all open PRs with the # tag 'automerge' and check if this commit is in that PR. # If so, merge. gh = github_helper.get_client() repository = github_helper.get_repository(gh, data) # This search actually takes a few seconds to work. Sleep for 10 seconds. time.sleep(10) results = gh.search_issues( query='type:pr label:automerge status:success is:open repo:{}'.format( data['repository']['full_name'])) # Covert to pull requests so we can get the commits. pulls = [result.issue.pull_request() for result in results] logging.info('Found {} potential PRs: {}'.format(len(pulls), pulls)) # See if this commit is in the PR. # this check isn't actually strictly necessary as the search above will # only return PRs that are 'green' which means we can safely merge all # of them. But, whatever, I'll leave it here for now anyway. commit_sha = data['commit']['sha'] pulls = [ pull for pull in pulls if commit_sha in [commit.sha for commit in pull.commits()] ] logging.info('Commit {} is present in PRs: {}'.format(commit_sha, pulls)) # Merge! for pull in pulls: # By supplying the sha here, it ensures that the PR will only be # merged if that sha is the HEAD of the branch. pull.merge(sha=commit_sha, squash=True) # Delete the branch if it's in this repo. ALSO DON'T DELETE MASTER. if (pull.head.ref != 'master' and '/'.join(pull.head.repo) == data['repository']['full_name']): repository.ref('heads/{}'.format(pull.head.ref)).delete()
def accept_invitations(): gh = github_helper.get_client() invitations = gh.session.get( 'https://api.github.com/user/repository_invitations').json() for invitation in invitations: gh.session.patch(invitation['url']) logging.info('Accepted invite to {}'.format( invitation['repository']['full_name']))
def commit_status_complete_merge_on_travis(data): """When all statuses on a PR are green, this hook will automatically merge it if it's labeled with 'automerge'. Status data reference: https://developer.github.com/v3/activity/events/types/#statusevent """ # TODO: Idea - if automerge has been triggered and the status fails, # nag the committer to fix? # If it's not successful don't even bother. if data['state'] != 'success': logging.info('Status not successful, returning.') return # NOTE: I'm not sure if there's a better way to do this. But, it seems # the status change message doesn't tell you which PR the commit is # from. Indeed, it's possible for a commit to actually be in multiple # PRs. Anyways, the idea here is to get all open PRs with the # tag 'automerge' and this commit in the PR. commit_sha = data['commit']['sha'] gh = github_helper.get_client() repository = github_helper.get_repository(gh, data) # Sleep for about 15 seconds. Github's search index needs a few seconds # before it'll find the results. time.sleep(15) query = '{} type:pr label:automerge status:success is:open repo:{}'.format( commit_sha, data['repository']['full_name']) logging.info('Querying with: {}'.format(query)) results = gh.search_issues(query=query) # Covert to pull requests so we can get the commits. pulls = [result.issue.pull_request() for result in results] logging.info('Found {} potential PRs: {}'.format( len(pulls), pulls)) # See if this commit is in the PR. # this check isn't actually strictly necessary as the search above will # only return PRs that are 'green' which means we can safely merge all # of them. But, whatever, I'll leave it here for now anyway. pulls = [ pull for pull in pulls if commit_sha in [commit.sha for commit in pull.commits()]] logging.info('Commit {} is present in PRs: {}'.format( commit_sha, pulls)) # Merge! for pull in pulls: merge_pull_request(repository, pull, commit_sha=commit_sha)
def commit_status_complete_merge_on_travis(data): """When all statuses on a PR are green, this hook will automatically merge it if it's labeled with 'automerge'. Status data reference: https://developer.github.com/v3/activity/events/types/#statusevent """ # TODO: Idea - if automerge has been triggered and the status fails, # nag the committer to fix? # If it's not successful don't even bother. if data['state'] != 'success': logging.info('Status not successful, returning.') return # NOTE: I'm not sure if there's a better way to do this. But, it seems # the status change message doesn't tell you which PR the commit is # from. Indeed, it's possible for a commit to actually be in multiple # PRs. Anyways, the idea here is to get all open PRs with the # tag 'automerge' and this commit in the PR. commit_sha = data['commit']['sha'] gh = github_helper.get_client() repository = github_helper.get_repository(gh, data) # Sleep for about 15 seconds. Github's search index needs a few seconds # before it'll find the results. time.sleep(15) query = '{} type:pr label:automerge is:open repo:{}'.format( commit_sha, data['repository']['full_name']) logging.info('Querying with: {}'.format(query)) results = gh.search_issues(query=query) # Covert to pull requests so we can get the commits. pulls = [result.issue.pull_request() for result in results] logging.info('Found {} potential PRs: {}'.format( len(pulls), pulls)) # See if this commit is in the PR. # this check isn't actually strictly necessary as the search above will # only return PRs that are 'green' which means we can safely merge all # of them. But, whatever, I'll leave it here for now anyway. pulls = [ pull for pull in pulls if commit_sha in [commit.sha for commit in pull.commits()]] logging.info('Commit {} is present in PRs: {}'.format( commit_sha, pulls)) # Merge! for pull in pulls: merge_pull_request(repository, pull, commit_sha=commit_sha)
def create_webhook(owner, repository): gh = github_helper.get_client() repo = gh.repository(owner, repository) hook = repo.create_hook( name='web', config={ 'url': webhook_url(), 'content_type': 'json', 'secret': webhook_secret().decode('utf-8')}, events=['*']) return hook
def create_webhooks(): """Auto-creates webhooks * Gets all open issues assigned to the bot. * Checks to see if the issue is title 'add webhook'. * Checks the creator and the bot are both admins. * Creates the hook and leaves a comment. """ gh = github_helper.get_client() issues = gh.issues(filter='assigned', state='open') for issue in issues: # Does someone want us to add the webhook? if issue.title.lower() not in ('add webhook', 'create webhook'): return logging.info('Processing issue {}'.format(issue.url)) # Make sure the user who filed the issue is an admin. permission = github_helper.get_permission( gh, issue.repository[0], issue.repository[1], issue.user.login) if permission != 'admin': logging.info( 'Not installing webhook because {} is not an ' 'admin.'.format(issue.user.login)) return # Make sure we're an admin. repo = gh.repository(*issue.repository) if not repo.permissions['admin']: logging.info( 'Not installing hook because depbot is not an admin') # TODO: leave a comment? return # Create the webhook. try: webhook_helper.create_webhook(repo.owner, repo.name) issue.create_comment('Webhook added!') except github3.exceptions.UnprocessableEntity: # Webhook already exists logging.info('Hook already existed.') issue.create_comment('Webhook is already here!') issue.close()
def acknowledge_merge_on_travis(data): """When a user comments on a pull request with one of the automerge triggers (e.g. merge on green), this hook will add the 'automerge' label. Issue comment data reference: https://developer.github.com/v3/activity/events/types/#issuecommentevent """ if data.get('action') != 'created': return # Make sure it's a PR. if not github_helper.is_pull_request(data): return # If comment has trigger text. comment = data['comment'] if not check_for_auto_merge_trigger(comment['body']): return # If user is a collaborator. gh = github_helper.get_client() repository = github_helper.get_repository(gh, data) if not repository.is_collaborator(data['sender']['login']): logging.info( '{} is not an owner and is trying to tell me what to do.'.format( data['sender']['login'])) # Write a comment about it. pr = github_helper.get_pull_request(gh, data) pr.create_comment( 'Okay! I\'ll merge when all statuses are green and all reviewers ' 'approve.') pr.issue().add_labels('automerge') pr.issue().assign(github_helper.github_user())