Files
Gitea-Tools/review_pr.py
T
sysadmin b78e9f2d40 docs: stop review_pr.py advertising CLI merge in docstring/help (#16)
Stale documentation only — no behavior change. The module docstring and the
--merge / --merge-method argparse help text no longer advertise a working CLI
merge. They now state CLI merge is disabled/fail-closed and that merge is
handled solely by the gated gitea_merge_pr MCP workflow (#16).

CLI merge remains disabled: --merge still fails closed with no API call, and
review_pr.py contains no /merge call. No MCP merge gate was changed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 17:35:06 -04:00

111 lines
4.5 KiB
Python
Executable File

#!/usr/bin/env python3
"""Review and sign-off on a Gitea pull request.
Submits a review (APPROVE, COMMENT, REQUEST_CHANGES). CLI merge is disabled:
the `--merge` flag is retained only for compatibility and fails closed without
making any API call. Merge is handled solely by the gated `gitea_merge_pr` MCP
workflow (#16), which enforces identity/profile/eligibility, explicit
confirmation, expected head SHA checking, and self-merge protection.
Usage (review only):
review_pr.py --pr-number 12 --event APPROVE --body "Approved and signed off"
"""
import os
import sys
import json
import base64
import argparse
import urllib.request
import urllib.error
# Auto-execute using the project's local virtual environment Python
PROJECT_ROOT = os.path.dirname(os.path.abspath(__file__))
venv_python = os.path.join(PROJECT_ROOT, "venv", "bin", "python3")
if os.path.exists(venv_python) and sys.executable != venv_python:
os.execv(venv_python, [venv_python] + sys.argv)
from gitea_auth import get_auth_header, resolve_remote, add_remote_args, api_request, repo_api_url
def main(argv=None):
parser = argparse.ArgumentParser(description="Review and sign-off on a Gitea pull request.")
add_remote_args(parser)
parser.add_argument("--pr-number", type=int, required=True, help="PR number/index to review.")
parser.add_argument("--event", choices=["APPROVE", "COMMENT", "REQUEST_CHANGES"], default="APPROVE",
help="Review event/action type (default: APPROVE).")
parser.add_argument("--body", default="", help="Review body/comment text.")
parser.add_argument("--body-file", help="Read review body from this file ('-' for stdin).")
parser.add_argument("--merge", action="store_true",
help="DISABLED — fails closed with no API call. CLI merge is not "
"supported; use the gated gitea_merge_pr MCP workflow (#16).")
parser.add_argument("--merge-method", choices=["merge", "squash", "rebase"], default="merge",
help="Ignored — CLI merge is disabled (see --merge).")
args = parser.parse_args(argv)
# Fail closed: direct CLI merge is disabled (#16). LLM automations were
# using this flag as an ungated merge bypass. Merge is only available via
# the gated `gitea_merge_pr` MCP workflow, which enforces
# identity/profile/eligibility, explicit confirmation, expected head SHA,
# and self-merge protection. No API call is made here.
if args.merge:
print(
"Direct CLI merge is disabled. Merge is only available through the "
"gated #16 workflow (MCP tool 'gitea_merge_pr'), which enforces "
"identity/profile/eligibility, explicit confirmation, expected head "
"SHA checking, and self-merge protection. Re-run without --merge to "
"submit a review only.",
file=sys.stderr,
)
return 2
host, org, repo = resolve_remote(args)
body = args.body
if args.body_file:
if args.body_file == "-":
body = sys.stdin.read()
else:
with open(args.body_file, "r", encoding="utf-8") as fh:
body = fh.read()
auth = get_auth_header(host)
if not auth:
print(f"Could not get credentials or token for {host}.", file=sys.stderr)
return 1
# 1. Fetch PR to get the latest head commit SHA (required for review validation)
pr_url = f"{repo_api_url(host, org, repo)}/pulls/{args.pr_number}"
try:
pr_data = api_request("GET", pr_url, auth)
except Exception as e:
print(f"Error fetching PR #{args.pr_number}: {e}", file=sys.stderr)
return 1
commit_sha = pr_data.get("head", {}).get("sha")
if not commit_sha:
print(f"Could not find head commit SHA for PR #{args.pr_number}.", file=sys.stderr)
return 1
# 2. Submit the PR review
review_url = f"{repo_api_url(host, org, repo)}/pulls/{args.pr_number}/reviews"
payload = {
"body": body,
"event": args.event,
"commit_id": commit_sha
}
try:
api_request("POST", review_url, auth, payload)
print(f"Successfully submitted review for PR #{args.pr_number}: event={args.event}")
except Exception as e:
print(f"Error submitting review: {e}", file=sys.stderr)
return 1
# Merge is intentionally not performed here — see the fail-closed guard
# above. Use the gated `gitea_merge_pr` MCP workflow (#16) to merge.
return 0
if __name__ == "__main__":
sys.exit(main())