Guess core engineers by their review marks

Part of blueprint review-disagreements

Change-Id: I6815c0641c7ef21ade958e3b8ecb03b61b307d13
This commit is contained in:
Ilya Shakhat 2013-11-28 19:24:26 +04:00 committed by Gerrit Code Review
parent 626c59a45c
commit a70a127c5e
4 changed files with 129 additions and 9 deletions

View File

@ -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>

View File

@ -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())

View File

@ -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'))

View File

@ -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)