Files
werkrevisor/tools/review-rounds
claude-code 5e91298b44
werkator build succeeded after 00:28
werkator/werkrevisor-statistics build succeeded after 00:55
werkrevisor 0.31.6: hints on PR documents are line comments again (#72)
Co-authored-by: claude-code <claude-code@javagil.de>
2026-10-10 12:33:39 +02:00

60 lines
2.4 KiB
Python
Executable File

#!/usr/bin/env python3
"""Usage: tools/review-rounds <gitea-url> <owner> <since> <repo>...
Lists per PR created since <since> (ISO date or time) the review rounds of werkrevisor, their verdicts,
the line comments of the bot and the findings that stood only in the result comment,
to see whether a change of the review costs or saves rounds.
Needs GITEA_TOKEN with read access in the environment; it never prints the token.
Example:
GITEA_TOKEN=… tools/review-rounds https://git.example.org mi 2026-10-09T20:00 werkrevisor werkator
"""
import json
import os
import re
import sys
import urllib.request
def main(argv):
if len(argv) < 4 or argv[0] in ("-h", "--help"):
print(__doc__.strip())
return 0
base, owner, since, repos = argv[0].rstrip("/"), argv[1], argv[2], argv[3:]
headers = {"Authorization": "token " + os.environ["GITEA_TOKEN"]}
def get(path):
request = urllib.request.Request(f"{base}/api/v1/repos/{owner}/{path}", headers=headers)
with urllib.request.urlopen(request, timeout=60) as response:
return json.load(response)
def pulls(repo):
page = 1
while True:
batch = get(f"{repo}/pulls?state=all&limit=50&page={page}")
if not batch:
return
yield from batch
page += 1
for repo in repos:
for pr in pulls(repo):
if pr["created_at"] < since:
continue
results = [c["body"] for c in get(f"{repo}/issues/{pr['number']}/comments") if "<!-- werkrevisor:" in c["body"]]
verdicts = [m.group(1) for b in results for m in [re.search(r"werkrevisor-verdict:(\w+)", b)] if m]
line_comments = sum(r["comments_count"] for r in get(f"{repo}/pulls/{pr['number']}/reviews")
if r["user"]["login"] != pr["user"]["login"])
only_here = [line for b in results for line in re.findall(r"^\d+\. \*\*.*", b, re.M)
if "as a line comment" not in line and "still open in" not in line]
state = "merged" if pr.get("merged") else pr["state"]
print(f"{repo} #{pr['number']}: {len(results)} round(s) {'→'.join(verdicts) or '-'}, "
f"{line_comments} line comment(s), {len(only_here)} finding(s) only in the result comment, {state}")
for line in only_here:
print(f" {line[:150]}")
return 0
if __name__ == "__main__":
sys.exit(main(sys.argv[1:]))