Files
clawmates/scripts/deploy.sh
T
Omar SobhandClaude Opus 4.8 1072ec159a
ci / gates (push) Failing after 13s
ci / rust (push) Has been skipped
ci / sandbox-k8s (push) Has been skipped
ci / frontend (push) Has been skipped
ci / e2e (push) Has been skipped
Terminals: unify on a shared resilient-terminal core + deploy script for agent images
- frontend/.../terminal/core.ts: `useResilientTerminal` owns the xterm lifecycle
  (init, fit, debounced resize, reconnect, refit-on-visible) with a pluggable
  transport. Two connectors: `wsConnector` (agent terminal → container PTY over WS)
  and `nodeWebrtcConnector` (node terminal → host PTY, direct WebRTC DataChannel
  with WS-relay fallback, input buffered during the race). The agent terminal now
  gets the node terminal's robust reconnect for free; both share one xterm setup.
- TerminalApp (agent) + NodeTerminalApp (node) reduced to thin wrappers over the
  core — net ~330 lines of duplicated transport/reconnect/xterm code removed.
- scripts/deploy.sh: the deploys were manual, so the locally-built agent images
  (agent-base/browser/terminal — not in any registry) were never shipped and 404'd
  on provision. The script always (re)builds + loads them onto gw-04 AND every
  fleet node, with a skip-if-identical guard so unchanged images aren't re-transferred.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
2026-06-26 07:55:43 -07:00

80 lines
3.4 KiB
Bash
Executable File

#!/usr/bin/env bash
# Deploy ClawMates: build the server, frontend, node daemon, AND the agent runtime
# images on the build host (tank), then load + recreate on the gateway. The agent
# images (agent-base / agent-browser / agent-terminal) are locally-built dev images
# — not in any registry — so a `docker pull` can't fetch them. This script loads
# them onto the gateway AND every fleet node, so agent/terminal containers never
# 404 with "No such image" (the failure mode this script exists to prevent).
#
# Usage: scripts/deploy.sh # full deploy
# IMAGES_ONLY=1 scripts/deploy.sh # just (re)build + load the agent images
#
# Override hosts via env: BUILD_HOST, GW, NODES, TAG.
set -euo pipefail
BUILD_HOST=${BUILD_HOST:-osobh@tank} # builds the images + the linux daemon
GW=${GW:-gw-04} # the gateway (server + frontend + postgres)
NODES=${NODES:-"morpheus osobh@tank"} # fleet nodes that provision agent containers
TAG=${TAG:-latest}
AGENT_IMAGES=(agent-base agent-browser agent-terminal)
load() { ssh "$BUILD_HOST" "docker save $1" | ssh "$2" "docker load"; }
# Load only if the target lacks the exact image (skips re-transferring unchanged
# multi-hundred-MB agent images to every node on each code deploy).
load_if_changed() {
local lid rid
lid=$(ssh "$BUILD_HOST" "docker image inspect -f '{{.Id}}' $1 2>/dev/null" || true)
rid=$(ssh "$2" "docker image inspect -f '{{.Id}}' $1 2>/dev/null" || true)
if [ -n "$lid" ] && [ "$lid" = "$rid" ]; then
echo " (unchanged — skip)"
return 0
fi
load "$1" "$2"
}
echo "→ sync to $BUILD_HOST"
rsync -az --delete --exclude target/ --exclude node_modules/ --exclude .git/ \
--exclude '.next/' --exclude 'frontend/public/dl/' --exclude '**/.DS_Store' \
./ "$BUILD_HOST":~/clawmates/
if [ -z "${IMAGES_ONLY:-}" ]; then
echo "→ build server + frontend + daemon on $BUILD_HOST"
ssh "$BUILD_HOST" 'set -e; cd ~/clawmates
export PATH=$HOME/.cargo/bin:$PATH CARGO_NET_GIT_FETCH_WITH_CLI=true SQLX_OFFLINE=true
cargo build --release -p clawmates-node
cp target/release/clawmates-node frontend/public/dl/clawmates-node-linux-amd64
docker build -f images/server.Dockerfile -t clawmates/server:'"$TAG"' .
docker build -f images/frontend.Dockerfile -t clawmates/frontend:'"$TAG"' .'
fi
echo "→ build agent runtime images on $BUILD_HOST"
ssh "$BUILD_HOST" 'set -e; cd ~/clawmates
for i in '"${AGENT_IMAGES[*]}"'; do
docker build -f images/$i/Dockerfile -t clawmates/$i:dev images/$i/
done'
if [ -z "${IMAGES_ONLY:-}" ]; then
echo "→ load + recreate server + frontend on $GW"
ssh "$GW" "docker tag clawmates/server:$TAG clawmates/server:rollback 2>/dev/null || true
docker tag clawmates/frontend:$TAG clawmates/frontend:rollback 2>/dev/null || true"
load "clawmates/server:$TAG" "$GW"
load "clawmates/frontend:$TAG" "$GW"
fi
echo "→ load agent runtime images onto $GW + every fleet node"
for img in "${AGENT_IMAGES[@]}"; do
for host in "$GW" $NODES; do
printf ' %-26s → %s\n' "clawmates/$img:dev" "$host"
load_if_changed "clawmates/$img:dev" "$host"
done
done
if [ -z "${IMAGES_ONLY:-}" ]; then
echo "→ recreate server + frontend"
ssh "$GW" "cd /root/clawmates && docker-compose -p clawmates up -d --force-recreate server frontend"
sleep 6
curl -s -o /dev/null -w "edge HTTP %{http_code}\n" -m 10 https://clawmates.work/ || true
fi
echo "✓ deploy complete"