Added time-based score for patches
Based on the number of days since the last patch was posted Also added a tooltip to explain scores Change-Id: I1f13a97ddd8714297a331be91146f9742bbb9766
This commit is contained in:
parent
e2c0efd86f
commit
0dfad93f30
|
@ -1,6 +1,7 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
from time import time
|
||||||
from reviewday.gerrit import reviews as gerrit_reviews
|
from reviewday.gerrit import reviews as gerrit_reviews
|
||||||
from reviewday.util import create_report
|
from reviewday.util import create_report
|
||||||
from reviewday.launchpad import LaunchPad
|
from reviewday.launchpad import LaunchPad
|
||||||
|
@ -21,13 +22,14 @@ smoker = SmokeStack('https://smokestack.openstack.org/jobs.json?limit=10000')
|
||||||
|
|
||||||
projects = {}
|
projects = {}
|
||||||
|
|
||||||
for project in ['nova', 'glance', 'keystone', 'swift', 'neutron', 'cinder',
|
cur_timestamp = time()
|
||||||
|
for project in ['nova', 'glance', 'keystone', 'swift', 'quantum', 'cinder',
|
||||||
'tempest', 'heat', 'ceilometer']:
|
'tempest', 'heat', 'ceilometer']:
|
||||||
if project not in projects:
|
if project not in projects:
|
||||||
projects[project] = []
|
projects[project] = []
|
||||||
for review in gerrit_reviews(project):
|
for review in gerrit_reviews(project):
|
||||||
try:
|
try:
|
||||||
mp = MergeProp(lp, smoker, review)
|
mp = MergeProp(lp, smoker, review, cur_timestamp)
|
||||||
projects[project].append(mp)
|
projects[project].append(mp)
|
||||||
except:
|
except:
|
||||||
print 'Error creating merge prop %s' % review
|
print 'Error creating merge prop %s' % review
|
||||||
|
|
|
@ -22,7 +22,11 @@ def fail_status(job_data, token):
|
||||||
|
|
||||||
|
|
||||||
def review_feedback(mp):
|
def review_feedback(mp):
|
||||||
return '
'.join(mp.feedback)
|
return ' '.join(mp.feedback)
|
||||||
|
|
||||||
|
|
||||||
|
def review_score(mp):
|
||||||
|
return ' '.join(mp.reason)
|
||||||
|
|
||||||
|
|
||||||
def display_feedback(mp):
|
def display_feedback(mp):
|
||||||
|
|
|
@ -1,22 +1,22 @@
|
||||||
class MergeProp(object):
|
class MergeProp(object):
|
||||||
|
|
||||||
def _calc_score(self, lp, project, topic):
|
def _calc_score(self, lp, cur_timestamp):
|
||||||
cause = 'No link'
|
cause = 'No link'
|
||||||
try:
|
try:
|
||||||
if topic.find('bug/') == 0:
|
if self.topic.find('bug/') == 0:
|
||||||
bug = lp.bug(topic[4:])
|
bug = lp.bug(self.topic[4:])
|
||||||
#FIXME: bug.importance doesn't seem to work but it should?
|
#FIXME: bug.importance doesn't seem to work but it should?
|
||||||
cause = '%s bugfix' % bug.bug_tasks[0].importance
|
cause = '%s bugfix' % bug.bug_tasks[0].importance
|
||||||
elif topic.find('bp/') == 0:
|
elif self.topic.find('bp/') == 0:
|
||||||
spec = lp.specification(project, topic[3:])
|
spec = lp.specification(self.project, self.topic[3:])
|
||||||
if spec:
|
if spec:
|
||||||
cause = '%s feature' % spec.priority
|
cause = '%s feature' % spec.priority
|
||||||
else:
|
else:
|
||||||
spec = lp.specification(project, topic)
|
spec = lp.specification(self.project, self.topic)
|
||||||
if spec:
|
if spec:
|
||||||
cause = '%s feature' % spec.priority
|
cause = '%s feature' % spec.priority
|
||||||
except:
|
except:
|
||||||
print 'WARNING: unable to find cause for %s' % topic
|
print 'WARNING: unable to find cause for %s' % self.topic
|
||||||
cause = 'No link'
|
cause = 'No link'
|
||||||
|
|
||||||
cause_score = {
|
cause_score = {
|
||||||
|
@ -37,11 +37,22 @@ class MergeProp(object):
|
||||||
}
|
}
|
||||||
|
|
||||||
if cause not in cause_score:
|
if cause not in cause_score:
|
||||||
print 'WARNING: unable to find score for (%s, %s)' % (topic, cause)
|
print 'WARNING: unable to find score for ' \
|
||||||
return ("Unknown cause: " + cause, 0)
|
'(%s, %s)' % (self.topic, cause)
|
||||||
return (cause, cause_score[cause])
|
return ("No link", "Unknown cause: " + cause, 0)
|
||||||
|
score = cause_score[cause]
|
||||||
|
reason = [cause + " (+%d)" % (score)]
|
||||||
|
# Add a score based on the time the patch has been waiting for approval
|
||||||
|
days_old = int((cur_timestamp - self.revisionCreatedOn) / 86400)
|
||||||
|
if ((days_old > 0) and (self.lowest_feedback != -2)):
|
||||||
|
# A medium bugfix will have to be around for 10 days before it is
|
||||||
|
# ranked higher than a low feature.
|
||||||
|
days_old_score = 3 * days_old
|
||||||
|
reason.append("%d days old (+%d)" % (days_old, days_old_score))
|
||||||
|
score = score + days_old_score
|
||||||
|
return (cause, reason, score)
|
||||||
|
|
||||||
def __init__(self, lp, smoker, review):
|
def __init__(self, lp, smoker, review, cur_timestamp):
|
||||||
self.owner_name = review['owner']['name']
|
self.owner_name = review['owner']['name']
|
||||||
self.url = '%s/#change,%s' % tuple(review['url'].rsplit('/', 1))
|
self.url = '%s/#change,%s' % tuple(review['url'].rsplit('/', 1))
|
||||||
self.subject = review['subject']
|
self.subject = review['subject']
|
||||||
|
@ -52,10 +63,8 @@ class MergeProp(object):
|
||||||
self.topic = ''
|
self.topic = ''
|
||||||
self.revision = review['currentPatchSet']['revision']
|
self.revision = review['currentPatchSet']['revision']
|
||||||
self.refspec = review['currentPatchSet']['ref']
|
self.refspec = review['currentPatchSet']['ref']
|
||||||
|
self.revisionCreatedOn = review['currentPatchSet']['createdOn']
|
||||||
self.number = review['number']
|
self.number = review['number']
|
||||||
cause, score = self._calc_score(lp, self.project, self.topic)
|
|
||||||
self.score = score
|
|
||||||
self.cause = cause
|
|
||||||
self.jobs = smoker.jobs(self.revision[:7])
|
self.jobs = smoker.jobs(self.revision[:7])
|
||||||
self.feedback = []
|
self.feedback = []
|
||||||
|
|
||||||
|
@ -69,3 +78,9 @@ class MergeProp(object):
|
||||||
|
|
||||||
self.lowest_feedback = min(self.lowest_feedback, value) or value
|
self.lowest_feedback = min(self.lowest_feedback, value) or value
|
||||||
self.highest_feedback = max(self.highest_feedback, value) or value
|
self.highest_feedback = max(self.highest_feedback, value) or value
|
||||||
|
|
||||||
|
# Make use of the feedback in calculating the score
|
||||||
|
cause, reason, score = self._calc_score(lp, cur_timestamp)
|
||||||
|
self.score = score
|
||||||
|
self.reason = reason
|
||||||
|
self.cause = cause
|
||||||
|
|
|
@ -93,8 +93,7 @@
|
||||||
$mp.owner_name
|
$mp.owner_name
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<span class="sortkey">$mp.score</span>
|
<a title="$helper.review_score($mp)">$mp.score</a>
|
||||||
$mp.score
|
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<a title="$helper.review_feedback($mp)">$helper.display_feedback($mp)</a>
|
<a title="$helper.review_feedback($mp)">$helper.display_feedback($mp)</a>
|
||||||
|
|
Loading…
Reference in New Issue