feat(harness): P3 — uniform ctx hook convention (rcust)
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
harness.meta.HookCtx (frozen): .domain, .base_url, .meta (RecipeMeta), .deps (provisioned dep creds from $CCCI_DEPS_FILE or None), .op (current lifecycle op or None); built via meta.hook_ctx() at each hook call site. All recipe callables now take ctx: EXTRA_ENV(ctx), UPGRADE_EXTRA_ENV(ctx), READY_PROBE(ctx), BACKUP_VERIFY(ctx), SCREENSHOT(page, ctx), ops.py pre_<op>(ctx). Dict-valued EXTRA_ENV/UPGRADE_EXTRA_ENV unchanged (only the callable signature moved). Call sites converted: deploy_app env shaping, perform_upgrade, wait_ready_probes (gains op=), _perform_op BACKUP_VERIFY, screenshot.capture, _run_pre_hook. Legacy signatures fail FAST with a clear migration message: the registry carries hook_params per hook key, enforced at meta.load() (MetaError names the old vs new signature); ops.py pre-op hooks get the same check at the orchestrator call site (meta.check_hook_signature) — no silent TypeError mid-run. Migrated every in-repo user mechanically (17 ops.py files; cryptpad/lasuite-*/ mailu EXTRA_ENV; mumble+lasuite-drive READY_PROBE; ghost/discourse BACKUP_VERIFY) — seeded values, probes and assertions byte-identical (domain -> ctx.domain; keycloak pre_restore's meta arg -> ctx.meta). Unit tests: hook_ctx field contract, ctx.deps from the run deps file, legacy- signature MetaError (READY_PROBE/EXTRA_ENV/SCREENSHOT + pre-op checker), ctx signatures accepted. Docs table regenerated (signature docs in key docs). Verified on cc-ci: cc-ci-run -m pytest tests/unit -q -> 180 passed; scripts/lint.sh -> PASS.
This commit is contained in:
@ -8,7 +8,7 @@ Secret-safety (R7, the cardinal screenshot guardrail): the screenshot step must
|
||||
that displays generated credentials (an install wizard showing the initial admin password, a secrets
|
||||
page, etc.). The DEFAULT capture is the app's **landing page** (a login form shows fields, not the
|
||||
password) — safe for every recipe. A recipe that needs a post-login view opts in via a recipe-meta
|
||||
`SCREENSHOT` hook: a callable `screenshot(page, domain, meta) -> None` that drives Playwright to a
|
||||
`SCREENSHOT` hook: a callable `SCREENSHOT(page, ctx) -> None` that drives Playwright to a
|
||||
safe, credential-free view and is responsible for not landing on a secrets page. The harness never
|
||||
auto-fills a wizard.
|
||||
|
||||
@ -21,6 +21,7 @@ from __future__ import annotations
|
||||
import os
|
||||
|
||||
from . import browser as harness_browser
|
||||
from . import meta as meta_mod
|
||||
|
||||
# Default viewport for the captured screenshot — a desktop-ish frame that crops well into the card.
|
||||
VIEWPORT = {"width": 1280, "height": 800}
|
||||
@ -74,8 +75,9 @@ def capture(domain: str, out_path: str, *, recipe_meta: dict | None = None) -> s
|
||||
if hook is not None:
|
||||
# Recipe-specific safe view (post-login etc.). The hook owns navigation +
|
||||
# the no-secret-page guarantee; it should call page.screenshot itself, but if
|
||||
# it doesn't, we still snap the resulting page below.
|
||||
hook(page, domain, recipe_meta)
|
||||
# it doesn't, we still snap the resulting page below. SCREENSHOT(page, ctx) —
|
||||
# the uniform ctx convention (rcust P3).
|
||||
hook(page, meta_mod.hook_ctx(domain, recipe_meta))
|
||||
if not os.path.exists(out_path):
|
||||
page.screenshot(path=out_path, full_page=False)
|
||||
else:
|
||||
|
||||
Reference in New Issue
Block a user