deploy: health gate and shape assertion follow the LAN publish address
Once the port is published on 192.168.20.13 the host no longer listens on 127.0.0.1:8096, so wait_healthy(), do_status() and the rollback path would all get connection-refused and every deploy would roll back. They now probe $PUBLISH_IP (RESUME_PUBLISH_IP, default 192.168.20.13). assert_shape() asserts the published host IP is that address instead of loopback; the mem_limit == memswap_limit checks are unchanged. check_port stays address-agnostic on `sport = :8096`. Records the amendment in reference/stack.md (ports table + the bind rule) and docs/phase-3-deploy.md (§3.2 bullet, flow diagram, DoD line), citing Sam's decision of 2026-10-26, interaction 54aeb1a2. AGENTS.md is Sam's to change and is untouched.
This commit is contained in:
@@ -44,6 +44,15 @@ PROJECT=ai-resume-site # compose project; distinct from the older
|
||||
PORT=8096
|
||||
HEALTH_PATH=/healthz
|
||||
|
||||
# The host address the port is published on. Caddy runs on .35 and proxies to
|
||||
# this address, so a loopback publish is unreachable from the edge (Sam's
|
||||
# decision, 2026-10-26, interaction 54aeb1a2). Never 0.0.0.0: the port must not
|
||||
# be reachable off the LAN. The health gate below follows this address — once the
|
||||
# port is published on the LAN address the host no longer listens on
|
||||
# 127.0.0.1:8096, so a loopback probe would refuse and every deploy would roll
|
||||
# back.
|
||||
PUBLISH_IP=${RESUME_PUBLISH_IP:-192.168.20.13}
|
||||
|
||||
ROOT=${RESUME_DEPLOY_ROOT:-/home/sam/deployment/resume}
|
||||
RELEASES=$ROOT/releases
|
||||
CURRENT=$ROOT/current
|
||||
@@ -231,7 +240,7 @@ start() {
|
||||
wait_healthy() {
|
||||
local i body
|
||||
for i in $(seq 1 "$HEALTH_TRIES"); do
|
||||
if body=$(curl -fsS --max-time 3 "http://127.0.0.1:$PORT$HEALTH_PATH" 2>/dev/null); then
|
||||
if body=$(curl -fsS --max-time 3 "http://$PUBLISH_IP:$PORT$HEALTH_PATH" 2>/dev/null); then
|
||||
if printf '%s' "$body" | grep -Eq '"status"[[:space:]]*:[[:space:]]*"ok"'; then
|
||||
log "health gate passed after ${i}s"
|
||||
return 0
|
||||
@@ -240,14 +249,15 @@ wait_healthy() {
|
||||
sleep 1
|
||||
done
|
||||
warn "health gate failed after ${HEALTH_TRIES}s; last response:"
|
||||
curl -sS --max-time 3 "http://127.0.0.1:$PORT$HEALTH_PATH" >&2 || true
|
||||
curl -sS --max-time 3 "http://$PUBLISH_IP:$PORT$HEALTH_PATH" >&2 || true
|
||||
compose logs --tail 40 resume >&2 || true
|
||||
return 1
|
||||
}
|
||||
|
||||
# Definition-of-Done evidence, checked on every deploy instead of by hand:
|
||||
# mem_limit == memswap_limit == the value declared in compose.yml, and the port
|
||||
# published on 127.0.0.1 only.
|
||||
# published on $PUBLISH_IP only (the LAN address Caddy proxies to — never
|
||||
# 0.0.0.0 and no longer loopback).
|
||||
assert_shape() {
|
||||
local cid mem swap ip declared
|
||||
declared=$(awk '/^[[:space:]]*mem_limit:/ {gsub(/[^0-9]/, "", $2); print $2}' "$COMPOSE")
|
||||
@@ -258,8 +268,8 @@ assert_shape() {
|
||||
[ "$mem" = "$swap" ] || die "mem_limit ($mem) != memswap_limit ($swap)"
|
||||
[ "$mem" = "$((declared * 1024 * 1024))" ] || die "mem_limit is $mem, expected ${declared} MiB"
|
||||
ip=$(docker inspect -f '{{range $p, $b := .HostConfig.PortBindings}}{{range $b}}{{.HostIp}} {{end}}{{end}}' "$cid" | xargs)
|
||||
[ "$ip" = "127.0.0.1" ] || die "published on '${ip}', expected 127.0.0.1 only"
|
||||
log "shape ok: mem_limit == memswap_limit == ${declared} MiB, published on 127.0.0.1:$PORT"
|
||||
[ "$ip" = "$PUBLISH_IP" ] || die "published on '${ip}', expected $PUBLISH_IP only"
|
||||
log "shape ok: mem_limit == memswap_limit == ${declared} MiB, published on $PUBLISH_IP:$PORT"
|
||||
}
|
||||
|
||||
deploy_release() {
|
||||
@@ -348,7 +358,7 @@ prune() {
|
||||
do_status() {
|
||||
local cur prev body
|
||||
cur=$(current_target); prev=$(previous_target)
|
||||
body=$(curl -fsS --max-time 3 "http://127.0.0.1:$PORT$HEALTH_PATH" 2>/dev/null || true)
|
||||
body=$(curl -fsS --max-time 3 "http://$PUBLISH_IP:$PORT$HEALTH_PATH" 2>/dev/null || true)
|
||||
printf 'root %s
|
||||
' "$ROOT"
|
||||
printf 'current %s
|
||||
|
||||
Reference in New Issue
Block a user