def handle_pull_request_approved(payload): if not current_app.config['AUTO_MERGE_ENABLED']: return repo = payload['repository'] pr = payload['pullrequest'] pr_id = pr['id'] title = pr['title'].lower() description = (pr['description'] or '').lower() for keyword in ('wip', 'merge skip', 'working in progress'): if keyword in title or keyword in description: logger.info('%s found, ignore auto merge.', keyword) return pull_request = PullRequest( bitbucket, repo['full_name'] ) try: pr_info = pull_request.get(pr_id) except BitbucketAPIError as exc: logger.exception('Error calling Bitbucket API') if exc.code != 404: sentry.captureException() return if pr_info['state'] != 'OPEN': return participants = pr_info['participants'] approved_users = [u for u in participants if u['approved']] if len(approved_users) < current_app.config['AUTO_MERGE_APPROVAL_COUNT']: return commit_hash = pr_info['source']['commit']['hash'] build_status = BuildStatus( bitbucket, pr_info['source']['repository']['full_name'], commit_hash, 'badwolf/test', url_for('log.build_log', sha=commit_hash, _external=True) ) message = 'Auto merge pull request #{}: {}'.format(pr_id, pr['title']) if description: message += '\n\n{}'.format(pr['description']) try: status = build_status.get() if status['state'] == 'SUCCESSFUL': pull_request.merge(pr_id, message) except BitbucketAPIError as exc: logger.exception('Error calling Bitbucket API') if exc.code != 404: sentry.captureException()
def check_mergeable(context, pr_api, pr_info): pr_id = pr_info['id'] merge_status = BuildStatus( bitbucket, pr_info['source']['repository']['full_name'], pr_info['source']['commit']['hash'], 'badwolf/pr/mergeable', 'https://bitbucket.org/{}/pull-requests/{}'.format( context.repository, pr_id)) notify = False status = {'state': None} try: status = merge_status.get() except BitbucketAPIError as e: if e.code != 404: raise notify = True else: if status['state'] == 'SUCCESSFUL': notify = True diff = pr_api.diff(pr_id, raw=True) if '+<<<<<<< destination:' not in diff: # Mergeable logger.info('Pull request #%s is mergeable', pr_id) if status['state'] != 'SUCCESSFUL': merge_status.update('SUCCESSFUL', 'Pull request is mergeable') return # Unmergeable if not notify: return logger.info('Pull request #%s is not mergeable', pr_id) merge_status.update('FAILED', 'Pull request is not mergeable') comment = ( ':umbrella: The latest upstream changes(presumably {}) made this pull request unmergeable. ' 'Please resolve the merge conflicts.') matches = _MERGE_COMMIT_RE.search(context.message) if matches: comment = comment.format('pull request #{}'.format(matches.group(1))) else: comment = comment.format('commit {}'.format( context.source['commit']['hash'])) pr_api.comment(pr_id, comment)