示例#1
0
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(
        '-s', '--stable', default='', metavar='BRANCH',
        help='Generate stats for the specified stable BRANCH ("havana") '
             'across all integrated projects')
    optparser.add_option(
        '-o', '--output', default='-',
        help='Where to write output. If - stdout is used and only one output'
            'format may be given. Otherwise the output format is appended to'
            'the output parameter to generate file names.')
    optparser.add_option(
        '--outputs', default=['txt'], action='append',
        help='Select what outputs to generate. (txt,csv).')
    optparser.add_option(
        '-d', '--days', type='int', default=14,
        help='Number of days to consider')
    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(
        '-r', '--csv-rows', default=0, help='Max rows for CSV output',
        type='int', dest='csv_rows')

    options, args = optparser.parse_args()

    if options.stable:
        projects = utils.get_projects_info('projects/stable.json', False)
    else:
        projects = utils.get_projects_info(options.project, options.all)

    if not projects:
        print "Please specify a project."
        sys.exit(1)

    reviewers = {}

    now = datetime.datetime.utcnow()
    cut_off = now - datetime.timedelta(days=options.days)
    ts = calendar.timegm(cut_off.timetuple())
    now_ts = calendar.timegm(now.timetuple())

    change_stats = {
        'patches': 0,
        'created': 0,
        'involved': 0,
        'merged': 0,
        'abandoned': 0,
        'wip': 0,
    }

    for project in projects:
        changes = utils.get_changes([project], options.user, options.key,
                                    stable=options.stable)
        for change in changes:
            patch_for_change = False
            first_patchset = True
            for patchset in change.get('patchSets', []):
                process_patchset(project, patchset, reviewers, ts)
                age = utils.get_age_of_patch(patchset, now_ts)
                if (now_ts - age) > ts:
                    change_stats['patches'] += 1
                    patch_for_change = True
                    if first_patchset:
                        change_stats['created'] += 1
                first_patchset = False
            if patch_for_change:
                change_stats['involved'] += 1
                if change['status'] == 'MERGED':
                    change_stats['merged'] += 1
                elif change['status'] == 'ABANDONED':
                    change_stats['abandoned'] += 1
                elif change['status'] == 'WORKINPROGRESS':
                    change_stats['wip'] += 1

    reviewers = [(v, k) for k, v in reviewers.iteritems()
                 if k.lower() not in ('jenkins', 'smokestack')]
    reviewers.sort(reverse=True, key=lambda r: r[0]['total'])
    # Do logical processing of reviewers.
    reviewer_data = []
    totals = {
        'all': 0,
        'core': 0,
    }
    for k, v in reviewers:
        in_core_team = False
        for project in projects:
            if v in project['core-team']:
                in_core_team = True
                break
        name = '%s%s' % (v, ' **' if in_core_team else '')
        plus = float(k['votes']['2'] + k['votes']['1'])
        minus = float(k['votes']['-2'] + k['votes']['-1'])
        all_reviews = plus + minus
        ratio = ((plus / (all_reviews)) * 100) if all_reviews > 0 else 0
        r = (k['total'], k['votes']['-2'],
             k['votes']['-1'], k['votes']['1'],
             k['votes']['2'], k['votes']['A'], "%5.1f%%" % ratio)
        dratio = (((float(k['disagreements']) / all_reviews) * 100)
                  if all_reviews else 0.0)
        d = (k['disagreements'], "%5.1f%%" % dratio)
        sratio = ((float(k['total']) / k['received']) * 100
                  if k['received'] else 0)
        s = (k['received'], "%5.1f%%" % sratio if k['received'] else 'inf')
        reviewer_data.append((name, r, d, s))
        totals['all'] += k['total']
        if in_core_team:
            totals['core'] += k['total']
    # And output.
    writers = {
        'csv': write_csv,
        'txt': write_pretty,
        }
    if options.output == '-':
        if len(options.outputs) != 1:
            raise Exception("Can only output one format to stdout.")
    for output in options.outputs:
        if options.output == '-':
            file_obj = sys.stdout
            on_done = None
        else:
            file_obj = open(options.output + '.' + output, 'wt')
            on_done = file_obj.close
        try:
            writer = writers[output]
            writer(reviewer_data, file_obj, options, reviewers, projects,
                   totals, change_stats)
        finally:
            if on_done:
                on_done()
    return 0
示例#2
0
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')

    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 change['status'] != 'NEW':
            # 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.html:
        print_stats_html(stats)
    else:
        print_stats_txt(stats)
示例#3
0
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(
        '-s',
        '--stable',
        default='',
        metavar='BRANCH',
        help='Generate stats for the specified stable BRANCH ("havana") '
        'across all integrated projects')
    optparser.add_option(
        '-o',
        '--output',
        default='-',
        help='Where to write output. If - stdout is used and only one output '
        'format may be given. Otherwise the output format is appended to '
        'the output parameter to generate file names.')
    optparser.add_option('--outputs',
                         default=['txt'],
                         action='append',
                         help='Select what outputs to generate. (txt,csv).')
    optparser.add_option('-d',
                         '--days',
                         type='int',
                         default=14,
                         help='Number of days to consider')
    optparser.add_option('-u',
                         '--user',
                         default=getpass.getuser(),
                         help='gerrit user')
    optparser.add_option('-P',
                         '--password',
                         default=getpass.getuser(),
                         help='gerrit HTTP password')
    optparser.add_option('-k',
                         '--key',
                         default=None,
                         help='ssh key for gerrit')
    optparser.add_option('-r',
                         '--csv-rows',
                         default=0,
                         help='Max rows for CSV output',
                         type='int',
                         dest='csv_rows')
    optparser.add_option('--server',
                         default='review.openstack.org',
                         help='Gerrit server to connect to')

    options, args = optparser.parse_args()

    if options.stable:
        projects = utils.get_projects_info('projects/stable.json', False)
    else:
        projects = utils.get_projects_info(options.project, options.all)

    if not projects:
        print "Please specify a project."
        sys.exit(1)

    reviewers = {}

    now = datetime.datetime.utcnow()
    cut_off = now - datetime.timedelta(days=options.days)
    ts = calendar.timegm(cut_off.timetuple())
    now_ts = calendar.timegm(now.timetuple())

    change_stats = {
        'patches': 0,
        'created': 0,
        'involved': 0,
        'merged': 0,
        'abandoned': 0,
        'wip': 0,
    }

    for project in projects:
        changes = utils.get_changes([project],
                                    options.user,
                                    options.key,
                                    stable=options.stable,
                                    server=options.server)
        for change in changes:
            patch_for_change = False
            first_patchset = True
            for patchset in change.get('patchSets', []):
                process_patchset(project, patchset, reviewers, ts, options)
                age = utils.get_age_of_patch(patchset, now_ts)
                if (now_ts - age) > ts:
                    change_stats['patches'] += 1
                    patch_for_change = True
                    if first_patchset:
                        change_stats['created'] += 1
                first_patchset = False
            if patch_for_change:
                change_stats['involved'] += 1
                if change['status'] == 'MERGED':
                    change_stats['merged'] += 1
                elif change['status'] == 'ABANDONED':
                    change_stats['abandoned'] += 1
                elif change['status'] == 'WORKINPROGRESS':
                    change_stats['wip'] += 1

    reviewers = [(v, k) for k, v in reviewers.iteritems()
                 if k.lower() not in ('jenkins', 'smokestack')]
    reviewers.sort(reverse=True, key=lambda r: r[0]['total'])
    # Do logical processing of reviewers.
    reviewer_data = []
    totals = {
        'all': 0,
        'core': 0,
    }
    for k, v in reviewers:
        in_core_team = False
        for project in projects:
            if v in utils.get_core_team(project, options.server, options.user,
                                        options.password):
                in_core_team = True
                break
        name = '%s%s' % (v, ' **' if in_core_team else '')
        plus = float(k['votes']['2'] + k['votes']['1'])
        minus = float(k['votes']['-2'] + k['votes']['-1'])
        all_reviews = plus + minus
        ratio = ((plus / (all_reviews)) * 100) if all_reviews > 0 else 0
        r = (k['total'], k['votes']['-2'], k['votes']['-1'], k['votes']['1'],
             k['votes']['2'], k['votes']['A'], "%5.1f%%" % ratio)
        dratio = (((float(k['disagreements']) / all_reviews) *
                   100) if all_reviews else 0.0)
        d = (k['disagreements'], "%5.1f%%" % dratio)
        sratio = ((float(k['total']) / k['received']) *
                  100 if k['received'] else 0)
        s = (k['received'], "%5.1f%%" % sratio if k['received'] else 'inf')
        reviewer_data.append((name, r, d, s))
        totals['all'] += k['total']
        if in_core_team:
            totals['core'] += k['total']
    # And output.
    writers = {
        'csv': write_csv,
        'txt': write_pretty,
    }
    if options.output == '-':
        if len(options.outputs) != 1:
            raise Exception("Can only output one format to stdout.")
    for output in options.outputs:
        if options.output == '-':
            file_obj = sys.stdout
            on_done = None
        else:
            file_obj = open(options.output + '.' + output, 'wt')
            on_done = file_obj.close
        try:
            writer = writers[output]
            writer(reviewer_data, file_obj, options, reviewers, projects,
                   totals, change_stats)
        finally:
            if on_done:
                on_done()
    return 0
示例#4
0
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()
示例#5
0
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(
        "-s",
        "--stable",
        default="",
        metavar="BRANCH",
        help='Generate stats for the specified stable BRANCH ("havana") ' "across all integrated projects",
    )
    optparser.add_option(
        "-o",
        "--output",
        default="-",
        help="Where to write output. If - stdout is used and only one output "
        "format may be given. Otherwise the output format is appended to "
        "the output parameter to generate file names.",
    )
    optparser.add_option(
        "--outputs", default=["txt"], action="append", help="Select what outputs to generate. (txt,csv)."
    )
    optparser.add_option("-d", "--days", type="int", default=14, help="Number of days to consider")
    optparser.add_option("-u", "--user", default=getpass.getuser(), help="gerrit user")
    optparser.add_option("-P", "--password", default=getpass.getuser(), help="gerrit HTTP password")
    optparser.add_option("-k", "--key", default=None, help="ssh key for gerrit")
    optparser.add_option("-r", "--csv-rows", default=0, help="Max rows for CSV output", type="int", dest="csv_rows")
    optparser.add_option("--server", default="review.openstack.org", help="Gerrit server to connect to")

    options, args = optparser.parse_args()

    if options.stable:
        projects = utils.get_projects_info("projects/stable.json", False)
    else:
        projects = utils.get_projects_info(options.project, options.all)

    if not projects:
        print "Please specify a project."
        sys.exit(1)

    reviewers = {}

    now = datetime.datetime.utcnow()
    cut_off = now - datetime.timedelta(days=options.days)
    ts = calendar.timegm(cut_off.timetuple())
    now_ts = calendar.timegm(now.timetuple())

    change_stats = {"patches": 0, "created": 0, "involved": 0, "merged": 0, "abandoned": 0, "wip": 0}

    for project in projects:
        changes = utils.get_changes([project], options.user, options.key, stable=options.stable, server=options.server)
        for change in changes:
            patch_for_change = False
            first_patchset = True
            for patchset in change.get("patchSets", []):
                process_patchset(project, patchset, reviewers, ts, options)
                age = utils.get_age_of_patch(patchset, now_ts)
                if (now_ts - age) > ts:
                    change_stats["patches"] += 1
                    patch_for_change = True
                    if first_patchset:
                        change_stats["created"] += 1
                first_patchset = False
            if patch_for_change:
                change_stats["involved"] += 1
                if change["status"] == "MERGED":
                    change_stats["merged"] += 1
                elif change["status"] == "ABANDONED":
                    change_stats["abandoned"] += 1
                elif change["status"] == "WORKINPROGRESS":
                    change_stats["wip"] += 1

    reviewers = [(v, k) for k, v in reviewers.iteritems() if k.lower() not in ("jenkins", "smokestack")]
    reviewers.sort(reverse=True, key=lambda r: r[0]["total"])
    # Do logical processing of reviewers.
    reviewer_data = []
    totals = {"all": 0, "core": 0}
    for k, v in reviewers:
        in_core_team = False
        for project in projects:
            if v in utils.get_core_team(project, options.server, options.user, options.password):
                in_core_team = True
                break
        name = "%s%s" % (v, " **" if in_core_team else "")
        plus = float(k["votes"]["2"] + k["votes"]["1"])
        minus = float(k["votes"]["-2"] + k["votes"]["-1"])
        all_reviews = plus + minus
        ratio = ((plus / (all_reviews)) * 100) if all_reviews > 0 else 0
        r = (
            k["total"],
            k["votes"]["-2"],
            k["votes"]["-1"],
            k["votes"]["1"],
            k["votes"]["2"],
            k["votes"]["A"],
            "%5.1f%%" % ratio,
        )
        dratio = ((float(k["disagreements"]) / all_reviews) * 100) if all_reviews else 0.0
        d = (k["disagreements"], "%5.1f%%" % dratio)
        sratio = (float(k["total"]) / k["received"]) * 100 if k["received"] else 0
        s = (k["received"], "%5.1f%%" % sratio if k["received"] else "inf")
        reviewer_data.append((name, r, d, s))
        totals["all"] += k["total"]
        if in_core_team:
            totals["core"] += k["total"]
    # And output.
    writers = {"csv": write_csv, "txt": write_pretty}
    if options.output == "-":
        if len(options.outputs) != 1:
            raise Exception("Can only output one format to stdout.")
    for output in options.outputs:
        if options.output == "-":
            file_obj = sys.stdout
            on_done = None
        else:
            file_obj = open(options.output + "." + output, "wt")
            on_done = file_obj.close
        try:
            writer = writers[output]
            writer(reviewer_data, file_obj, options, reviewers, projects, totals, change_stats)
        finally:
            if on_done:
                on_done()
    return 0