Merge pull request #9 from madhura68/feat/deploy-script
feat(deploy): bin/deploy-to-nas.sh — één-commando Mac→NAS redeploy
This commit is contained in:
commit
3e3d0e5b10
4 changed files with 157 additions and 0 deletions
16
.env.deploy.example
Normal file
16
.env.deploy.example
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
# .env.deploy — config voor bin/deploy-to-nas.sh
|
||||||
|
# Kopieer naar .env.deploy en pas aan; staat in .gitignore.
|
||||||
|
|
||||||
|
# SSH-target voor de NAS. Moet werkend zijn met SSH-key (geen password).
|
||||||
|
NAS_HOST=admin@nas.local
|
||||||
|
|
||||||
|
# Pad op de NAS waar tarball + compose + .env terechtkomen.
|
||||||
|
# Default: /share/Agent/scrum4me-agent-runner
|
||||||
|
# NAS_REMOTE_DIR=/share/Agent/scrum4me-agent-runner
|
||||||
|
|
||||||
|
# Build-args (overrides). Standaard:
|
||||||
|
# MCP_GIT_REF=main — pin een commit in productie indien gewenst
|
||||||
|
# CLAUDE_CODE_VERSION=latest — pin een claude-code release indien gewenst
|
||||||
|
# AGENT_UID=1000, AGENT_GID=1000
|
||||||
|
# MCP_GIT_REF=main
|
||||||
|
# CLAUDE_CODE_VERSION=latest
|
||||||
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -1,5 +1,6 @@
|
||||||
# Secrets
|
# Secrets
|
||||||
.env
|
.env
|
||||||
|
.env.deploy
|
||||||
*.env.local
|
*.env.local
|
||||||
|
|
||||||
# Local dev overrides (niet committen, per ontwikkelaar)
|
# Local dev overrides (niet committen, per ontwikkelaar)
|
||||||
|
|
|
||||||
28
README.md
28
README.md
|
|
@ -117,6 +117,34 @@ docker compose logs -f
|
||||||
> mapt deze stack standaard `18080:8080`. Override via
|
> mapt deze stack standaard `18080:8080`. Override via
|
||||||
> `AGENT_HEALTH_PORT_HOST` in `.env` als je een andere host-poort wilt.
|
> `AGENT_HEALTH_PORT_HOST` in `.env` als je een andere host-poort wilt.
|
||||||
|
|
||||||
|
## Snelle redeploy — `bin/deploy-to-nas.sh`
|
||||||
|
|
||||||
|
Voor een **bestaande deploy** die je opnieuw wil bouwen + deployen
|
||||||
|
(bijvoorbeeld na een merge in `scrum4me-mcp` of een aanpassing aan
|
||||||
|
`CLAUDE.md`):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Eenmalig: NAS-target instellen
|
||||||
|
cp .env.deploy.example .env.deploy
|
||||||
|
vi .env.deploy # zet NAS_HOST=admin@<nas>
|
||||||
|
|
||||||
|
# Daarna: één commando voor de hele cyclus
|
||||||
|
bin/deploy-to-nas.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
Het script doet:
|
||||||
|
|
||||||
|
1. `docker buildx build --platform linux/amd64 --load`
|
||||||
|
2. `docker save | gzip → scrum4me-agent-runner-amd64.tar.gz`
|
||||||
|
3. `scp` van tarball + `docker-compose.yml` + (eerste keer) `.env` naar NAS
|
||||||
|
4. `ssh` op NAS: `docker load` + sanity-check op `.env` + `docker compose up -d --force-recreate`
|
||||||
|
5. `docker compose logs -f` — lokaal-volgbaar terwijl pre-flight + eerste batch starten
|
||||||
|
|
||||||
|
`.env` op de NAS wordt **niet** overschreven als 'ie er al staat. Bij een
|
||||||
|
verse NAS-installatie wordt 'ie wél geüpload + ge-sed't (NAS_BASE,
|
||||||
|
AGENT_UID, etc.). Voor de **eerste deploy** of een schoon volume zie de
|
||||||
|
volledige procedure hieronder.
|
||||||
|
|
||||||
## Deploy — cross-build vanaf Mac (Apple Silicon → amd64-NAS)
|
## Deploy — cross-build vanaf Mac (Apple Silicon → amd64-NAS)
|
||||||
|
|
||||||
Alternatief voor de in-place build hierboven. Bouw de image op je Mac voor
|
Alternatief voor de in-place build hierboven. Bouw de image op je Mac voor
|
||||||
|
|
|
||||||
112
bin/deploy-to-nas.sh
Executable file
112
bin/deploy-to-nas.sh
Executable file
|
|
@ -0,0 +1,112 @@
|
||||||
|
#!/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"
|
||||||
Loading…
Add table
Add a link
Reference in a new issue