Exemple #1
0
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()
Exemple #2
0
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)