Lost terugkerende pijn op: na cross-build op Mac vergeet je makkelijk de .env mee te nemen of vanuit de juiste directory te starten, met "FAIL: ... is not set" als gevolg in pre-flight. Script doet in volgorde: 1. docker buildx build --platform linux/amd64 --load 2. docker save | gzip → scrum4me-agent-runner-amd64.tar.gz 3. scp tarball + compose + (eerste keer) .env naar NAS 4. ssh: docker load + sanity-check op .env + compose up --force-recreate 5. ssh: docker compose logs -f (Ctrl-C om te stoppen) Bestaande NAS-.env wordt niet overschreven. Eerste deploy patcht de NAS-paden via sed. Sanity-check faalt expliciet als anthropic-, SCRUM4ME_- of DATABASE_URL-vars ontbreken — ipv stille pre-flight-fail. Config via .env.deploy (zit in .gitignore). Voor eerste deploy en volledige procedure: README "Deploy — cross-build" sectie. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
112 lines
4.3 KiB
Bash
Executable file
112 lines
4.3 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
# deploy-to-nas.sh — Mac → NAS cross-build deploy in één commando.
|
|
#
|
|
# Voert in volgorde uit:
|
|
# 1. docker buildx build (linux/amd64, --load)
|
|
# 2. docker save | gzip → scrum4me-agent-runner-amd64.tar.gz
|
|
# 3. scp tarball + docker-compose.yml + (eerste keer) .env naar NAS
|
|
# 4. ssh: docker load + sed-patch .env paths (eerste keer) + compose up --force-recreate
|
|
# 5. ssh: docker compose logs -f voor verificatie
|
|
#
|
|
# Gebruik:
|
|
# bin/deploy-to-nas.sh # gebruikt env vars uit .env.deploy
|
|
# NAS_HOST=admin@nas bin/deploy-to-nas.sh
|
|
#
|
|
# Vereisten:
|
|
# - docker buildx geïnstalleerd
|
|
# - .env aanwezig in repo-root (deze wordt naar NAS gestuurd op eerste run)
|
|
# - .env.deploy met NAS_HOST + NAS_REMOTE_DIR (optioneel — anders prompted)
|
|
# - SSH-key access naar de NAS (geen password-prompts)
|
|
|
|
set -euo pipefail
|
|
|
|
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
cd "$REPO_ROOT"
|
|
|
|
# ----- config -----------------------------------------------------------
|
|
if [[ -f .env.deploy ]]; then
|
|
# shellcheck disable=SC1091
|
|
source .env.deploy
|
|
fi
|
|
|
|
: "${NAS_HOST:?NAS_HOST not set — bv. admin@nas.local. Zet 'm in .env.deploy of als env-var.}"
|
|
: "${NAS_REMOTE_DIR:=/share/Agent/scrum4me-agent-runner}"
|
|
: "${IMAGE_TAG:=scrum4me-agent-runner:local}"
|
|
: "${TARBALL:=scrum4me-agent-runner-amd64.tar.gz}"
|
|
: "${MCP_GIT_REF:=main}"
|
|
: "${CLAUDE_CODE_VERSION:=latest}"
|
|
: "${AGENT_UID:=1000}"
|
|
: "${AGENT_GID:=1000}"
|
|
|
|
log() { echo "[deploy-to-nas] $*"; }
|
|
|
|
# ----- pre-flight -------------------------------------------------------
|
|
if [[ ! -f .env ]]; then
|
|
log "FAIL: .env ontbreekt in repo-root. Maak 'm aan via: cp .env.example .env"
|
|
exit 1
|
|
fi
|
|
|
|
# ----- 1. buildx --------------------------------------------------------
|
|
log "1/5 docker buildx build (linux/amd64, MCP_GIT_REF=$MCP_GIT_REF)"
|
|
docker buildx build \
|
|
--platform linux/amd64 \
|
|
--build-arg "MCP_GIT_REF=${MCP_GIT_REF}" \
|
|
--build-arg "CLAUDE_CODE_VERSION=${CLAUDE_CODE_VERSION}" \
|
|
--build-arg "AGENT_UID=${AGENT_UID}" \
|
|
--build-arg "AGENT_GID=${AGENT_GID}" \
|
|
-t "$IMAGE_TAG" \
|
|
--load \
|
|
.
|
|
|
|
# ----- 2. tarball -------------------------------------------------------
|
|
log "2/5 docker save | gzip → $TARBALL"
|
|
docker save "$IMAGE_TAG" | gzip > "$TARBALL"
|
|
ls -lh "$TARBALL"
|
|
|
|
# ----- 3. scp -----------------------------------------------------------
|
|
log "3/5 scp tarball + compose naar $NAS_HOST:$NAS_REMOTE_DIR"
|
|
ssh "$NAS_HOST" "mkdir -p '$NAS_REMOTE_DIR'"
|
|
|
|
# Check of er al een .env op de NAS staat. Zo niet: stuur de Mac-versie en
|
|
# patch hem. Zo wel: laat 'm met rust (kan NAS-specifiek aangepast zijn).
|
|
if ssh "$NAS_HOST" "test -f '$NAS_REMOTE_DIR/.env'" 2>/dev/null; then
|
|
log " (.env bestaat al op NAS — niet overschreven)"
|
|
else
|
|
log " geen .env op NAS, kopiëren + patchen"
|
|
scp .env "$NAS_HOST:$NAS_REMOTE_DIR/.env"
|
|
ssh "$NAS_HOST" "
|
|
cd '$NAS_REMOTE_DIR'
|
|
chmod 600 .env
|
|
sed -i \\
|
|
-e 's|^NAS_BASE=.*|NAS_BASE=/share/Agent|' \\
|
|
-e 's|^AGENT_BASE=.*|AGENT_BASE=/share/Agent|' \\
|
|
-e 's|^AGENT_PLATFORM=.*|AGENT_PLATFORM=linux/amd64|' \\
|
|
-e 's|^AGENT_UID=.*|AGENT_UID=${AGENT_UID}|' \\
|
|
-e 's|^AGENT_GID=.*|AGENT_GID=${AGENT_GID}|' \\
|
|
-e 's|^AGENT_HEALTH_PORT_HOST=.*|AGENT_HEALTH_PORT_HOST=18080|' \\
|
|
.env
|
|
"
|
|
fi
|
|
|
|
scp "$TARBALL" docker-compose.yml package.json README.md \
|
|
"$NAS_HOST:$NAS_REMOTE_DIR/"
|
|
|
|
# ----- 4. load + restart ------------------------------------------------
|
|
log "4/5 docker load + compose up --force-recreate op NAS"
|
|
ssh "$NAS_HOST" "
|
|
set -eu
|
|
source /etc/profile
|
|
cd '$NAS_REMOTE_DIR'
|
|
|
|
# Sanity: env-vars die check-tokens.sh nodig heeft
|
|
grep -qE '^(CLAUDE_CODE_OAUTH_TOKEN|ANTHROPIC_API_KEY)=' .env || { echo 'FAIL: anthropic credential ontbreekt in .env'; exit 1; }
|
|
grep -qE '^SCRUM4ME_TOKEN=' .env || { echo 'FAIL: SCRUM4ME_TOKEN ontbreekt in .env'; exit 1; }
|
|
grep -qE '^DATABASE_URL=' .env || { echo 'FAIL: DATABASE_URL ontbreekt in .env'; exit 1; }
|
|
|
|
gunzip -c '$TARBALL' | docker load
|
|
docker compose up -d --force-recreate
|
|
"
|
|
|
|
# ----- 5. tail logs ------------------------------------------------------
|
|
log "5/5 docker compose logs (Ctrl-C om te stoppen)"
|
|
ssh "$NAS_HOST" "cd '$NAS_REMOTE_DIR' && docker compose logs -f --tail=50"
|