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>
40 lines
2.1 KiB
Markdown
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.
|