From 4ff56749a9ce349dc6ff8f702e3259861190e110 Mon Sep 17 00:00:00 2001 From: GeckoEidechse Date: Mon, 26 Aug 2024 16:00:15 +0200 Subject: [PATCH 01/21] feat: Add initial Python script --- scripts/scrape-for-reviews.py | 142 ++++++++++++++++++++++++++++++++++ 1 file changed, 142 insertions(+) create mode 100644 scripts/scrape-for-reviews.py diff --git a/scripts/scrape-for-reviews.py b/scripts/scrape-for-reviews.py new file mode 100644 index 0000000..ba7c08e --- /dev/null +++ b/scripts/scrape-for-reviews.py @@ -0,0 +1,142 @@ +import requests +from collections import defaultdict +import sys + +github_token = ( + None +) + +# supply a github token in an arg avoid ratelimit, or don't, it's up to you +if len(sys.argv) > 1: + github_token = sys.argv[1] + +# Replace with the GitHub organization name +github_org = "R2Northstar" + +# Base URL for GitHub API +base_url = f"https://api.github.com/orgs/{github_org}" + +# Headers for authentication +headers = {"Authorization": f"token {github_token}"} + + +def get_repos(): + """Fetch all repositories for the organization, handling pagination.""" + repos = [] + page = 1 + + while True: + url = f"{base_url}/repos?per_page=100&page={page}" + response = requests.get(url, headers=headers) + response.raise_for_status() + page_repos = response.json() + + if not page_repos: # If the list is empty, we've reached the last page + break + + repos.extend(page_repos) + page += 1 + + return repos + + +def get_pull_requests(repo_name): + """Fetch all pull requests in the repository, handling pagination.""" + print(f"{repo_name=}") + prs = [] + page = 1 + + while True: + print(f"{page=}") + url = f"https://api.github.com/repos/{github_org}/{repo_name}/pulls?state=all&per_page=100&page={page}" + response = requests.get(url, headers=headers) + response.raise_for_status() + page_prs = response.json() + + if not page_prs: # If the list is empty, we've reached the last page + break + + prs.extend(page_prs) + page += 1 + + return prs + + +def get_reviews_for_pr(repo_name, pr_number): + """Fetch all reviews for a given pull request in a specific repository.""" + url = f"https://api.github.com/repos/{github_org}/{repo_name}/pulls/{pr_number}/reviews" + response = requests.get(url, headers=headers) + response.raise_for_status() + return response.json() + + +# Fetch all repositories in the organization +repos = get_repos() + +# Dictionary to store the count of reviews per user +review_counts = defaultdict(int) + +for repo in repos: + repo_name = repo["name"] + prs = get_pull_requests(repo_name) + + for pr in prs: + pr_number = pr["number"] + reviews = get_reviews_for_pr(repo_name, pr_number) + + for review in reviews: + if not review["user"] or not review["user"]["login"]: + continue + if review["body"] != "": + # Current object is comment on a review not an actual review, skip + continue + user = review["user"]["login"] + review_counts[user] += 1 + +# Sort the review counts dictionary by count in descending order +sorted_review_counts = sorted( + review_counts.items(), key=lambda item: item[1], reverse=True +) + + +# Generate TypeScript code +def generate_typescript_code(sorted_review_counts): + + file_header_string = "// Auto-generated from Python script\n" + + definition_string = """ +export interface ReviewCount { + url?: string; + name: string; + count: number; +} +""" + list_start_string = ( + """export const review_counts: ReviewCount[] = [""" + ) + list_end_string = """ +] +""" + + contributor_list_string = "" + for user, count in sorted_review_counts: + contributor_list_string += f""" + {{ + url: "https://github.com/{user}", + name: "{user}", + count: {count}, + }},""" + + return ( + file_header_string + + definition_string + + list_start_string + + contributor_list_string + + list_end_string + ) + + +typscript_code = generate_typescript_code(sorted_review_counts) + +with open("../src/data/reviewer-count.ts", "w") as f: + f.write(typscript_code) From e927b4c8a003e694f53ff2448c55e9049e1709f9 Mon Sep 17 00:00:00 2001 From: GeckoEidechse Date: Sun, 6 Oct 2024 18:35:59 +0200 Subject: [PATCH 02/21] refactor: Rename variable --- scripts/scrape-for-reviews.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/scrape-for-reviews.py b/scripts/scrape-for-reviews.py index ba7c08e..0c27c01 100644 --- a/scripts/scrape-for-reviews.py +++ b/scripts/scrape-for-reviews.py @@ -74,7 +74,7 @@ def get_reviews_for_pr(repo_name, pr_number): repos = get_repos() # Dictionary to store the count of reviews per user -review_counts = defaultdict(int) +review_dict = defaultdict(int) for repo in repos: repo_name = repo["name"] @@ -91,11 +91,11 @@ def get_reviews_for_pr(repo_name, pr_number): # Current object is comment on a review not an actual review, skip continue user = review["user"]["login"] - review_counts[user] += 1 + review_dict[user] += 1 # Sort the review counts dictionary by count in descending order sorted_review_counts = sorted( - review_counts.items(), key=lambda item: item[1], reverse=True + review_dict.items(), key=lambda item: item[1], reverse=True ) From 300752337b65e72965aa996910955ec5d8610b9c Mon Sep 17 00:00:00 2001 From: GeckoEidechse Date: Sun, 6 Oct 2024 18:39:40 +0200 Subject: [PATCH 03/21] feat: Store time of review in dict --- scripts/scrape-for-reviews.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/scripts/scrape-for-reviews.py b/scripts/scrape-for-reviews.py index 0c27c01..3a22e04 100644 --- a/scripts/scrape-for-reviews.py +++ b/scripts/scrape-for-reviews.py @@ -1,5 +1,6 @@ import requests from collections import defaultdict +import datetime import sys github_token = ( @@ -74,7 +75,7 @@ def get_reviews_for_pr(repo_name, pr_number): repos = get_repos() # Dictionary to store the count of reviews per user -review_dict = defaultdict(int) +review_dict = defaultdict(list) for repo in repos: repo_name = repo["name"] @@ -91,11 +92,17 @@ def get_reviews_for_pr(repo_name, pr_number): # Current object is comment on a review not an actual review, skip continue user = review["user"]["login"] - review_dict[user] += 1 + review_dict[user].append( + datetime.datetime.fromisoformat( + review["submitted_at"].replace("Z", "+00:00") + ) + ) # Sort the review counts dictionary by count in descending order sorted_review_counts = sorted( - review_dict.items(), key=lambda item: item[1], reverse=True + {k: len(v) for k, v, in review_dict.items()}.items(), + key=lambda item: item[1], + reverse=True, ) From 281117b595a21c3134c89fd2bfcf564acdf99c3b Mon Sep 17 00:00:00 2001 From: GeckoEidechse Date: Sun, 6 Oct 2024 18:40:53 +0200 Subject: [PATCH 04/21] style: Autoformat --- scripts/scrape-for-reviews.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/scripts/scrape-for-reviews.py b/scripts/scrape-for-reviews.py index 3a22e04..0332cf4 100644 --- a/scripts/scrape-for-reviews.py +++ b/scripts/scrape-for-reviews.py @@ -3,9 +3,7 @@ import datetime import sys -github_token = ( - None -) +github_token = None # supply a github token in an arg avoid ratelimit, or don't, it's up to you if len(sys.argv) > 1: @@ -118,9 +116,7 @@ def generate_typescript_code(sorted_review_counts): count: number; } """ - list_start_string = ( - """export const review_counts: ReviewCount[] = [""" - ) + list_start_string = """export const review_counts: ReviewCount[] = [""" list_end_string = """ ] """ From 8ce3e83d3059f1760a5ce96f68e565ef03e9712e Mon Sep 17 00:00:00 2001 From: GeckoEidechse Date: Thu, 10 Oct 2024 23:57:23 +0200 Subject: [PATCH 05/21] fix: Invert condition for checking review body The previous check was wrong and ignored all top level reviews, meaning it only counted comments on reviews --- scripts/scrape-for-reviews.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/scrape-for-reviews.py b/scripts/scrape-for-reviews.py index 0332cf4..671e853 100644 --- a/scripts/scrape-for-reviews.py +++ b/scripts/scrape-for-reviews.py @@ -86,7 +86,7 @@ def get_reviews_for_pr(repo_name, pr_number): for review in reviews: if not review["user"] or not review["user"]["login"]: continue - if review["body"] != "": + if review["body"] == "": # Current object is comment on a review not an actual review, skip continue user = review["user"]["login"] From 1c0d764042ec4dbea76a22cc5b486797d0392f3b Mon Sep 17 00:00:00 2001 From: GeckoEidechse Date: Thu, 10 Oct 2024 23:58:41 +0200 Subject: [PATCH 06/21] feat: Add initial check for reviews with non-informative content Adds an initial function to filter out reviews like "LGTM" that are not helpful in deciding whether a PR should be approved or not --- scripts/scrape-for-reviews.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/scripts/scrape-for-reviews.py b/scripts/scrape-for-reviews.py index 671e853..f0bb2da 100644 --- a/scripts/scrape-for-reviews.py +++ b/scripts/scrape-for-reviews.py @@ -75,6 +75,16 @@ def get_reviews_for_pr(repo_name, pr_number): # Dictionary to store the count of reviews per user review_dict = defaultdict(list) + +def is_trivial_review(review_text: str): + """Perform a variety of checks to determine whether a review should be discarded due to not being extensive enough""" + min_review_length = 20 + if "lgtm" in review_text.lower() and len(review_text) < min_review_length: + return True + + return False + + for repo in repos: repo_name = repo["name"] prs = get_pull_requests(repo_name) @@ -89,6 +99,9 @@ def get_reviews_for_pr(repo_name, pr_number): if review["body"] == "": # Current object is comment on a review not an actual review, skip continue + if is_trivial_review(review["body"]): + continue + user = review["user"]["login"] review_dict[user].append( datetime.datetime.fromisoformat( From c02be0d09b1e1c898aac85632e62b9785fc140f1 Mon Sep 17 00:00:00 2001 From: GeckoEidechse Date: Fri, 11 Oct 2024 00:49:21 +0200 Subject: [PATCH 07/21] feat: Add functions for summing review counts and sorting by reviewer name --- scripts/scrape-for-reviews.py | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/scripts/scrape-for-reviews.py b/scripts/scrape-for-reviews.py index f0bb2da..96bb8c0 100644 --- a/scripts/scrape-for-reviews.py +++ b/scripts/scrape-for-reviews.py @@ -109,12 +109,19 @@ def is_trivial_review(review_text: str): ) ) -# Sort the review counts dictionary by count in descending order -sorted_review_counts = sorted( - {k: len(v) for k, v, in review_dict.items()}.items(), - key=lambda item: item[1], - reverse=True, -) + +def sum_up_reviews(reviews_dict): + """Sum up review counts per reviewer""" + return {k: len(v) for k, v, in reviews_dict.items()} + + +def sort_alphabetically(reviews_dict): + """Sort alphabetivally by reviewer name""" + sorted_reviewers = sorted( + reviews_dict.items(), + key=lambda item: item[0].lower(), + ) + return sorted_reviewers # Generate TypeScript code @@ -152,7 +159,6 @@ def generate_typescript_code(sorted_review_counts): ) -typscript_code = generate_typescript_code(sorted_review_counts) - +# Total stats with open("../src/data/reviewer-count.ts", "w") as f: - f.write(typscript_code) + f.write(generate_typescript_code(sort_alphabetically(sum_up_reviews(review_dict)))) From 2ac3b56bb7ea9d09aa0cfeb7e38c8209161a240c Mon Sep 17 00:00:00 2001 From: GeckoEidechse Date: Fri, 11 Oct 2024 00:53:18 +0200 Subject: [PATCH 08/21] feat: Addtionally generate monthly and weekly reviewer stats --- scripts/scrape-for-reviews.py | 48 +++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/scripts/scrape-for-reviews.py b/scripts/scrape-for-reviews.py index 96bb8c0..285d273 100644 --- a/scripts/scrape-for-reviews.py +++ b/scripts/scrape-for-reviews.py @@ -110,6 +110,38 @@ def is_trivial_review(review_text: str): ) + +def filter_by_timeframe(reviews_dict, weeks=1): + """ + Filters out reviews older than `weeks` weeks. + Additionally removes empty reviewer entries after filtering. + """ + # Apply the filter using a dictionary comprehension + now = datetime.datetime.now(datetime.timezone.utc) + filtered_review_counts = defaultdict( + list, + { + reviewer: [ + review_time + for review_time in reviews + if now - review_time < datetime.timedelta(weeks=weeks) + ] + for reviewer, reviews in reviews_dict.items() + }, + ) + + # Remove empty entries + filtered_review_counts = defaultdict( + list, + { + reviewer: reviews + for reviewer, reviews in filtered_review_counts.items() + if len(reviews) > 0 + }, + ) + + return filtered_review_counts + def sum_up_reviews(reviews_dict): """Sum up review counts per reviewer""" return {k: len(v) for k, v, in reviews_dict.items()} @@ -162,3 +194,19 @@ def generate_typescript_code(sorted_review_counts): # Total stats with open("../src/data/reviewer-count.ts", "w") as f: f.write(generate_typescript_code(sort_alphabetically(sum_up_reviews(review_dict)))) + +# Monthly stats +with open("../src/data/reviewer-count-monthly.ts", "w") as f: + f.write( + generate_typescript_code( + sort_alphabetically(sum_up_reviews(filter_by_timeframe(review_dict, weeks=4))) + ) + ) + +# Weekly stats +with open("../src/data/reviewer-count-weekly.ts", "w") as f: + f.write( + generate_typescript_code( + sort_alphabetically(sum_up_reviews(filter_by_timeframe(review_dict, weeks=1))) + ) + ) From 12ee962bedb87a310e439d342dafadbe690998d8 Mon Sep 17 00:00:00 2001 From: GeckoEidechse Date: Fri, 11 Oct 2024 00:54:16 +0200 Subject: [PATCH 09/21] style: Autoformat --- scripts/scrape-for-reviews.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/scripts/scrape-for-reviews.py b/scripts/scrape-for-reviews.py index 285d273..8a90037 100644 --- a/scripts/scrape-for-reviews.py +++ b/scripts/scrape-for-reviews.py @@ -110,7 +110,6 @@ def is_trivial_review(review_text: str): ) - def filter_by_timeframe(reviews_dict, weeks=1): """ Filters out reviews older than `weeks` weeks. @@ -142,6 +141,7 @@ def filter_by_timeframe(reviews_dict, weeks=1): return filtered_review_counts + def sum_up_reviews(reviews_dict): """Sum up review counts per reviewer""" return {k: len(v) for k, v, in reviews_dict.items()} @@ -158,7 +158,6 @@ def sort_alphabetically(reviews_dict): # Generate TypeScript code def generate_typescript_code(sorted_review_counts): - file_header_string = "// Auto-generated from Python script\n" definition_string = """ @@ -199,7 +198,9 @@ def generate_typescript_code(sorted_review_counts): with open("../src/data/reviewer-count-monthly.ts", "w") as f: f.write( generate_typescript_code( - sort_alphabetically(sum_up_reviews(filter_by_timeframe(review_dict, weeks=4))) + sort_alphabetically( + sum_up_reviews(filter_by_timeframe(review_dict, weeks=4)) + ) ) ) @@ -207,6 +208,8 @@ def generate_typescript_code(sorted_review_counts): with open("../src/data/reviewer-count-weekly.ts", "w") as f: f.write( generate_typescript_code( - sort_alphabetically(sum_up_reviews(filter_by_timeframe(review_dict, weeks=1))) + sort_alphabetically( + sum_up_reviews(filter_by_timeframe(review_dict, weeks=1)) + ) ) ) From 31a56b4f05ac463d68855a8c1b2fad5f5fa863e3 Mon Sep 17 00:00:00 2001 From: GeckoEidechse Date: Fri, 11 Oct 2024 00:56:38 +0200 Subject: [PATCH 10/21] feat: Add initial empty TypeScript files for holding review stats --- src/data/reviewer-count-monthly.ts | 9 +++++++++ src/data/reviewer-count-weekly.ts | 9 +++++++++ src/data/reviewer-count.ts | 9 +++++++++ 3 files changed, 27 insertions(+) create mode 100644 src/data/reviewer-count-monthly.ts create mode 100644 src/data/reviewer-count-weekly.ts create mode 100644 src/data/reviewer-count.ts diff --git a/src/data/reviewer-count-monthly.ts b/src/data/reviewer-count-monthly.ts new file mode 100644 index 0000000..6290bcf --- /dev/null +++ b/src/data/reviewer-count-monthly.ts @@ -0,0 +1,9 @@ +// Auto-generated from Python script + +export interface ReviewCount { + url?: string; + name: string; + count: number; +} +export const review_counts: ReviewCount[] = [ +] diff --git a/src/data/reviewer-count-weekly.ts b/src/data/reviewer-count-weekly.ts new file mode 100644 index 0000000..6290bcf --- /dev/null +++ b/src/data/reviewer-count-weekly.ts @@ -0,0 +1,9 @@ +// Auto-generated from Python script + +export interface ReviewCount { + url?: string; + name: string; + count: number; +} +export const review_counts: ReviewCount[] = [ +] diff --git a/src/data/reviewer-count.ts b/src/data/reviewer-count.ts new file mode 100644 index 0000000..6290bcf --- /dev/null +++ b/src/data/reviewer-count.ts @@ -0,0 +1,9 @@ +// Auto-generated from Python script + +export interface ReviewCount { + url?: string; + name: string; + count: number; +} +export const review_counts: ReviewCount[] = [ +] From 343074a0c2ffc32b6ad55197c4de62e1df0c0356 Mon Sep 17 00:00:00 2001 From: GeckoEidechse Date: Fri, 11 Oct 2024 16:13:55 +0200 Subject: [PATCH 11/21] feat: Initial rendering of review count --- src/components/Reviewers.astro | 17 +++++++++++++++++ src/pages/credits.astro | 8 ++++++++ 2 files changed, 25 insertions(+) create mode 100644 src/components/Reviewers.astro diff --git a/src/components/Reviewers.astro b/src/components/Reviewers.astro new file mode 100644 index 0000000..de5878c --- /dev/null +++ b/src/components/Reviewers.astro @@ -0,0 +1,17 @@ +--- +import { review_counts } from "../data/reviewer-count-monthly"; +--- + +
+
    + { + review_counts + .sort((a, b) => b.count - a.count) + .map((reviewer) => ( +
  • + {reviewer.name} - {reviewer.count} +
  • + )) + } +
+
diff --git a/src/pages/credits.astro b/src/pages/credits.astro index ff8a8fb..0bfae85 100644 --- a/src/pages/credits.astro +++ b/src/pages/credits.astro @@ -1,6 +1,7 @@ --- import Contributors from "../components/Contributors.astro"; import CommunityContributors from "../components/CommunityContributors.astro"; +import Reviewers from "../components/Reviewers.astro"; import { ContributorType } from "../data/contributors"; import Layout from "../layouts/Layout.astro"; --- @@ -28,6 +29,13 @@ import Layout from "../layouts/Layout.astro"; + +
+
Reviewers
+

TODO

+ +
+
Missing anyone on this list? Outdated entries? Feel free to Date: Fri, 11 Oct 2024 16:14:29 +0200 Subject: [PATCH 12/21] temp: commit stats to make it easier to work with current version stats should be added by separate commit from CI later --- src/data/reviewer-count-monthly.ts | 40 +++++ src/data/reviewer-count-weekly.ts | 15 ++ src/data/reviewer-count.ts | 240 +++++++++++++++++++++++++++++ 3 files changed, 295 insertions(+) diff --git a/src/data/reviewer-count-monthly.ts b/src/data/reviewer-count-monthly.ts index 6290bcf..cd49fea 100644 --- a/src/data/reviewer-count-monthly.ts +++ b/src/data/reviewer-count-monthly.ts @@ -6,4 +6,44 @@ export interface ReviewCount { count: number; } export const review_counts: ReviewCount[] = [ + { + url: "https://github.com/Alystrasz", + name: "Alystrasz", + count: 7, + }, + { + url: "https://github.com/catornot", + name: "catornot", + count: 1, + }, + { + url: "https://github.com/F1F7Y", + name: "F1F7Y", + count: 7, + }, + { + url: "https://github.com/GeckoEidechse", + name: "GeckoEidechse", + count: 14, + }, + { + url: "https://github.com/JMM889901", + name: "JMM889901", + count: 2, + }, + { + url: "https://github.com/NachosChipeados", + name: "NachosChipeados", + count: 1, + }, + { + url: "https://github.com/uniboi", + name: "uniboi", + count: 1, + }, + { + url: "https://github.com/Zanieon", + name: "Zanieon", + count: 1, + }, ] diff --git a/src/data/reviewer-count-weekly.ts b/src/data/reviewer-count-weekly.ts index 6290bcf..218211e 100644 --- a/src/data/reviewer-count-weekly.ts +++ b/src/data/reviewer-count-weekly.ts @@ -6,4 +6,19 @@ export interface ReviewCount { count: number; } export const review_counts: ReviewCount[] = [ + { + url: "https://github.com/Alystrasz", + name: "Alystrasz", + count: 5, + }, + { + url: "https://github.com/GeckoEidechse", + name: "GeckoEidechse", + count: 8, + }, + { + url: "https://github.com/uniboi", + name: "uniboi", + count: 1, + }, ] diff --git a/src/data/reviewer-count.ts b/src/data/reviewer-count.ts index 6290bcf..a876ba2 100644 --- a/src/data/reviewer-count.ts +++ b/src/data/reviewer-count.ts @@ -6,4 +6,244 @@ export interface ReviewCount { count: number; } export const review_counts: ReviewCount[] = [ + { + url: "https://github.com/0neGal", + name: "0neGal", + count: 1, + }, + { + url: "https://github.com/0xMihir", + name: "0xMihir", + count: 1, + }, + { + url: "https://github.com/abarichello", + name: "abarichello", + count: 27, + }, + { + url: "https://github.com/Alystrasz", + name: "Alystrasz", + count: 68, + }, + { + url: "https://github.com/AnActualEmerald", + name: "AnActualEmerald", + count: 1, + }, + { + url: "https://github.com/AshesToAshes76", + name: "AshesToAshes76", + count: 1, + }, + { + url: "https://github.com/ASpoonPlaysGames", + name: "ASpoonPlaysGames", + count: 213, + }, + { + url: "https://github.com/barnabwhy", + name: "barnabwhy", + count: 5, + }, + { + url: "https://github.com/BigSpice", + name: "BigSpice", + count: 3, + }, + { + url: "https://github.com/BobTheBob9", + name: "BobTheBob9", + count: 55, + }, + { + url: "https://github.com/catornot", + name: "catornot", + count: 37, + }, + { + url: "https://github.com/cpdt", + name: "cpdt", + count: 4, + }, + { + url: "https://github.com/Dinorush", + name: "Dinorush", + count: 1, + }, + { + url: "https://github.com/EladNLG", + name: "EladNLG", + count: 25, + }, + { + url: "https://github.com/EM4Volts", + name: "EM4Volts", + count: 8, + }, + { + url: "https://github.com/emma-miler", + name: "emma-miler", + count: 24, + }, + { + url: "https://github.com/Erlite", + name: "Erlite", + count: 6, + }, + { + url: "https://github.com/F1F7Y", + name: "F1F7Y", + count: 137, + }, + { + url: "https://github.com/GeckoEidechse", + name: "GeckoEidechse", + count: 691, + }, + { + url: "https://github.com/H0L0theBard", + name: "H0L0theBard", + count: 8, + }, + { + url: "https://github.com/IcePixelx", + name: "IcePixelx", + count: 1, + }, + { + url: "https://github.com/itscynxx", + name: "itscynxx", + count: 22, + }, + { + url: "https://github.com/Jan200101", + name: "Jan200101", + count: 31, + }, + { + url: "https://github.com/JMM889901", + name: "JMM889901", + count: 8, + }, + { + url: "https://github.com/KittenPopo", + name: "KittenPopo", + count: 3, + }, + { + url: "https://github.com/Klemmbaustein", + name: "Klemmbaustein", + count: 3, + }, + { + url: "https://github.com/laundmo", + name: "laundmo", + count: 12, + }, + { + url: "https://github.com/Mauler125", + name: "Mauler125", + count: 3, + }, + { + url: "https://github.com/MiloAkerman", + name: "MiloAkerman", + count: 1, + }, + { + url: "https://github.com/NachosChipeados", + name: "NachosChipeados", + count: 1, + }, + { + url: "https://github.com/NoCatt", + name: "NoCatt", + count: 28, + }, + { + url: "https://github.com/p0358", + name: "p0358", + count: 3, + }, + { + url: "https://github.com/pg9182", + name: "pg9182", + count: 100, + }, + { + url: "https://github.com/r3muxd", + name: "r3muxd", + count: 1, + }, + { + url: "https://github.com/RoyalBlue1", + name: "RoyalBlue1", + count: 38, + }, + { + url: "https://github.com/ScureX", + name: "ScureX", + count: 3, + }, + { + url: "https://github.com/SenorGeese", + name: "SenorGeese", + count: 2, + }, + { + url: "https://github.com/Slipstreamm", + name: "Slipstreamm", + count: 1, + }, + { + url: "https://github.com/taskinoz", + name: "taskinoz", + count: 1, + }, + { + url: "https://github.com/TH3-S4LM0N", + name: "TH3-S4LM0N", + count: 2, + }, + { + url: "https://github.com/timoreo22", + name: "timoreo22", + count: 2, + }, + { + url: "https://github.com/tomb-msft", + name: "tomb-msft", + count: 1, + }, + { + url: "https://github.com/uniboi", + name: "uniboi", + count: 116, + }, + { + url: "https://github.com/VITALISED", + name: "VITALISED", + count: 2, + }, + { + url: "https://github.com/x3Karma", + name: "x3Karma", + count: 6, + }, + { + url: "https://github.com/xamionex", + name: "xamionex", + count: 1, + }, + { + url: "https://github.com/xFrannM", + name: "xFrannM", + count: 1, + }, + { + url: "https://github.com/Zanieon", + name: "Zanieon", + count: 21, + }, ] From 1b957f3e55ac7f54196f79dab83c10eeb7a33980 Mon Sep 17 00:00:00 2001 From: GeckoEidechse Date: Mon, 14 Oct 2024 14:20:41 +0200 Subject: [PATCH 13/21] Increase minimum review character length to be considered for counting --- scripts/scrape-for-reviews.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/scrape-for-reviews.py b/scripts/scrape-for-reviews.py index 8a90037..73fba84 100644 --- a/scripts/scrape-for-reviews.py +++ b/scripts/scrape-for-reviews.py @@ -78,7 +78,7 @@ def get_reviews_for_pr(repo_name, pr_number): def is_trivial_review(review_text: str): """Perform a variety of checks to determine whether a review should be discarded due to not being extensive enough""" - min_review_length = 20 + min_review_length = 30 if "lgtm" in review_text.lower() and len(review_text) < min_review_length: return True From 9224e0637862a56a4a86d879fb979121db9a3112 Mon Sep 17 00:00:00 2001 From: GeckoEidechse Date: Mon, 14 Oct 2024 14:21:26 +0200 Subject: [PATCH 14/21] Split LGTM and text length check --- scripts/scrape-for-reviews.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/scripts/scrape-for-reviews.py b/scripts/scrape-for-reviews.py index 73fba84..a47fc94 100644 --- a/scripts/scrape-for-reviews.py +++ b/scripts/scrape-for-reviews.py @@ -79,7 +79,10 @@ def get_reviews_for_pr(repo_name, pr_number): def is_trivial_review(review_text: str): """Perform a variety of checks to determine whether a review should be discarded due to not being extensive enough""" min_review_length = 30 - if "lgtm" in review_text.lower() and len(review_text) < min_review_length: + if "lgtm" in review_text.lower(): + return True + + if len(review_text) < min_review_length: return True return False From b9b9c0b70b7312e1cab98bf6ae73ae0fa58ba797 Mon Sep 17 00:00:00 2001 From: GeckoEidechse Date: Mon, 14 Oct 2024 16:13:05 +0200 Subject: [PATCH 15/21] feat: Render stats as table --- src/components/Reviewers.astro | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/components/Reviewers.astro b/src/components/Reviewers.astro index de5878c..77bb7d7 100644 --- a/src/components/Reviewers.astro +++ b/src/components/Reviewers.astro @@ -3,15 +3,20 @@ import { review_counts } from "../data/reviewer-count-monthly"; ---
-
    + + + + + { review_counts .sort((a, b) => b.count - a.count) .map((reviewer) => ( -
  • - {reviewer.name} - {reviewer.count} -
  • + + + + )) } - +
    Reviewer# of reviews
    {reviewer.name}{reviewer.count}
From 17d15ff16a6181b4e0fe1439a63b8d20e02d270e Mon Sep 17 00:00:00 2001 From: GeckoEidechse Date: Mon, 14 Oct 2024 16:17:03 +0200 Subject: [PATCH 16/21] Include weekly and total reviews --- src/components/Reviewers.astro | 41 ++++++++++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/src/components/Reviewers.astro b/src/components/Reviewers.astro index 77bb7d7..f39a386 100644 --- a/src/components/Reviewers.astro +++ b/src/components/Reviewers.astro @@ -1,15 +1,52 @@ --- -import { review_counts } from "../data/reviewer-count-monthly"; +import { review_counts_total } from "../data/reviewer-count"; +import { review_counts_monthly } from "../data/reviewer-count-monthly"; +import { review_counts_weekly } from "../data/reviewer-count-weekly"; ---
+

Weekly review count

{ - review_counts + review_counts_weekly + .sort((a, b) => b.count - a.count) + .map((reviewer) => ( + + + + + )) + } +
Reviewer # of reviews
{reviewer.name}{reviewer.count}
+

Monthly review count

+ + + + + + { + review_counts_monthly + .sort((a, b) => b.count - a.count) + .map((reviewer) => ( + + + + + )) + } +
Reviewer# of reviews
{reviewer.name}{reviewer.count}
+

Total review count

+ + + + + + { + review_counts_total .sort((a, b) => b.count - a.count) .map((reviewer) => ( From 418c9303828c581354f1c8bc4d39a8c6692e8dc6 Mon Sep 17 00:00:00 2001 From: GeckoEidechse Date: Mon, 14 Oct 2024 16:18:12 +0200 Subject: [PATCH 17/21] Annotate category type --- scripts/scrape-for-reviews.py | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/scripts/scrape-for-reviews.py b/scripts/scrape-for-reviews.py index a47fc94..2c111f0 100644 --- a/scripts/scrape-for-reviews.py +++ b/scripts/scrape-for-reviews.py @@ -160,7 +160,7 @@ def sort_alphabetically(reviews_dict): # Generate TypeScript code -def generate_typescript_code(sorted_review_counts): +def generate_typescript_code(sorted_review_counts, timeframe="total"): file_header_string = "// Auto-generated from Python script\n" definition_string = """ @@ -170,7 +170,7 @@ def generate_typescript_code(sorted_review_counts): count: number; } """ - list_start_string = """export const review_counts: ReviewCount[] = [""" + list_start_string = f"""export const review_counts_{timeframe}: ReviewCount[] = [""" list_end_string = """ ] """ @@ -195,7 +195,11 @@ def generate_typescript_code(sorted_review_counts): # Total stats with open("../src/data/reviewer-count.ts", "w") as f: - f.write(generate_typescript_code(sort_alphabetically(sum_up_reviews(review_dict)))) + f.write( + generate_typescript_code( + sort_alphabetically(sum_up_reviews(review_dict)), "total" + ) + ) # Monthly stats with open("../src/data/reviewer-count-monthly.ts", "w") as f: @@ -203,7 +207,8 @@ def generate_typescript_code(sorted_review_counts): generate_typescript_code( sort_alphabetically( sum_up_reviews(filter_by_timeframe(review_dict, weeks=4)) - ) + ), + "monthly", ) ) @@ -213,6 +218,7 @@ def generate_typescript_code(sorted_review_counts): generate_typescript_code( sort_alphabetically( sum_up_reviews(filter_by_timeframe(review_dict, weeks=1)) - ) + ), + "weekly", ) ) From aeeb1eb487eb6357d135b76f46e34554d0540789 Mon Sep 17 00:00:00 2001 From: GeckoEidechse Date: Mon, 14 Oct 2024 16:19:57 +0200 Subject: [PATCH 18/21] Fill out subtext --- src/pages/credits.astro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/credits.astro b/src/pages/credits.astro index 0bfae85..2622d2e 100644 --- a/src/pages/credits.astro +++ b/src/pages/credits.astro @@ -32,7 +32,7 @@ import Layout from "../layouts/Layout.astro";
Reviewers
-

TODO

+

Stats for number of reviews performed over certain time durations

From 300e159bb9fa332ae0688aee4143be65763d927f Mon Sep 17 00:00:00 2001 From: GeckoEidechse Date: Mon, 14 Oct 2024 16:20:21 +0200 Subject: [PATCH 19/21] Switch headings to H2 --- src/components/Reviewers.astro | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/Reviewers.astro b/src/components/Reviewers.astro index f39a386..cb56b18 100644 --- a/src/components/Reviewers.astro +++ b/src/components/Reviewers.astro @@ -5,7 +5,7 @@ import { review_counts_weekly } from "../data/reviewer-count-weekly"; ---
-

Weekly review count

+

Weekly review count

Reviewer# of reviews
@@ -22,7 +22,7 @@ import { review_counts_weekly } from "../data/reviewer-count-weekly"; )) }
Reviewer
-

Monthly review count

+

Monthly review count

@@ -39,7 +39,7 @@ import { review_counts_weekly } from "../data/reviewer-count-weekly"; )) }
Reviewer
-

Total review count

+

Total review count

From cfe1f010709e41a8042866f29aa5bc02bd3bb6ca Mon Sep 17 00:00:00 2001 From: GeckoEidechse Date: Mon, 14 Oct 2024 16:22:11 +0200 Subject: [PATCH 20/21] Require at least 2 reviews to show up in table --- src/components/Reviewers.astro | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/Reviewers.astro b/src/components/Reviewers.astro index cb56b18..ce3bfc6 100644 --- a/src/components/Reviewers.astro +++ b/src/components/Reviewers.astro @@ -48,6 +48,7 @@ import { review_counts_weekly } from "../data/reviewer-count-weekly"; { review_counts_total .sort((a, b) => b.count - a.count) + .filter((c) => c.count > 1) // Require at least 2 reviews to reduce table size .map((reviewer) => ( From c8f9fa32047b520e5e844f248c47683d786ee120 Mon Sep 17 00:00:00 2001 From: GeckoEidechse Date: Mon, 14 Oct 2024 16:22:26 +0200 Subject: [PATCH 21/21] temp: Add updated stats --- src/data/reviewer-count-monthly.ts | 15 ++---- src/data/reviewer-count-weekly.ts | 18 +++---- src/data/reviewer-count.ts | 76 +++++++++++------------------- 3 files changed, 42 insertions(+), 67 deletions(-) diff --git a/src/data/reviewer-count-monthly.ts b/src/data/reviewer-count-monthly.ts index cd49fea..68e79c0 100644 --- a/src/data/reviewer-count-monthly.ts +++ b/src/data/reviewer-count-monthly.ts @@ -5,36 +5,31 @@ export interface ReviewCount { name: string; count: number; } -export const review_counts: ReviewCount[] = [ +export const review_counts_monthly: ReviewCount[] = [ { url: "https://github.com/Alystrasz", name: "Alystrasz", - count: 7, + count: 6, }, { url: "https://github.com/catornot", name: "catornot", count: 1, }, - { - url: "https://github.com/F1F7Y", - name: "F1F7Y", - count: 7, - }, { url: "https://github.com/GeckoEidechse", name: "GeckoEidechse", - count: 14, + count: 19, }, { url: "https://github.com/JMM889901", name: "JMM889901", - count: 2, + count: 3, }, { url: "https://github.com/NachosChipeados", name: "NachosChipeados", - count: 1, + count: 2, }, { url: "https://github.com/uniboi", diff --git a/src/data/reviewer-count-weekly.ts b/src/data/reviewer-count-weekly.ts index 218211e..88d7259 100644 --- a/src/data/reviewer-count-weekly.ts +++ b/src/data/reviewer-count-weekly.ts @@ -5,20 +5,20 @@ export interface ReviewCount { name: string; count: number; } -export const review_counts: ReviewCount[] = [ - { - url: "https://github.com/Alystrasz", - name: "Alystrasz", - count: 5, - }, +export const review_counts_weekly: ReviewCount[] = [ { url: "https://github.com/GeckoEidechse", name: "GeckoEidechse", - count: 8, + count: 11, + }, + { + url: "https://github.com/JMM889901", + name: "JMM889901", + count: 2, }, { - url: "https://github.com/uniboi", - name: "uniboi", + url: "https://github.com/NachosChipeados", + name: "NachosChipeados", count: 1, }, ] diff --git a/src/data/reviewer-count.ts b/src/data/reviewer-count.ts index a876ba2..fa188fa 100644 --- a/src/data/reviewer-count.ts +++ b/src/data/reviewer-count.ts @@ -5,7 +5,7 @@ export interface ReviewCount { name: string; count: number; } -export const review_counts: ReviewCount[] = [ +export const review_counts_total: ReviewCount[] = [ { url: "https://github.com/0neGal", name: "0neGal", @@ -19,12 +19,12 @@ export const review_counts: ReviewCount[] = [ { url: "https://github.com/abarichello", name: "abarichello", - count: 27, + count: 15, }, { url: "https://github.com/Alystrasz", name: "Alystrasz", - count: 68, + count: 63, }, { url: "https://github.com/AnActualEmerald", @@ -39,32 +39,32 @@ export const review_counts: ReviewCount[] = [ { url: "https://github.com/ASpoonPlaysGames", name: "ASpoonPlaysGames", - count: 213, + count: 165, }, { url: "https://github.com/barnabwhy", name: "barnabwhy", - count: 5, + count: 4, }, { url: "https://github.com/BigSpice", name: "BigSpice", - count: 3, + count: 1, }, { url: "https://github.com/BobTheBob9", name: "BobTheBob9", - count: 55, + count: 40, }, { url: "https://github.com/catornot", name: "catornot", - count: 37, + count: 32, }, { url: "https://github.com/cpdt", name: "cpdt", - count: 4, + count: 2, }, { url: "https://github.com/Dinorush", @@ -74,7 +74,7 @@ export const review_counts: ReviewCount[] = [ { url: "https://github.com/EladNLG", name: "EladNLG", - count: 25, + count: 14, }, { url: "https://github.com/EM4Volts", @@ -84,47 +84,42 @@ export const review_counts: ReviewCount[] = [ { url: "https://github.com/emma-miler", name: "emma-miler", - count: 24, + count: 20, }, { url: "https://github.com/Erlite", name: "Erlite", - count: 6, + count: 5, }, { url: "https://github.com/F1F7Y", name: "F1F7Y", - count: 137, + count: 79, }, { url: "https://github.com/GeckoEidechse", name: "GeckoEidechse", - count: 691, + count: 624, }, { url: "https://github.com/H0L0theBard", name: "H0L0theBard", - count: 8, - }, - { - url: "https://github.com/IcePixelx", - name: "IcePixelx", - count: 1, + count: 4, }, { url: "https://github.com/itscynxx", name: "itscynxx", - count: 22, + count: 21, }, { url: "https://github.com/Jan200101", name: "Jan200101", - count: 31, + count: 29, }, { url: "https://github.com/JMM889901", name: "JMM889901", - count: 8, + count: 7, }, { url: "https://github.com/KittenPopo", @@ -139,7 +134,7 @@ export const review_counts: ReviewCount[] = [ { url: "https://github.com/laundmo", name: "laundmo", - count: 12, + count: 10, }, { url: "https://github.com/Mauler125", @@ -154,12 +149,12 @@ export const review_counts: ReviewCount[] = [ { url: "https://github.com/NachosChipeados", name: "NachosChipeados", - count: 1, + count: 2, }, { url: "https://github.com/NoCatt", name: "NoCatt", - count: 28, + count: 26, }, { url: "https://github.com/p0358", @@ -169,7 +164,7 @@ export const review_counts: ReviewCount[] = [ { url: "https://github.com/pg9182", name: "pg9182", - count: 100, + count: 78, }, { url: "https://github.com/r3muxd", @@ -179,17 +174,17 @@ export const review_counts: ReviewCount[] = [ { url: "https://github.com/RoyalBlue1", name: "RoyalBlue1", - count: 38, + count: 29, }, { url: "https://github.com/ScureX", name: "ScureX", - count: 3, + count: 1, }, { url: "https://github.com/SenorGeese", name: "SenorGeese", - count: 2, + count: 1, }, { url: "https://github.com/Slipstreamm", @@ -204,38 +199,23 @@ export const review_counts: ReviewCount[] = [ { url: "https://github.com/TH3-S4LM0N", name: "TH3-S4LM0N", - count: 2, - }, - { - url: "https://github.com/timoreo22", - name: "timoreo22", - count: 2, - }, - { - url: "https://github.com/tomb-msft", - name: "tomb-msft", count: 1, }, { url: "https://github.com/uniboi", name: "uniboi", - count: 116, + count: 77, }, { url: "https://github.com/VITALISED", name: "VITALISED", - count: 2, + count: 1, }, { url: "https://github.com/x3Karma", name: "x3Karma", count: 6, }, - { - url: "https://github.com/xamionex", - name: "xamionex", - count: 1, - }, { url: "https://github.com/xFrannM", name: "xFrannM", @@ -244,6 +224,6 @@ export const review_counts: ReviewCount[] = [ { url: "https://github.com/Zanieon", name: "Zanieon", - count: 21, + count: 17, }, ]
Reviewer
{reviewer.name}