[fix]. Remove host review fallback
All checks were successful
ci / test (push) Successful in 35s
ci / publish (push) Successful in 55s

This commit is contained in:
Space-Banane
2026-05-23 00:10:53 +02:00
parent 0ab2d62609
commit 328c7f2290
3 changed files with 35 additions and 15 deletions

View File

@@ -4,7 +4,7 @@
### P0 (Critical) ### P0 (Critical)
- [ ] `BUG`: True isolated runner flow: clone/fetch/checkout PR branch inside the ephemeral container itself, not on host before prompt generation. - [ ] `BUG`: True isolated runner flow: clone/fetch/checkout PR branch inside the ephemeral container itself, not on host before prompt generation.
- [ ] `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`: 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`: Enforce `.codex-review.yml` `enabled=false` at runtime (currently loaded but not enforced).
- [x] `BUG`: Remove `.codex-review.yml` fix policy (`commands.allow_fix`) and rely on global `ENABLE_FIX_COMMANDS`. - [x] `BUG`: Remove `.codex-review.yml` fix policy (`commands.allow_fix`) and rely on global `ENABLE_FIX_COMMANDS`.
- [x] `BUG`: Add stuck-job recovery for `running` jobs (lease timeout + requeue/fail) so one crashed worker does not deadlock the queue. - [x] `BUG`: Add stuck-job recovery for `running` jobs (lease timeout + requeue/fail) so one crashed worker does not deadlock the queue.

View File

@@ -14,7 +14,7 @@ from typing import Any
from gitea_codex_bot.config import Settings from gitea_codex_bot.config import Settings
from gitea_codex_bot.services.gitea import GiteaClient from gitea_codex_bot.services.gitea import GiteaClient
from gitea_codex_bot.services.repo_config import RepoReviewConfig from gitea_codex_bot.services.repo_config import RepoReviewConfig
from gitea_codex_bot.services.reviewer import normalize_review_result, prepare_review_prompt, run_review_for_pr from gitea_codex_bot.services.reviewer import normalize_review_result, prepare_review_prompt
from gitea_codex_bot.types import ParsedCommand from gitea_codex_bot.types import ParsedCommand
CONTAINER_CODEX_HOME = "/root/.codex" CONTAINER_CODEX_HOME = "/root/.codex"
@@ -52,11 +52,8 @@ def run_review_ephemeral(
parsed["_meta"] = _extract_result_meta_from_codex_stdout(completed.stdout, settings) parsed["_meta"] = _extract_result_meta_from_codex_stdout(completed.stdout, settings)
return normalize_review_result(parsed), repo_cfg return normalize_review_result(parsed), repo_cfg
except Exception as exc: except Exception as exc:
if settings.codex_auth_mode == "chatgpt": logger.warning("Ephemeral runner failed without host fallback: %s", exc)
logger.warning("Ephemeral chatgpt runner failed, skipping API-key fallback: %s", exc) return _ephemeral_runner_failure_result(exc, settings.codex_auth_mode), repo_cfg
return _chatgpt_runner_failure_result(exc), repo_cfg
result, _repo_cfg = run_review_for_pr(settings, gitea, repo, pr_number, command)
return result, _repo_cfg
def _build_install_and_run_command(settings: Settings) -> str: def _build_install_and_run_command(settings: Settings) -> str:
@@ -121,9 +118,10 @@ def _build_docker_command(settings: Settings, *, container_name: str, install_an
return cmd return cmd
def _chatgpt_runner_failure_result(exc: Exception) -> dict[str, Any]: def _ephemeral_runner_failure_result(exc: Exception, auth_mode: str) -> dict[str, Any]:
message = str(exc).strip() or exc.__class__.__name__ message = str(exc).strip() or exc.__class__.__name__
summary = f"ChatGPT auth runner failed before review execution. Error: {message}" mode_label = "ChatGPT auth" if auth_mode == "chatgpt" else "API-key auth"
summary = f"{mode_label} runner failed before review execution. Error: {message}"
return { return {
"verdict": "has_issues", "verdict": "has_issues",
"confidence": 0.6, "confidence": 0.6,
@@ -134,7 +132,7 @@ def _chatgpt_runner_failure_result(exc: Exception) -> dict[str, Any]:
"file": "runner", "file": "runner",
"line_start": 1, "line_start": 1,
"line_end": 1, "line_end": 1,
"title": "Ephemeral chatgpt review runner failed", "title": "Ephemeral review runner failed",
"body": message, "body": message,
"suggestion": "Check ephemeral runner logs for model/auth/network issues, then rerun @codex review.", "suggestion": "Check ephemeral runner logs for model/auth/network issues, then rerun @codex review.",
} }

View File

@@ -117,11 +117,6 @@ def test_run_review_ephemeral_chatgpt_does_not_fallback_to_api_key_path(
lambda *_args, **_kwargs: (_ for _ in ()).throw(RuntimeError("docker unavailable")), lambda *_args, **_kwargs: (_ for _ in ()).throw(RuntimeError("docker unavailable")),
) )
def _api_fallback_should_not_run(*_args, **_kwargs):
raise AssertionError("API-key fallback should not run in chatgpt mode")
monkeypatch.setattr("gitea_codex_bot.workers.container_runner.run_review_for_pr", _api_fallback_should_not_run)
from gitea_codex_bot.types import ParsedCommand from gitea_codex_bot.types import ParsedCommand
result, _repo_cfg = run_review_ephemeral( result, _repo_cfg = run_review_ephemeral(
@@ -135,6 +130,33 @@ def test_run_review_ephemeral_chatgpt_does_not_fallback_to_api_key_path(
assert "ChatGPT auth runner failed" in result["summary"] assert "ChatGPT auth runner failed" in result["summary"]
def test_run_review_ephemeral_api_key_mode_does_not_fallback_to_host(monkeypatch: pytest.MonkeyPatch) -> None:
get_settings.cache_clear()
settings = get_settings()
monkeypatch.setattr(
"gitea_codex_bot.workers.container_runner.prepare_review_prompt",
lambda *_args, **_kwargs: ("prompt", {"diff": ""}, object()),
)
monkeypatch.setattr("gitea_codex_bot.workers.container_runner.GiteaClient", lambda _settings: object())
monkeypatch.setattr(
"gitea_codex_bot.workers.container_runner.subprocess.run",
lambda *_args, **_kwargs: (_ for _ in ()).throw(RuntimeError("docker unavailable")),
)
from gitea_codex_bot.types import ParsedCommand
result, _repo_cfg = run_review_ephemeral(
settings,
repo="acme/repo",
pr_number=1,
command=ParsedCommand(name="review", raw="@codex review"),
)
assert result["verdict"] == "has_issues"
assert "API-key auth runner failed" in result["summary"]
def test_parse_codex_exec_stdout_from_stream_item_text_json() -> None: def test_parse_codex_exec_stdout_from_stream_item_text_json() -> None:
stdout = '\n'.join( stdout = '\n'.join(
[ [