def process_changes(changes): now = datetime.datetime.utcnow() # NOTE(bnemec): This is only used in days_since_negative_feedback, # but there's no sense recalculating it every iteration through the loop. now_ts = calendar.timegm(now.timetuple()) for change in changes: if utils.is_workinprogress(change): continue # NOTE(bnemec): I think Gerrit already returns patch sets sorted, but # it won't hurt to make sure. change['patchSets'].sort(key=lambda a: int(a['number'])) last_patchset = change['patchSets'][-1] if utils.patch_set_approved(last_patchset): continue approvals = last_patchset.get('approvals', []) if not approvals: continue approvals.sort(key=lambda a: a['grantedOn']) # This most likely means the change was abandoned and restored # since the last vote. Let's not abandon it again. if change['lastUpdated'] > approvals[-1]['grantedOn']: continue days = days_since_negative_feedback(approvals, now_ts) #warn(change['id'], last_patchset['revision']) if days > ABANDON_DAYS: print 'Abandoning %s' % change['url'] abandon(change['id'])
def main(argv=None): if argv is None: argv = sys.argv optparser = optparse.OptionParser() optparser.add_option( '-p', '--project', default='projects/nova.json', help='JSON file describing the project to generate stats for') optparser.add_option( '-a', '--all', action='store_true', help='Generate stats across all known projects (*.json)') optparser.add_option('-u', '--user', default=getpass.getuser(), help='gerrit user') optparser.add_option('-k', '--key', default=None, help='ssh key for gerrit') optparser.add_option('-s', '--stable', action='store_true', help='Include stable branch commits') optparser.add_option( '-l', '--longest-waiting', type='int', default=5, help='Show n changesets that have waited the longest)') optparser.add_option( '-m', '--waiting-more', type='int', default=7, help='Show number of changesets that have waited more than n days)') optparser.add_option('-H', '--html', action='store_true', help='Use HTML output instead of plain text') optparser.add_option('--server', default='review.openstack.org', help='Gerrit server to connect to') optparser.add_option('--debug', action='store_true', help='Show extra debug output') optparser.add_option('--projects-dir', default='./projects', help='Directory where to locate the project files') optparser.add_option( '--output', '-o', default='-', help="Where to write output. - for stdout. The file will be appended" " if it exists.") options, args = optparser.parse_args() logging.basicConfig(level=logging.ERROR) if options.debug: logging.root.setLevel(logging.DEBUG) projects = utils.get_projects_info(options.project, options.all, base_dir=options.projects_dir) if not projects: print "Please specify a project." sys.exit(1) changes = utils.get_changes(projects, options.user, options.key, only_open=True, server=options.server) waiting_on_submitter = [] waiting_on_reviewer = [] now = datetime.datetime.utcnow() now_ts = calendar.timegm(now.timetuple()) for change in changes: if 'rowCount' in change: continue if not options.stable and 'stable' in change['branch']: continue if utils.is_workinprogress(change): # Filter out WORKINPROGRESS continue latest_patch = change['patchSets'][-1] if utils.patch_set_approved(latest_patch): # Ignore patches already approved and just waiting to merge continue waiting_for_review = True approvals = latest_patch.get('approvals', []) approvals.sort(key=lambda a: a['grantedOn']) for review in approvals: if review['type'] not in ('CRVW', 'VRIF', 'Code-Review', 'Verified'): continue if review['value'] in ('-1', '-2'): waiting_for_review = False break change['age'] = utils.get_age_of_patch(latest_patch, now_ts) change['age2'] = utils.get_age_of_patch(change['patchSets'][0], now_ts) patch = find_oldest_no_nack(change) change['age3'] = utils.get_age_of_patch(patch, now_ts) if patch else 0 if waiting_for_review: waiting_on_reviewer.append(change) else: waiting_on_submitter.append(change) stats = gen_stats(projects, waiting_on_reviewer, waiting_on_submitter, options) if options.output == '-': output = sys.stdout else: output = open(options.output, 'at') try: if options.html: print_stats_html(stats, f=output) else: print_stats_txt(stats, f=output) finally: if output is not sys.stdout: output.close()
def main(argv=None): if argv is None: argv = sys.argv optparser = optparse.OptionParser() optparser.add_option( '-p', '--project', default='projects/nova.json', help='JSON file describing the project to generate stats for') optparser.add_option( '-a', '--all', action='store_true', help='Generate stats across all known projects (*.json)') optparser.add_option( '-u', '--user', default=getpass.getuser(), help='gerrit user') optparser.add_option( '-k', '--key', default=None, help='ssh key for gerrit') optparser.add_option( '-s', '--stable', action='store_true', help='Include stable branch commits') optparser.add_option( '-l', '--longest-waiting', type='int', default=5, help='Show n changesets that have waited the longest)') optparser.add_option( '-m', '--waiting-more', type='int', default=7, help='Show number of changesets that have waited more than n days)') optparser.add_option( '-H', '--html', action='store_true', help='Use HTML output instead of plain text') optparser.add_option( '--server', default='review.opendev.org', help='Gerrit server to connect to') optparser.add_option( '--debug', action='store_true', help='Show extra debug output') optparser.add_option( '--projects-dir', default='./projects', help='Directory where to locate the project files') optparser.add_option( '--output', '-o', default='-', help="Where to write output. - for stdout. The file will be appended" " if it exists.") options, args = optparser.parse_args() logging.basicConfig(level=logging.ERROR) if options.debug: logging.root.setLevel(logging.DEBUG) projects = utils.get_projects_info(options.project, options.all, base_dir=options.projects_dir) if not projects: print "Please specify a project." sys.exit(1) changes = utils.get_changes(projects, options.user, options.key, only_open=True, server=options.server) waiting_on_submitter = [] waiting_on_reviewer = [] now = datetime.datetime.utcnow() now_ts = calendar.timegm(now.timetuple()) for change in changes: if 'rowCount' in change: continue if not options.stable and 'stable' in change['branch']: continue if utils.is_workinprogress(change): # Filter out WORKINPROGRESS continue latest_patch = change['patchSets'][-1] if utils.patch_set_approved(latest_patch): # Ignore patches already approved and just waiting to merge continue waiting_for_review = True approvals = latest_patch.get('approvals', []) approvals.sort(key=lambda a: a['grantedOn']) for review in approvals: if review['type'] not in ('CRVW', 'VRIF', 'Code-Review', 'Verified'): continue if review['value'] in ('-1', '-2'): waiting_for_review = False break change['age'] = utils.get_age_of_patch(latest_patch, now_ts) change['age2'] = utils.get_age_of_patch(change['patchSets'][0], now_ts) patch = find_oldest_no_nack(change) change['age3'] = utils.get_age_of_patch(patch, now_ts) if patch else 0 if waiting_for_review: waiting_on_reviewer.append(change) else: waiting_on_submitter.append(change) stats = gen_stats(projects, waiting_on_reviewer, waiting_on_submitter, options) if options.output == '-': output = sys.stdout else: output = open(options.output, 'at') try: if options.html: print_stats_html(stats, f=output) else: print_stats_txt(stats, f=output) finally: if output is not sys.stdout: output.close()