#!/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/:latest → clawmates/: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/: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/: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:-} 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[*]}"