List NEEDSPONSOR tickets with POST or ASSIGNED status

FAS account name extracted from the first few comments of POST or ASSIGNED Review tickets blocked on NEEDSPONSOR are compared with the member list of FAS.
Notes:
1.adminfasusername and adminfaspassword fields needs to be added to review-stats.cfg for querying the member list.
2.Some new tickets are coloured green because they are assigned to user other than nobody@fedoraproject.org
Potential issues:
The script will stall rather than throwing exception if the network was disconnected while querying comments on a bug.(A bug of  python bugzilla modulus?)
This commit is contained in:
yceh 2017-10-01 22:23:59 +08:00 committed by GitHub
parent a4e7278691
commit 0a3276af7f

View file

@ -14,7 +14,7 @@ from copy import deepcopy
from genshi.template import TemplateLoader from genshi.template import TemplateLoader
from optparse import OptionParser from optparse import OptionParser
from validate import Validator from validate import Validator
from fedora.client.fas2 import AccountSystem
VERSION = "4.1" VERSION = "4.1"
# Red Hat's bugzilla # Red Hat's bugzilla
@ -39,6 +39,10 @@ maxpackages = 5
# So the bugzilla module has some way to complain # So the bugzilla module has some way to complain
logging.basicConfig() logging.basicConfig()
fasusernamemap = {}
isnewpackager = {}
nonefasinfo = {}
approvedpackagers = {}
def parse_commandline(): def parse_commandline():
usage = "usage: %prog [options] -c <bugzilla_config> -d <dest_dir> -t <template_dir>" usage = "usage: %prog [options] -c <bugzilla_config> -d <dest_dir> -t <template_dir>"
@ -76,6 +80,8 @@ def parse_config(file):
url = string(default='https://bugzilla.redhat.com/xmlrpc.cgi') url = string(default='https://bugzilla.redhat.com/xmlrpc.cgi')
username = string() username = string()
password = string() password = string()
adminfasusername = string()
adminfaspassword = string()
'''.splitlines() '''.splitlines()
cfg = ConfigObj(file, configspec=spec) cfg = ConfigObj(file, configspec=spec)
@ -177,7 +183,7 @@ def run_query(bz):
'alias', 'assigned_to', 'product', 'creator', 'creator_id', 'status', 'resolution', 'alias', 'assigned_to', 'product', 'creator', 'creator_id', 'status', 'resolution',
'component', 'blocks', 'depends_on', 'summary', 'component', 'blocks', 'depends_on', 'summary',
'whiteboard', 'flags'] 'whiteboard', 'flags']
querydata['bug_status'] = ['NEW', 'ASSIGNED', 'MODIFIED'] querydata['bug_status'] = ['NEW', 'ASSIGNED', 'MODIFIED','POST']
querydata['product'] = ['Fedora', 'Fedora EPEL'] querydata['product'] = ['Fedora', 'Fedora EPEL']
querydata['component'] = ['Package Review'] querydata['component'] = ['Package Review']
querydata['query_format'] = 'advanced' querydata['query_format'] = 'advanced'
@ -190,6 +196,7 @@ def run_query(bz):
dbprint("Running main query.") dbprint("Running main query.")
t = time.time() t = time.time()
bugs = filter(lambda b: b.id not in trackers, bz.query(querydata)) bugs = filter(lambda b: b.id not in trackers, bz.query(querydata))
bugs = bugs[200:500]
dbprint("Done, took {0:.2f}.".format(time.time() - t)) dbprint("Done, took {0:.2f}.".format(time.time() - t))
for bug in bugs: for bug in bugs:
@ -337,6 +344,49 @@ def select_merge(bug, bugd):
return 1 return 1
return 0 return 0
def get_fas_username(bug):
''' find the fas name of package submiter based on first few comments'''
comments = bug.getcomments()
# some review ticket have an empty first comment(ex.1282012)
for comment in comments:
username_idx = comment['text'].find('sername')
if username_idx != -1:
fas_username = comment['text'][username_idx:]
break
try:
fas_username = fas_username[fas_username.find(':')+1:]
if fas_username[0] == '\n':
fas_username = fas_username[1:][:fas_username.find('\n')]
def stripe_spaces(fas_username):
if fas_username[0] == ' ':
return fas_username[1:]
stripe_spaces(fas_username)
else:
return fas_username
except UnboundLocalError:
dbprint(comment)
return ''
#most have space before fas username, but some don't.(ex.879752)
def is_new_packager(bug):
#global variable used: isnewpackager,fasusernamemap,nonefasinfo
try:
return isnewpackager[bug.reporter]
except KeyError :
fasusername = get_fas_username(bug)
if fasusername == '' :
try:
nonefasinfo[bug.reporter].append(bug)
except KeyError :
nonefasinfo[bug.reporter] = [bug]
return False
else:
fasusernamemap[bug.reporter] = fasusername
isnewpackager[bug.reporter] = not (fasusername in approvedpackagers)
return not (fasusername in approvedpackagers)
def select_needsponsor(bug, bugd): def select_needsponsor(bug, bugd):
wb = string.lower(bug.whiteboard) wb = string.lower(bug.whiteboard)
@ -345,11 +395,12 @@ def select_needsponsor(bug, bugd):
and NEEDSPONSOR in bugd['blocks'] and NEEDSPONSOR in bugd['blocks']
and LEGAL not in bugd['blocks'] and LEGAL not in bugd['blocks']
and bug.bug_status != 'CLOSED' and bug.bug_status != 'CLOSED'
and nobody(bug.assigned_to) == '(Nobody)'
and wb.find('buildfails') < 0 and wb.find('buildfails') < 0
and wb.find('notready') < 0 and wb.find('notready') < 0
and wb.find('stalledsubmitter') < 0 and wb.find('stalledsubmitter') < 0
and wb.find('awaitingsubmitter') < 0): and wb.find('awaitingsubmitter') < 0
and (nobody(bug.assigned_to) == '(Nobody)'
or is_new_packager(bug))):
return 1 return 1
return 0 return 0
@ -411,6 +462,14 @@ def rowclass_with_sponsor(bug, count):
rowclass = 'bz_row_even' rowclass = 'bz_row_even'
return rowclass return rowclass
def rowclass_accepted_packages(bug, count):
rowclass = 'bz_row_odd'
if (bug.bug_status in ['ASSIGNED','POST']
or nobody(bug.assigned_to) != '(Nobody)'):
rowclass = 'bz_state_NEEDSPONSOR'
elif count % 2 == 1:
rowclass = 'bz_row_even'
return rowclass
# The data from a standard row in a bug list # The data from a standard row in a bug list
def std_row(bug, rowclass): def std_row(bug, rowclass):
@ -516,7 +575,8 @@ def report_merge(bugs, bugdata, loader, tmpdir, subs):
def report_needsponsor(bugs, bugdata, loader, usermap, tmpdir, subs): def report_needsponsor(bugs, bugdata, loader, usermap, tmpdir, subs):
data = deepcopy(subs) data = deepcopy(subs)
data['description'] = 'This page lists all new NEEDSPONSOR tickets (those without the fedora-review flag set).' data['description'] = ('This page lists new NEEDSPONSOR tickets submitted by new packagers who are not yet sponsored.'
'Tickets colored green are already being assigned for review.')
data['title'] = 'NEEDSPONSOR tickets' data['title'] = 'NEEDSPONSOR tickets'
curreporter = '' curreporter = ''
curcount = 0 curcount = 0
@ -526,7 +586,14 @@ def report_needsponsor(bugs, bugdata, loader, usermap, tmpdir, subs):
for i in bugs: for i in bugs:
if select_needsponsor(i, bugdata[i.id]): if select_needsponsor(i, bugdata[i.id]):
selected.append(i) selected.append(i)
#cleanup bugs that have no fas username
for i in nonefasinfo:
try:
if isnewpackager[i]:
selected += nonefasinfo[i]
except KeyError :
pass
# Determine the oldest reported bug # Determine the oldest reported bug
for i in selected: for i in selected:
if i.reporter not in oldest: if i.reporter not in oldest:
@ -538,7 +605,6 @@ def report_needsponsor(bugs, bugdata, loader, usermap, tmpdir, subs):
selected.sort(key=lambda a: oldest[a.reporter]) selected.sort(key=lambda a: oldest[a.reporter])
for i in selected: for i in selected:
rowclass = rowclass_plain(data['count'])
r = i.reporter r = i.reporter
if curreporter != r: if curreporter != r:
@ -549,7 +615,7 @@ def report_needsponsor(bugs, bugdata, loader, usermap, tmpdir, subs):
data['packagers'].append({'email': r, 'name': name, 'oldest': human_date(oldest[r]), 'bugs': []}) data['packagers'].append({'email': r, 'name': name, 'oldest': human_date(oldest[r]), 'bugs': []})
curreporter = r curreporter = r
curcount = 0 curcount = 0
rowclass = rowclass_accepted_packages(i, curcount)
data['packagers'][-1]['bugs'].append(std_row(i, rowclass)) data['packagers'][-1]['bugs'].append(std_row(i, rowclass))
data['count'] += 1 data['count'] += 1
curcount += 1 curcount += 1
@ -630,6 +696,9 @@ if __name__ == '__main__':
bz = bugzilla.RHBugzilla(url=config['url'], cookiefile=None, user=config['username'], password=config['password']) bz = bugzilla.RHBugzilla(url=config['url'], cookiefile=None, user=config['username'], password=config['password'])
t = time.time() t = time.time()
(bugs, bugdata, usermap) = run_query(bz) (bugs, bugdata, usermap) = run_query(bz)
approvedpackagers=[]
for indi in AccountSystem(username=config['adminfasusername'],password=config['adminfaspassword']).group_members('packager'):
approvedpackagers.append(indi.toDict()['username'].encode('utf-8'))
querytime = time.time() - t querytime = time.time() - t
# Don't bother running this stuff until the query completes, since it fails # Don't bother running this stuff until the query completes, since it fails