def list_bugs(query): ''' List all the bugs from a Bugzilla query ''' def _bughandler(bug, data): bugid = bug['id'] data[bugid] = bug def _attachmenthandler(attachments, bugid, data): data[int(bugid)] = attachments bugs, attachments = {}, {} bz = Bugzilla(query, bughandler=_bughandler, attachmenthandler=_attachmenthandler, bugdata=bugs, attachmentdata=attachments) bz.get_data().wait() # Map attachments on bugs for bugid, _attachments in attachments.items(): if bugid not in bugs: continue bugs[bugid]['attachments'] = _attachments return bugs
def get_bugs(): def bug_handler(bug_data, other_data): if bzdata_save_path: add_bugzilla_data_to_save(['sec-critical-high'], bug_data) bug_creation_time_str = bug_data['creation_time'] bug_creation_time = datetime.datetime.strptime(bug_creation_time_str, '%Y-%m-%dT%H:%M:%SZ') bug_creation_time = pytz.utc.localize(bug_creation_time) sec_important_start = None sec_important_end = None sec_important_rating = None sec_important_times = [] stalled_added_last = None # Look for changes to the 'keywords' field. for historyItem in bug_data['history']: for change in historyItem['changes']: if change['field_name'] == 'keywords': change_time_str = historyItem['when'] change_time = datetime.datetime.strptime( change_time_str, '%Y-%m-%dT%H:%M:%SZ') change_time = pytz.utc.localize(change_time) keywords_removed = change['removed'].split(', ') keywords_added = change['added'].split(', ') sec_rating_removed = critical in keywords_removed or high in keywords_removed sec_rating_added = critical in keywords_added or high in keywords_added if sec_rating_removed or sec_rating_added: # Find and set security rating for time range. if sec_rating_removed: if critical in keywords_removed: sec_important_rating = critical elif high in keywords_removed: sec_important_rating = high if not sec_important_start: sec_important_start = max( date_start, bug_creation_time) sec_important_end = change_time sec_important_times.append({ 'rating': sec_important_rating, 'start': sec_important_start, 'end': sec_important_end, }) if sec_rating_added: if critical in keywords_added: sec_important_rating = critical elif high in keywords_added: sec_important_rating = high sec_important_start = change_time # no relevant security added else: sec_important_start = None sec_important_rating = None sec_important_end = None # Bugs which got the 'stalled' keyword added are inactive # and not counted as open (active). stalled_removed = 'stalled' in keywords_removed stalled_added = 'stalled' in keywords_added if stalled_added: stalled_added_last = change_time elif stalled_removed: stalled_added_last = None if sec_important_start: # Open time range at the end of the investigated time range. if not sec_important_end: sec_important_end = date_end sec_important_times.append({ 'rating': sec_important_rating, 'start': sec_important_start, 'end': sec_important_end, }) # No keyword changes at all, keyword should have been set when bug got # created. if len(sec_important_times) == 0: keywords = bug_data['keywords'] sec_important_rating = None if critical in keywords: sec_important_rating = critical elif high in keywords: sec_important_rating = high else: sys.exit( 'Found neither sec-critical nor sec-high in keywords but expected one of them.' ) sec_important_times.append({ 'rating': sec_important_rating, 'start': max(date_start, bug_creation_time), 'end': date_end, }) sec_open_end = None if critical in bug_data['keywords'] or high in bug_data['keywords']: if bug_data['is_open']: if 'stalled' in bug_data['keywords']: # Open but stalled bug with a security rating if stalled_added_last: sec_open_end = max(stalled_added_last, date_start) else: # Can only get here if bug got created with 'stalled' # keyword, e.g. if bug got cloned. sec_open_end = max(date_start, bug_creation_time) else: sec_open_end = date_end else: # Bug closed, last time it got resolved used as ended of # affected time range. last_resolved_str = bug_data['cf_last_resolved'] last_resolved = datetime.datetime.strptime( last_resolved_str, '%Y-%m-%dT%H:%M:%SZ') last_resolved = pytz.utc.localize(last_resolved) sec_open_end = min(sec_important_times[-1]['end'], last_resolved) else: sec_open_end = sec_important_times[0]['start'] stalled = True if 'stalled' in bug_data['keywords'] else False bug_data_to_export = { 'id': bug_data['id'], 'rating': sec_important_times[-1]['rating'], 'start': sec_important_times[0]['start'], 'end': sec_open_end, 'stalled': stalled, 'status': bug_data['status'], 'resolution': bug_data['resolution'], } bug_sec_open_ranges.append(bug_data_to_export) # Load Bugzilla data from file if bzdata_load_path: for bug_data in bugzilla_data_loaded['sec-critical-high']['data']: other_data = {} bug_handler(bug_data, other_data) # Load Bugzilla data from Bugzilla server else: queries = [] fields = [ 'id', 'creation_time', 'status', 'is_open', 'resolution', 'cf_last_resolved', 'keywords', 'history', ] params = { 'include_fields': fields, 'product': PRODUCTS_TO_CHECK, 'j_top': 'OR', # Either the keywords 'sec-critical' or 'sec-high' got removed # after the given date. 'f1': 'OP', 'j1': 'AND_G', 'f2': 'keywords', 'o2': 'changedfrom', 'v2': 'sec-critical', 'f3': 'keywords', 'o3': 'changedafter', 'v3': '', 'f4': 'CP', 'f5': 'OP', 'j5': 'AND_G', 'f6': 'keywords', 'o6': 'changedfrom', 'v6': 'sec-high', 'f7': 'keywords', 'o7': 'changedafter', 'v7': '', 'f8': 'CP', # Or the bug still has either the keyword 'sec-critical' or # 'sec-high' and 'f9': 'OP', 'f10': 'keywords', 'o10': 'anywords', 'v10': 'sec-critical, sec-high', 'f11': 'OP', 'j11': 'OR', # ... got resolved after the given date ... 'f12': 'cf_last_resolved', 'o12': 'changedafter', 'v12': '', # or hasn't been resolved yet. 'f13': 'bug_status', 'o13': 'anywords', 'v13': 'UNCONFIRMED, NEW, ASSIGNED, REOPENED', 'f14': 'CP', 'f15': 'CP', } params['v3'] = date_start_str params['v7'] = date_start_str params['v12'] = date_start_str query = Bugzilla(params, bughandler=bug_handler, bugdata={}, timeout=960) query.get_data().wait()