run_review
CLI для ручного запуска LLM-ревью.
Примеры:
python run_review.py e.anisimov/LostAndFound 15
python run_review.py e.anisimov/LostAndFound 15 --head-sha
1""" 2CLI для ручного запуска LLM-ревью. 3 4Примеры: 5 python run_review.py e.anisimov/LostAndFound 15 6 python run_review.py e.anisimov/LostAndFound 15 --head-sha <sha> 7 python run_review.py e.anisimov/LostAndFound --all-open 8""" 9 10from __future__ import annotations 11 12import argparse 13import sys 14 15from config import Config 16from gitea_client import GiteaClient 17from review import ReviewOutcome, run_review 18 19 20def _repo_arg(value: str) -> tuple[str, str]: 21 """Разбирает 'owner/repo'.""" 22 if "/" not in value: 23 raise argparse.ArgumentTypeError("Ожидается формат owner/repo") 24 owner, repo = value.split("/", 1) 25 return owner, repo 26 27 28def main() -> int: 29 parser = argparse.ArgumentParser(description="LLM code review для PR в Gitea") 30 parser.add_argument("repo", type=_repo_arg, help="owner/repo") 31 parser.add_argument("pr_number", nargs="?", type=int, help="номер PR") 32 parser.add_argument( 33 "--head-sha", 34 help="head-коммит (по умолчанию — head PR)", 35 ) 36 parser.add_argument( 37 "--all-open", action="store_true", help="ревью всех открытых PR репозитория" 38 ) 39 args = parser.parse_args() 40 41 owner, repo = args.repo 42 config = Config.from_env() 43 client = GiteaClient(config) 44 45 if args.all_open: 46 prs = client.get(f"/repos/{owner}/{repo}/pulls?state=open") 47 for pr in prs: 48 print(f"-- {owner}/{repo}#{pr['number']}: {pr['title']}") 49 run_review(client, config, owner, repo, pr["number"], pr["head"]["sha"]) 50 return 0 51 52 if not args.pr_number: 53 parser.error("нужен номер PR или --all-open") 54 55 outcome: ReviewOutcome = run_review( 56 client, config, owner, repo, args.pr_number, args.head_sha 57 ) 58 if outcome.skipped: 59 print(f"Пропущено: {outcome.reason}") 60 else: 61 print(f"Готово: event={outcome.event}, findings={outcome.findings}") 62 return 0 63 64 65if __name__ == "__main__": 66 sys.exit(main())
def
main() -> int:
29def main() -> int: 30 parser = argparse.ArgumentParser(description="LLM code review для PR в Gitea") 31 parser.add_argument("repo", type=_repo_arg, help="owner/repo") 32 parser.add_argument("pr_number", nargs="?", type=int, help="номер PR") 33 parser.add_argument( 34 "--head-sha", 35 help="head-коммит (по умолчанию — head PR)", 36 ) 37 parser.add_argument( 38 "--all-open", action="store_true", help="ревью всех открытых PR репозитория" 39 ) 40 args = parser.parse_args() 41 42 owner, repo = args.repo 43 config = Config.from_env() 44 client = GiteaClient(config) 45 46 if args.all_open: 47 prs = client.get(f"/repos/{owner}/{repo}/pulls?state=open") 48 for pr in prs: 49 print(f"-- {owner}/{repo}#{pr['number']}: {pr['title']}") 50 run_review(client, config, owner, repo, pr["number"], pr["head"]["sha"]) 51 return 0 52 53 if not args.pr_number: 54 parser.error("нужен номер PR или --all-open") 55 56 outcome: ReviewOutcome = run_review( 57 client, config, owner, repo, args.pr_number, args.head_sha 58 ) 59 if outcome.skipped: 60 print(f"Пропущено: {outcome.reason}") 61 else: 62 print(f"Готово: event={outcome.event}, findings={outcome.findings}") 63 return 0