fix(deploy): ship the immutable main-<sha> tag, not the mutable :latest
ci / gates (push) Successful in 6s
ci / rust (push) Failing after 12s
ci / frontend (push) Successful in 27s
ci / e2e (push) Skipped
ci / publish (push) Skipped

`docker-compose pull server frontend` pulls `:latest`, and the registry
served a STALE manifest for that mutable tag: a deploy pushed
`main-9bc5f6a` correctly, but the gateway's `pull :latest` reported
"image is up to date" and left the previous image running. The verify
step caught it (running 9f2349 = main-0a647c0, expected bbf19f7e), so
the deploy failed loudly rather than silently — but it still could not
ship.

Immutable tags always resolve correctly, so pull `main-<sha>` and retag
it to `:latest` locally on the gateway, then recreate with `--no-deps`
and no compose pull. `:latest` is now just a local alias satisfying the
compose file's image reference; the sha tag is the source of truth.

Also switch the recreate to `--no-deps` (compose v1 has no
`--no-recreate-deps`) so a server/frontend deploy stops recreating
postgres.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
This commit is contained in:
Omar Sobh
2026-07-28 14:26:22 +02:00
co-authored by Claude Opus 5
parent 9bc5f6a142
commit d676a9e089
+10 -2
View File
@@ -83,13 +83,21 @@ if [ -z "${IMAGES_ONLY:-}" ]; then
# Snapshot the currently-deployed images as :rollback (a repoint, cheap) so a # Snapshot the currently-deployed images as :rollback (a repoint, cheap) so a
# bad deploy can be reverted without a rebuild, then pull the freshly-pushed # bad deploy can be reverted without a rebuild, then pull the freshly-pushed
# images and recreate. # images and recreate.
# Pull the IMMUTABLE main-<sha> tag and retag it to :latest locally, then
# recreate WITHOUT a compose pull. Pulling `:latest` here is not reliable —
# the registry has served a stale manifest for that mutable tag (a deploy
# pushed main-9bc5f6a fine, but `pull :latest` reported "up to date" and
# left the OLD image running). Immutable tags always resolve correctly, so
# the sha tag is the source of truth and `:latest` is just a local alias
# for the compose file's image reference.
ssh "$GW" "set -e ssh "$GW" "set -e
for svc in server frontend; do for svc in server frontend; do
docker tag $REGISTRY/clawmates/\$svc:$TAG $REGISTRY/clawmates/\$svc:rollback 2>/dev/null || true docker tag $REGISTRY/clawmates/\$svc:$TAG $REGISTRY/clawmates/\$svc:rollback 2>/dev/null || true
docker pull $REGISTRY/clawmates/\$svc:main-$SHA
docker tag $REGISTRY/clawmates/\$svc:main-$SHA $REGISTRY/clawmates/\$svc:$TAG
done done
cd $GW_DIR cd $GW_DIR
docker-compose -p clawmates pull server frontend docker-compose -p clawmates up -d --force-recreate --no-deps server frontend"
docker-compose -p clawmates up -d --force-recreate server frontend"
fi fi
echo "→ load agent runtime images onto $GW + every fleet node" echo "→ load agent runtime images onto $GW + every fleet node"