feat(3 U1): wire app screenshot capture into run_recipe_ci (best-effort, post-healthy, secret-safe; sets results.json screenshot)
This commit is contained in:
@ -50,6 +50,7 @@ from harness import ( # noqa: E402
|
|||||||
lifecycle,
|
lifecycle,
|
||||||
naming,
|
naming,
|
||||||
results as results_mod,
|
results as results_mod,
|
||||||
|
screenshot as screenshot_mod,
|
||||||
warm,
|
warm,
|
||||||
warmsnap,
|
warmsnap,
|
||||||
)
|
)
|
||||||
@ -914,6 +915,7 @@ def main() -> int:
|
|||||||
results: dict[str, str] = {}
|
results: dict[str, str] = {}
|
||||||
lifecycle.janitor()
|
lifecycle.janitor()
|
||||||
dep_teardown_error: str | None = None
|
dep_teardown_error: str | None = None
|
||||||
|
screenshot_rel: str | None = None # Phase 3 U1 (R4): set once the app screenshot is captured
|
||||||
try:
|
try:
|
||||||
# ---- (Q3.2a) install-time OIDC: provision the warm-dep realm BEFORE the single deploy so
|
# ---- (Q3.2a) install-time OIDC: provision the warm-dep realm BEFORE the single deploy so
|
||||||
# install_steps.sh can read $CCCI_DEPS_FILE and wire the OIDC env into that one deploy. On
|
# install_steps.sh can read $CCCI_DEPS_FILE and wire the OIDC env into that one deploy. On
|
||||||
@ -963,6 +965,19 @@ def main() -> int:
|
|||||||
print(f"!! deploy/readiness failed: {e}", flush=True)
|
print(f"!! deploy/readiness failed: {e}", flush=True)
|
||||||
deploy_ok = False
|
deploy_ok = False
|
||||||
|
|
||||||
|
# ---- Phase 3 U1 (R4): capture a real app screenshot while the app is up, at the cleanest
|
||||||
|
# "freshly installed + healthy" moment (before any tier mutates state and before teardown).
|
||||||
|
# Placed OUTSIDE the deploy try/except so a screenshot issue can NEVER flip deploy_ok.
|
||||||
|
# Secret-safe by default (landing page, never a credentials page; recipes opt into a
|
||||||
|
# post-login view via a SCREENSHOT meta hook). Best-effort — capture() swallows all errors and
|
||||||
|
# returns None, so this never blocks or fails the run (R7). None → results.json `screenshot`
|
||||||
|
# stays null → the card shows the "no screenshot" placeholder (cosmetics never change verdict).
|
||||||
|
if deploy_ok:
|
||||||
|
shot = screenshot_mod.capture(
|
||||||
|
domain, screenshot_mod.screenshot_path(run_artifact_dir), recipe_meta=meta
|
||||||
|
)
|
||||||
|
screenshot_rel = os.path.basename(shot) if shot else None
|
||||||
|
|
||||||
# ---- INSTALL tier (always; additive generic + overlay, no op) ----
|
# ---- INSTALL tier (always; additive generic + overlay, no op) ----
|
||||||
if "install" in stages:
|
if "install" in stages:
|
||||||
results["install"] = (
|
results["install"] = (
|
||||||
@ -1213,6 +1228,7 @@ def main() -> int:
|
|||||||
sso_unverified=sso_unverified,
|
sso_unverified=sso_unverified,
|
||||||
clean_teardown=clean_teardown,
|
clean_teardown=clean_teardown,
|
||||||
no_secret_leak=True, # narrowed below by an actual scan of the serialised artifact
|
no_secret_leak=True, # narrowed below by an actual scan of the serialised artifact
|
||||||
|
screenshot=screenshot_rel, # Phase 3 U1 (R4): relative PNG name iff capture succeeded
|
||||||
finished_ts=time.time(),
|
finished_ts=time.time(),
|
||||||
)
|
)
|
||||||
# Real (if narrow) leak check: no known infra-secret value may appear in the artifact (R7).
|
# Real (if narrow) leak check: no known infra-secret value may appear in the artifact (R7).
|
||||||
|
|||||||
Reference in New Issue
Block a user