case-create: surface Gitea repo result + UI retry button
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 1m29s
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 1m29s
The auto-creation in case_create had two failure modes that combined to
make repos silently missing: a stale GITEA_TOKEN returning 401, and the
outer try/except in case_create that swallowed every exception with a
bare pass. Result: cases like 8174-24 ended up with a local git repo and
Paperclip project but no Gitea repo, with no signal anywhere.
_setup_gitea_remote now returns {ok, url, error} and never raises; the
result is attached to the case JSON and the FastAPI endpoint logs a
warning when ok=false. The UI gets a "צור ריפו ב-Gitea" button on the
case header that appears only when the repo or remote is missing.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -28,12 +28,17 @@ def _gitea_token() -> str:
|
||||
return os.environ.get("GITEA_ACCESS_TOKEN") or os.environ.get("GITEA_TOKEN", "")
|
||||
|
||||
|
||||
async def _setup_gitea_remote(case_number: str, title: str, case_dir: Path) -> bool:
|
||||
"""Create Gitea repo and configure git remote. Best-effort — returns False on failure."""
|
||||
async def _setup_gitea_remote(case_number: str, title: str, case_dir: Path) -> dict:
|
||||
"""Create Gitea repo and configure git remote.
|
||||
|
||||
Returns a dict with: ok (bool), url (str|None), error (str|None).
|
||||
Never raises — failures are reported via the dict so callers can surface
|
||||
them to the UI instead of silently swallowing them.
|
||||
"""
|
||||
token = _gitea_token()
|
||||
if not token:
|
||||
logger.info("No GITEA_TOKEN — skipping Gitea repo creation for %s", case_number)
|
||||
return False
|
||||
return {"ok": False, "url": None, "error": "no_token"}
|
||||
|
||||
try:
|
||||
async with httpx.AsyncClient(verify=False, timeout=30) as client:
|
||||
@@ -59,8 +64,9 @@ async def _setup_gitea_remote(case_number: str, title: str, case_dir: Path) -> b
|
||||
repo = resp.json()
|
||||
|
||||
clone_url = repo.get("clone_url", "")
|
||||
html_url = repo.get("html_url", "")
|
||||
if not clone_url:
|
||||
return False
|
||||
return {"ok": False, "url": None, "error": "no_clone_url"}
|
||||
|
||||
auth_url = clone_url.replace("https://", f"https://chaim:{token}@")
|
||||
|
||||
@@ -94,15 +100,20 @@ async def _setup_gitea_remote(case_number: str, title: str, case_dir: Path) -> b
|
||||
cwd=case_dir, capture_output=True, text=True, env=git_env,
|
||||
)
|
||||
if push.returncode != 0:
|
||||
logger.warning("Gitea push failed for %s: %s", case_number, push.stderr)
|
||||
return False
|
||||
stderr = push.stderr.strip()
|
||||
logger.warning("Gitea push failed for %s: %s", case_number, stderr)
|
||||
return {"ok": False, "url": html_url or None, "error": f"push_failed: {stderr[:200]}"}
|
||||
|
||||
logger.info("Gitea repo created and pushed for %s", case_number)
|
||||
return True
|
||||
return {"ok": True, "url": html_url or None, "error": None}
|
||||
|
||||
except httpx.HTTPStatusError as exc:
|
||||
msg = f"http_{exc.response.status_code}"
|
||||
logger.warning("Gitea setup failed for %s: %s", case_number, msg)
|
||||
return {"ok": False, "url": None, "error": msg}
|
||||
except Exception as exc:
|
||||
logger.warning("Gitea setup failed for %s: %s", case_number, exc)
|
||||
return False
|
||||
return {"ok": False, "url": None, "error": f"{type(exc).__name__}: {exc}"[:200]}
|
||||
|
||||
|
||||
async def case_create(
|
||||
@@ -214,11 +225,10 @@ async def case_create(
|
||||
except Exception:
|
||||
pass # git not available — non-critical
|
||||
|
||||
# Create Gitea repo and configure remote (best-effort)
|
||||
try:
|
||||
await _setup_gitea_remote(case_number, title, case_dir)
|
||||
except Exception:
|
||||
pass # Gitea not available — non-critical
|
||||
# Create Gitea repo and configure remote — surface result so callers can
|
||||
# show failures (e.g. stale token) and offer a retry button instead of
|
||||
# silently producing a case with no remote.
|
||||
case["gitea"] = await _setup_gitea_remote(case_number, title, case_dir)
|
||||
|
||||
return json.dumps(case, default=str, ensure_ascii=False, indent=2)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user