Skip to content

Instantly share code, notes, and snippets.

@akirk
Created May 6, 2024 04:41
Show Gist options
  • Save akirk/a621bea21ee24573ea1920269301e22a to your computer and use it in GitHub Desktop.
Save akirk/a621bea21ee24573ea1920269301e22a to your computer and use it in GitHub Desktop.
# Run this script inside a git directory and have Githubs gh command in the path.
import subprocess
import json
from datetime import datetime
import statistics
def run_command(command):
result = subprocess.run(command, shell=True, text=True, capture_output=True)
if result.returncode != 0:
print(f'Error: {result.stderr}')
exit(1)
return json.loads(result.stdout)
pr_data = run_command('gh pr list --json number,title,createdAt,reviews -s closed -s merged')
def get_pull_request_stats(pr_data):
pr_stats = {}
for pull_request in pr_data:
pr_id = pull_request['number']
pr_title = pull_request['title']
created_at = datetime.fromisoformat(pull_request['createdAt'])
if pull_request.get('reviews', []):
for review in pull_request['reviews']:
review_state = review['state'].lower()
if review_state in ['approved', 'changes_requested']:
reviewer = review['author']['login']
review_time = (datetime.fromisoformat(review['submittedAt']) - created_at).total_seconds() / 3600 # Convert to hours
if reviewer in pr_stats:
if not any([pr[0] == pr_id for pr in pr_stats[reviewer]]):
pr_stats[reviewer].append((pr_id, review_time, pr_title))
else:
pr_stats[reviewer] = [(pr_id, review_time, pr_title)]
return pr_stats
pull_request_stats = get_pull_request_stats(pr_data)
for reviewer, reviews in pull_request_stats.items():
avg_review_time = sum([review[1] for review in reviews]) / len(reviews)
median_review_time = statistics.median([review[1] for review in reviews])
print(f'Reviewer: {reviewer} | Num PRs Reviewed: {len(reviews)} | Avg. Review Time: {"{:.2f} hours".format(avg_review_time) if avg_review_time <= 24 else "{:.0f} days and {:.2f} hours".format(avg_review_time // 24, avg_review_time % 24)} | Median Review Time: {"{:.2f} hours".format(median_review_time) if median_review_time <= 24 else "{:.0f} days and {:.2f} hours".format(median_review_time // 24, median_review_time % 24)}')
for pr_id, review_time, pr_title in reviews:
out = f' First Review: {"{:.2f} hours".format(review_time) if review_time <= 24 else "{:.0f} days and {:.2f} hours".format(review_time // 24, review_time % 24)}'
rpad = 40 - len(out)
print(out + ' ' * rpad + f' #{pr_id} {pr_title}' )
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment