Files
cc-ci/tests/gitea/recipe_meta.py
autonomic-bot 33561c8609
Some checks failed
continuous-integration/drone/push Build is failing
feat(gtea): build full gitea test suite (M1 build — all files)
- 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>
2026-06-15 19:50:08 +00:00

96 lines
4.5 KiB
Python

# Per-recipe harness config for gitea — used in TWO roles:
#
# 1. DEP PROVIDER (RECIPE=drone): gitea is deployed as an install-time dependency for the drone
# recipe. The harness deploys it before drone, provisions an admin user + OAuth2 app inside it
# (sso.setup_gitea_oauth), and tears it down after. All keys below apply to this path too.
#
# 2. RECIPE-UNDER-TEST (RECIPE=gitea): gitea is the enrolled recipe being tested. The full
# install/upgrade/backup/restore/custom lifecycle runs against it. The recipe-under-test keys
# (BACKUP_CAPABLE, SCREENSHOT, READY_PROBE, EXPECTED_NA) below are harmless to the dep path.
#
# Database: sqlite3 (compose.sqlite3.yml) — matches the dep config + lightest footprint.
# Backup: REAL tier — compose.yml carries backupbot.backup=true labels.
#
# LFS overlay (compose.lfs.yml, PR #1 lfs-plain-gitea): enabled ONLY when
# (a) compose.lfs.yml is present in the recipe checkout (it's on the PR branch, not main), AND
# (b) RECIPE=gitea (this is a recipe-under-test run, not a drone dep deploy).
# See DECISIONS.md (phase gtea) and tests/gitea/PARITY.md for the full split rationale.
import os as _os
HEALTH_PATH = "/api/healthz"
HEALTH_OK = (200,)
DEPLOY_TIMEOUT = 600
HTTP_TIMEOUT = 600
BACKUP_CAPABLE = True # compose.yml carries backupbot.backup=true labels — force on
def READY_PROBE(ctx):
# Extra readiness: the /api/v1/version endpoint returns 200 JSON when the API is fully up
# (healthz passes earlier, before the API router is fully wired). Avoids flaky test_install
# failures where healthz=200 but admin API calls fail with 503.
return [{"host": ctx.domain, "path": "/api/v1/version", "ok": (200,)}]
def SCREENSHOT(page, ctx):
# Navigate to the sign-in page — a credential-free view that shows the gitea UI.
from playwright.sync_api import sync_playwright # noqa: F401 — re-entry guard
page.goto(f"{ctx.base_url}/user/login", wait_until="networkidle", timeout=30_000)
page.wait_for_selector("form.ui.form", timeout=15_000)
def _lfs_enabled():
"""True when compose.lfs.yml is available in the recipe checkout AND this is a
recipe-under-test run (RECIPE=gitea). Both conditions prevent LFS leaking into the dep path."""
abra_dir = _os.environ.get("ABRA_DIR") or _os.path.expanduser("~/.abra")
lfs_overlay = _os.path.join(abra_dir, "recipes", "gitea", "compose.lfs.yml")
return _os.path.exists(lfs_overlay) and _os.environ.get("RECIPE", "") == "gitea"
def EXTRA_ENV(ctx):
lfs = _lfs_enabled()
compose_file = "compose.yml:compose.sqlite3.yml"
if lfs:
compose_file += ":compose.lfs.yml"
env = {
"COMPOSE_FILE": compose_file,
"GITEA_APP_NAME": "CI Dep Gitea",
"GITEA_ALLOW_ONLY_EXTERNAL_REGISTRATION": "false",
"GITEA_AUTO_WATCH_NEW_REPOS": "false",
"GITEA_DISABLE_REGISTRATION": "false",
"GITEA_ENABLE_NOTIFY_MAIL": "false",
"GITEA_ENABLE_OPENID_SIGNIN": "false",
"GITEA_ENABLE_OPENID_SIGNUP": "false",
"GITEA_DISABLE_GRAVATAR": "true",
"GITEA_ENABLE_FEDERATED_AVATAR": "false",
# Not requiring sign-in lets the /api/healthz endpoint work without a session.
"GITEA_REQUIRE_SIGNIN_VIEW": "false",
"GITEA_LANDING_PAGE": "explore",
"GITEA_SHOW_USER_EMAIL": "false",
"GITEA_DISABLE_REGULAR_ORG_CREATION": "false",
"GITEA_DEFAULT_KEEP_EMAIL_PRIVATE": "false",
"GITEA_DEFAULT_ALLOW_CREATE_ORGANIZATION": "true",
"GITEA_ENABLE_USER_HEATMAP": "false",
"GITEA_DEFAULT_USER_VISIBILITY": "public",
"GITEA_ALLOWED_USER_VISIBILITY_MODES": "public,limited,private",
"GITEA_DEFAULT_ORG_VISIBILITY": "public",
"GITEA_SSH_PORT": "2222",
"GITEA_REPO_UPLOAD_ENABLED": "false",
"GITEA_REPO_UPLOAD_ALLOWED_TYPES": "",
"GITEA_REPO_UPLOAD_MAX_SIZE": "0",
"GITEA_REPO_UPLOAD_MAX_FILES": "0",
"GITEA_ENABLE_PUSH_CREATE_USER": "false",
"GITEA_ENABLE_PUSH_CREATE_ORG": "false",
"GITEA_LFS_START_SERVER": "true" if lfs else "false",
# CORS allow-domain — left empty; OAuth2 redirects are not CORS-gated.
"GITEA_CORS_ALLOW_DOMAIN": "",
# Mailer placeholder — required by app.ini.tmpl but SMTP is not enabled.
"GITEA_MAILER_FROM": "noreply@ci.local",
"GITEA_MAILER_USER": "noreply@ci.local",
}
if lfs:
# Tell abra's secret generator which version to use for lfs_jwt_secret.
env["SECRET_LFS_JWT_SECRET_VERSION"] = "v1"
return env