chore(2): bootstrap Phase 2 loop state + decisions
- STATUS-2.md / BACKLOG-2.md / JOURNAL-2.md seeded from plan §6 (Q0-Q5). - DECISIONS.md appended Phase 2 section: functional/ + playwright/ subdirs, PARITY.md mapping convention, vendored helpers in runner/harness/ (http, abra_tty, deps, sso, data_integrity), recipe-versioned tests. - Bootstrap access re-verified: ssh cc-ci ok, Gitea API 200, wildcard DNS to gateway 143.244.213.108. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@ -379,3 +379,64 @@ Three operator-review corrections to the Phase-1d shared harness, settled here (
|
||||
`coop-cloud.<stack>.chaos`/`.chaos-version`) — the chaos label IS the proof PR-head was deployed.
|
||||
Non-PR `!testme` (no SRC/REF): "PR head" = the catalogue current checkout, so upgrade is prev→current
|
||||
— still a genuine move via chaos. (Exact chaos label name verified on the live abra during E2.)
|
||||
|
||||
## Phase 2 — per-recipe test authoring (design, 2026-05-28)
|
||||
Inherits the Phase 1d/1e shared-deployment + additive-overlay + op/assertion-split model. Phase 2
|
||||
adds **content**, not infra, with a few small harness primitives ported from
|
||||
`references/recipe-maintainer/utils/tests/helpers.py`.
|
||||
|
||||
- **Per-recipe layout (per plan §4.1).** The cc-ci `tests/<recipe>/` dir continues to use the
|
||||
Phase-1d/1e overlays at the top level (`test_install.py`, `test_upgrade.py`, `test_backup.py`,
|
||||
`test_restore.py`, `ops.py`, `recipe_meta.py`, optional `install_steps.sh`). NEW Phase-2
|
||||
subdirectories:
|
||||
- `tests/<recipe>/functional/` — parity-port tests (one per recipe-maintainer `tests/*.py`) +
|
||||
≥2 NEW recipe-specific functional tests (P2/P3). Each file is `test_*.py` (pytest-discoverable);
|
||||
each parity port carries a **`SOURCE = "recipe-info/<recipe>/tests/<file>"`** comment near the
|
||||
top so the audit trail is in the file, not just in PARITY.md.
|
||||
- `tests/<recipe>/playwright/` — browser flows (P6) where the app's UX is a UI flow. Same
|
||||
`test_*.py` convention; each file imports `playwright.sync_api`.
|
||||
- `tests/<recipe>/PARITY.md` — required mapping table (P2) with one row per
|
||||
recipe-info parity test: `| recipe-maintainer file | cc-ci file | what's verified | status |`.
|
||||
A deliberate non-port is a documented row in DECISIONS.md (linked from PARITY.md), not a silent
|
||||
omission.
|
||||
- **Discovery for the new subdirs.** `runner/harness/discovery.custom_tests` recurses into
|
||||
`tests/<recipe>/functional/` and `tests/<recipe>/playwright/` (in addition to the top-level glob),
|
||||
so Phase-2 functional tests run as part of the **custom** stage automatically. Repo-local (HC2)
|
||||
gate still applies if the recipe is approved; otherwise only cc-ci's own functional/ + playwright/
|
||||
run. The top-level `test_install.py`/etc. continue to drive the lifecycle overlays — the
|
||||
`functional/` + `playwright/` files are **always custom-stage**, never lifecycle (so they don't
|
||||
perform an op; they assert against the post-install live deployment).
|
||||
- **Vendored helpers in `runner/harness/`.** Capabilities ported from `recipe-maintainer/utils/tests/
|
||||
helpers.py` (cc-ci is self-contained at runtime — does NOT import recipe-maintainer's workspace,
|
||||
per plan §8 default):
|
||||
- `harness.http` — `http_get(url, headers=, timeout=) -> (status, json_or_None)`,
|
||||
`http_post(...)`, `retry_http_get(url, timeout=, **)`, `wait_for_http(url, label, max_wait=)`,
|
||||
`assert_converges(fn, description, max_wait=, interval=)`. (Several variants exist
|
||||
`lifecycle.http_fetch/http_get/http_body` already; the harness.http module is the **canonical**
|
||||
Phase-2 HTTP API for tests; lifecycle.* helpers stay for infra-level checks.)
|
||||
- `harness.abra_tty` — `script -qefc "abra …" /dev/null` wrapper for the abra commands that
|
||||
require a TTY (backup/restore/secret/run/logs/lint), used by parity tests that drive abra
|
||||
directly. Lifecycle already exposes typed wrappers — this is for tests that need raw shell-abra.
|
||||
- `harness.deps` — dependency resolver primitive. Reads `tests/<recipe>/recipe.toml`
|
||||
(`requires` / `test_requires`), deploys each declared dep via the same `lifecycle.deploy_app`
|
||||
+ `wait_healthy` path (so the dep is a real `<dep[:4]>-<6hex>.ci.commoninternet.net` on the
|
||||
same swarm), persists per-run, tears down with the parent in the orchestrator's `finally`.
|
||||
Heavy recipes sequence sequentially; `MAX_TESTS`/node budget is the cap.
|
||||
- `harness.sso` — OIDC-flow primitive (Q2 deliverable). Given a deployed provider domain and a
|
||||
recipe-defined realm/client/test-user, performs the full "deploy provider → setup realm/client
|
||||
via admin API → obtain access token (password + client-credentials grants) → assert protected
|
||||
API call accepts it" assertion. Reusable by every SSO-dependent recipe (cryptpad, lasuite-*,
|
||||
immich, etc.). Setup scripts ported from `recipe-info/<dep>/setup_<provider>_integration.py`.
|
||||
- `harness.data_integrity` — backup data-integrity primitive: a recipe-aware "seed a marker
|
||||
→ backup → mutate → restore → assert seeded marker survived" helper around `lifecycle.exec_in_app`
|
||||
/ `http_get` (the recipe chooses the marker mechanism, the helper guarantees the pattern).
|
||||
- **Run-scoped credentials for SSO/recipe-specific tests** (plan §4.4 class-B). Generated secrets
|
||||
(realm/client/test-user passwords, API tokens) persist for the run via the existing
|
||||
`runs/<app-name>/` mechanism (Phase 1d). Destroyed at teardown alongside abra secrets/volumes.
|
||||
- **Recipe-versioned tests (anti-anchoring).** Per plan §7.1, tests read versions/endpoints
|
||||
dynamically (the app's own discovery endpoints, env from `live_app`) — never hardcode published
|
||||
release values. Each functional test file declares the recipe-info SOURCE path it ports from so
|
||||
the Adversary can audit parity cold.
|
||||
- **Heavy-recipe parking.** Drone's `MAX_TESTS=1` + per-build timeout already serialize runs; for
|
||||
Phase 2 we DO NOT lift it. Within a single run, the orchestrator deploys deps before the
|
||||
recipe-under-test sequentially (never concurrently) per plan §4.2.
|
||||
|
||||
Reference in New Issue
Block a user