Created
May 6, 2024 04:41
-
-
Save akirk/a621bea21ee24573ea1920269301e22a to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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