add a tool for determining unaccounted for rechecks
this is specifically not in cmd because this is designed as a local spot checking tool only. However it's more useful in the er repository than on my local disk. builds a summary report of rechecks found in gerrit in the last 2 weeks, including how many had a bug, and how many had a bug we don't know about. Change-Id: I6a99a3bcec527652901c8aa3639926a8e4a518d5
This commit is contained in:
parent
2fa86a63cc
commit
b60efa16d4
11
tools/README.rst
Normal file
11
tools/README.rst
Normal file
@ -0,0 +1,11 @@
|
||||
====================================
|
||||
Elastic Recheck Useful Point Tools
|
||||
====================================
|
||||
|
||||
These are useful point tools that are examples of using elastic
|
||||
recheck to get additionally useful information out of the
|
||||
system. Items in this directory do not have unit tests,
|
||||
intentionally. This is about useful examples, that are better shared
|
||||
than left on people's hard drives to get lost in the mists of time.
|
||||
|
||||
All tools should have a -h which explain what they do.
|
134
tools/unaccounted_rechecks.py
Executable file
134
tools/unaccounted_rechecks.py
Executable file
@ -0,0 +1,134 @@
|
||||
#!/usr/bin/python
|
||||
#
|
||||
# Copyright 2014 Hewlett-Packard Development Company, L.P.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import argparse
|
||||
import getpass
|
||||
import os.path
|
||||
import re
|
||||
import time
|
||||
|
||||
from gerritlib import gerrit
|
||||
|
||||
|
||||
def get_options():
|
||||
parser = argparse.ArgumentParser(
|
||||
description='Find rechecks not accounted for in ER')
|
||||
parser.add_argument('-u', '--user', help='Gerrit User',
|
||||
default=getpass.getuser())
|
||||
tryfiles = ('id_gerrit', 'id_rsa', 'id_dsa')
|
||||
default_key = ""
|
||||
for f in tryfiles:
|
||||
trykey = os.path.join(os.path.expanduser("~"), '.ssh', f)
|
||||
if os.path.exists(trykey):
|
||||
default_key = trykey
|
||||
break
|
||||
parser.add_argument('-k', '--key', help='Gerrit SSH Key',
|
||||
default=default_key)
|
||||
parser.add_argument('-d', '--dir', help="Queries Directory",
|
||||
default="queries")
|
||||
parser.add_argument('-D', '--days', help="Number of Days to Query",
|
||||
default=14)
|
||||
return parser.parse_args()
|
||||
|
||||
|
||||
def connect_to_gerrit(user, key):
|
||||
return gerrit.Gerrit('review.openstack.org', user, 29418, key)
|
||||
|
||||
|
||||
def collect_rechecks(gerrit, days="14"):
|
||||
# query only during the last 2 weeks, as that's what ER knows about
|
||||
since = int(time.time()) - 24 * 60 * 60 * int(days)
|
||||
changes = []
|
||||
sortkey = None
|
||||
while True:
|
||||
query = ("--patch-sets --comments project:^openstack.* "
|
||||
" NOT age:%sd" % days)
|
||||
if sortkey:
|
||||
query += " resume_sortkey:%s" % sortkey
|
||||
|
||||
data = gerrit.bulk_query(query)
|
||||
if len(data) <= 1:
|
||||
# means we only have the counter row
|
||||
break
|
||||
|
||||
for d in data:
|
||||
if 'comments' in d:
|
||||
sortkey = d['sortKey']
|
||||
comments = d['comments']
|
||||
project = d['project']
|
||||
for comment in comments:
|
||||
if comment['timestamp'] < since:
|
||||
# bail early if the comment is outside the ER window
|
||||
continue
|
||||
|
||||
m = re.search('recheck (no bug|bug (\#)?(?P<bugno>\d+))$',
|
||||
comment['message'])
|
||||
if m:
|
||||
dev = None
|
||||
if 'username' in comment['reviewer']:
|
||||
dev = comment['reviewer']['username']
|
||||
bug = m.group('bugno') or 'no bug'
|
||||
changes.append(
|
||||
{'dev': dev,
|
||||
'project': project,
|
||||
'bug': bug,
|
||||
'review': d['url']})
|
||||
return changes
|
||||
|
||||
|
||||
def has_er_bug(dirname, bug):
|
||||
return os.path.exists(os.path.join(dirname, "%s.yaml" % bug))
|
||||
|
||||
|
||||
def cross_ref_with_er(changes, dirname):
|
||||
for i in range(len(changes)):
|
||||
changes[i]['er'] = has_er_bug(dirname, changes[i]['bug'])
|
||||
return changes
|
||||
|
||||
|
||||
def summarize_changes(changes):
|
||||
no_er = {}
|
||||
print "Summary"
|
||||
print "%4.4s - Total Rechecks" % (len(changes))
|
||||
print "%4.4s - Total w/Bug" % (
|
||||
len([c for c in changes if c['bug'] != 'no bug']))
|
||||
print "%4.4s - Total w/Bug and new recheck" % (
|
||||
len([c for c in changes if (c['bug'] != 'no bug' and not c['er'])]))
|
||||
|
||||
for c in changes:
|
||||
bug = c['bug']
|
||||
if bug != 'no bug' and not c['er']:
|
||||
if bug not in no_er:
|
||||
no_er[bug] = {'count': 0, 'reviews': []}
|
||||
no_er[bug]['count'] += 1
|
||||
no_er[bug]['reviews'].append(c['review'])
|
||||
print
|
||||
print "New bugs"
|
||||
for k, v in no_er.iteritems():
|
||||
print "Bug %s found %d times" % (k, v['count'])
|
||||
for rev in v['reviews']:
|
||||
print " - %s" % rev
|
||||
|
||||
|
||||
def main():
|
||||
opts = get_options()
|
||||
g = connect_to_gerrit(opts.user, opts.key)
|
||||
changes = collect_rechecks(g, opts.days)
|
||||
changes = cross_ref_with_er(changes, opts.dir)
|
||||
summarize_changes(changes)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
Loading…
Reference in New Issue
Block a user