- Bind review decision state to in-process session (pid + profile lock); drop /tmp file path. - Fail closed on review_pr.py CLI; route live reviews through gated MCP tools only. - Require operator_authorized on review correction; allow re-mark after correction. - Validate remote/org/repo on mark and submit; wire review mutation proof into build_final_report. - Add security regression tests for spoofed locks, correction flow, and CLI bypass. Refs #211
67 lines
3.0 KiB
Python
Executable File
67 lines
3.0 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.
|
|
|
|
Live review submission is also disabled (#211): use the gated
|
|
``gitea_submit_pr_review`` MCP workflow, which enforces validation-phase
|
|
dry-run, final decision marking, and single-terminal review mutation rules.
|
|
|
|
Usage (review only — disabled):
|
|
review_pr.py --pr-number 12 --event APPROVE --body "Approved and signed off"
|
|
"""
|
|
import os
|
|
import sys
|
|
import argparse
|
|
|
|
# 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 add_remote_args
|
|
|
|
|
|
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)
|
|
|
|
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 "
|
|
"see the review-submission guard message.",
|
|
file=sys.stderr,
|
|
)
|
|
return 2
|
|
|
|
print(
|
|
"Direct CLI review submission is disabled (#211). Use the gated "
|
|
"'gitea_submit_pr_review' MCP workflow, which enforces validation-phase "
|
|
"dry-run, gitea_mark_final_review_decision, and single-terminal review "
|
|
"mutation rules.",
|
|
file=sys.stderr,
|
|
)
|
|
return 2
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main()) |