Skip to content

Commit d6d0ef9

Browse files
authored
refactor(github_metrics): improve PR processing and metrics collection
2 parents ab6a802 + 48cb340 commit d6d0ef9

File tree

2 files changed

+52
-58
lines changed

2 files changed

+52
-58
lines changed

src/wellcode_cli/github/github_metrics.py

Lines changed: 52 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,12 @@ def process_repository_batch(
221221
def process_pr(pr, repo_metrics, org_metrics, start_date, end_date):
222222
"""Process a single PR with optimized data fetching"""
223223
try:
224+
logging.info(f"Starting to process PR #{pr.number} by {pr.user.login}")
225+
226+
# Add PR author to contributors and create user metrics
227+
repo_metrics.contributors.add(pr.user.login)
228+
org_metrics.get_or_create_user(pr.user.login)
229+
224230
pr_data = collect_pr_data(pr)
225231

226232
futures = [
@@ -289,99 +295,123 @@ def collect_pr_data(pr):
289295

290296
def update_code_metrics(pr, repo_metrics, org_metrics):
291297
"""Update code metrics for a PR"""
298+
# Update organization and repository metrics
292299
org_metrics.code_metrics.update_from_pr(pr)
293300
repo_metrics.code_metrics.update_from_pr(pr)
294-
repo_metrics.code_metrics.update_from_pr(pr)
301+
302+
# Update author's code metrics
303+
author_metrics = org_metrics.get_or_create_user(pr.user.login)
304+
author_metrics.code_metrics.update_from_pr(pr)
295305

296306

297307
def update_review_metrics(pr, pr_data, repo_metrics, org_metrics):
298308
"""Update review metrics for a PR"""
299309
reviews = pr_data["reviews"]
300310
review_comments = pr_data["review_comments"]
301311
issue_comments = pr_data["issue_comments"]
302-
issue_comments = pr_data["issue_comments"]
312+
313+
# Get author metrics and update received comments
314+
author_metrics = org_metrics.get_or_create_user(pr.user.login)
315+
author_metrics.review_metrics.review_comments_received += len(review_comments)
316+
303317
# Update PR author's received comments
304318
org_metrics.review_metrics.review_comments_received += len(review_comments)
305-
org_metrics.review_metrics.review_comments_received += len(review_comments)
306319
# Process all comments
307320
for comment in review_comments + issue_comments:
308321
if not comment.user:
309322
continue
310-
continue
323+
311324
commenter = comment.user.login
312325
commenter_metrics = org_metrics.get_or_create_user(commenter)
313-
commenter_metrics = org_metrics.get_or_create_user(commenter)
314326
# Update comment counts
315327
commenter_metrics.review_metrics.review_comments_given += 1
316328
repo_metrics.review_metrics.review_comments_given += 1
317329
org_metrics.review_metrics.review_comments_given += 1
318-
org_metrics.review_metrics.review_comments_given += 1
319330
# Update collaboration metrics
320331
commenter_metrics.collaboration_metrics.update_from_comments(
321332
[comment], pr.number
322333
)
323334
repo_metrics.collaboration_metrics.update_from_comments([comment], pr.number)
324335
org_metrics.collaboration_metrics.update_from_comments([comment], pr.number)
325-
org_metrics.collaboration_metrics.update_from_comments([comment], pr.number)
326336
# Process reviews
327337
process_reviews(pr, reviews, repo_metrics, org_metrics)
328-
process_reviews(pr, reviews, repo_metrics, org_metrics)
329338
if reviews:
330339
first_review = min(reviews, key=lambda r: r.submitted_at)
331340
wait_time = (
332341
first_review.submitted_at - pr.created_at
333342
).total_seconds() / 60 # Convert to minutes
343+
344+
# Add to author metrics
345+
author_metrics.review_metrics.review_wait_times.append(wait_time)
346+
334347
org_metrics.bottleneck_metrics.review_wait_times.append(wait_time)
335348
repo_metrics.bottleneck_metrics.review_wait_times.append(wait_time)
336-
repo_metrics.bottleneck_metrics.review_wait_times.append(wait_time)
337349
for review in reviews:
338350
if review.submitted_at and pr.created_at:
339351
response_time = (review.submitted_at - pr.created_at).total_seconds() / 60
352+
353+
# Add to author metrics
354+
author_metrics.review_metrics.time_to_first_review.append(response_time)
355+
340356
org_metrics.bottleneck_metrics.review_response_times.append(response_time)
341357
repo_metrics.bottleneck_metrics.review_response_times.append(response_time)
342-
repo_metrics.bottleneck_metrics.review_response_times.append(response_time)
343358
org_metrics.bottleneck_metrics.review_wait_times.append(wait_time)
344359

345360

346361
def update_time_metrics(pr, commits, repo_metrics, org_metrics, start_date, end_date):
347362
"""Update time metrics for a PR"""
348363
try:
349364
if pr.merged_at:
365+
# Get author metrics
366+
author_metrics = org_metrics.get_or_create_user(pr.user.login)
367+
350368
# Convert all times to datetime with timezone
351369
merge_time = ensure_datetime(pr.merged_at)
352370
created_time = ensure_datetime(pr.created_at)
353-
created_time = ensure_datetime(pr.created_at)
354371
# Calculate time to merge in hours
355372
merge_duration = (merge_time - created_time).total_seconds() / 3600
373+
374+
# Add author metrics
375+
author_metrics.time_metrics.time_to_merge.append(merge_duration)
376+
356377
repo_metrics.time_metrics.time_to_merge.append(merge_duration)
357378
org_metrics.time_metrics.time_to_merge.append(merge_duration)
358-
org_metrics.time_metrics.time_to_merge.append(merge_duration)
359379
# Calculate lead time if we have commits
360380
if commits and len(commits) > 0:
361381
first_commit = min(
362382
commits, key=lambda c: ensure_datetime(c.commit.author.date)
363383
)
364384
first_commit_date = ensure_datetime(first_commit.commit.author.date)
365385
lead_time = (merge_time - first_commit_date).total_seconds() / 3600
386+
387+
# Add author metrics
388+
author_metrics.time_metrics.lead_times.append(lead_time)
366389
repo_metrics.time_metrics.lead_times.append(lead_time)
367390
org_metrics.time_metrics.lead_times.append(lead_time)
368-
org_metrics.time_metrics.lead_times.append(lead_time)
369391
# Calculate cycle time
370392
cycle_time = (merge_time - first_commit_date).total_seconds() / 3600
393+
394+
# Add author metrics
395+
author_metrics.time_metrics.cycle_time.append(cycle_time)
371396
repo_metrics.time_metrics.cycle_time.append(cycle_time)
372397
org_metrics.time_metrics.cycle_time.append(cycle_time)
373-
org_metrics.time_metrics.cycle_time.append(cycle_time)
374398
# Update merge distribution
375399
if merge_time.weekday() >= 5: # Weekend
400+
# Add author metrics
401+
author_metrics.time_metrics.merge_distribution["weekends"] += 1
376402
repo_metrics.time_metrics.merge_distribution["weekends"] += 1
377403
org_metrics.time_metrics.merge_distribution["weekends"] += 1
378404
elif 9 <= merge_time.hour < 17: # Business hours
405+
# Add author metrics
406+
author_metrics.time_metrics.merge_distribution["business_hours"] += 1
379407
repo_metrics.time_metrics.merge_distribution["business_hours"] += 1
380408
org_metrics.time_metrics.merge_distribution["business_hours"] += 1
381409
else: # After hours
410+
# Add author metrics
411+
author_metrics.time_metrics.merge_distribution["after_hours"] += 1
382412
repo_metrics.time_metrics.merge_distribution["after_hours"] += 1
383413
org_metrics.time_metrics.merge_distribution["after_hours"] += 1
384-
org_metrics.time_metrics.merge_distribution["after_hours"] += 1
414+
385415
# Calculate deployment frequency with safety check
386416
if pr.base.ref == repo_metrics.default_branch:
387417
one_day_seconds = 24 * 60 * 60
@@ -433,11 +463,15 @@ def process_reviews(pr, reviews, repo_metrics, org_metrics):
433463

434464
def update_collaboration_metrics(pr, reviews, repo_metrics, org_metrics):
435465
"""Update collaboration metrics including participation rate"""
436-
# Process reviews for collaboration
437-
if reviews:
466+
# Check for self-merges by comparing PR author with merger
467+
if pr.merged and pr.merged_by and pr.user.login == pr.merged_by.login:
438468
repo_metrics.collaboration_metrics.self_merges += 1
439469
org_metrics.collaboration_metrics.self_merges += 1
440-
org_metrics.collaboration_metrics.self_merges += 1
470+
471+
# Update author's metrics
472+
author_metrics = org_metrics.get_or_create_user(pr.user.login)
473+
author_metrics.collaboration_metrics.self_merges += 1
474+
441475
# Update collaboration metrics at all levels
442476
if (
443477
reviews
@@ -462,7 +496,6 @@ def update_collaboration_metrics(pr, reviews, repo_metrics, org_metrics):
462496
else:
463497
repo_metrics.collaboration_metrics.external_reviews += 1
464498
org_metrics.collaboration_metrics.external_reviews += 1
465-
org_metrics.collaboration_metrics.external_reviews += 1
466499
# Calculate review participation rate for repository
467500
repo_total_reviews = (
468501
repo_metrics.collaboration_metrics.team_reviews

src/wellcode_cli/github/models/metrics.py

Lines changed: 0 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -477,45 +477,6 @@ def get_all_contributors(self):
477477
all_contributors.update(repo.contributors)
478478
return all_contributors
479479

480-
def aggregate_metrics(self):
481-
"""Aggregate metrics from all repositories"""
482-
for repo in self.repositories.values():
483-
# Code metrics
484-
self.code_metrics.total_additions += repo.code_metrics.total_additions
485-
self.code_metrics.total_deletions += repo.code_metrics.total_deletions
486-
self.code_metrics.changes_per_pr.extend(repo.code_metrics.changes_per_pr)
487-
self.code_metrics.files_changed.extend(repo.code_metrics.files_changed)
488-
self.code_metrics.commits_count.extend(repo.code_metrics.commits_count)
489-
self.code_metrics.reverts += repo.code_metrics.reverts
490-
self.code_metrics.hotfixes += repo.code_metrics.hotfixes
491-
492-
# Review metrics
493-
self.review_metrics.reviews_performed += (
494-
repo.review_metrics.reviews_performed
495-
)
496-
self.review_metrics.blocking_reviews_given += (
497-
repo.review_metrics.blocking_reviews_given
498-
)
499-
self.review_metrics.review_comments_given += (
500-
repo.review_metrics.review_comments_given
501-
)
502-
self.review_metrics.time_to_first_review.extend(
503-
repo.review_metrics.time_to_first_review
504-
)
505-
self.review_metrics.review_cycles.extend(repo.review_metrics.review_cycles)
506-
self.review_metrics.review_wait_times.extend(
507-
repo.review_metrics.review_wait_times
508-
)
509-
510-
# Time metrics
511-
self.time_metrics.time_to_merge.extend(repo.time_metrics.time_to_merge)
512-
self.time_metrics.lead_times.extend(repo.time_metrics.lead_times)
513-
self.time_metrics.cycle_time.extend(repo.time_metrics.cycle_time)
514-
for key in self.time_metrics.merge_distribution:
515-
self.time_metrics.merge_distribution[
516-
key
517-
] += repo.time_metrics.merge_distribution[key]
518-
519480
def to_dict(self):
520481
return {
521482
"name": self.name,

0 commit comments

Comments
 (0)