fix(deploy-hook): --build-staging must build from validated worktree, recreate+health 8501
All checks were successful
CI / test (push) Successful in 17s

Closes reviewer P0/P1 (ORCH-058 attempt 3): the committed --build-staging hook
recomputed GIT_SHA=$(git rev-parse HEAD) in $REPO (prod clone on `main`) and built
`docker build ... "$REPO"`, ignoring the caller-supplied BUILD_CONTEXT/GIT_SHA. On
the deploy-staging -> deploy edge the PR is not yet merged, so `main` HEAD != the
validated SHA -> the staging image got the wrong revision label and Strategy-B's
guard fail-closed on EVERY valid self-deploy (AC-6 deadlock). It also only did
`docker build` + exit 0 — never recreating 8501 nor health-checking — so
rebuild_staging_image's rc=0 ("rebuilt and healthy") was a lie (AC-4 unmet).

- Hook --build-staging now honours caller BUILD_CONTEXT (validated worktree) and
  GIT_SHA, recreates orchestrator-staging on the fresh image and runs the 10x6s
  health-check; build/health failure -> exit 1 (FAILED contract preserved).
- image_freshness.rebuild_staging_image: document why COMPOSE_PROFILE/TARGET_SERVICE/
  TARGET_PORT are intentionally omitted (hook STAGING defaults -> 8501 only, P2).
- tests: assert the caller<->hook contract (builds from $BUILD_CONTEXT, no
  `git rev-parse HEAD` recompute, recreates + health-checks 8501) so the P0
  regression can't pass green again (P1).

Refs: ORCH-058

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-06-07 08:37:51 +00:00
parent 3b3d587300
commit 2ee06ae676
3 changed files with 103 additions and 13 deletions

View File

@@ -248,6 +248,13 @@ def rebuild_staging_image(repo: str, branch: str, sha: str) -> tuple[bool, str]:
if not target:
return False, "no ssh host configured for staging rebuild"
host_ctx = _host_worktree_path(repo, branch)
# We pass ONLY GIT_SHA (validated commit -> revision label, the shared anchor
# with Strategy B), BUILD_CONTEXT (the validated worktree to build FROM) and
# TARGET_IMAGE (the staging image name to retag in prod later). COMPOSE_PROFILE
# / TARGET_SERVICE / TARGET_PORT are deliberately omitted so the hook keeps its
# built-in STAGING defaults (profile=staging, orchestrator-staging, 8501): this
# rebuild/recreate must touch STAGING ONLY (8501), NEVER prod (8500) (AC-9), and
# the prod defaults are never reachable on this path.
env_assignments = (
f"GIT_SHA={shlex.quote(sha)} "
f"BUILD_CONTEXT={shlex.quote(host_ctx)} "