Guess core engineers by their review marks
Part of blueprint review-disagreements Change-Id: I6815c0641c7ef21ade958e3b8ecb03b61b307d13
This commit is contained in:
parent
626c59a45c
commit
a70a127c5e
@ -16,6 +16,20 @@
|
||||
{% block content %}
|
||||
<h1>{{ user.user_name }} activity report</h1>
|
||||
|
||||
<h2>Profile</h2>
|
||||
<ul>
|
||||
{% if user.launchpad_id %}
|
||||
<li>Launchpad: {{ user.launchpad_id }}</li>
|
||||
{% endif %}
|
||||
{% if user.core %}
|
||||
<li>Core in:
|
||||
{% for item in user.core %}
|
||||
{{ item[0] }} ({{ item[1] }})
|
||||
{% endfor %}
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
|
||||
{{ show_contribution_summary(contribution) }}
|
||||
|
||||
<div id="punch_card" style="width: 100%; height: 350px;"></div>
|
||||
|
@ -14,6 +14,7 @@
|
||||
# limitations under the License.
|
||||
|
||||
import bisect
|
||||
import time
|
||||
|
||||
from stackalytics.openstack.common import log as logging
|
||||
from stackalytics.processor import launchpad_utils
|
||||
@ -153,9 +154,12 @@ class RecordProcessor(object):
|
||||
user['user_id'] = user['launchpad_id']
|
||||
|
||||
emails = set([])
|
||||
core_in = set([])
|
||||
for u in [user_a, user_b, user_c]:
|
||||
emails |= set(u.get('emails', []))
|
||||
core_in |= set(u.get('core', []))
|
||||
user['emails'] = list(emails)
|
||||
user['core'] = list(core_in)
|
||||
|
||||
self._update_user_affiliation(user)
|
||||
if (self._get_user_exact_company(user_b) and
|
||||
@ -263,6 +267,7 @@ class RecordProcessor(object):
|
||||
def _spawn_marks(self, record):
|
||||
review_id = record['id']
|
||||
module = record['module']
|
||||
branch = record['branch']
|
||||
|
||||
for patch in record.get('patchSets', []):
|
||||
if 'approvals' not in patch:
|
||||
@ -286,6 +291,7 @@ class RecordProcessor(object):
|
||||
mark['author_name'] = reviewer['name']
|
||||
mark['author_email'] = reviewer['email'].lower()
|
||||
mark['module'] = module
|
||||
mark['branch'] = branch
|
||||
mark['review_id'] = review_id
|
||||
|
||||
self._update_record_and_user(mark)
|
||||
@ -417,6 +423,8 @@ class RecordProcessor(object):
|
||||
users_reviews = {}
|
||||
valid_blueprints = {}
|
||||
mentioned_blueprints = {}
|
||||
core_engineers = {}
|
||||
quarter_ago = int(time.time()) - 60 * 60 * 24 * 30 * 3 # a quarter ago
|
||||
for record in self.runtime_storage_inst.get_all_records():
|
||||
for bp in record.get('blueprint_id', []):
|
||||
if bp in mentioned_blueprints:
|
||||
@ -464,9 +472,9 @@ class RecordProcessor(object):
|
||||
|
||||
need_update = False
|
||||
|
||||
user_id = record['user_id']
|
||||
if user_id in self.updated_users:
|
||||
user = utils.load_user(self.runtime_storage_inst, user_id)
|
||||
if record['user_id'] in self.updated_users:
|
||||
user = utils.load_user(self.runtime_storage_inst,
|
||||
record['user_id'])
|
||||
user_company_name = user['companies'][0]['company_name']
|
||||
if record['company_name'] != user_company_name:
|
||||
LOG.debug('Update record %s: company changed to: %s',
|
||||
@ -505,9 +513,25 @@ class RecordProcessor(object):
|
||||
record['review_number'] = review['review_number']
|
||||
need_update = True
|
||||
|
||||
if (record['record_type'] == 'mark' and
|
||||
record['date'] > quarter_ago and
|
||||
record['value'] in [2, -2]):
|
||||
module_branch = (record['module'], record['branch'])
|
||||
user_id = record['user_id']
|
||||
if user_id in core_engineers:
|
||||
core_engineers[user_id].add(module_branch)
|
||||
else:
|
||||
core_engineers[user_id] = set([module_branch])
|
||||
|
||||
if need_update:
|
||||
yield record
|
||||
|
||||
for user in self.runtime_storage_inst.get_all_users():
|
||||
core_old = user.get('core')
|
||||
user['core'] = list(core_engineers.get(user['user_id'], []))
|
||||
if user['core'] != core_old:
|
||||
utils.store_user(self.runtime_storage_inst, user)
|
||||
|
||||
def finalize(self):
|
||||
self.runtime_storage_inst.set_records(
|
||||
self._get_records_for_users_to_update())
|
||||
|
@ -119,6 +119,12 @@ class MemcachedStorage(RuntimeStorage):
|
||||
def inc_user_count(self):
|
||||
return self.memcached.incr('user:count')
|
||||
|
||||
def get_all_users(self):
|
||||
for n in xrange(0, self.get_by_key('user:count') + 1):
|
||||
user = self.get_by_key('user:%s' % n)
|
||||
if user:
|
||||
yield user
|
||||
|
||||
def get_by_key(self, key):
|
||||
return self.memcached.get(key.encode('utf8'))
|
||||
|
||||
|
@ -404,7 +404,7 @@ class TestRecordProcessor(testtools.TestCase):
|
||||
'email': 'john_doe@gmail.com',
|
||||
'username': 'john_doe'},
|
||||
'createdOn': 1379404951,
|
||||
'module': 'nova'}
|
||||
'module': 'nova', 'branch': 'master'}
|
||||
]))
|
||||
|
||||
self.assertRecordsMatch(
|
||||
@ -423,6 +423,7 @@ class TestRecordProcessor(testtools.TestCase):
|
||||
processed_records[1])
|
||||
|
||||
user = {'seq': 1,
|
||||
'core': [],
|
||||
'user_id': 'john_doe',
|
||||
'launchpad_id': 'john_doe',
|
||||
'user_name': 'John Doe',
|
||||
@ -472,6 +473,7 @@ class TestRecordProcessor(testtools.TestCase):
|
||||
processed_records[1])
|
||||
|
||||
user = {'seq': 1,
|
||||
'core': [],
|
||||
'user_id': 'john_doe',
|
||||
'launchpad_id': 'john_doe',
|
||||
'user_name': 'John Doe',
|
||||
@ -495,7 +497,7 @@ class TestRecordProcessor(testtools.TestCase):
|
||||
'email': 'john_doe@gmail.com',
|
||||
'username': 'john_doe'},
|
||||
'createdOn': 1379404951,
|
||||
'module': 'nova'},
|
||||
'module': 'nova', 'branch': 'master'},
|
||||
{'record_type': 'bp',
|
||||
'id': 'mod:blueprint',
|
||||
'self_link': 'http://launchpad.net/blueprint',
|
||||
@ -519,6 +521,7 @@ class TestRecordProcessor(testtools.TestCase):
|
||||
processed_records[1])
|
||||
|
||||
user = {'seq': 1,
|
||||
'core': [],
|
||||
'user_id': 'john_doe',
|
||||
'launchpad_id': 'john_doe',
|
||||
'user_name': 'John Doe',
|
||||
@ -548,10 +551,11 @@ class TestRecordProcessor(testtools.TestCase):
|
||||
'email': 'john_doe@gmail.com',
|
||||
'username': 'john_doe'},
|
||||
'createdOn': 1379404951,
|
||||
'module': 'nova'}
|
||||
'module': 'nova', 'branch': 'master'}
|
||||
]))
|
||||
|
||||
user = {'seq': 1,
|
||||
'core': [],
|
||||
'user_id': 'john_doe',
|
||||
'launchpad_id': 'john_doe',
|
||||
'user_name': 'John Doe',
|
||||
@ -590,12 +594,13 @@ class TestRecordProcessor(testtools.TestCase):
|
||||
'email': 'john_doe@ibm.com',
|
||||
'username': 'john_doe'},
|
||||
'createdOn': 1379404951,
|
||||
'module': 'nova'}
|
||||
'module': 'nova', 'branch': 'master'}
|
||||
]))
|
||||
|
||||
record_processor_inst.finalize()
|
||||
|
||||
user = {'seq': 2,
|
||||
'core': [],
|
||||
'user_id': 'john_doe',
|
||||
'launchpad_id': 'john_doe',
|
||||
'user_name': 'John Doe',
|
||||
@ -617,6 +622,70 @@ class TestRecordProcessor(testtools.TestCase):
|
||||
self.assertEquals('IBM', record['company_name'],
|
||||
message='Record %s' % record['primary_key'])
|
||||
|
||||
def test_core_user_guess(self):
|
||||
record_processor_inst = self.make_record_processor(
|
||||
lp_user_name={
|
||||
'john_doe': {'name': 'john_doe', 'display_name': 'John Doe'}
|
||||
},
|
||||
companies=[{'company_name': 'IBM', 'domains': ['ibm.com']}],
|
||||
)
|
||||
runtime_storage_inst = record_processor_inst.runtime_storage_inst
|
||||
|
||||
runtime_storage_inst.set_records(record_processor_inst.process([
|
||||
{'record_type': 'review',
|
||||
'id': 'I1045730e47e9e6ad31fcdfbaefdad77e2f3b2c3e',
|
||||
'subject': 'Fix AttributeError in Keypair._add_details()',
|
||||
'owner': {'name': 'John Doe',
|
||||
'email': 'john_doe@ibm.com',
|
||||
'username': 'john_doe'},
|
||||
'createdOn': 1379404951,
|
||||
'module': 'nova',
|
||||
'branch': 'master',
|
||||
'patchSets': [
|
||||
{'number': '1',
|
||||
'revision': '4d8984e92910c37b7d101c1ae8c8283a2e6f4a76',
|
||||
'ref': 'refs/changes/16/58516/1',
|
||||
'uploader': {
|
||||
'name': 'Bill Smith',
|
||||
'email': 'bill@smith.to',
|
||||
'username': 'bsmith'},
|
||||
'createdOn': 1385470730,
|
||||
'approvals': [
|
||||
{'type': 'CRVW', 'description': 'Code Review',
|
||||
'value': '2', 'grantedOn': 1385478464,
|
||||
'by': {
|
||||
'name': 'John Doe',
|
||||
'email': 'john_doe@ibm.com',
|
||||
'username': 'john_doe'}},
|
||||
{'type': 'CRVW', 'description': 'Code Review',
|
||||
'value': '-1', 'grantedOn': 1385478465,
|
||||
'by': {
|
||||
'name': 'Homer Simpson',
|
||||
'email': 'hsimpson@gmail.com',
|
||||
'username': 'homer'}}
|
||||
]
|
||||
}]}
|
||||
]))
|
||||
|
||||
record_processor_inst.finalize()
|
||||
|
||||
user_1 = {'seq': 1, 'user_id': 'john_doe',
|
||||
'launchpad_id': 'john_doe', 'user_name': 'John Doe',
|
||||
'emails': ['john_doe@ibm.com'],
|
||||
'core': [('nova', 'master')],
|
||||
'companies': [{'company_name': 'IBM', 'end_date': 0}]}
|
||||
user_2 = {'seq': 2, 'user_id': 'homer',
|
||||
'launchpad_id': 'homer', 'user_name': 'Homer Simpson',
|
||||
'emails': ['hsimpson@gmail.com'],
|
||||
'core': [],
|
||||
'companies': [{'company_name': '*independent',
|
||||
'end_date': 0}]}
|
||||
runtime_storage_inst = record_processor_inst.runtime_storage_inst
|
||||
self.assertEquals(user_1, utils.load_user(runtime_storage_inst,
|
||||
'john_doe'))
|
||||
self.assertEquals(user_2, utils.load_user(runtime_storage_inst,
|
||||
'homer'))
|
||||
|
||||
# record post-processing
|
||||
|
||||
def test_blueprint_mention_count(self):
|
||||
@ -675,7 +744,7 @@ class TestRecordProcessor(testtools.TestCase):
|
||||
'email': 'john_doe@gmail.com',
|
||||
'username': 'john_doe'},
|
||||
'createdOn': 10,
|
||||
'module': 'nova'},
|
||||
'module': 'nova', 'branch': 'master'},
|
||||
{'record_type': 'review',
|
||||
'id': 'I222',
|
||||
'subject': 'Fix AttributeError in Keypair._add_details()',
|
||||
@ -683,7 +752,7 @@ class TestRecordProcessor(testtools.TestCase):
|
||||
'email': 'john_doe@gmail.com',
|
||||
'username': 'john_doe'},
|
||||
'createdOn': 5,
|
||||
'module': 'glance'},
|
||||
'module': 'glance', 'branch': 'master'},
|
||||
]))
|
||||
record_processor_inst.finalize()
|
||||
|
||||
@ -994,6 +1063,12 @@ def make_runtime_storage(users=None, companies=None, releases=None,
|
||||
runtime_storage_cache['user:count'] = count
|
||||
return count
|
||||
|
||||
def get_all_users():
|
||||
for n in xrange(0, (runtime_storage_cache.get('user:count') or 0) + 1):
|
||||
u = runtime_storage_cache.get('user:%s' % n)
|
||||
if u:
|
||||
yield u
|
||||
|
||||
def set_records(records_iterator):
|
||||
for record in records_iterator:
|
||||
runtime_storage_cache[record['primary_key']] = record
|
||||
@ -1011,6 +1086,7 @@ def make_runtime_storage(users=None, companies=None, releases=None,
|
||||
rs.set_by_key = mock.Mock(side_effect=set_by_key)
|
||||
rs.delete_by_key = mock.Mock(side_effect=delete_by_key)
|
||||
rs.inc_user_count = mock.Mock(side_effect=inc_user_count)
|
||||
rs.get_all_users = mock.Mock(side_effect=get_all_users)
|
||||
rs.set_records = mock.Mock(side_effect=set_records)
|
||||
rs.get_all_records = mock.Mock(side_effect=get_all_records)
|
||||
rs.get_by_primary_key = mock.Mock(side_effect=get_by_primary_key)
|
||||
|
Loading…
x
Reference in New Issue
Block a user