fix(1e): F1e-1 exec_in_app race + HC1 head_ref/move hardening
F1e-1 (Adversary): exec_in_app silently returned '' on a failed docker exec, flipping a healthy recipe RED under opt-out (post-backup container cycle, no readiness buffer). Now polls (re-resolve container + re-exec) until rc==0 or 90s, then RAISES — never masks an exec failure as empty data. No assertion weakened. Verified: opt-out install,backup,restore on custom-html now PASS. HC1: head_ref = ref or recipe_head_commit (prefer explicit PR head sha $REF — robust, no git race; production !testme always sets REF). assert_upgraded, when head_ref known, REQUIRES the deployed chaos-version commit to MATCH head_ref (direct + non-vacuous proof the PR-head code was deployed; a stale prev-checkout chaos redeploy fails). Falls back to version/image/chaos move check otherwise. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@ -152,6 +152,18 @@ def restore(domain: str, timeout: int = 900) -> None:
|
||||
_run_pty(["app", "restore", domain, "-n", "-C", "-o"], timeout=timeout)
|
||||
|
||||
|
||||
def recipe_head_commit(recipe: str) -> str | None:
|
||||
"""The current HEAD commit of the recipe checkout — captured right after fetch (the PR head, or
|
||||
the catalogue current) so the upgrade tier can re-checkout it for the chaos redeploy after the
|
||||
prev-tag base deploy reset the working tree (HC1)."""
|
||||
import os
|
||||
|
||||
path = os.path.expanduser(f"~/.abra/recipes/{recipe}")
|
||||
proc = subprocess.run(["git", "-C", path, "rev-parse", "HEAD"], capture_output=True, text=True)
|
||||
out = proc.stdout.strip()
|
||||
return out or None
|
||||
|
||||
|
||||
def recipe_versions(recipe: str) -> list[str]:
|
||||
"""Published versions of a recipe, oldest→newest (from the recipe git tags)."""
|
||||
import os
|
||||
|
||||
Reference in New Issue
Block a user