Resolve Runner issue, runner refused to launch
All checks were successful
ci / test (pull_request) Successful in 35s
ci / publish (pull_request) Has been skipped

This commit is contained in:
Space-Banane
2026-05-23 13:53:26 +02:00
parent d6a9397914
commit c3925f37e1
9 changed files with 17 additions and 112 deletions

View File

@@ -63,8 +63,6 @@ def run_review_ephemeral(
gitea = GiteaClient(settings)
pr = gitea.get_pull_request(repo, pr_number)
repo_cfg = _load_repo_review_config_from_gitea(gitea, repo, pr.head_sha)
_apply_repo_default_review_mode(command, repo_cfg)
prompt = _build_review_instructions(command, repo_cfg)
container_name = f"codex-review-{uuid.uuid4().hex[:12]}"
extra_env: dict[str, str] = {
"GITEA_TOKEN": settings.gitea_token.get_secret_value(),
@@ -83,24 +81,9 @@ def run_review_ephemeral(
settings,
pr=pr,
container_name=container_name,
prompt=prompt,
extra_env=extra_env,
include_reasoning_effort=True,
)
if _needs_reasoning_effort_compat_retry(completed):
logger.info("Ephemeral runner does not support --reasoning-effort; retrying without it.")
completed = _run_ephemeral_container(
settings,
pr=pr,
container_name=container_name,
prompt=prompt,
extra_env=extra_env,
include_reasoning_effort=False,
)
if completed.returncode != 0:
compat_failure = _summarize_review_prompt_compat_failure(completed)
if compat_failure:
raise RuntimeError(compat_failure)
raise RuntimeError(_format_runner_failure(completed))
parsed = _parse_review_result_from_stdout_artifact(completed.stdout)
parsed["_meta"] = _extract_result_meta_from_codex_stdout(completed.stdout, settings)
@@ -115,15 +98,12 @@ def _run_ephemeral_container(
*,
pr: PullRequestContext,
container_name: str,
prompt: str,
extra_env: dict[str, str],
include_reasoning_effort: bool,
) -> subprocess.CompletedProcess[str]:
install_and_run = _build_install_and_run_command(settings, pr=pr, include_reasoning_effort=include_reasoning_effort)
install_and_run = _build_install_and_run_command(settings, pr=pr)
cmd = _build_docker_command(settings, container_name=container_name, install_and_run=install_and_run)
return subprocess.run(
cmd,
input=prompt,
text=True,
check=False,
capture_output=True,
@@ -136,7 +116,6 @@ def _build_install_and_run_command(
settings: Settings,
*,
pr: PullRequestContext,
include_reasoning_effort: bool = True,
) -> str:
steps = ["set -euo pipefail"]
if settings.codex_auth_mode != "chatgpt":
@@ -162,7 +141,8 @@ def _build_install_and_run_command(
steps.extend(
[
"apt-get update >/tmp/apt-update.log 2>&1 && apt-get install -y --no-install-recommends ca-certificates git >/tmp/apt-install.log 2>&1 || { rc=$?; echo 'ca-certificates/git install failed'; tail -n 80 /tmp/apt-update.log || true; tail -n 80 /tmp/apt-install.log || true; exit $rc; }",
"npm install -g @openai/codex >/tmp/codex-install.log 2>&1 || { rc=$?; echo 'codex install failed'; tail -n 200 /tmp/codex-install.log || true; exit $rc; }",
"npm install -g @openai/codex@latest >/tmp/codex-install.log 2>&1 || { rc=$?; echo 'codex install failed'; tail -n 200 /tmp/codex-install.log || true; exit $rc; }",
"codex --version >/tmp/codex-version.log 2>&1 || { rc=$?; echo 'codex version check failed'; tail -n 40 /tmp/codex-version.log || true; exit $rc; }",
]
)
schema_json = json.dumps(REVIEW_RESULT_SCHEMA, separators=(",", ":"))
@@ -181,7 +161,6 @@ def _build_install_and_run_command(
]
)
model = settings.openai_review_model.strip()
reasoning_effort = settings.openai_reasoning_effort.strip()
codex_exec_parts = [
"codex exec review",
f"--base {shlex.quote(pr.base_sha)}",
@@ -193,9 +172,6 @@ def _build_install_and_run_command(
]
if model:
codex_exec_parts.append(f"-m {shlex.quote(model)}")
if include_reasoning_effort and reasoning_effort:
codex_exec_parts.append(f"--reasoning-effort {shlex.quote(reasoning_effort)}")
codex_exec_parts.append("-")
steps.extend(
[
" ".join(codex_exec_parts),
@@ -207,13 +183,6 @@ def _build_install_and_run_command(
return "\n".join(steps)
def _needs_reasoning_effort_compat_retry(completed: subprocess.CompletedProcess[str]) -> bool:
if completed.returncode == 0:
return False
stderr_text = completed.stderr or ""
return "unexpected argument '--reasoning-effort' found" in stderr_text
def _build_docker_command(settings: Settings, *, container_name: str, install_and_run: str) -> list[str]:
cmd = [
"docker",
@@ -263,7 +232,7 @@ def _ephemeral_runner_failure_result(exc: Exception, auth_mode: str) -> dict[str
summary = f"{mode_label} runner failed before review execution. Error: {message}"
return {
"verdict": "has_issues",
"confidence": 0.6,
"confidence": 0.67,
"summary": summary,
"findings": [
{
@@ -328,32 +297,6 @@ def _load_repo_review_config_from_gitea(gitea: GiteaClient, repo: str, head_sha:
return parse_repo_review_config_text(content, configured=True)
def _apply_repo_default_review_mode(command: ParsedCommand, repo_cfg: RepoReviewConfig) -> None:
if command.name != "review" or command.mode_explicit:
return
configured_mode = repo_cfg.default_mode
command.mode = configured_mode if configured_mode in {"summary", "security", "performance", "tests", "full"} else "summary"
def _build_review_instructions(command: ParsedCommand, repo_cfg: RepoReviewConfig) -> str:
focus = ", ".join(repo_cfg.focus) if repo_cfg.focus else "correctness, security, maintainability"
ignore = ", ".join(repo_cfg.ignore) if repo_cfg.ignore else "(none)"
lines = [
"Review this pull request using local git data in this checkout only.",
"Focus on issues introduced by this PR.",
"Prioritize correctness, security, data loss, broken behavior, bad migrations, and missing tests.",
"Avoid style-only nitpicks.",
f"Requested mode: {command.mode}",
f"Command: {command.raw}",
f"Focus areas: {focus}",
f"Ignore patterns: {ignore}",
f"Repository include_tests setting: {repo_cfg.include_tests}",
f"Full-content review requested: {command.full}",
"Return strict JSON matching the provided output schema.",
]
return "\n".join(lines)
def _parse_review_result_from_stdout_artifact(stdout: str) -> dict[str, Any]:
start = stdout.find(RESULT_START_MARKER)
end = stdout.find(RESULT_END_MARKER)
@@ -371,19 +314,6 @@ def _parse_review_result_from_stdout_artifact(stdout: str) -> dict[str, Any]:
return payload
def _summarize_review_prompt_compat_failure(completed: subprocess.CompletedProcess[str]) -> str | None:
text = " ".join([(completed.stdout or "").strip(), (completed.stderr or "").strip()]).lower()
has_prompt_conflict = "prompt" in text and (
"cannot be used with" in text or "can't be used with" in text or "incompatible" in text
)
if "--base" not in text or not has_prompt_conflict:
return None
return (
"Installed Codex CLI rejected `codex exec review --base ...` with custom instructions. "
"This runner is configured to fail fast on that compatibility issue."
)
def _extract_result_meta_from_codex_stdout(stdout: str, settings: Settings) -> dict[str, Any]:
model = settings.openai_review_model
usage: dict[str, int] = {}