docs(2): Q5.1 — enroll-recipe.md §2.4 non-HTTP/multi-service/host-dependent recipes + mumble/mailu examples
Documents the Phase-2 Q4 patterns proven this session: EXTRA_ENV callable, READY_PROBE (HTTP+TCP), CHAOS_BASE_DEPLOY, recipe_checkout -f, install_steps overlay-drop; non-HTTP protocol tests (mumble host-ports + _mumble_proto), in-container functional tests (mailu flask/sendmail/doveadm under TLS_FLAVOR=notls), and P4-N/A when a recipe ships no backupbot label. Worked-example pointers to tests/mumble + tests/mailu. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@ -139,6 +139,52 @@ keycloak-specific; when authentik comes online a parallel `setup_authentik_realm
|
||||
land in `harness.sso`. The flow primitives (`oidc_password_grant`, `assert_discovery_endpoint`)
|
||||
ARE provider-pluggable.
|
||||
|
||||
### 2.4 Non-HTTP, multi-service, and host-dependent recipes (Phase 2 Q4)
|
||||
|
||||
Not every recipe is a single HTTP app. `recipe_meta.py` + a few harness mechanisms cover the harder
|
||||
shapes (proven on mumble, mailu, and the SSO-dependent suite):
|
||||
|
||||
- **`EXTRA_ENV`** — a dict **or** a `callable(domain) -> dict`. The callable form derives values from
|
||||
the per-run domain (e.g. `MAIL_DOMAIN`/`HOSTNAMES` for mailu, `SANDBOX_DOMAIN` for cryptpad). Applied
|
||||
at every deploy (`abra.env_set`), so a recipe enrolls with NO shared-harness change.
|
||||
- **`READY_PROBE(domain) -> [...]`** — readiness signals beyond replica-convergence + the app's
|
||||
`HEALTH_PATH`. Two probe shapes:
|
||||
- HTTP: `{"host": "...", "path": "/...", "ok": (200,)}` (e.g. lasuite-drive collabora WOPI discovery).
|
||||
- **TCP**: `{"tcp_host": "127.0.0.1", "tcp_port": 64738, "stable": 3}` — polls a socket connect N
|
||||
consecutive times. Use for non-HTTP services whose `HEALTH_PATH` reflects a sidecar, not the real
|
||||
service (mumble: the mumble-web sidecar serves HTTP 200 while the voice server on 64738 is still
|
||||
rebinding after an upgrade redeploy — the TCP probe gates the backup tier until the voice server is
|
||||
actually up). Runs after install AND after the upgrade chaos redeploy.
|
||||
- **`CHAOS_BASE_DEPLOY = True`** — make the pinned base deploy use `--chaos` (skips abra's clean-tree +
|
||||
lint gates, still deploys the explicitly-checked-out pinned version, NOT latest). Needed when an
|
||||
`install_steps.sh` adds an UNTRACKED file to the recipe checkout (e.g. mumble copies a
|
||||
`compose.host-ports.yml` into versions that predate it) — abra's pinned-deploy clean-tree check would
|
||||
otherwise FATA. `abra.recipe_checkout` force-checks-out (`-f`) so the upgrade tier's re-checkout to
|
||||
PR-head overwrites such overlays cleanly.
|
||||
- **`install_steps.sh`** (auto-discovered at `tests/<recipe>/install_steps.sh`) — runs after
|
||||
`abra app new` + EXTRA_ENV + secret-generate, BEFORE the single deploy, with `CCCI_APP_DOMAIN` /
|
||||
`CCCI_APP_ENV` / `CCCI_RECIPE` (and `CCCI_DEPS_FILE` when DEPS are provisioned at install). Use it to
|
||||
drop a cc-ci-owned compose overlay into the checkout, wire dep-derived env/secrets, etc.
|
||||
|
||||
**Non-HTTP protocol tests (mumble).** Reach a TCP service published `mode: host` (via a host-ports
|
||||
overlay) at `127.0.0.1:<port>` — cc-ci runs tests on-host (cc-ci-run). mumble ships a stdlib protocol
|
||||
client (`tests/mumble/functional/_mumble_proto.py`) doing the real TLS handshake → ServerSync; the
|
||||
recipe-specific tests assert channel presence and config round-trips (a deploy-set `WELCOME_TEXT`/
|
||||
`USERS` value surfaces over the protocol — version-independent, non-vacuous).
|
||||
|
||||
**In-container functional tests (mailu).** When network access to a service is constrained (mailu uses
|
||||
`TLS_FLAVOR=notls` because certdumper needs traefik ACME which cc-ci does not run → dovecot refuses
|
||||
plaintext auth over the network), exercise the app via `lifecycle.exec_in_app(domain, [...],
|
||||
service="<svc>")` against the relevant container: e.g. `flask mailu user ...` (admin) to create a
|
||||
mailbox, then a local `sendmail` inject (smtp) → `doveadm search` (imap) to prove real
|
||||
postfix→rspamd→dovecot delivery. This hits the same stack the network path would, without the env
|
||||
constraint.
|
||||
|
||||
**P4 when the recipe ships no backup (`backupbot`) labels.** `generic.backup_capable` auto-detects the
|
||||
`backupbot.backup` label; recipes without it (mailu, drone) cleanly SKIP the backup/restore tiers —
|
||||
P4 is genuinely N/A (nothing to back up), not a cut corner. Document it in `PARITY.md` + a `DEFERRED.md`
|
||||
entry (the durable fix is a backupbot recipe-PR, like immich), and seek Adversary §7.1 sign-off.
|
||||
|
||||
## 3. Recipe-local tests (D4) — default-deny (HC2)
|
||||
|
||||
If the recipe's own repo contains `tests/test_*.py` / `install_steps.sh` / `ops.py`, the runner
|
||||
@ -204,3 +250,16 @@ tests/lasuite-docs/
|
||||
4. Teardown lasuite-docs, then the keycloak dep (LAST), both with verify=True.
|
||||
5. Print the run summary; non-zero exit code on any failure (DG4.1 deploy-count mismatch, tier
|
||||
FAIL, dep teardown leak — all surfaced).
|
||||
|
||||
### Other shapes (concrete references)
|
||||
|
||||
- **TCP / voice recipe — `tests/mumble/`**: `recipe_meta.py` (EXTRA_ENV sets
|
||||
`COMPOSE_FILE=compose.yml:compose.mumbleweb.yml:compose.host-ports.yml`, `WELCOME_TEXT`/`USERS`
|
||||
markers, `CHAOS_BASE_DEPLOY=True`, `READY_PROBE` TCP 64738), `install_steps.sh` (provides the
|
||||
host-ports overlay to older versions), `functional/_mumble_proto.py` + the protocol/config-round-trip
|
||||
tests, `ops.py`/`test_backup.py`/`test_restore.py` (sqlite P4). See §2.4.
|
||||
- **Multi-service, dep-less, in-container functional — `tests/mailu/`**: `recipe_meta.py`
|
||||
(`EXTRA_ENV(domain)` with `TLS_FLAVOR=notls` + `MAIL_DOMAIN`/`HOSTNAMES`/`TRAEFIK_STACK_NAME`),
|
||||
`functional/_mailu.py` (flask-CLI helpers), `test_mailbox.py` (create→config-export read-back),
|
||||
`test_mail_flow.py` (in-container sendmail→doveadm delivery). No backupbot → P4 N/A (PARITY.md +
|
||||
DEFERRED.md). See §2.4.
|
||||
|
||||
Reference in New Issue
Block a user