#!/usr/bin/env bash # ============================================================================= # /opt/timmy-tower/deploy.sh # Pull latest from Hermes Gitea, build, deploy, health-check, rollback on fail. # Invoked by the webhook receiver (webhook.js) or manually by an operator. # ============================================================================= set -euo pipefail DEPLOY_DIR="/opt/timmy-tower" WORK_DIR="/tmp/timmy-deploy-$$" LOG="$DEPLOY_DIR/deploy.log" TOKEN_FILE="/root/.gitea-replit-token" GITEA_HOST="143.198.27.163:3000" GITEA_REPO="replit/timmy-tower" HEALTH_URL="http://localhost:8088/api/healthz" log() { echo "[$(date -u +%FT%TZ)] [deploy] $*" | tee -a "$LOG"; } fail() { log "ERROR: $*"; exit 1; } log "========================================" log "Deploy started" # ── 1. Backup current bundle ────────────────────────────────────────────────── if [ -f "$DEPLOY_DIR/index.js" ]; then cp "$DEPLOY_DIR/index.js" "$DEPLOY_DIR/index.js.bak" log "Previous bundle backed up → index.js.bak" fi # ── 2. Clone repo from Hermes Gitea ────────────────────────────────────────── TOKEN=$(tr -d '[:space:]' < "$TOKEN_FILE") log "Cloning repo from Hermes Gitea..." git clone --depth=1 \ "http://replit:${TOKEN}@${GITEA_HOST}/${GITEA_REPO}.git" \ "$WORK_DIR" 2>&1 | tail -3 | tee -a "$LOG" # ── 3. Install deps + build ─────────────────────────────────────────────────── cd "$WORK_DIR" log "Ensuring pnpm is available..." if ! command -v pnpm &>/dev/null; then corepack enable corepack prepare pnpm@latest --activate fi log "Installing dependencies..." pnpm install --frozen-lockfile 2>&1 | tail -5 | tee -a "$LOG" \ || fail "pnpm install failed" log "Building api-server..." pnpm --filter @workspace/api-server run build 2>&1 | tail -15 | tee -a "$LOG" \ || fail "build failed" # ── 4. Deploy bundle ────────────────────────────────────────────────────────── BUNDLE="$WORK_DIR/artifacts/api-server/dist/index.js" [ -f "$BUNDLE" ] || fail "Bundle not found at $BUNDLE after build" cp "$BUNDLE" "$DEPLOY_DIR/index.js" log "Bundle deployed." # ── 5. Restart service ──────────────────────────────────────────────────────── log "Restarting timmy-tower..." systemctl restart timmy-tower sleep 6 # ── 6. Health check — rollback on failure ──────────────────────────────────── if curl -sf --max-time 15 "$HEALTH_URL" > /dev/null; then log "Health check passed ✓" else log "Health check FAILED — rolling back" if [ -f "$DEPLOY_DIR/index.js.bak" ]; then cp "$DEPLOY_DIR/index.js.bak" "$DEPLOY_DIR/index.js" systemctl restart timmy-tower log "Rollback complete. Previous bundle restored." else log "No backup available — service may be down" fi cd /; rm -rf "$WORK_DIR" exit 1 fi # ── 7. Cleanup ──────────────────────────────────────────────────────────────── cd / rm -rf "$WORK_DIR" log "Deploy complete" log "========================================"