Files
cc-ci/tests/ghost/PARITY.md
autonomic-bot 1bd7c7a1d3 feat(2): Q4.4 ghost + DEPLOY_TIMEOUT plumb-through for heavy recipes
Harness change (small, surgical):
- runner/harness/lifecycle.deploy_app gains a deploy_timeout param (default 900s); passes
  through to abra.deploy(timeout=...). For heavy recipes (ghost, matrix-synapse, lasuite-meet),
  the orchestrator + dep resolver now read recipe_meta.DEPLOY_TIMEOUT and pass it so the Python
  subprocess wrapping abra deploy doesn't SIGKILL it before the recipe's INTERNAL TIMEOUT
  (via EXTRA_ENV) finishes swarm convergence.
- runner/run_recipe_ci.py + runner/harness/deps.py: thread recipe_meta.DEPLOY_TIMEOUT into
  the per-recipe deploy_app call.

Q4.4 ghost enrollment:
- recipe_meta.py: HEALTH_PATH=/, DEPLOY_TIMEOUT=1200 (subprocess), EXTRA_ENV={TIMEOUT: 1200}
  (recipe internal). Ghost cold-start with theme + DB migration runs ~12-15min on cc-ci.
- functional/test_health_check.py: GET / returns 200 (themed site).
- functional/test_content_api.py: GET /ghost/api/content/settings/ returns 200 (settings JSON)
  or 401/403 (Ghost error envelope) — distinguishes ghost-server up + JSON API working from
  static fallback.
- functional/test_admin_redirect.py: GET /ghost/ returns 200 or 302 + Ghost branding;
  proves admin route is wired through nginx proxy.
- PARITY.md: recipe-maintainer corpus has no ghost tests/, Phase-2 health_check is the
  parity baseline; create-a-post deeper test deferred (DEFERRED.md, --extra-tests linked).

Cold-verifiable (log /root/ccci-q44-ghost-r3.log):
  RECIPE=ghost STAGES=install,custom cc-ci-run runner/run_recipe_ci.py
  install + 3 functional tests PASS, deploy-count=1. 28/28 unit tests still PASS.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 17:23:40 +01:00

40 lines
2.1 KiB
Markdown

# Parity — ghost
The recipe-maintainer corpus has **no** `recipe-info/ghost/tests/` directory — ghost was not in
their parity suite. This PARITY.md documents the Phase-2 health_check (parity-aligned baseline)
+ recipe-specific tests beyond.
## Recipe-specific tests (Phase-2 P3, ≥2 beyond parity)
Ghost is a **publishing platform** with a public themed site at `/`, an admin UI at `/ghost/`,
and a JSON Content/Admin API at `/ghost/api/*`. Defining behaviors exercised:
| cc-ci file | what's verified | rationale |
|---|---|---|
| `tests/ghost/functional/test_content_api.py` | GETs `/ghost/api/content/settings/`; asserts 200 with `{"settings": {...}}` envelope OR 401/403 with a Ghost error envelope. | Distinguishes "the ghost-server JS process is up + emitting its API" from "a static themed page is served at /." A wedged Ghost backend → 5xx; misrouted nginx → 404. |
| `tests/ghost/functional/test_admin_redirect.py` | GETs `/ghost/`; asserts 200 or 302 + Ghost branding/SPA references in the response (or a redirect to /ghost/#/setup on fresh deploy). | Proves the admin route is wired through the nginx proxy. Distinguishes "admin SPA bound" from "404 (route missing)" or "5xx (broken)." |
Two specific tests + parity health_check = ≥2 floor met.
## Plan §4.3 prescribed deeper test (deferred to Q4 follow-up)
§4.3 named "create-a-post round-trip" for ghost. That requires:
1. Setup the Ghost owner (POST `/ghost/api/v3/admin/authentication/setup/`) with a per-run
admin email+password.
2. Login → JWT bearer token.
3. POST `/ghost/api/v3/admin/posts/` to create a post.
4. GET `/ghost/api/v3/admin/posts/<id>/` to read it back.
Doable; adds a per-run setup secret + token-management. Tracked for Q4 follow-up.
## Backup data-integrity (P4)
Lifecycle overlays not authored. The base recipe stores state in SQLite + a content volume;
backup-capable is auto-detected from compose. Q5 catch-up if backup data-integrity proves
needed for this recipe.
## Playwright (P6)
Not yet authored. Ghost's admin UI is an Ember SPA; a Playwright flow would exercise the
setup wizard + post creation. Q4 follow-up.