60 lines
2.4 KiB
Python
Executable File
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:]))
|