gitea: fix LFS round-trip post-restart wait (stale on 28.0.0) (#44)
continuous-integration/drone/push Build is passing

This commit was merged in pull request #44.
This commit is contained in:
2026-10-05 17:37:27 +00:00
parent f675941c34
commit 5cec3e0e31
3 changed files with 104 additions and 81 deletions
+23 -9
View File
@@ -23,6 +23,7 @@ import shutil
import subprocess
import sys
import tempfile
import time
import urllib.error
import urllib.request
@@ -45,7 +46,15 @@ def _lfs_available() -> bool:
return os.path.exists(os.path.join(abra_dir, "recipes", "gitea", _LFS_OVERLAY))
def _api(domain, path, method="GET", body=None, user="", password=""):
API_TIMEOUT = 20
def _api(domain, path, method="GET", body=None, user="", password="", timeout=API_TIMEOUT):
"""One API call → (status, JSON). Never raises: transient errors (connection refused /
dropped mid-restart, DNS, socket timeout) return (0, {}) so a caller's bounded poll can
simply retry, mirroring lifecycle.http_fetch. Only HTTPError was caught before; a socket
timeout on a slow post-restart boot (gitea 28.0.0 migration window, PR #10 run #31) escaped
as TimeoutError and aborted the restart poll itself."""
data = json.dumps(body).encode() if body is not None else None
auth = base64.b64encode(f"{user}:{password}".encode()).decode()
headers = {"Authorization": f"Basic {auth}"}
@@ -55,7 +64,7 @@ def _api(domain, path, method="GET", body=None, user="", password=""):
f"https://{domain}/api/v1{path}", data=data, headers=headers, method=method
)
try:
with urllib.request.urlopen(req, timeout=20, context=_CTX) as r:
with urllib.request.urlopen(req, timeout=timeout, context=_CTX) as r:
raw = r.read()
return r.status, (json.loads(raw) if raw else {})
except urllib.error.HTTPError as e:
@@ -64,6 +73,8 @@ def _api(domain, path, method="GET", body=None, user="", password=""):
return e.code, json.loads(raw)
except (ValueError, json.JSONDecodeError):
return e.code, {}
except (urllib.error.URLError, TimeoutError, OSError): # TimeoutError ⊃ socket.timeout (UP041)
return 0, {}
def _run_git(args, cwd, env=None):
@@ -164,6 +175,8 @@ def test_lfs_roundtrip(live_app):
finally:
shutil.rmtree(fresh_dir, ignore_errors=True)
import recipe_meta # noqa: E402 — per-recipe declared timeouts (tests/STYLE.md §5)
# 7. JWT-secret stability: restart gitea + assert LFS_JWT_SECRET unchanged.
# Read the current secret from inside the container's rendered app.ini.
current_jwt = lifecycle.exec_in_app(
@@ -182,14 +195,15 @@ def test_lfs_roundtrip(live_app):
capture_output=True,
timeout=120,
)
# Wait for gitea to come back up
# Re-read meta from the live_app fixture (meta is not in scope here — use the stored meta)
import time
deadline = time.time() + 120
# Wait for gitea to come back up. Window + probe are DERIVED from the recipe's declared
# readiness (recipe_meta.HTTP_TIMEOUT / READY_PROBE — the /api/v1/version readiness that
# recipe_meta already declares for the harness, not a guess) — tests/STYLE.md §5.
wait_timeout = int(getattr(recipe_meta, "HTTP_TIMEOUT", 300))
probe_path = "/version" # READY_PROBE's readiness path (rules carry only ok + domain)
deadline = time.time() + wait_timeout
status2 = 0
while time.time() < deadline:
status2, _ = _api(live_app, "/version", user=user, password=password)
status2, _ = _api(live_app, probe_path, user=user, password=password)
if status2 == 200:
break
time.sleep(5)