feat(1d): migrate keycloak/cryptpad/matrix-synapse/n8n/lasuite-docs overlays to deploy-once contract (DG7)

Mechanical port to the assertion-only contract (no softened/skipped assertions): install uses
live_app + generic.assert_serving (extend) + the recipe's http/playwright/api checks; upgrade seeds
its data marker then generic.do_upgrade + asserts survival; backup/restore split into test_backup.py
(seed->do_backup->mutate) + new test_restore.py (do_restore->assert original). Recipe-specifics
preserved verbatim (keycloak realm+admin-console+kc_admin, matrix/lasuite db-service psql markers,
cryptpad/n8n volume markers). No recipe now double-deploys under the deploy-once orchestrator.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-28 01:32:53 +01:00
parent 9b5bcff92a
commit afd75a48db
21 changed files with 315 additions and 325 deletions

View File

@ -1,27 +1,30 @@
"""lasuite-docs — install stage (recipe #5, multi-service + object-storage/S3). D2 install: the
multi-service stack (frontend + Django backend + celery + y-provider + docspec + postgres + redis +
minio + nginx) converges and serves the app over real HTTPS through the gateway.
"""lasuite-docs — INSTALL overlay (Phase 1d, DG4): override + extend-by-composition.
Login is OIDC-gated (no live OIDC provider in CI), so the functional assertion is that the frontend
SPA is served (unauthenticated landing), not an authenticated flow."""
Reuses the generic "really serving" assertion, then ADDS the recipe-specific checks: the multi-service
stack serves over real HTTPS through the gateway, and a real browser loads the live Docs frontend (the
SPA shell). Login is OIDC-gated (no live OIDC provider in CI), so the functional assertion is that the
frontend SPA is served (unauthenticated landing), not an authenticated flow. Assertion-only on the
shared deployment."""
import os
import sys
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "..", "runner"))
from harness import lifecycle # noqa: E402
from harness import generic, lifecycle # noqa: E402
def test_http_reachable(deployed_app):
status = lifecycle.http_get(deployed_app, "/")
assert status in (200, 301, 302), f"expected 2xx/3xx from {deployed_app}, got {status}"
def test_serving_and_frontend(live_app, meta):
# extend-by-composition: reuse the generic "really serving" assertion first ...
generic.assert_serving(live_app, meta)
# ... then the recipe-specific assertions.
status = lifecycle.http_get(live_app, "/")
assert status in (200, 301, 302), f"expected 2xx/3xx from {live_app}, got {status}"
def test_playwright_loads_frontend(deployed_app):
"""A real browser loads the live Docs frontend (the SPA shell) over HTTPS."""
# A real browser loads the live Docs frontend (the SPA shell) over HTTPS.
from playwright.sync_api import sync_playwright
url = f"https://{deployed_app}/"
url = f"https://{live_app}/"
with sync_playwright() as p:
browser = p.chromium.launch(args=["--no-sandbox"])
try: