#!/bin/bash set -euo pipefail # ----------------------------- # CONFIG # ----------------------------- NODE_VERSION="v22.14.0" NVM_DIR="/root/.nvm" APP_NAME="erpfrontend" # PM2 process name used in ecosystem.cjs MEDIASERVER_NAME="mediaserver" # PM2 process name for media server SRC_DIR="/root/test/workspace/erp-frontend-pipeline-production" STAGE_DIR="/opt/erp-nuxt-frontend-temp" LIVE_DIR="/opt/erp-nuxt-frontend" ROLLBACK_DIR="/opt/erp-nuxt-frontend-rollback" MEDIASERVER_DIR="/opt/mediaserver" DB_FILE="push-subscriptions.db" DB_LIVE_DIR="$LIVE_DIR/data" DB_BACKUP_DIR="/opt/erp-nuxt-frontend-db-backups" ENV_SRC="$SRC_DIR/.env-prod" ENV_DST="$STAGE_DIR/.env" # ----------------------------- # NVM + NODE 22 # ----------------------------- export NVM_DIR="$NVM_DIR" # shellcheck disable=SC1090 [ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh" nvm install "$NODE_VERSION" nvm alias default "$NODE_VERSION" nvm use "$NODE_VERSION" # Ensure pm2 is installed for THIS Node version npm install -g pm2 NODE_BIN="$NVM_DIR/versions/node/$NODE_VERSION/bin/node" NPM_BIN="$NVM_DIR/versions/node/$NODE_VERSION/bin/npm" PM2_BIN="$NVM_DIR/versions/node/$NODE_VERSION/bin/pm2" echo "Using Node: $("$NODE_BIN" -v)" echo "ABI: $("$NODE_BIN" -p 'process.versions.modules')" echo "PM2: $("$PM2_BIN" -v)" # ----------------------------- # STAGE WORKSPACE # ----------------------------- mkdir -p "$STAGE_DIR" rm -rf "$STAGE_DIR"/* cp -r "$SRC_DIR"/* "$STAGE_DIR"/ cp "$ENV_SRC" "$ENV_DST" # Inject build metadata cd "$SRC_DIR" git_hash=$(git rev-parse --short HEAD || echo "unknown") current_datetime=$(date '+%d.%m.%Y %H:%M') cd "$STAGE_DIR" sed -i "s//$git_hash/g" "$ENV_DST" sed -i "s//$current_datetime/g" "$ENV_DST" export NODE_OPTIONS="--max-old-space-size=12288" # Clean install + build under Node 22 $NPM_BIN install patch-package --save-dev --ignore-scripts rm -rf node_modules package-lock.json .nuxt .output $NPM_BIN install $NPM_BIN run build # ----------------------------- # VERSION SERVICE WORKER CACHE # ----------------------------- echo "Versioning service worker cache with git hash: $git_hash" if [ -f "$STAGE_DIR/.output/public/sw-notifications.js" ]; then sed -i "s/const CACHE_NAME = 'logship-erp-v1'/const CACHE_NAME = 'logship-erp-$git_hash'/" \ "$STAGE_DIR/.output/public/sw-notifications.js" echo "Service worker cache versioned: logship-erp-$git_hash" else echo "Warning: Service worker file not found at expected location" fi # ----------------------------- # BACKUP SQLITE DB # ----------------------------- echo "Backing up SQLite database..." mkdir -p "$DB_BACKUP_DIR" if [ -f "$LIVE_DIR/data/$DB_FILE" ]; then backup_filename="push-subscriptions-$(date +%Y%m%d-%H%M%S).db" cp "$LIVE_DIR/data/$DB_FILE" "$DB_BACKUP_DIR/$backup_filename" echo "Database backed up: $DB_BACKUP_DIR/$backup_filename" # keep last 10 cd "$DB_BACKUP_DIR" ls -t push-subscriptions-*.db | tail -n +11 | xargs -r rm else echo "No existing database found - fresh deployment" fi # ----------------------------- # DEPLOY (with rollback) # ----------------------------- rm -rf "$ROLLBACK_DIR" if [ -d "$LIVE_DIR" ]; then cp -rf "$LIVE_DIR" "$ROLLBACK_DIR" fi rm -rf "$LIVE_DIR" mkdir -p "$LIVE_DIR" cp -r "$STAGE_DIR"/. "$LIVE_DIR"/ # ----------------------------- # RESTORE SQLITE DB # ----------------------------- echo "Restoring SQLite database..." mkdir -p "$DB_LIVE_DIR" if [ -f "$ROLLBACK_DIR/data/$DB_FILE" ]; then cp "$ROLLBACK_DIR/data/$DB_FILE" "$DB_LIVE_DIR"/ echo "Database restored from rollback" else echo "No previous database found - will be created on first run" fi chown -R root:root "$DB_LIVE_DIR" chmod 755 "$DB_LIVE_DIR" [ -f "$DB_LIVE_DIR/$DB_FILE" ] && chmod 644 "$DB_LIVE_DIR/$DB_FILE" # ----------------------------- # REBUILD NATIVE MODULES FOR NODE 22 # ----------------------------- cd "$LIVE_DIR/.output/server" echo "Rebuilding better-sqlite3 for Node $NODE_VERSION..." $NPM_BIN rebuild better-sqlite3 # ----------------------------- # START WITH PM2 (force Node 22) # ----------------------------- cd "$LIVE_DIR" # Kill old PM2 daemon to ensure it restarts under Node 22 $PM2_BIN kill || true # Stop old ERP frontend process if exists $PM2_BIN delete "$APP_NAME" || true # Start ERP frontend using Node 22 interpreter $PM2_BIN start ecosystem.config.cjs \ --only "$APP_NAME" \ --update-env \ --interpreter "$NODE_BIN" # Start or restart mediaserver (ensure it's running with correct config) cd "$MEDIASERVER_DIR" if $PM2_BIN describe "$MEDIASERVER_NAME" > /dev/null 2>&1; then echo "Restarting existing mediaserver..." $PM2_BIN restart "$MEDIASERVER_NAME" --update-env --interpreter "$NODE_BIN" else echo "Starting mediaserver for the first time..." $PM2_BIN start ecosystem.config.js --update-env --interpreter "$NODE_BIN" fi # Save PM2 state (both apps) $PM2_BIN save --force # Ensure PM2 resurrects at boot WITH the right PATH/NVM $PM2_BIN startup systemd -u root --hp /root # Create a systemd drop-in to guarantee Node 22 is found on boot mkdir -p /etc/systemd/system/pm2-root.service.d cat >/etc/systemd/system/pm2-root.service.d/override.conf <