Files
clawmates/deploy/gw-04/clawmates-deploy.sh
T
Omar Sobh 3f82d9efe4
ci / gates (push) Successful in 21s
ci / frontend (push) Successful in 35s
ci / rust (push) Failing after 1m2s
ci / e2e (push) Has been skipped
ci / publish (push) Successful in 4m35s
deploy(gw-04): running-container drift check + docker-compose v1 fallback
Two fixes needed to make the timer actually roll correctly on gw-04:

1. Drift check compares the running container's image ID against the
   local `clawmates/<svc>:latest` tag, not just pre/post-pull digests.
   The pre/post check only catches new pulls — if a previous roll failed
   between the retag and `docker compose up` (e.g. compose CLI failed),
   the tag was updated but the container wasn't, and the next tick saw
   no drift and silently left the stale container running. The
   running-vs-tag check catches that case on the next tick.

2. Prefer `docker compose` (v2 plugin) but fall back to legacy
   `docker-compose` (v1). GW-04 ships v1 only right now, and calling
   `docker compose up -d` failed with "unknown shorthand flag: 'd'"
   because docker had no `compose` subcommand at all. The fallback
   keeps the script portable when the stack moves to a host with v2.
2026-07-05 18:55:12 -07:00

78 lines
2.8 KiB
Bash
Executable File

#!/usr/bin/env bash
#
# clawmates rolling deploy — polls the fleet registry for :latest of the three
# prod images (broker, server, frontend). On drift, pulls the new image, retags
# it under the un-prefixed name the running compose file uses, and rolls the
# affected services with `docker compose up -d`.
#
# Install:
# sudo install -m 0755 clawmates-deploy.sh /usr/local/bin/clawmates-deploy.sh
# sudo install -m 0644 clawmates-deploy.service /etc/systemd/system/
# sudo install -m 0644 clawmates-deploy.timer /etc/systemd/system/
# sudo systemctl daemon-reload
# sudo systemctl enable --now clawmates-deploy.timer
#
# Verify:
# systemctl list-timers clawmates-deploy.timer
# tail -f /var/log/clawmates-deploy.log
#
# The retag step (registry/clawmates/<svc>:latest → clawmates/<svc>:latest)
# keeps the current /root/clawmates/docker-compose.yml working unchanged until
# we're ready to migrate the compose file to registry-prefixed image names.
set -euo pipefail
REGISTRY="${REGISTRY:-100.94.185.103:5000}"
NAMESPACE="${NAMESPACE:-clawmates}"
COMPOSE_DIR="${COMPOSE_DIR:-/root/clawmates}"
LOG="${LOG:-/var/log/clawmates-deploy.log}"
SERVICES=(broker server frontend)
log() { printf '%s %s\n' "$(date -Iseconds)" "$*" | tee -a "$LOG" >/dev/null; }
changed=()
for svc in "${SERVICES[@]}"; do
ref="${REGISTRY}/${NAMESPACE}/${svc}:latest"
local_ref="${NAMESPACE}/${svc}:latest"
if ! docker pull -q "$ref" >/dev/null 2>&1; then
log "pull failed: $ref"
continue
fi
# Keep the un-prefixed tag pointing at the fresh image so the compose file
# (which references clawmates/<svc>:latest) picks up the new image on `up`.
docker tag "$ref" "$local_ref"
# True drift check: is the running container's image ID the same as what
# `clawmates/<svc>:latest` now points to? Comparing pre/post pull digests
# only catches new pulls — if a previous roll failed after the retag but
# before `up`, the tag was updated but the container wasn't. This catches
# that case on the next run.
target=$(docker inspect --format '{{.Id}}' "$local_ref")
cid=$(docker ps -q --filter "name=clawmates_${svc}_1")
running=""
[ -n "$cid" ] && running=$(docker inspect --format '{{.Image}}' "$cid")
if [[ "$running" != "$target" ]]; then
log "$svc drift: running=${running:-<none>} target=$target"
changed+=("$svc")
fi
done
if [[ ${#changed[@]} -eq 0 ]]; then
exit 0
fi
log "rolling: ${changed[*]}"
cd "$COMPOSE_DIR"
# Prefer `docker compose` (v2 plugin); fall back to legacy `docker-compose`
# (v1). GW-04 currently ships v1 only; this makes the script portable if we
# ever move the stack to a host with the plugin.
if docker compose version >/dev/null 2>&1; then
docker compose up -d "${changed[@]}"
else
docker-compose up -d "${changed[@]}"
fi
log "roll complete: ${changed[*]}"