| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110 |
- #!/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"
|