Files
2026-07-13 13:05:14 +08:00

132 lines
3.5 KiB
Python
Executable File

#!/usr/bin/env python3
"""Generate a list of GitHub issues that need attention."""
from __future__ import annotations
import argparse
import multiprocessing
import sys
from typing import Any
import requests
from tqdm import tqdm
OWNER = "rerun-io"
REPO = "rerun"
OFFICIAL_RERUN_DEVS = [
"abey79",
"emilk",
"jleibs",
"jondo2010",
"jprochazk",
"karimo87",
"martenbjork",
"nikolausWest",
"roym899",
"teh-cmc",
"Wumpf",
"zehiko",
]
def get_github_token() -> str:
import os
token = os.environ.get("GH_ACCESS_TOKEN", "")
if token != "":
return token
home_dir = os.path.expanduser("~")
token_file = os.path.join(home_dir, ".githubtoken")
try:
with open(token_file, encoding="utf8") as f:
token = f.read().strip()
return token
except Exception:
pass
print("ERROR: expected a GitHub token in the environment variable GH_ACCESS_TOKEN or in ~/.githubtoken")
sys.exit(1)
def fetch_issue(issue_json: dict[str, Any]) -> dict[str, Any]:
url = issue_json["url"]
gh_access_token = get_github_token()
headers = {"Authorization": f"Token {gh_access_token}"}
response = requests.get(url, headers=headers)
json: dict[str, Any] = response.json()
if response.status_code != 200:
print(f"ERROR {url}: {response.status_code} - {json['message']}")
sys.exit(1)
return json
def main() -> None:
parser = argparse.ArgumentParser(description="Generate a list of GitHub issues that need attention.")
parser.add_argument("--list-external", action="store_true", help="List all external issues")
args = parser.parse_args()
access_token = get_github_token()
headers = {"Authorization": f"Bearer {access_token}"}
all_issues = []
urls = [f"https://api.github.com/repos/{OWNER}/{REPO}/issues"]
while urls:
url = urls.pop()
print(f"Fetching {url}…")
response = requests.get(url, headers=headers)
json = response.json()
if response.status_code != 200:
print(f"ERROR {url}: {response.status_code} - {json['message']}")
sys.exit(1)
all_issues += list(json)
# Check if there is a next page:
if "Link" in response.headers:
links = response.headers["Link"].split(", ")
for link in links:
if 'rel="next"' in link:
next_url = link.split(";")[0][1:-1]
urls += [next_url]
pool = multiprocessing.Pool()
issues_list = list(
tqdm(
pool.imap(fetch_issue, all_issues),
total=len(all_issues),
desc="Fetching issue details",
),
)
issues_list.sort(key=lambda issue: issue["number"])
# Print the response content
for issue in issues_list:
author = issue["user"]["login"]
html_url = issue["html_url"]
comments = issue["comments"]
state = issue["state"]
labels = [label["name"] for label in issue["labels"]]
if args.list_external and state == "open" and author not in OFFICIAL_RERUN_DEVS:
print(f"{html_url} by {author}")
continue
if "👀 needs triage" in labels:
print(f"{html_url} by {author} needs triage")
elif len(labels) == 0:
print(f"{html_url} by {author} has no labels")
elif comments == 0 and state == "open" and author not in OFFICIAL_RERUN_DEVS:
print(f"{html_url} by {author} has {comments} comments")
if __name__ == "__main__":
main()