128 lines
3.5 KiB
Python
128 lines
3.5 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Generate Claude Code PRs data.
|
|
|
|
Fetches all PRs from the GitHub API that were created from branches
|
|
starting with 'claude/' and writes a static JSON file for the dashboard.
|
|
|
|
Usage:
|
|
python scripts/generate_claude_prs.py
|
|
|
|
Optionally set GITHUB_TOKEN env var to avoid rate limits.
|
|
"""
|
|
|
|
import json
|
|
import os
|
|
import requests
|
|
import time
|
|
from datetime import datetime, timezone
|
|
|
|
REPO = "davila7/claude-code-templates"
|
|
API_URL = f"https://api.github.com/repos/{REPO}/pulls"
|
|
OUTPUT_FILE = os.path.join(os.path.dirname(__file__), "..", "docs", "claude-prs", "data.json")
|
|
|
|
|
|
def fetch_prs(state="all", token=None):
|
|
"""Fetch all PRs with pagination."""
|
|
headers = {"Accept": "application/vnd.github+json"}
|
|
if token:
|
|
headers["Authorization"] = f"Bearer {token}"
|
|
|
|
all_prs = []
|
|
page = 1
|
|
|
|
while True:
|
|
url = f"{API_URL}?state={state}&per_page=100&page={page}&sort=created&direction=desc"
|
|
print(f" Fetching page {page}...")
|
|
|
|
for attempt in range(3):
|
|
try:
|
|
resp = requests.get(url, headers=headers, timeout=30)
|
|
break
|
|
except requests.exceptions.RequestException as e:
|
|
if attempt < 2:
|
|
wait = 2 ** (attempt + 1)
|
|
print(f" Retry in {wait}s: {e}")
|
|
time.sleep(wait)
|
|
else:
|
|
raise
|
|
|
|
if resp.status_code == 403:
|
|
print(f" Rate limited. Set GITHUB_TOKEN env var to increase limits.")
|
|
break
|
|
|
|
if resp.status_code != 200:
|
|
print(f" Error {resp.status_code}: {resp.text[:200]}")
|
|
break
|
|
|
|
data = resp.json()
|
|
if not data:
|
|
break
|
|
|
|
all_prs.extend(data)
|
|
page += 1
|
|
|
|
if len(data) < 100:
|
|
break
|
|
|
|
return all_prs
|
|
|
|
|
|
def is_claude_pr(pr):
|
|
"""Check if a PR was created by Claude Code (branch starts with claude/)."""
|
|
ref = pr.get("head", {}).get("ref", "")
|
|
return ref.startswith("claude/")
|
|
|
|
|
|
def extract_pr_data(pr):
|
|
"""Extract only the fields needed for the dashboard."""
|
|
return {
|
|
"number": pr["number"],
|
|
"title": pr["title"],
|
|
"state": pr["state"],
|
|
"merged": pr.get("merged_at") is not None,
|
|
"branch": pr["head"]["ref"],
|
|
"created_at": pr["created_at"],
|
|
"merged_at": pr.get("merged_at"),
|
|
"closed_at": pr.get("closed_at"),
|
|
"url": pr["html_url"],
|
|
"user": pr.get("user", {}).get("login", "unknown"),
|
|
}
|
|
|
|
|
|
def main():
|
|
print("Generating Claude Code PRs data...")
|
|
|
|
token = os.environ.get("GITHUB_TOKEN")
|
|
if token:
|
|
print(" Using GITHUB_TOKEN for authentication")
|
|
else:
|
|
print(" No GITHUB_TOKEN set (60 req/hr limit). Set it to avoid rate limits.")
|
|
|
|
all_prs = fetch_prs(token=token)
|
|
print(f" Total PRs fetched: {len(all_prs)}")
|
|
|
|
claude_prs = [extract_pr_data(pr) for pr in all_prs if is_claude_pr(pr)]
|
|
print(f" Claude Code PRs found: {len(claude_prs)}")
|
|
|
|
# Sort by creation date descending
|
|
claude_prs.sort(key=lambda p: p["created_at"], reverse=True)
|
|
|
|
output = {
|
|
"generated_at": datetime.now(timezone.utc).isoformat(),
|
|
"repo": REPO,
|
|
"total": len(claude_prs),
|
|
"prs": claude_prs,
|
|
}
|
|
|
|
os.makedirs(os.path.dirname(OUTPUT_FILE), exist_ok=True)
|
|
with open(OUTPUT_FILE, "w") as f:
|
|
json.dump(output, f, indent=2)
|
|
|
|
print(f" Written to {OUTPUT_FILE}")
|
|
print("Done.")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|