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)
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)