Files
clawmates/deploy/gw-04/clawmates-deploy.sh
T
Omar Sobh 8f29cf8e44
ci / gates (push) Successful in 6s
ci / frontend (push) Successful in 37s
ci / rust (push) Successful in 2m57s
ci / e2e (push) Failing after 15s
ci / publish (push) Successful in 21s
deploy(gw-04): run the timer as a dedicated clawmates user under /opt
Move the running stack off root ownership. The systemd service now runs
as User=clawmates:clawmates with WorkingDirectory=/opt/clawmates, and the
script's COMPOSE_DIR default follows. This closes the "rootful compose
stack" ask from the original ship-readiness audit — deploys no longer
require any part of the pipeline to run as root beyond docker access
(the clawmates user gets that via the docker group).

Docker-managed volumes (pgdata, broker_run, broker_key, brains, filedata)
stay put; the compose project name is unchanged so docker resolves them
to the same physical volumes. The old /root/clawmates directory stays in
place as an emergency rollback for a week, then gets removed as follow-up.
2026-07-05 19:39:08 -07:00

73 lines
2.5 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 and
# rolls the affected services with `docker compose up -d`.
#
# The compose file must reference the registry-prefixed image names
# (100.94.185.103:5000/clawmates/<svc>:latest) so `up` picks up the pulled
# image directly. Previous versions of this script retagged to un-prefixed
# names as a bridge; that step is retired now that the compose file points
# at the registry directly.
#
# 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
set -euo pipefail
REGISTRY="${REGISTRY:-100.94.185.103:5000}"
NAMESPACE="${NAMESPACE:-clawmates}"
COMPOSE_DIR="${COMPOSE_DIR:-/opt/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"
if ! docker pull -q "$ref" >/dev/null 2>&1; then
log "pull failed: $ref"
continue
fi
# Drift check: does the running container's image ID match what
# `$ref` (the registry-prefixed :latest) now points to? Catches both
# a fresh pull AND the case where a previous roll failed after pull
# but before `up` — the tag was updated but the container wasn't.
target=$(docker inspect --format '{{.Id}}' "$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[*]}"