improvements: Big Reviewer Update #4
2
TODO.md
2
TODO.md
@@ -3,7 +3,7 @@
|
||||
## Open Items By Priority
|
||||
|
||||
### P0 (Critical)
|
||||
- [ ] `BUG`: True isolated runner flow: clone/fetch/checkout PR branch inside the ephemeral container itself, not on host before prompt generation.
|
||||
- [x] `BUG`: True isolated runner flow: clone/fetch/checkout PR branch inside the ephemeral container itself, not on host before prompt generation.
|
||||
- [x] `BUG`: Remove host-side fallback path for review execution, or gate it behind explicit `ALLOW_HOST_FALLBACK=false` by default so isolation cannot be bypassed silently.
|
||||
- [x] `BUG`: Enforce `.codex-review.yml` `enabled=false` at runtime (currently loaded but not enforced).
|
||||
- [x] `BUG`: Remove fix command support from runtime and command parsing.
|
||||
|
||||
@@ -17,7 +17,7 @@ from sqlalchemy.orm import Session
|
||||
from gitea_codex_bot.config import Settings, get_settings
|
||||
from gitea_codex_bot.db import get_session
|
||||
from gitea_codex_bot.models import JobStatus, ReviewJob
|
||||
from gitea_codex_bot.services.commands import parse_command
|
||||
from gitea_codex_bot.services.commands import detect_prefixed_command, parse_command
|
||||
from gitea_codex_bot.services.gitea import GiteaClient
|
||||
from gitea_codex_bot.services.jobs import cooldown_remaining_seconds, enqueue_job, persist_webhook_event
|
||||
from gitea_codex_bot.services.repo_config import RepoReviewConfig, parse_repo_review_config_text
|
||||
@@ -421,9 +421,31 @@ async def gitea_webhook(
|
||||
if sender_username == settings.gitea_bot_username:
|
||||
return {"accepted": False, "reason": "bot comment ignored"}
|
||||
|
||||
if repo not in settings.allowed_repo_set:
|
||||
logger.info(
|
||||
"Webhook ignored: repo not in ALLOWED_REPOS repo=%s pr=%s comment_id=%s sender=%s",
|
||||
repo,
|
||||
pr_number,
|
||||
comment_id,
|
||||
sender_username,
|
||||
)
|
||||
return {"accepted": False, "reason": "repo not allowed"}
|
||||
|
||||
comment_body = str(payload.get("comment", {}).get("body", "")).strip()
|
||||
parsed_command = parse_command(comment_body, aliases=settings.bot_command_aliases)
|
||||
if not parsed_command:
|
||||
attempted_command = detect_prefixed_command(comment_body, aliases=settings.bot_command_aliases)
|
||||
if attempted_command:
|
||||
gitea = GiteaClient(settings)
|
||||
if attempted_command == "fix":
|
||||
gitea.post_issue_comment(repo, pr_number, "⚠️ `@codex fix` is no longer supported on this bot.")
|
||||
return {"accepted": False, "reason": "unsupported command", "command": attempted_command}
|
||||
gitea.post_issue_comment(
|
||||
repo,
|
||||
pr_number,
|
||||
f"⚠️ Command `@codex {attempted_command}` is not supported. Try `@codex -h`.",
|
||||
)
|
||||
return {"accepted": False, "reason": "unsupported command", "command": attempted_command}
|
||||
logger.info(
|
||||
"Webhook ignored: no @codex review command repo=%s pr=%s comment_id=%s sender=%s",
|
||||
repo,
|
||||
@@ -442,16 +464,6 @@ async def gitea_webhook(
|
||||
parsed_command.name,
|
||||
)
|
||||
|
||||
if repo not in settings.allowed_repo_set:
|
||||
logger.info(
|
||||
"Webhook ignored: repo not in ALLOWED_REPOS repo=%s pr=%s comment_id=%s sender=%s",
|
||||
repo,
|
||||
pr_number,
|
||||
comment_id,
|
||||
sender_username,
|
||||
)
|
||||
return {"accepted": False, "reason": "repo not allowed"}
|
||||
|
||||
inserted = persist_webhook_event(
|
||||
session,
|
||||
delivery_id=x_gitea_delivery,
|
||||
|
||||
@@ -10,6 +10,21 @@ HELP_ALIASES = {"-h", "--help", "help"}
|
||||
SUPPORTED_COMMANDS = {"review", "explain", "ignore", "rerun"}
|
||||
|
||||
|
||||
def detect_prefixed_command(body: str, aliases: Iterable[str] | None = None) -> str | None:
|
||||
stripped = body.strip()
|
||||
match = PREFIX_RE.match(stripped)
|
||||
if not match:
|
||||
return None
|
||||
command_alias = match.group(1).lstrip("@").lower()
|
||||
allowed_aliases = {alias.lstrip("@").lower() for alias in (aliases or {"codex"})}
|
||||
if command_alias not in allowed_aliases:
|
||||
return None
|
||||
remainder = match.group(2).strip()
|
||||
if not remainder:
|
||||
return None
|
||||
return remainder.split(maxsplit=1)[0].lower()
|
||||
|
||||
|
||||
def parse_command(body: str, aliases: Iterable[str] | None = None) -> ParsedCommand | None:
|
||||
stripped = body.strip()
|
||||
match = PREFIX_RE.match(stripped)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from gitea_codex_bot.services.commands import parse_command
|
||||
from gitea_codex_bot.services.commands import detect_prefixed_command, parse_command
|
||||
|
||||
|
||||
def test_parse_review_command_modes() -> None:
|
||||
@@ -49,3 +49,11 @@ def test_parse_help_long_flag_and_arguments() -> None:
|
||||
assert cmd is not None
|
||||
assert cmd.name == "help"
|
||||
assert cmd.arguments == ["status", "quick"]
|
||||
|
||||
|
||||
def test_detect_prefixed_command_for_unsupported_name() -> None:
|
||||
assert detect_prefixed_command("@codex shipit now", aliases={"codex"}) == "shipit"
|
||||
|
||||
|
||||
def test_detect_prefixed_command_returns_none_for_non_alias() -> None:
|
||||
assert detect_prefixed_command("@someone review", aliases={"codex"}) is None
|
||||
|
||||
@@ -254,6 +254,66 @@ def test_webhook_accepts_help_short_flag_and_queues(monkeypatch) -> None:
|
||||
assert queued.command == "help"
|
||||
|
||||
|
||||
def test_webhook_replies_fix_is_no_longer_supported(monkeypatch) -> None:
|
||||
posted_comments: list[str] = []
|
||||
monkeypatch.setattr(
|
||||
"gitea_codex_bot.services.gitea.GiteaClient.post_issue_comment",
|
||||
lambda _self, _repo, _pr, body: posted_comments.append(body) or 100,
|
||||
)
|
||||
|
||||
client = TestClient(app)
|
||||
payload_obj = _payload("@codex fix --branch", username="alice", comment_id=444)
|
||||
raw = json.dumps(payload_obj).encode()
|
||||
|
||||
response = client.post(
|
||||
"/webhook/gitea",
|
||||
content=raw,
|
||||
headers={
|
||||
"X-Gitea-Event": "issue_comment",
|
||||
"X-Gitea-Delivery": "d-fix-unsupported",
|
||||
"X-Gitea-Signature": _sign(raw),
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
)
|
||||
|
||||
assert response.status_code == 200
|
||||
assert response.json()["reason"] == "unsupported command"
|
||||
assert response.json()["command"] == "fix"
|
||||
assert any("no longer supported" in body for body in posted_comments)
|
||||
session_factory = get_session_factory()
|
||||
with session_factory() as session:
|
||||
queued = session.execute(select(ReviewJob).where(ReviewJob.trigger_comment_id == 444)).scalar_one_or_none()
|
||||
assert queued is None
|
||||
|
||||
|
||||
def test_webhook_replies_for_unknown_prefixed_command(monkeypatch) -> None:
|
||||
posted_comments: list[str] = []
|
||||
monkeypatch.setattr(
|
||||
"gitea_codex_bot.services.gitea.GiteaClient.post_issue_comment",
|
||||
lambda _self, _repo, _pr, body: posted_comments.append(body) or 100,
|
||||
)
|
||||
|
||||
client = TestClient(app)
|
||||
payload_obj = _payload("@codex deploy", username="alice", comment_id=445)
|
||||
raw = json.dumps(payload_obj).encode()
|
||||
|
||||
response = client.post(
|
||||
"/webhook/gitea",
|
||||
content=raw,
|
||||
headers={
|
||||
"X-Gitea-Event": "issue_comment",
|
||||
"X-Gitea-Delivery": "d-unknown-unsupported",
|
||||
"X-Gitea-Signature": _sign(raw),
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
)
|
||||
|
||||
assert response.status_code == 200
|
||||
assert response.json()["reason"] == "unsupported command"
|
||||
assert response.json()["command"] == "deploy"
|
||||
assert any("not supported" in body for body in posted_comments)
|
||||
|
||||
|
||||
def test_webhook_logs_when_repo_not_allowed(monkeypatch) -> None:
|
||||
messages: list[str] = []
|
||||
|
||||
|
||||
Reference in New Issue
Block a user