Skip to content

Commit 4633b66

Browse files
committed
add support for merge requests
1 parent ae58ed9 commit 4633b66

File tree

1 file changed

+195
-0
lines changed

1 file changed

+195
-0
lines changed

grimoire_elk/enriched/gitlabcomments.py

Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,8 +157,28 @@ def get_time_to_first_attention(self, item):
157157
reaction_dates = [str_to_datetime(reaction['created_at']) for reaction in item['award_emoji_data']
158158
if item['author']['username'] != reaction['user']['username']]
159159
reaction_dates.extend(comments_dates)
160+
160161
if reaction_dates:
161162
return min(reaction_dates)
163+
164+
return None
165+
166+
def get_time_to_merge_request_response(self, item):
167+
"""Get the first date at which a review was made on the PR by someone
168+
other than the user who created the PR
169+
"""
170+
review_dates = []
171+
172+
for comment in item['notes_data']:
173+
# skip comments of the pull request creator
174+
if item['author']['username'] == comment['author']['username']:
175+
continue
176+
177+
review_dates.append(str_to_datetime(comment['created_at']))
178+
179+
if review_dates:
180+
return min(review_dates)
181+
162182
return None
163183

164184
def __get_reactions(self, item):
@@ -266,8 +286,112 @@ def __get_rich_issue(self, item):
266286
if self.sortinghat:
267287
item[self.get_field_date()] = rich_issue[self.get_field_date()]
268288
rich_issue.update(self.get_item_sh(item, self.issue_roles))
289+
269290
return rich_issue
270291

292+
def __get_rich_merge(self, item):
293+
rich_mr = {}
294+
295+
self.copy_raw_fields(self.RAW_FIELDS_COPY, item, rich_mr)
296+
# The real data
297+
merge_request = item['data']
298+
299+
rich_mr['time_to_close_days'] = \
300+
get_time_diff_days(merge_request['created_at'], merge_request['closed_at'])
301+
302+
if merge_request['state'] != 'closed':
303+
rich_mr['time_open_days'] = \
304+
get_time_diff_days(pull_request['created_at'], datetime_utcnow().replace(tzinfo=None))
305+
else:
306+
rich_mr['time_open_days'] = rich_mr['time_to_close_days']
307+
308+
rich_mr['user_login'] = merge_request['author']['username']
309+
310+
user = merge_request.get('author', None)
311+
if user is not None and user:
312+
rich_mr['user_name'] = user['name']
313+
rich_mr['author_name'] = user['name']
314+
rich_mr["user_domain"] = self.get_email_domain(user['email']) if user['email'] else None
315+
rich_mr['user_org'] = user.get('company', None)
316+
rich_mr['user_location'] = user.get('location', None)
317+
rich_mr['user_geolocation'] = None
318+
else:
319+
rich_mr['user_name'] = None
320+
rich_mr["user_domain"] = None
321+
rich_mr['user_org'] = None
322+
rich_mr['user_location'] = None
323+
rich_mr['user_geolocation'] = None
324+
rich_mr['author_name'] = None
325+
326+
merged_by = merge_request.get('merged_by', None)
327+
if merged_by is not None and merged_by:
328+
rich_mr['merge_author_login'] = merged_by['login']
329+
rich_mr['merge_author_name'] = merged_by['name']
330+
rich_mr["merge_author_domain"] = self.get_email_domain(merged_by['email']) if merged_by['email'] else None
331+
rich_mr['merge_author_org'] = merged_by.get('company', None)
332+
rich_mr['merge_author_location'] = merged_by.get('location', None)
333+
rich_mr['merge_author_geolocation'] = None
334+
else:
335+
rich_mr['merge_author_name'] = None
336+
rich_mr['merge_author_login'] = None
337+
rich_mr["merge_author_domain"] = None
338+
rich_mr['merge_author_org'] = None
339+
rich_mr['merge_author_location'] = None
340+
rich_mr['merge_author_geolocation'] = None
341+
342+
rich_mr['id'] = merge_request['id']
343+
rich_mr['merge_id'] = merge_request['id']
344+
rich_mr['merge_id_in_repo'] = merge_request['web_url'].split("/")[-1]
345+
rich_mr['repository'] = self.get_project_repository(rich_mr)
346+
rich_mr['merge_title'] = merge_request['title']
347+
rich_mr['merge_title_analyzed'] = merge_request['title']
348+
rich_mr['merge_state'] = merge_request['state']
349+
rich_mr['merge_created_at'] = merge_request['created_at']
350+
rich_mr['merge_updated_at'] = merge_request['updated_at']
351+
rich_mr['merge_status'] = merge_request['merge_status']
352+
rich_mr['merge_merged_at'] = merge_request['merged_at']
353+
rich_mr['merge_closed_at'] = merge_request['closed_at']
354+
rich_mr['url'] = merge_request['web_url']
355+
rich_mr['merge_url'] = merge_request['web_url']
356+
357+
# extract reactions and add it to enriched item
358+
# rich_mr.update(self.__get_reactions(merge_request))
359+
360+
rich_mr['merge_labels'] = merge_request['labels']
361+
rich_mr['item_type'] = MERGE_TYPE
362+
363+
rich_mr['gitlab_repo'] = rich_mr['repository'].replace(GITLAB, '')
364+
rich_mr['gitlab_repo'] = re.sub('.git$', '', rich_mr['gitlab_repo'])
365+
366+
# GMD code development metrics
367+
rich_mr['code_merge_duration'] = get_time_diff_days(merge_request['created_at'],
368+
merge_request['merged_at'])
369+
rich_mr['num_versions'] = len(merge_request['versions_data'])
370+
371+
rich_mr['time_to_merge_request_response'] = None
372+
if merge_request['notes_data'] != 0:
373+
min_review_date = self.get_time_to_merge_request_response(pull_request)
374+
rich_pr['time_to_merge_request_response'] = \
375+
get_time_diff_days(str_to_datetime(pull_request['created_at']), min_review_date)
376+
377+
if self.prjs_map:
378+
rich_mr.update(self.get_item_project(rich_mr))
379+
380+
if 'project' in item:
381+
rich_mr['project'] = item['project']
382+
383+
rich_mr.update(self.get_grimoire_fields(merge_request['created_at'], MERGE_TYPE))
384+
385+
# due to backtrack compatibility, `is_gitlabcomments_*` is replaced with `is_gitlab_*`
386+
rich_mr.pop('is_gitlabcomments_{}'.format(MERGE_TYPE))
387+
rich_mr['is_gitlab_{}'.format(MERGE_TYPE)] = 1
388+
389+
if self.sortinghat:
390+
item[self.get_field_date()] = rich_mr[self.get_field_date()]
391+
rich_mr.update(self.get_item_sh(item, self.mr_roles))
392+
393+
return rich_mr
394+
271395
@metadata
272396
def get_rich_item(self, item):
273397
rich_item = {}
@@ -318,9 +442,70 @@ def get_rich_issue_comments(self, comments, eitem):
318442

319443
ecomment['comment_updated_at'] = comment['updated_at']
320444

445+
# Add id info to allow to coexistence of items of different types in the same index
446+
ecomment['id'] = '{}_review_comment_{}'.format(eitem['id'], comment['id'])
447+
ecomment.update(self.get_grimoire_fields(comment['updated_at'], ISSUE_COMMENT_TYPE))
448+
449+
# due to backtrack compatibility, `is_gitlabcomments_*` is replaced with `is_gitlab_*`
450+
ecomment.pop('is_gitlabcomments_{}'.format(ISSUE_COMMENT_TYPE))
451+
ecomment['is_gitlab_{}'.format(ISSUE_COMMENT_TYPE)] = 1
452+
ecomment['is_gitlab_comment'] = 1
453+
454+
if self.sortinghat:
455+
ecomment.update(self.get_item_sh(comment, self.comment_roles, 'updated_at'))
456+
457+
if self.prjs_map:
458+
ecomment.update(self.get_item_project(ecomment))
459+
460+
if 'project' in eitem:
461+
ecomment['project'] = eitem['project']
462+
463+
self.add_repository_labels(ecomment)
464+
self.add_metadata_filter_raw(ecomment)
465+
self.add_gelk_metadata(ecomment)
466+
467+
ecomments.append(ecomment)
468+
469+
return ecomments
470+
471+
def get_rich_merge_reviews(self, comments, eitem):
472+
ecomments = []
473+
474+
for comment in comments:
475+
ecomment = {}
476+
477+
self.copy_raw_fields(self.RAW_FIELDS_COPY, eitem, ecomment)
478+
# Copy data from the enriched pull
479+
ecomment['merge_labels'] = eitem['merge_labels']
480+
ecomment['merge_id'] = eitem['merge_id']
481+
ecomment['merge_id_in_repo'] = eitem['merge_id_in_repo']
482+
ecomment['merge_title'] = eitem['merge_title']
483+
ecomment['merge_url'] = eitem['merge_url']
484+
ecomment['merge_state'] = eitem['merge_state']
485+
ecomment['merge_created_at'] = eitem['merge_created_at']
486+
ecomment['merge_updated_at'] = eitem['merge_updated_at']
487+
ecomment['merge_merged_at'] = eitem['merge_merged_at']
488+
ecomment['merge_closed_at'] = eitem['merge_closed_at']
489+
ecomment['merge_status'] = eitem['merge_status']
490+
ecomment['gitlab_repo'] = eitem['gitlab_repo']
491+
ecomment['repository'] = eitem['repository']
492+
ecomment['item_type'] = COMMENT_TYPE
493+
ecomment['sub_type'] = REVIEW_COMMENT_TYPE
494+
495+
# Copy data from the raw comment
496+
ecomment['body'] = comment['body'][:self.KEYWORD_MAX_LENGTH]
497+
ecomment['body_analyzed'] = comment['body']
498+
# ecomment['url'] = comment['html_url']
499+
500+
# extract reactions and add it to enriched item
501+
# ecomment.update(self.__get_reactions(comment))
502+
503+
ecomment['comment_updated_at'] = comment['updated_at']
504+
321505
# Add id info to allow to coexistence of items of different types in the same index
322506
ecomment['id'] = '{}_review_comment_{}'.format(eitem['id'], comment['id'])
323507
ecomment.update(self.get_grimoire_fields(comment['updated_at'], REVIEW_COMMENT_TYPE))
508+
324509
# due to backtrack compatibility, `is_gitlabcomments_*` is replaced with `is_gitlab_*`
325510
ecomment.pop('is_gitlabcomments_{}'.format(REVIEW_COMMENT_TYPE))
326511
ecomment['is_gitlab_{}'.format(REVIEW_COMMENT_TYPE)] = 1
@@ -353,6 +538,16 @@ def enrich_issue(self, item, eitem):
353538

354539
return eitems
355540

541+
def enrich_merge(self, item, eitem):
542+
eitems = []
543+
544+
comments = item['data'].get('notes_data', [])
545+
if comments:
546+
rich_item_comments = self.get_rich_merge_reviews(comments, eitem)
547+
eitems.extend(rich_item_comments)
548+
549+
return eitems
550+
356551
def enrich_items(self, ocean_backend):
357552
items_to_enrich = []
358553
num_items = 0

0 commit comments

Comments
 (0)