예제 #1
0
def create_bug():
    '''
    Create a new bug, or update its payload
    '''
    # Load bug
    bugzilla_id = request.json.get('bugzilla_id')
    if not bugzilla_id:
        raise Exception('Missing bugzilla id')
    try:
        bug = BugResult.query.filter_by(bugzilla_id=bugzilla_id).one()
        analysis_existing = [a[0] for a in bug.analysis.values('analysis_id')]
    except Exception:
        bug = BugResult(bugzilla_id=bugzilla_id)
        analysis_existing = []

    # Update bug payload
    payload = request.json.get('payload')
    payload_hash = request.json.get('payload_hash')
    if not payload or not payload_hash:
        raise Exception('Missing payload updates.')
    if 'analysis' not in payload:
        raise Exception('Missing analysis in payload')
    if payload['analysis'].get('uplift_comment') is None:
        raise Exception('Missing uplift comment in analysis')
    bug.payload = pickle.dumps(payload, 2)
    bug.payload_hash = payload_hash

    # Sync analysis in both ways:
    # * adding new bugs
    # * removing deprecated bugs
    analysis_needed = request.json.get('analysis', [])
    add = set(analysis_needed).difference(analysis_existing)
    analysis = BugAnalysis.query \
        .filter(BugAnalysis.id.in_(add)) \
        .all()
    for a in analysis:
        logger.debug('Adding new bug', analysis=a.id, bug=bug.bugzilla_id)
        a.bugs.append(bug)

    rm = set(analysis_existing).difference(analysis_needed)
    analysis = BugAnalysis.query \
        .filter(BugAnalysis.id.in_(rm)) \
        .all()
    for a in analysis:
        logger.debug('Removing old bug', analysis=a.id, bug=bug.bugzilla_id)
        a.bugs.remove(bug)

    # Save all changes
    db.session.add(bug)

    # Load users
    for user in payload.get('users', []):

        # Get or create user in db
        try:
            contrib = Contributor.query.filter_by(bugzilla_id=user['id']).one()
        except:
            contrib = Contributor(bugzilla_id=user['id'])
            contrib.name = user.get('real_name', user['name'])
            contrib.email = user['email']
            contrib.avatar_url = gravatar(user['email'])
            db.session.add(contrib)

        # Link contributor to bug
        try:
            link = BugContributor.query.filter_by(
                bug_id=bug.id, contributor_id=contrib.id).one()
        except Exception:
            link = BugContributor(bug=bug, contributor=contrib)
        link.roles = ','.join(user['roles'])
        db.session.add(link)

    # Commit all those changes
    db.session.commit()

    # Send back the bug
    return serialize_bug(bug)
예제 #2
0
def update_bug(bugzilla_id):
    '''
    Update a bug after modifications on Bugzilla
    '''
    # Load bug
    try:
        bug = BugResult.query.filter_by(bugzilla_id=bugzilla_id).one()
    except:
        raise Exception('Missing bug {}'.format(bugzilla_id))

    # Browse changes
    payload = bug.payload_data
    for update in request.json:
        # Build flags map
        source = update['changes'].get('flagtypes.name', {})
        removed, added = source['removed'].split(', '), source['added'].split(
            ', ')  # noqa
        flags_map = zip(removed, added)

        if update['target'] == 'bug':
            # Update bug flags (tracking & status)
            if update['bugzilla_id'] != bug.bugzilla_id:
                # should never happen
                raise Exception('Invalid bugzilla_id in changes list')
            for flag_name, actions in update['changes'].items():
                payload['bug'][flag_name] = actions.get('added')

            # Update generic flags
            flags_index = dict([
                (f['name'], i) for i, f in enumerate(payload['bug']['flags'])
            ])
            for rm, add in flags_map:
                add_name, rm_name = add[:-1], rm[:-1]
                if add_name in flags_index:
                    # Update flag status
                    index = flags_index[add_name]
                    payload['bug']['flags'][index]['status'] = add[-1]

                elif rm_name in flags_index:
                    # Remove flag entirely
                    index = flags_index[rm_name]
                    del payload['bug']['flags'][index]

                else:
                    # Create new flag
                    payload['bug']['flags'].append({
                        'name': add_name,
                        'status': add[-1],
                    })

        elif update['target'] == 'attachment':

            def _split(fullkey):
                # From 'approval-mozilla-beta+' to
                # ('beta +', 'approval-mozilla-beta', '+')
                assert fullkey.startswith('approval-mozilla-'), \
                    '{} is not approval-mozilla-XXX'.format(fullkey)
                out = fullkey[17:]
                return out[:-1] + ' ' + out[-1], fullkey[:-1], fullkey[-1]

            # Update versions directly
            versions = payload.get('versions', {})
            for before, after in flags_map:
                before, _, _ = _split(before)
                after, name, status = _split(after)
                if before in versions:
                    versions[after] = versions[before]
                    versions[after].update({
                        'name': name,
                        'status': status,
                    })
                    del versions[before]

        else:
            raise Exception('Invalid update target {}'.format(
                update['target']))  # noqa

    # Save changes
    bug.payload = pickle.dumps(payload, 2)
    db.session.add(bug)
    db.session.commit()

    # Send back the bug
    return serialize_bug(bug)