Some checks failed
continuous-integration/drone/push Build is failing
- tests/gitea/recipe_meta.py: updated from dep-provider stub to dual-role (dep + recipe-under-test).
Adds BACKUP_CAPABLE=True, READY_PROBE (/api/v1/version), SCREENSHOT (sign-in page), LFS-
conditional EXTRA_ENV (compose.lfs.yml + GITEA_LFS_START_SERVER only when RECIPE=gitea AND
overlay present — dep path unchanged). All existing dep keys preserved; 10/10 dep unit tests pass.
- tests/gitea/ops.py: NEW — admin user creation via gitea CLI (ci_admin, creds in /tmp per-domain
file), marker repo lifecycle (pre_install/pre_upgrade/pre_backup create; pre_restore deletes to
diverge from backup state).
- tests/gitea/test_{install,upgrade,backup,restore}.py: NEW — lifecycle overlays. Install checks
API + admin auth + Playwright sign-in. Upgrade/backup/restore assert marker repo continuity.
- tests/gitea/custom/: NEW — test_health.py (parity: HTTP 200 root), test_git_push.py (parity:
create→clone→push→verify→delete), test_admin_api.py (beyond-parity: user+org+token CRUD),
test_lfs_roundtrip.py (LFS OID round-trip + JWT stability; skips on main, runs on PR #1 head).
- tests/gitea/PARITY.md: NEW — mapping table, source note (recipe-info corpus not upstream repo),
beyond-parity rationale, backup/restore real-tier note, DB choice, dep-split mechanism, LFS skip.
- machine-docs/STATUS-gtea.md: NEW — phase status (building M1).
- machine-docs/BACKLOG-gtea.md: merged with Adversary init.
- machine-docs/JOURNAL-gtea.md: Builder log with design decisions + unit test results.
- machine-docs/REVIEW-gtea.md: kept Adversary init content.
- machine-docs/DECISIONS.md: appended gtea section (LFS split, admin mgmt, marker design).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
68 lines
2.7 KiB
Python
68 lines
2.7 KiB
Python
"""gitea — INSTALL overlay (phase gtea).
|
|
|
|
Extends the generic serving assertion with gitea-specific checks:
|
|
- /api/healthz returns 200 (already covered by HEALTH_PATH, reinforced here)
|
|
- /api/v1/version returns 200 JSON (API router is up)
|
|
- Admin API is reachable and authenticated (ops.pre_install created the admin user)
|
|
- Playwright: the sign-in page renders in a real browser
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import os
|
|
import sys
|
|
|
|
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "..", "runner"))
|
|
from harness import browser as harness_browser # noqa: E402
|
|
from harness import generic, lifecycle # noqa: E402
|
|
|
|
sys.path.insert(0, os.path.dirname(__file__))
|
|
from ops import admin_creds # noqa: E402
|
|
|
|
|
|
def test_install_gitea(live_app, meta):
|
|
"""Gitea is serving, API is up, admin API is authenticated, UI loads in browser."""
|
|
# 1. Generic serving (services converged + HEALTH_PATH 200 + TLS valid)
|
|
generic.assert_serving(live_app, meta)
|
|
|
|
# 2. API version endpoint
|
|
status, body = lifecycle.http_fetch(live_app, "/api/v1/version")
|
|
assert status == 200, f"{live_app}/api/v1/version: HTTP {status} (expected 200)"
|
|
assert body, "/api/v1/version: empty response body"
|
|
|
|
# 3. Admin API reachable + authenticated — GET /api/v1/users/search as ci_admin
|
|
user, password = admin_creds(live_app)
|
|
import base64
|
|
import urllib.request
|
|
import ssl
|
|
ctx = ssl.create_default_context()
|
|
ctx.check_hostname = False
|
|
ctx.verify_mode = ssl.CERT_NONE
|
|
auth = base64.b64encode(f"{user}:{password}".encode()).decode()
|
|
req = urllib.request.Request(
|
|
f"https://{live_app}/api/v1/users/search?limit=1",
|
|
headers={"Authorization": f"Basic {auth}"},
|
|
)
|
|
import urllib.error
|
|
try:
|
|
with urllib.request.urlopen(req, timeout=15, context=ctx) as r:
|
|
assert r.status == 200, f"Admin API /users/search returned {r.status}"
|
|
except urllib.error.HTTPError as e:
|
|
raise AssertionError(f"Admin API /users/search failed: HTTP {e.code}") from e
|
|
|
|
# 4. Playwright: sign-in page renders
|
|
from playwright.sync_api import sync_playwright
|
|
url = f"https://{live_app}/user/login"
|
|
with sync_playwright() as p:
|
|
browser = p.chromium.launch(args=["--no-sandbox"])
|
|
try:
|
|
page = browser.new_context(ignore_https_errors=True).new_page()
|
|
harness_browser.goto_with_retry(page, url, accept_statuses=(200, 302), goto_timeout_ms=30_000)
|
|
page.wait_for_selector("input[name='_csrf']", timeout=20_000)
|
|
content = page.content()
|
|
assert "gitea" in content.lower() or "sign in" in content.lower(), (
|
|
"Sign-in page did not render expected gitea content"
|
|
)
|
|
finally:
|
|
browser.close()
|