Massive Improvements & MVP Patches
All checks were successful
ci / test (push) Successful in 27s
ci / publish (push) Successful in 1m24s

This commit is contained in:
Space-Banane
2026-05-22 21:27:48 +02:00
parent ae18420744
commit 7b63ecd536
20 changed files with 713 additions and 72 deletions

View File

@@ -1,8 +1,10 @@
from __future__ import annotations
import asyncio
import json
import logging
from contextlib import asynccontextmanager
from pathlib import Path
from typing import Any
from fastapi import Depends, FastAPI, Header, HTTPException, Request, status
@@ -26,10 +28,56 @@ logger = logging.getLogger(__name__)
def _validate_required_env(settings: Settings) -> None:
if not settings.openai_api_key.get_secret_value().strip():
if settings.codex_auth_mode != "api_key":
return
api_key = settings.openai_api_key.get_secret_value() if settings.openai_api_key else ""
if not api_key.strip():
raise RuntimeError("OPENAI_API_KEY is required")
def _configured_auth_json_path(settings: Settings) -> Path:
raw_path = settings.codex_auth_json_path.strip() if settings.codex_auth_json_path else "~/.codex/auth.json"
return Path(raw_path).expanduser()
def _log_startup_identity(settings: Settings) -> None:
logger.info(
"Bot startup identity: username=%s gitea_base_url=%s auth_mode=%s",
settings.gitea_bot_username,
settings.gitea_base_url,
settings.codex_auth_mode,
)
def _log_startup_auth_json_status(settings: Settings) -> None:
if settings.codex_auth_mode != "chatgpt":
logger.info("Codex auth configuration: mode=api_key (auth.json not used)")
return
auth_path = _configured_auth_json_path(settings)
try:
content = auth_path.read_text(encoding="utf-8")
parsed = json.loads(content)
except FileNotFoundError:
logger.warning("Codex auth configuration: mode=chatgpt auth.json missing path=%s", auth_path)
return
except json.JSONDecodeError as exc:
logger.warning("Codex auth configuration: mode=chatgpt invalid auth.json path=%s error=%s", auth_path, exc.msg)
return
except OSError as exc:
logger.warning("Codex auth configuration: mode=chatgpt auth.json unreadable path=%s error=%s", auth_path, exc)
return
root_type = type(parsed).__name__
configured_mode = parsed.get("auth_mode") if isinstance(parsed, dict) else None
logger.info(
"Codex auth configuration: mode=chatgpt auth.json valid path=%s root_type=%s auth_mode=%s",
auth_path,
root_type,
configured_mode or "unknown",
)
def _extract_pr_event(payload: dict[str, Any], event_name: str) -> tuple[str, int, str, int, str] | None:
repository = payload.get("repository", {})
repo = repository.get("full_name")
@@ -68,6 +116,8 @@ def _extract_pr_event(payload: dict[str, Any], event_name: str) -> tuple[str, in
async def lifespan(app: FastAPI):
settings = get_settings()
_validate_required_env(settings)
_log_startup_identity(settings)
_log_startup_auth_json_status(settings)
Base.metadata.create_all(bind=get_engine())
stop_event = asyncio.Event()
@@ -119,7 +169,23 @@ async def gitea_webhook(
comment_body = str(payload.get("comment", {}).get("body", "")).strip()
parsed_command = parse_command(comment_body)
if not parsed_command:
logger.info(
"Webhook ignored: no @codex review command repo=%s pr=%s comment_id=%s sender=%s",
repo,
pr_number,
comment_id,
sender_username,
)
return {"accepted": False, "reason": "no codex command"}
if parsed_command.name != "review":
logger.info(
"Webhook without @codex review command repo=%s pr=%s comment_id=%s sender=%s parsed_command=%s",
repo,
pr_number,
comment_id,
sender_username,
parsed_command.name,
)
if repo not in settings.allowed_repo_set:
return {"accepted": False, "reason": "repo not allowed"}