Files
BizGaze_Remote/deploy.sh
T

111 lines
3.8 KiB
Bash
Executable File

#!/usr/bin/env bash
#
# deploy.sh — run this ON THE SERVER, from inside the cloned repo
# (the app lives at /opt/bizgaze-support).
#
# What it does:
# 1. Snapshots the current working tree (code + .env + certs, excluding .git)
# into a rotating backup, keeping the newest $KEEP_BACKUPS.
# 2. Pulls the latest commit of $GIT_BRANCH (git reset --hard, so the box
# always matches origin exactly).
# 3. Rebuilds the image and recreates the container. The named data volume
# (data.db) persists; the untracked .env / server/cert.pem / server/key.pem
# are gitignored and therefore preserved across every pull.
# 4. Verifies the app is serving.
#
# Usage (on the server):
# cd /opt/bizgaze-support
# ./deploy.sh # pull latest + rebuild
# ./deploy.sh --no-pull # rebuild current checkout (no git pull)
# ./deploy.sh --rollback # restore newest backup snapshot + rebuild
#
# Fire it from your laptop without logging in:
# plink -ssh -P 61 -pw '<pw>' root@118.95.33.89 \
# "cd /opt/bizgaze-support && ./deploy.sh"
set -euo pipefail
GIT_BRANCH="${GIT_BRANCH:-master}"
KEEP_BACKUPS="${KEEP_BACKUPS:-3}"
CONTAINER="${CONTAINER:-bizgaze-support}"
cd "$(dirname "$(readlink -f "$0")")"
APP_DIR="$(pwd)"
BK_DIR="${APP_DIR}.backups"
log() { printf '\033[1;36m==>\033[0m %s\n' "$*"; }
ok() { printf '\033[1;32m ✓\033[0m %s\n' "$*"; }
warn(){ printf '\033[1;33m ! %s\033[0m\n' "$*"; }
die() { printf '\033[1;31mERROR:\033[0m %s\n' "$*" >&2; exit 1; }
[ -d .git ] || die "Not a git checkout. Run the one-time bootstrap first (see DEPLOY.md)."
command -v docker >/dev/null || die "docker not found on this host."
# --- args ---
DO_PULL=1; ROLLBACK=0
for a in "$@"; do case "$a" in
--no-pull) DO_PULL=0 ;;
--rollback) ROLLBACK=1 ;;
-h|--help) grep '^#' "$0" | sed 's/^# \{0,1\}//'; exit 0 ;;
*) die "Unknown argument: $a" ;;
esac; done
snapshot() {
mkdir -p "$BK_DIR"
local ts rev
ts="$(date +%Y%m%d-%H%M%S)"
rev="$(git rev-parse --short HEAD 2>/dev/null || echo nogit)"
log "Snapshot -> $BK_DIR/${ts}-${rev}.tgz"
tar --exclude=./.git --exclude=./node_modules \
--exclude=./server/node_modules -czf "$BK_DIR/${ts}-${rev}.tgz" -C "$APP_DIR" .
# rotate: keep newest $KEEP_BACKUPS
local old
old="$(ls -1t "$BK_DIR"/*.tgz 2>/dev/null | tail -n +$((KEEP_BACKUPS + 1)) || true)"
if [ -n "$old" ]; then
echo "Pruning old backups:"; echo "$old" | sed 's/^/ rm /'
echo "$old" | xargs -r rm -f
fi
}
rebuild() {
[ -f .env ] || warn "No .env present — TURN/SSO secrets will be unset."
log "Rebuilding and recreating the container …"
docker compose config >/dev/null || die "docker-compose.yml is invalid."
docker compose up -d --build
docker compose ps
}
verify() {
log "Verifying /api/ice …"
if docker exec "$CONTAINER" wget -qO- http://localhost:8090/api/ice 2>/dev/null | grep -q iceServers; then
ok "App is serving."
else
warn "Could not confirm /api/ice — check: docker logs $CONTAINER"
fi
}
# --- rollback mode ---
if [ "$ROLLBACK" -eq 1 ]; then
latest="$(ls -1t "$BK_DIR"/*.tgz 2>/dev/null | head -n1 || true)"
[ -n "$latest" ] || die "No backups found in $BK_DIR"
log "Rolling back from: $latest"
snapshot # snapshot the (broken) current state first
tar -xzf "$latest" -C "$APP_DIR"
rebuild; verify
ok "Rolled back to $latest"
exit 0
fi
# --- normal deploy ---
snapshot
if [ "$DO_PULL" -eq 1 ]; then
log "Fetching origin/$GIT_BRANCH …"
git fetch origin "$GIT_BRANCH"
git reset --hard "origin/$GIT_BRANCH" # untracked .env / *.pem are preserved
ok "Now at $(git rev-parse --short HEAD): $(git log -1 --pretty=%s)"
fi
rebuild
verify
ok "Deploy complete. Backups kept: $KEEP_BACKUPS (in $BK_DIR)."
echo " Rollback with: ./deploy.sh --rollback"