def main(): config = ConfigParser.ConfigParser() config.read(os.environ['REDMINE_BUGZILLA_CONF']) username = config.get('bugzilla', 'username') password = config.get('bugzilla', 'password') key = config.get('redmine', 'key') redmine = get_redmine_connection(key) BZ = get_bugzilla_connection(username, password) redmine_issues = [issue for issue in redmine.issue.filter(query_id=24)] non_closed_bug_with_ext_tracker = BUGZILLA_URL + '/buglist.cgi?bug_status=NEW&' \ 'bug_status=ASSIGNED&bug_status=POST&bug_status=MODIFIED&bug_status=ON_DEV&' \ 'bug_status=ON_QA&bug_status=VERIFIED&bug_status=RELEASE_PENDING&' \ 'columnlist=priority%2Cbug_severity%2Cbug_status%2Cshort_desc%2Cchangeddate%2C' \ 'component%2Ctarget_release%2Cassigned_to%2Creporter&f1=external_bugzilla.url&' \ 'list_id=3309842&o1=substring&query_format=advanced&v1=pulp.plan.io' bugzilla_bugs = BZ.query(RHBugzilla.url_to_query(non_closed_bug_with_ext_tracker)) links_issues_record = '' ext_bug_record = '' for issue in redmine_issues: for custom_field in issue.custom_fields.resources: if custom_field['name'] == 'Bugzilla': if custom_field['value'] == '': continue bug = BZ.getbug(int(custom_field['value'])) links_back = False for external_bug in bug.external_bugs: if external_bug['type']['description'] == 'Pulp Redmine' and \ external_bug['ext_bz_bug_id'] == str(issue.id): add_cc_list_to_bugzilla_bug(bug) ext_params = {} if external_bug['ext_description'] != issue.subject: ext_params['ext_description'] = issue.subject if external_bug['ext_status'] != issue.status.name: ext_params['ext_status'] = issue.status.name if external_bug['ext_priority'] != issue.priority.name: ext_params['ext_priority'] = issue.priority.name if len(ext_params.keys()) > 0: ext_bug_record += 'Bugzilla bug %s updated from upstream bug %s with ' \ '%s\n' % (bug.id, issue.id, ext_params) ext_params['ids'] = external_bug['id'] BZ.update_external_tracker(**ext_params) if 'ext_status' in ext_params: bug.addcomment( 'The Pulp upstream bug status is at %s. Updating the external ' 'tracker on this bug.' % issue.status.name) if 'ext_priority' in ext_params: bug.addcomment( 'The Pulp upstream bug priority is at %s. Updating the ' 'external tracker on this bug.' % issue.priority.name) # Remove the bug list gotten via search so we don't examine it again when # bugzilla_bugs are iterated through bug_in_search_index_to_remove = None for i, bug_in_search in enumerate(bugzilla_bugs): if bug_in_search.id == bug.id: bug_in_search_index_to_remove = i break if bug_in_search_index_to_remove is not None: bugzilla_bugs.pop(bug_in_search_index_to_remove) links_back = True if not links_back: links_issues_record += 'Redmine #%s -> Bugzilla %s, but Bugzilla %s does not ' \ 'link back\n' % (issue.id, bug.id, bug.id) for bug in bugzilla_bugs: for external_bug in bug.external_bugs: if external_bug['type']['description'] == 'Pulp Redmine': add_cc_list_to_bugzilla_bug(bug) issue_id = external_bug['ext_bz_bug_id'] issue = redmine.issue.get(issue_id) links_back = False for custom_field in issue.custom_fields.resources: if custom_field['name'] == 'Bugzilla': try: if int(custom_field['value']) == bug.id: links_back = True except KeyError: # If value isn't present this field is not linking back so continue continue except ValueError: # If value is present but empty this field is not linking back continue if not links_back: links_issues_record += 'Bugzilla #%s -> Redmine %s, but Redmine %s does ' \ 'not link back\n' % (bug.id, issue.id, issue.id) if ext_bug_record != '': print '\nBugzilla Updates From Upstream' print '------------------------------' print ext_bug_record if links_issues_record != '': print '\nLink Issues' print '-----------' print links_issues_record # Raise an exception so the job fails and Jenkins will send e-mail raise RuntimeError('Upstream/Downstream Link issues are detected')
def main(): config = ConfigParser.ConfigParser() config.read(os.environ['REDMINE_BUGZILLA_CONF']) username = config.get('bugzilla', 'username') password = config.get('bugzilla', 'password') key = config.get('redmine', 'key') redmine = get_redmine_connection(key) BZ = get_bugzilla_connection(username, password) bug_with_ext_tracker = \ BUGZILLA_URL + '/buglist.cgi?classification=Red%20Hat&columnlist=priority%2Cbug_severity' \ '%2Cbug_status%2Cshort_desc%2Cchangeddate%2Ccomponent%2Ctarget_release%2C' \ 'assigned_to%2Creporter&f1=external_bugzilla.url&list_id=7254713&o1=' \ 'substring&product=Red%20Hat%20Satellite%206&query_format=advanced&' \ 'resolution=---&resolution=CURRENTRELEASE&resolution=RAWHIDE&resolution=' \ 'ERRATA&resolution=NEXTRELEASE&resolution=INSUFFICIENT_DATA&resolution=EOL' \ '&v1=pulp.plan.io' bugzilla_bugs = BZ.query(RHBugzilla.url_to_query(bug_with_ext_tracker)) upstream_issues_checked_memo = {} # A memo allowing us to never check an issue twice all_BZs = set() BZs_fixed_by_version = defaultdict(lambda : set()) for i, bug in enumerate(bugzilla_bugs): # if i == 20: # break all_BZs.add(bug.id) bug = BZ.getbug(bug.id) upstream_associated_issue_numbers = [] for external_bug in bug.external_bugs: if external_bug['type']['description'] == 'Pulp Redmine': upstream_associated_issue_numbers.append(int(external_bug['ext_bz_bug_id'])) upstream_fixed_versions_for_bz = [] for upstream_id in upstream_associated_issue_numbers: # Check the memo to see if we already know the fix version if upstream_id in upstream_fixed_versions_for_bz: if upstream_fixed_versions_for_bz[upstream_id] != u'': # We already know the upstream version with the fix available upstream_fixed_versions_for_bz.append( upstream_fixed_versions_for_bz[upstream_id] ) all_BZs.add(bug.id) # The memo info was used so we can move on to the next upstream issue to check continue upstream_issue = redmine.issue.get(upstream_id) # Issues in 'External' are not actual issues so they should be ignored if upstream_issue.project.name == u'External': # Never check an upstream issue twice upstream_issues_checked_memo[upstream_id] = u'' continue platform_release_field = upstream_issue.custom_fields.get(4) # 'Platform Release' field # Never check an upstream issue twice upstream_issues_checked_memo[upstream_id] = platform_release_field[u'value'] if platform_release_field[u'value'] != u'': upstream_fixed_versions_for_bz.append(platform_release_field[u'value']) all_BZs.add(bug.id) if upstream_fixed_versions_for_bz != []: fix_in = max([semantic_version.Version(v) for v in upstream_fixed_versions_for_bz]) BZs_fixed_by_version[str(fix_in)].add(bug.id) upstream_versions = [semantic_version.Version(v) for v in BZs_fixed_by_version.keys()] upstream_versions.sort() # Ensure in increasing order BZs_fixed_list = [BZs_fixed_by_version[str(v)] for v in upstream_versions] for i in range(1, len(BZs_fixed_list)): BZs_fixed_list[i] = BZs_fixed_list[i - 1] | BZs_fixed_list[i] for i, version in enumerate(upstream_versions): BZs_fixed_by_version[str(version)] = BZs_fixed_list[i] BZs_missing_by_version = {} for version, bugs in BZs_fixed_by_version.iteritems(): BZs_missing_by_version[version] = all_BZs - BZs_fixed_by_version[version] minimum_version = semantic_version.Version(MINIMUM_VERSION) for v in upstream_versions: if v < minimum_version: continue bugs_in_this_version = BZs_missing_by_version[str(v)] print '%s, %s, https://bugzilla.redhat.com/buglist.cgi?quicksearch=%s' % ( v, len(bugs_in_this_version), ','.join([str(i) for i in bugs_in_this_version]) )
def main(): config = ConfigParser.ConfigParser() config.read(os.environ["REDMINE_BUGZILLA_CONF"]) username = config.get("bugzilla", "username") password = config.get("bugzilla", "password") key = config.get("redmine", "key") redmine = get_redmine_connection(key) BZ = get_bugzilla_connection(username, password) redmine_issues = [issue for issue in redmine.issue.filter(query_id=24)] non_closed_bug_with_ext_tracker = ( BUGZILLA_URL + "/buglist.cgi?bug_status=NEW&" "bug_status=ASSIGNED&bug_status=POST&bug_status=MODIFIED&bug_status=ON_DEV&" "bug_status=ON_QA&bug_status=VERIFIED&bug_status=RELEASE_PENDING&" "columnlist=priority%2Cbug_severity%2Cbug_status%2Cshort_desc%2Cchangeddate%2C" "component%2Ctarget_release%2Cassigned_to%2Creporter&f1=external_bugzilla.url&" "list_id=3309842&o1=substring&query_format=advanced&v1=pulp.plan.io" ) bugzilla_bugs = BZ.query(RHBugzilla.url_to_query(non_closed_bug_with_ext_tracker)) links_issues_record = "" ext_bug_record = "" downstream_state_issue_record = "" downstream_changes = "" for issue in redmine_issues: for custom_field in issue.custom_fields.resources: if custom_field["name"] == "Bugzillas": if custom_field["value"] == "": continue for bug_id in [int(id_str) for id_str in custom_field["value"].split(",")]: links_back = False try: bug = BZ.getbug(bug_id) except xmlrpclib.Fault as e: if e.faultCode == 102: print "Bugzilla %s could not be accessed." % bug_id continue else: raise for external_bug in bug.external_bugs: if external_bug["type"]["description"] == "Pulp Redmine" and external_bug[ "ext_bz_bug_id" ] == str(issue.id): add_cc_list_to_bugzilla_bug(bug) ext_params = {} if external_bug["ext_description"] != issue.subject: ext_params["ext_description"] = issue.subject if external_bug["ext_status"] != issue.status.name: ext_params["ext_status"] = issue.status.name if external_bug["ext_priority"] != issue.priority.name: ext_params["ext_priority"] = issue.priority.name if len(ext_params.keys()) > 0: ext_bug_record += "Bugzilla bug %s updated from upstream bug %s " "with %s\n" % ( bug.id, issue.id, ext_params, ) ext_params["ids"] = external_bug["id"] BZ.update_external_tracker(**ext_params) if "ext_status" in ext_params: bug.addcomment( "The Pulp upstream bug status is at %s. Updating the " "external tracker on this bug." % issue.status.name ) if "ext_priority" in ext_params: bug.addcomment( "The Pulp upstream bug priority is at %s. Updating the " "external tracker on this bug." % issue.priority.name ) downstream_POST_plus = [ "POST", "MODIFIED", "ON_QA", "VERIFIED", "RELEASE_PENDING", "CLOSED", ] upstream_POST_minus = ["NEW", "ASSIGNED", "POST"] if bug.status in downstream_POST_plus and issue.status.name in upstream_POST_minus: msg = "The downstream bug %s is at POST+ but the upstream bug %s " "at POST-.\n" % ( bug.id, issue.id, ) downstream_state_issue_record += msg links_back = True transition_to_post = [] for external_bug in bug.external_bugs: if external_bug["type"]["description"] == "Foreman Issue Tracker": # If the bug has an external foreman issue, don't transition the BZ transition_to_post.append(False) if external_bug["type"]["description"] == "Pulp Redmine": if bug.status in ["NEW", "ASSIGNED"]: if external_bug["ext_status"] in [ "MODIFIED", "ON_QA", "VERIFIED", "CLOSED - CURRENTRELEASE", ]: transition_to_post.append(True) else: transition_to_post.append(False) if not links_back: links_issues_record += "Redmine #%s -> Bugzilla %s, but Bugzilla %s does " "not link back\n" % ( issue.id, bug.id, bug.id, ) if len(transition_to_post) > 0 and all(transition_to_post): msg = "All upstream Pulp bugs are at MODIFIED+. Moving this bug to POST." bug.setstatus("POST", msg) downstream_changes += "Bugzilla %s was transitioned to POST\n" % bug.id for bug in bugzilla_bugs: for external_bug in bug.external_bugs: if external_bug["type"]["description"] == "Pulp Redmine": add_cc_list_to_bugzilla_bug(bug) issue_id = external_bug["ext_bz_bug_id"] issue = redmine.issue.get(issue_id) links_back = False for custom_field in issue.custom_fields.resources: if custom_field["name"] == "Bugzillas" and custom_field["value"]: bug_list = [int(id_str) for id_str in custom_field["value"].split(",")] for bug_id in bug_list: try: if bug_id == bug.id: links_back = True except KeyError: # If value isn't present this field is not linking back continue except ValueError: # If value is present but empty this field is not linking back continue if not links_back: links_issues_record += "Bugzilla #%s -> Redmine %s, but Redmine %s does " "not link back\n" % ( bug.id, issue.id, issue.id, ) if ext_bug_record != "": print "\nBugzilla Updates From Upstream" print "------------------------------" print ext_bug_record if downstream_changes != "": print "\nBugzilla Transitions to POST" print "----------------------------" print downstream_changes if links_issues_record != "": print "\nLink Issues" print "-----------" print links_issues_record if downstream_state_issue_record != "": print "\nDownstream State Issues" print "-----------------------" print downstream_state_issue_record if links_issues_record != "" or downstream_state_issue_record != "": # Raise an exception so the job fails and Jenkins will send e-mail raise RuntimeError("We need a human here")
def main(): config = ConfigParser.ConfigParser() config.read(os.environ['REDMINE_BUGZILLA_CONF']) username = config.get('bugzilla', 'username') password = config.get('bugzilla', 'password') key = config.get('redmine', 'key') redmine = get_redmine_connection(key) BZ = get_bugzilla_connection(username, password) redmine_issues = [issue for issue in redmine.issue.filter(query_id=24)] non_closed_bug_with_ext_tracker = BUGZILLA_URL + '/buglist.cgi?bug_status=NEW&' \ 'bug_status=ASSIGNED&bug_status=POST&bug_status=MODIFIED&bug_status=ON_DEV&' \ 'bug_status=ON_QA&bug_status=VERIFIED&bug_status=RELEASE_PENDING&' \ 'columnlist=priority%2Cbug_severity%2Cbug_status%2Cshort_desc%2Cchangeddate%2C' \ 'component%2Ctarget_release%2Cassigned_to%2Creporter&f1=external_bugzilla.url&' \ 'list_id=3309842&o1=substring&query_format=advanced&v1=pulp.plan.io' bugzilla_bugs = BZ.query( RHBugzilla.url_to_query(non_closed_bug_with_ext_tracker)) links_issues_record = '' ext_bug_record = '' downstream_state_issue_record = '' downstream_changes = '' new_failed_qa_record = '' failed_qa_bugzillas = [] for issue in redmine_issues: for custom_field in issue.custom_fields.resources: if custom_field['name'] == 'Bugzillas': if custom_field['value'] == '': continue for bug_id in [ int(id_str) for id_str in custom_field['value'].split(',') ]: links_back = False if bug_id in failed_qa_bugzillas: continue try: bug = BZ.getbug(bug_id) except xmlrpclib.Fault as e: if e.faultCode == 102: print 'Bugzilla %s could not be accessed.' % bug_id continue else: raise for external_bug in bug.external_bugs: if external_bug['type']['description'] == 'Pulp Redmine' and \ external_bug['ext_bz_bug_id'] == str(issue.id): add_cc_list_to_bugzilla_bug(bug) ext_params = {} if external_bug['ext_description'] != issue.subject: ext_params['ext_description'] = issue.subject if external_bug['ext_status'] != issue.status.name: ext_params['ext_status'] = issue.status.name if external_bug[ 'ext_priority'] != issue.priority.name: ext_params[ 'ext_priority'] = issue.priority.name if len(ext_params.keys()) > 0: ext_bug_record += 'Bugzilla bug %s updated from upstream bug %s ' \ 'with %s\n' % (bug.id, issue.id, ext_params) ext_params['ids'] = external_bug['id'] BZ.update_external_tracker(**ext_params) if 'ext_status' in ext_params: bug.addcomment( 'The Pulp upstream bug status is at %s. Updating the ' 'external tracker on this bug.' % issue.status.name) if 'ext_priority' in ext_params: bug.addcomment( 'The Pulp upstream bug priority is at %s. Updating the ' 'external tracker on this bug.' % issue.priority.name) downstream_POST_plus = [ 'POST', 'MODIFIED', 'ON_QA', 'VERIFIED', 'RELEASE_PENDING', 'CLOSED' ] downstream_ACCEPTABLE_resolution = [ 'NOTABUG', 'WONTFIX', 'DEFERRED', 'WORKSFORME' ] upstream_POST_minus = ['NEW', 'ASSIGNED', 'POST'] if bug.status in downstream_POST_plus and \ issue.status.name in upstream_POST_minus: if bug.resolution not in downstream_ACCEPTABLE_resolution: msg = 'The downstream bug %s is at POST+ but the upstream ' \ 'bug %s at POST-.\n' % (bug.id, issue.id) downstream_state_issue_record += msg links_back = True transition_to_post = [] for external_bug in bug.external_bugs: if external_bug['type'][ 'description'] == 'Foreman Issue Tracker': # If the bug has an external foreman issue, don't transition the BZ transition_to_post.append(False) if external_bug['type'][ 'description'] == 'Pulp Redmine': if bug.status in ['NEW', 'ASSIGNED']: if external_bug['ext_status'] in [ 'MODIFIED', 'ON_QA', 'VERIFIED', 'CLOSED - CURRENTRELEASE' ]: if 'FailedQA' in bug.cf_verified: needinfo = True external_bug_id = external_bug[ 'ext_bz_bug_id'] redmine_issue = redmine.issue.get( external_bug_id) redmine_user_id = redmine_issue.assigned_to.id needinfo_email = redmine.user.get( redmine_user_id).mail msg = "Bugzilla %s failed QA. Needinfo is set for %s." % \ (bug.id, needinfo_email) for flag in bug.flags: if flag['name'] == 'needinfo' and \ flag['requestee'] == needinfo_email: needinfo = False if needinfo: BZ.update_flags( bug.id, [{ "name": "needinfo", "status": "?", "requestee": needinfo_email, "new": True }]) bug.addcomment("Requesting needsinfo from upstream " \ "developer %s because the 'FailedQA' " \ "flag is set." % needinfo_email) new_failed_qa_record += "%s\n" % msg print msg failed_qa_bugzillas.append(bug.id) else: transition_to_post.append(True) else: transition_to_post.append(False) if not links_back: links_issues_record += 'Redmine #%s -> Bugzilla %s, but Bugzilla %s does ' \ 'not link back\n' % (issue.id, bug.id, bug.id) if len(transition_to_post) > 0 and all(transition_to_post): msg = 'All upstream Pulp bugs are at MODIFIED+. Moving this bug to POST.' bug.setstatus('POST', msg) downstream_changes += 'Bugzilla %s was transitioned to POST\n' % bug.id for bug in bugzilla_bugs: for external_bug in bug.external_bugs: if external_bug['type']['description'] == 'Pulp Redmine': add_cc_list_to_bugzilla_bug(bug) issue_id = external_bug['ext_bz_bug_id'] issue = redmine.issue.get(issue_id) links_back = False for custom_field in issue.custom_fields.resources: if custom_field['name'] == 'Bugzillas' and custom_field[ 'value']: bug_list = [ int(id_str) for id_str in custom_field['value'].split(',') ] for bug_id in bug_list: try: if bug_id == bug.id: links_back = True except KeyError: # If value isn't present this field is not linking back continue except ValueError: # If value is present but empty this field is not linking back continue if not links_back: links_issues_record += 'Bugzilla #%s -> Redmine %s, but Redmine %s does ' \ 'not link back\n' % (bug.id, issue.id, issue.id) if ext_bug_record != '': print '\nBugzilla Updates From Upstream' print '------------------------------' print ext_bug_record if downstream_changes != '': print '\nBugzilla Transitions to POST' print '----------------------------' print downstream_changes if links_issues_record != '': print '\nLink Issues' print '-----------' print links_issues_record if downstream_state_issue_record != '': print '\nDownstream State Issues' print '-----------------------' print downstream_state_issue_record if new_failed_qa_record != '': print '\nNew Bugzillas That Failed QA' print '----------------------------' print new_failed_qa_record if links_issues_record != '' or downstream_state_issue_record != '' or new_failed_qa_record: # Raise an exception so the job fails and Jenkins will send e-mail raise RuntimeError('We need a human here')
def main(): config = ConfigParser.ConfigParser() config.read(os.environ['REDMINE_BUGZILLA_CONF']) username = config.get('bugzilla', 'username') password = config.get('bugzilla', 'password') key = config.get('redmine', 'key') redmine = get_redmine_connection(key) BZ = get_bugzilla_connection(username, password) redmine_issues = [issue for issue in redmine.issue.filter(query_id=24)] non_closed_bug_with_ext_tracker = BUGZILLA_URL + '/buglist.cgi?bug_status=NEW&' \ 'bug_status=ASSIGNED&bug_status=POST&bug_status=MODIFIED&bug_status=ON_DEV&' \ 'bug_status=ON_QA&bug_status=VERIFIED&bug_status=RELEASE_PENDING&' \ 'columnlist=priority%2Cbug_severity%2Cbug_status%2Cshort_desc%2Cchangeddate%2C' \ 'component%2Ctarget_release%2Cassigned_to%2Creporter&f1=external_bugzilla.url&' \ 'list_id=3309842&o1=substring&query_format=advanced&v1=pulp.plan.io' bugzilla_bugs = BZ.query(RHBugzilla.url_to_query(non_closed_bug_with_ext_tracker)) links_issues_record = '' ext_bug_record = '' downstream_state_issue_record = '' downstream_changes = '' for issue in redmine_issues: for custom_field in issue.custom_fields.resources: if custom_field['name'] == 'Bugzillas': if custom_field['value'] == '': continue for bug_id in [int(id_str) for id_str in custom_field['value'].split(',')]: links_back = False try: bug = BZ.getbug(bug_id) except xmlrpclib.Fault as e: if e.faultCode == 102: print 'Bugzilla %s could not be accessed.' % bug_id continue else: raise transition_to_post = [] for external_bug in bug.external_bugs: if external_bug['type']['description'] == 'Foreman Issue Tracker': # If the bug has an external foreman issue, don't transition the BZ transition_to_post.append(False) if external_bug['type']['description'] == 'Pulp Redmine' and \ external_bug['ext_bz_bug_id'] == str(issue.id): add_cc_list_to_bugzilla_bug(bug) ext_params = {} if external_bug['ext_description'] != issue.subject: ext_params['ext_description'] = issue.subject if external_bug['ext_status'] != issue.status.name: ext_params['ext_status'] = issue.status.name if external_bug['ext_priority'] != issue.priority.name: ext_params['ext_priority'] = issue.priority.name if len(ext_params.keys()) > 0: ext_bug_record += 'Bugzilla bug %s updated from upstream bug %s ' \ 'with %s\n' % (bug.id, issue.id, ext_params) ext_params['ids'] = external_bug['id'] BZ.update_external_tracker(**ext_params) if 'ext_status' in ext_params: bug.addcomment( 'The Pulp upstream bug status is at %s. Updating the ' 'external tracker on this bug.' % issue.status.name) if 'ext_priority' in ext_params: bug.addcomment( 'The Pulp upstream bug priority is at %s. Updating the ' 'external tracker on this bug.' % issue.priority.name) if bug.status in ['NEW', 'ASSIGNED']: if issue.status.name in ['MODIFIED', 'ON_QA', 'VERIFIED', 'CLOSED - CURRENTRELEASE']: transition_to_post.append(True) else: transition_to_post.append(False) downstream_POST_plus = ['POST', 'MODIFIED', 'ON_QA', 'VERIFIED', 'RELEASE_PENDING', 'CLOSED'] upstream_POST_minus = ['NEW', 'ASSIGNED', 'POST'] if bug.status in downstream_POST_plus and \ issue.status.name in upstream_POST_minus: msg = 'The downstream bug %s is at POST+ but the upstream bug %s ' \ 'at POST-.\n' % (bug.id, issue.id) downstream_state_issue_record += msg links_back = True if not links_back: links_issues_record += 'Redmine #%s -> Bugzilla %s, but Bugzilla %s does ' \ 'not link back\n' % (issue.id, bug.id, bug.id) if len(transition_to_post) > 0 and all(transition_to_post): msg = 'All upstream Pulp bugs are at MODIFIED+. Moving this bug to POST.' bug.setstatus('POST', msg) downstream_changes += 'Bugzilla %s was transitioned to POST\n' % bug.id for bug in bugzilla_bugs: for external_bug in bug.external_bugs: if external_bug['type']['description'] == 'Pulp Redmine': add_cc_list_to_bugzilla_bug(bug) issue_id = external_bug['ext_bz_bug_id'] issue = redmine.issue.get(issue_id) links_back = False for custom_field in issue.custom_fields.resources: if custom_field['name'] == 'Bugzillas' and custom_field['value']: bug_list = [int(id_str) for id_str in custom_field['value'].split(',')] for bug_id in bug_list: try: if bug_id == bug.id: links_back = True except KeyError: # If value isn't present this field is not linking back continue except ValueError: # If value is present but empty this field is not linking back continue if not links_back: links_issues_record += 'Bugzilla #%s -> Redmine %s, but Redmine %s does ' \ 'not link back\n' % (bug.id, issue.id, issue.id) if ext_bug_record != '': print '\nBugzilla Updates From Upstream' print '------------------------------' print ext_bug_record if downstream_changes != '': print '\nBugzilla Transitions to POST' print '----------------------------' print downstream_changes if links_issues_record != '': print '\nLink Issues' print '-----------' print links_issues_record if downstream_state_issue_record != '': print '\nDownstream State Issues' print '-----------------------' print downstream_state_issue_record if links_issues_record != '' or downstream_state_issue_record != '': # Raise an exception so the job fails and Jenkins will send e-mail raise RuntimeError('We need a human here')
def main(): config = ConfigParser.ConfigParser() config.read(os.environ['REDMINE_BUGZILLA_CONF']) username = config.get('bugzilla', 'username') password = config.get('bugzilla', 'password') key = config.get('redmine', 'key') redmine = get_redmine_connection(key) BZ = get_bugzilla_connection(username, password) bug_with_ext_tracker = \ BUGZILLA_URL + '/buglist.cgi?classification=Red%20Hat&columnlist=priority%2Cbug_severity' \ '%2Cbug_status%2Cshort_desc%2Cchangeddate%2Ccomponent%2Ctarget_release%2C' \ 'assigned_to%2Creporter&f1=external_bugzilla.url&list_id=7254713&o1=' \ 'substring&product=Red%20Hat%20Satellite%206&query_format=advanced&' \ 'resolution=---&resolution=CURRENTRELEASE&resolution=RAWHIDE&resolution=' \ 'ERRATA&resolution=NEXTRELEASE&resolution=INSUFFICIENT_DATA&resolution=EOL' \ '&v1=pulp.plan.io' bugzilla_bugs = BZ.query(RHBugzilla.url_to_query(bug_with_ext_tracker)) upstream_issues_checked_memo = { } # A memo allowing us to never check an issue twice all_BZs = set() BZs_fixed_by_version = defaultdict(lambda: set()) for i, bug in enumerate(bugzilla_bugs): # if i == 20: # break all_BZs.add(bug.id) bug = BZ.getbug(bug.id) upstream_associated_issue_numbers = [] for external_bug in bug.external_bugs: if external_bug['type']['description'] == 'Pulp Redmine': upstream_associated_issue_numbers.append( int(external_bug['ext_bz_bug_id'])) upstream_fixed_versions_for_bz = [] for upstream_id in upstream_associated_issue_numbers: # Check the memo to see if we already know the fix version if upstream_id in upstream_fixed_versions_for_bz: if upstream_fixed_versions_for_bz[upstream_id] != u'': # We already know the upstream version with the fix available upstream_fixed_versions_for_bz.append( upstream_fixed_versions_for_bz[upstream_id]) all_BZs.add(bug.id) # The memo info was used so we can move on to the next upstream issue to check continue upstream_issue = redmine.issue.get(upstream_id) # Issues in 'External' are not actual issues so they should be ignored if upstream_issue.project.name == u'External': # Never check an upstream issue twice upstream_issues_checked_memo[upstream_id] = u'' continue platform_release_field = upstream_issue.custom_fields.get( 4) # 'Platform Release' field # Never check an upstream issue twice upstream_issues_checked_memo[upstream_id] = platform_release_field[ u'value'] if platform_release_field[u'value'] != u'': upstream_fixed_versions_for_bz.append( platform_release_field[u'value']) all_BZs.add(bug.id) if upstream_fixed_versions_for_bz != []: fix_in = max([ semantic_version.Version(v) for v in upstream_fixed_versions_for_bz ]) BZs_fixed_by_version[str(fix_in)].add(bug.id) upstream_versions = [ semantic_version.Version(v) for v in BZs_fixed_by_version.keys() ] upstream_versions.sort() # Ensure in increasing order BZs_fixed_list = [BZs_fixed_by_version[str(v)] for v in upstream_versions] for i in range(1, len(BZs_fixed_list)): BZs_fixed_list[i] = BZs_fixed_list[i - 1] | BZs_fixed_list[i] for i, version in enumerate(upstream_versions): BZs_fixed_by_version[str(version)] = BZs_fixed_list[i] BZs_missing_by_version = {} for version, bugs in BZs_fixed_by_version.iteritems(): BZs_missing_by_version[ version] = all_BZs - BZs_fixed_by_version[version] minimum_version = semantic_version.Version(MINIMUM_VERSION) for v in upstream_versions: if v < minimum_version: continue bugs_in_this_version = BZs_missing_by_version[str(v)] print '%s, %s, https://bugzilla.redhat.com/buglist.cgi?quicksearch=%s' % ( v, len(bugs_in_this_version), ','.join( [str(i) for i in bugs_in_this_version]))