review(2): Q4.4 ghost PASS — COLD full lifecycle GREEN (my clone, log adv-ghost-pr1) 5 tiers, deploy-count=1, real upgrade crossover 1.1.1+6-alpine→1.3.0+6.21.2-alpine (chaos 6d6227f7+U, HC1 preserved), create_post_roundtrip + restore + backup + upgrade markers PASS, clean teardown; P4 MySQL ci_marker restore proven NON-VACUOUS via PR=0 negative control (published recipe → test_restore_returns_state FAILED 'Table ghost.ci_marker doesnt exist', fail-loud) — recipe-PR ghost#1 is a genuine reimport-on-restore fix (4th data-loss recipe bug cc-ci caught); §4.3 create-post real (cookie admin session + unique-marker title+body read-back) CLOSES the ghost §4.3 floor; +U HC1 fix & healthcheck overlay reviewed legit (not weakening); clean teardown after FAILED run too; no veto
This commit is contained in:
@ -1737,3 +1737,75 @@ upgrade/backup/restore tiers were not in this scoped run (install,custom only)
|
||||
plausible still ride the normal gate path if/when claimed; this probe targeted the §4.3 floor that was
|
||||
my standing obligation. No VETO. NOTE: ClickHouse boot is intermittently flaky on the single node
|
||||
(1-in-2 here) — a real env-fragility worth a retry/readiness margin if plausible runs go in CI rotation.
|
||||
|
||||
## Q4.4 ghost — PASS @2026-05-30T06:57Z (COLD, first-hand, my clone /root/adv-verify @origin/main c60d5b5)
|
||||
|
||||
Cold full-lifecycle re-run from my OWN clone — the exact claimed command — PLUS a negative control.
|
||||
Logs `/root/adv-ghost-pr1.log` (PR=1, the fix) and `/root/adv-ghost-pr0-neg.log` (PR=0, published).
|
||||
|
||||
**Primary — PR=1 (recipe-PR `recipe-maintainers/ghost#1`, REF=6d6227f7), all 5 tiers GREEN:**
|
||||
- RUN SUMMARY: `deploy-count = 1 (expect 1)`; `install/upgrade/backup/restore/custom` **all pass**.
|
||||
No cold-init flake on my run (install passed first try; ENV-NOTE retry not needed).
|
||||
- Upgrade: `head_ref=6d6227f7 chaos-version=6d6227f7+U version=1.1.1+6-alpine→1.3.0+6.21.2-alpine`
|
||||
(HC1, real prev→PR-head crossover; the `+U` untracked-overlay marker correctly tolerated by the
|
||||
`a7e2af4` fix — which I reviewed: it strips ONLY the working-tree marker and still requires the
|
||||
commit to equal head_ref, so HC1 is preserved, not weakened).
|
||||
- `tests/ghost/test_upgrade.py::test_upgrade_preserves_state PASSED`,
|
||||
`test_backup.py::test_backup_captures_state PASSED`,
|
||||
`test_restore.py::test_restore_returns_state PASSED` (MySQL `ci_marker='original'` read back),
|
||||
`functional/test_post_roundtrip.py::test_create_post_roundtrip PASSED` (6s).
|
||||
- Clean teardown: post-run no ghost stack; 0 ghost secrets / 0 volumes / 0 networks.
|
||||
|
||||
**P4 — the headline crux — restore PROVEN non-vacuous via NEGATIVE CONTROL (decisive).** Re-ran the
|
||||
SAME overlay against the **published** recipe (`PR=0`, no fix), STAGES=install,backup,restore:
|
||||
- `tests/_generic/test_restore.py::test_restore_healthy PASSED` (app healthy after restore) **but**
|
||||
`tests/ghost/test_restore.py::test_restore_returns_state FAILED` —
|
||||
`RuntimeError: docker exec … failed (rc=1) … ERROR 1146 (42S02) … Table 'ghost.ci_marker' doesn't
|
||||
exist`. RUN SUMMARY: `restore : fail` (install+backup pass).
|
||||
- Confirms: (a) the published ghost recipe's restore is a **silent no-op** — it ships a mysqldump
|
||||
`--tab` backup pre-hook but **no `backupbot.restore.*` reimport hook**, so the dropped table never
|
||||
returns (looks healthy, data lost — the immich#1 / mattermost-lts#1 class); (b) the P4 overlay is
|
||||
**non-vacuous** (health-only passes here, the data-integrity assertion catches it); (c) it fails
|
||||
**LOUD** — `exec_in_app` RAISES on a failed exec, never a silent `''`; (d) `ops.pre_restore` DROPs
|
||||
`ci_marker` AND asserts the drop took (information_schema count=0), so a no-op restore is observable
|
||||
in-band on EVERY run too. recipe-PR #1 (`ci/mysql-backup`) adds the reimport-on-restore hook →
|
||||
`test_restore_returns_state` PASSES (PR=1). The recipe-PR is a **genuine fix**, verified end-to-end
|
||||
by running both halves myself.
|
||||
|
||||
**P3 — §4.3 create-post is REAL (read the body), closes the standing ghost §4.3 floor:**
|
||||
`test_create_post_roundtrip` waits for the Admin API → bootstraps the owner (`/authentication/setup/`)
|
||||
→ establishes a real cookie-aware admin **session** (`_ghost.GhostAdmin` builds a urllib opener with
|
||||
an HTTPCookieProcessor + the CSRF `Origin` header Ghost requires) → POSTs a **published** post with a
|
||||
unique-per-run marker in title+body (`/posts/?source=html`) → GETs it back by id (`?formats=html`) →
|
||||
asserts BOTH the title and the body-html marker round-trip. Per-run UUID marker ⇒ no stale/echo
|
||||
false-pass; exercises DB-write + Admin-API + publishing path. This **replaces the weak**
|
||||
`test_content_api` (which accepted 401/403/400) as the §4.3 floor — my standing DONE-blocker #3 for
|
||||
ghost is CLEARED. (`test_admin_redirect`, `test_content_api`, `test_health_check` also PASS as
|
||||
supporting liveness.)
|
||||
|
||||
**P2 N/A** (no recipe-maintainer corpus — documented in `tests/ghost/PARITY.md`). **P5/P6 N/A** —
|
||||
postgres/MySQL is in-recipe (no external dep); core publishing exercised via the Admin API; no
|
||||
browser-only UX owed. **P7** — no weakened/skipped/mocked tests. The two cc-ci infra changes are
|
||||
legitimate, NOT test-weakening: (1) `compose.ccci-health.yml` start_period overlay gives Ghost's
|
||||
~6-9min fresh MySQL migration time to finish so the healthcheck doesn't kill it mid-migration
|
||||
(`migrations_lock` deadlock) — a test-harness fixture for a real slow-cold-boot, the migration itself
|
||||
is genuine; (2) the `+U` HC1 fix (reviewed above, preserves the commit match).
|
||||
|
||||
**Break-it checks:** (1) PR=0 negative control → restore RED on the published recipe (teeth proven);
|
||||
(2) clean teardown after a **FAILED** run — post-PR=0 node fully clean (no ghost residue); (3) per-run
|
||||
unique post marker defeats stale-response false-pass; (4) in-band pre_restore drop+assert-took; (5)
|
||||
deploy-count=1 (no hidden redeploy). ENV fragility noted: ghost's mysql:8.0 cold-init healthcheck is
|
||||
flaky (Builder saw one install timeout pr1c → passed on retry pr1d); my PR=1 install passed first try.
|
||||
|
||||
**Verdict: Q4.4 ghost PASS.** Full lifecycle GREEN cold, deploy-count=1, real upgrade crossover
|
||||
1.1.1+6-alpine→1.3.0+6.21.2-alpine, P4 MySQL ci_marker survives backup→restore (non-vacuous, proven
|
||||
by PR=0 negative control), §4.3 create-post real (closes the ghost §4.3 floor), clean teardown (incl.
|
||||
after failure). No `## VETO`. Advances P1 coverage (ghost full green). recipe-PR
|
||||
`recipe-maintainers/ghost#1` is a real restore fix — 4th data-loss-class recipe bug cc-ci has caught
|
||||
(immich, mattermost-lts, ghost; bluesky's volume restore was already sound). **My standing ghost §4.3
|
||||
DONE-blocker is CLEARED.**
|
||||
|
||||
**Isolation note:** verdict from the plan (P1–P8) + the test code (ops.py / test_{restore,backup,
|
||||
upgrade}.py / functional/{_ghost,test_post_roundtrip}.py) + the `a7e2af4` HC1 diff + the STATUS
|
||||
Gate-Q4.4 verification info + my own cold PR=1 full run AND PR=0 negative control. JOURNAL-2 not
|
||||
consulted before this verdict.
|
||||
|
||||
Reference in New Issue
Block a user