All checks were successful
continuous-integration/drone/push Build is passing
a) compose.ccci.yml is FIRST-CLASS: the harness auto-copies tests/<recipe>/ compose.ccci.yml into the run's recipe checkout (ABRA_DIR-aware, lifecycle. provide_ccci_overlay) and auto-chaoses the pinned base deploy on its presence (kills the R7 implicit coupling). ghost/discourse install_steps.sh (copy-only boilerplate) deleted; CHAOS_BASE_DEPLOY removed from both metas + the registry. b) install-time deps wiring is the ONLY mode: deps with DEPS provision BEFORE the single deploy; legacy post-deploy provisioning + the setup_custom_tests.sh invocation machinery deleted. lasuite-docs migrated to install_steps.sh OIDC wiring (same env names/values as the old hook — only the timing moved); lasuite-drive's remaining post-deploy MinIO bucket one-shot moved to ops.py pre_install; both setup_custom_tests.sh files deleted; OIDC_AT_INSTALL removed from drive/meet metas + the registry. c) SKIP_GENERIC meta key deleted (zero users). Env form CCCI_SKIP_GENERIC* stays as the documented dev-only escape hatch; when active in a drone CI run the orchestrator prints a loud !! warning (manifest embedding lands in P5). d) conftest cleanup: dead pre-deploy-once fixtures deployed/deployed_app deleted (zero users), app_domain + _short + _wait_healthy dropped (only users were the deleted fixtures); deps_apps+deps_creds consolidated into ONE deps fixture (entries expose .domain etc. as attributes; dict access intact); the 6 lasuite test files renamed deps_creds->deps (fixture name only — assertions and flows byte-identical). requires_deps marker + F2-11 skip-report plumbing unchanged. Registry is now exactly the 14 final keys; docs §4 table regenerated. Stale setup_custom_tests/OIDC_AT_INSTALL prose in docstrings/comments/assert MESSAGES updated (no assert logic or expected value touched). Verified on cc-ci: cc-ci-run -m pytest tests/unit -q -> 175 passed; scripts/lint.sh -> PASS.
112 lines
4.7 KiB
Python
112 lines
4.7 KiB
Python
"""lasuite-drive — pre-op seed hooks (Phase 1e HC3). The orchestrator runs these BEFORE the op; the
|
|
matching test_<op>.py asserts post-op (assertion-only). The marker is a dedicated `ci_marker` row in
|
|
postgres (independent of the app's Django migrations — CREATE TABLE IF NOT EXISTS), written via psql
|
|
in the `db` service. The backup path exercises the recipe's pg_backup.sh DB-dump hook (postgres is
|
|
backupbot-labelled)."""
|
|
|
|
import os
|
|
import subprocess
|
|
import sys
|
|
import time
|
|
|
|
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "..", "runner"))
|
|
from harness import lifecycle # noqa: E402
|
|
|
|
|
|
def pre_install(domain, meta):
|
|
"""Post-deploy seed for the custom tier (the former setup_custom_tests.sh, moved here in rcust
|
|
P2b — install_steps.sh runs PRE-deploy and cannot touch the live stack). The deploy alone does
|
|
NOT create the MinIO bucket: `minio-createbuckets` is a `replicas:0` one-shot (restart_policy:
|
|
none) that must be triggered. The MinIO storage test asserts the bucket exists, so trigger it
|
|
here and poll. `--detach` is REQUIRED: the job creates the bucket then EXITS 0, so it never
|
|
holds a steady 1/1 replica — a blocking scale would wait forever."""
|
|
stack = domain.replace(".", "_")
|
|
print(" pre_install: creating MinIO bucket via the minio-createbuckets one-shot", flush=True)
|
|
subprocess.run(
|
|
["docker", "service", "scale", "--detach", f"{stack}_minio-createbuckets=1"],
|
|
capture_output=True,
|
|
check=False,
|
|
)
|
|
check = (
|
|
'mc alias set _c http://localhost:9000 "$(cat /run/secrets/minio_ru)" '
|
|
'"$(cat /run/secrets/minio_rp)" >/dev/null 2>&1 && '
|
|
"mc ls _c/drive-media-storage >/dev/null 2>&1"
|
|
)
|
|
for i in range(30):
|
|
cid = subprocess.run(
|
|
["docker", "ps", "-q", "-f", f"name={stack}_minio.1"],
|
|
capture_output=True,
|
|
text=True,
|
|
check=False,
|
|
).stdout.split()
|
|
if cid and (
|
|
subprocess.run(
|
|
["docker", "exec", cid[0], "sh", "-c", check], capture_output=True, check=False
|
|
).returncode
|
|
== 0
|
|
):
|
|
print(
|
|
f" pre_install: bucket drive-media-storage present after {i + 1} poll(s)",
|
|
flush=True,
|
|
)
|
|
return
|
|
time.sleep(3)
|
|
raise AssertionError("minio-createbuckets one-shot did not create drive-media-storage in 90s")
|
|
|
|
|
|
def _wait_collabora_ready(domain, timeout=420):
|
|
"""Gate the upgrade op on collabora being FULLY ready (WOPI discovery endpoint → 200), not just
|
|
container 1/1 'running'. coolwsd takes ~2min to boot (pre-reads 1300+ l10n files + RSA keygen);
|
|
the install wait_healthy returns on container 1/1 while coolwsd is still loading. An in-place
|
|
`abra app deploy --chaos` upgrade that lands on a still-booting collabora SIGTERMs it mid-init
|
|
("Shutdown requested while starting up", forced exit 70) → abra aborts the deploy (Q3.2a run 1,
|
|
JOURNAL 2026-05-29). Waiting for discovery=200 first makes the redeploy replace a ready collabora
|
|
cleanly. collabora routes on the COLLABORA_DOMAIN sibling (collabora-<domain>); /hosting/discovery
|
|
is the WOPI discovery endpoint celery's configure_wopi calls."""
|
|
host = f"collabora-{domain}"
|
|
deadline = time.time() + timeout
|
|
last = 0
|
|
while time.time() < deadline:
|
|
last = lifecycle.http_get(host, "/hosting/discovery", timeout=15)
|
|
if last == 200:
|
|
print(f" pre_upgrade: collabora WOPI discovery ready (200) on {host}", flush=True)
|
|
return
|
|
time.sleep(5)
|
|
raise AssertionError(
|
|
f"collabora WOPI discovery not ready on {host} (last status {last}) within {timeout}s"
|
|
)
|
|
|
|
|
|
def _psql(domain, sql):
|
|
cmd = f'PGPASSWORD=$(cat /run/secrets/postgres_p) psql -U drive -d drive -tAc "{sql}"'
|
|
return lifecycle.exec_in_app(domain, ["sh", "-c", cmd], service="db").strip()
|
|
|
|
|
|
def _seed(domain, value):
|
|
_psql(
|
|
domain,
|
|
"CREATE TABLE IF NOT EXISTS ci_marker(v text); DELETE FROM ci_marker; "
|
|
f"INSERT INTO ci_marker VALUES('{value}');",
|
|
)
|
|
assert _psql(domain, "SELECT v FROM ci_marker;") == value
|
|
|
|
|
|
def pre_upgrade(domain, meta):
|
|
# Gate the chaos redeploy on a fully-ready collabora (else it kills a still-booting coolwsd and
|
|
# abra aborts the upgrade deploy — Q3.2a run 1). Then seed the data-integrity marker.
|
|
_wait_collabora_ready(domain)
|
|
_seed(domain, "upgrade-survives")
|
|
|
|
|
|
def pre_backup(domain, meta):
|
|
_seed(domain, "original")
|
|
|
|
|
|
def pre_restore(domain, meta):
|
|
# drop the marker table (diverge from the backup) so a successful restore is observable
|
|
_psql(domain, "DROP TABLE ci_marker;")
|
|
assert _psql(domain, "SELECT to_regclass('public.ci_marker');") in (
|
|
"",
|
|
"NULL",
|
|
), "drop did not take"
|