#!/bin/bash set -euo pipefail # Check if a build package already exists if [ -f "out.zip" ]; then echo "๐Ÿ“ฆ Detected existing build package: out.zip" echo "๐Ÿ“ฆ Package size: $(du -sh out.zip | cut -f1)" echo "๐Ÿ“ Build info:" if [ -f "out/deploy-info.txt" ]; then cat out/deploy-info.txt fi echo "" echo "โš ๏ธ Choose an option:" echo " 1. Deploy existing package" echo " 2. Rebuild and deploy" echo " 3. Exit" echo "" read -p "Select (1/2/3): " -n 1 -r echo "" case $REPLY in 1) echo "๐Ÿš€ Deploying existing package..." DEPLOY_EXISTING=true ;; 2) echo "๐Ÿ”„ Rebuilding..." rm -rf out out.zip ;; 3) echo "๐Ÿ‘‹ Exit" exit 0 ;; *) echo "โŒ Invalid option, aborting" exit 1 ;; esac fi if [ "${DEPLOY_EXISTING:-}" != "true" ]; then echo "๐Ÿš€ Start local build..." # Clean previous build outputs echo "๐Ÿงน Cleaning previous build outputs..." rm -rf frontend/.next rm -rf backend/dist rm -rf out # Create output directory for packaging mkdir -p out # Build frontend echo "๐Ÿ“ฆ Building frontend..." cd frontend pnpm install pnpm build cd .. # Build backend echo "๐Ÿ“ฆ Building backend..." cd backend pnpm install pnpm build cd .. # Prepare deploy bundle echo "๐Ÿ“‹ Preparing deploy bundle..." mkdir -p out/frontend mkdir -p out/backend # Copy frontend artifacts cp -r frontend/.next out/frontend/ cp frontend/package.json out/frontend/ cp -r frontend/public out/frontend/ 2>/dev/null || true cp -r frontend/app out/frontend/ 2>/dev/null || true cp -r frontend/components out/frontend/ 2>/dev/null || true cp -r frontend/lib out/frontend/ 2>/dev/null || true cp -r frontend/styles out/frontend/ 2>/dev/null || true cp frontend/next.config.js out/frontend/ 2>/dev/null || true cp frontend/tailwind.config.ts out/frontend/ 2>/dev/null || true cp frontend/postcss.config.js out/frontend/ 2>/dev/null || true cp -r frontend/content out/frontend/ 2>/dev/null || true # Copy backend artifacts cp -r backend/dist out/backend/ cp backend/package.json out/backend/ # Write deployment info echo "๐Ÿ“ Writing deployment info..." cat > out/deploy-info.txt << EOF Build time: $(date) Git commit: $(git rev-parse --short HEAD) Git branch: $(git branch --show-current) Frontend BUILD_ID: $(cat frontend/.next/BUILD_ID 2>/dev/null || echo "N/A") EOF # Archive deploy bundle echo "๐Ÿ“ฆ Archiving deploy bundle..." cd out zip -r ../out.zip . cd .. echo "โœ… Local build and packaging completed!" echo "๐Ÿ“ฆ Package: out.zip" echo "๐Ÿ“ฆ Size: $(du -sh out.zip | cut -f1)" fi # Deploy logic if [ -f "out.zip" ]; then echo "" echo "๐Ÿš€ Detected out.zip, ready to deploy to server" echo "โš ๏ธ Deployment will:" echo " 1. Upload out.zip to server" echo " 2. Backup current version" echo " 3. Unzip and replace files" echo " 4. Restart PM2 apps" echo "" read -p "Proceed with deployment? (y/N): " -n 1 -r echo "" if [[ $REPLY =~ ^[Yy]$ ]]; then echo "๐Ÿš€ Starting deployment..." # Load deploy config file if [ -f "deploy.config" ]; then source deploy.config fi # Validate required environment variables if [ -z "$DEPLOY_SERVER" ] || [ -z "$DEPLOY_USER" ] || [ -z "$DEPLOY_PATH" ]; then echo "โŒ Missing server configuration. Please configure one of the following:" echo " 1. Copy deploy.config.example to deploy.config and edit values" echo " 2. Or set environment variables:" echo " export DEPLOY_SERVER=your-server-ip" echo " export DEPLOY_USER=root" echo " export DEPLOY_PATH=/root/PrivyDrop" exit 1 fi # Build SSH options (port/key) SSH_OPTS="" SCP_OPTS="" if [ -n "${SSH_PORT:-}" ]; then SSH_OPTS+=" -p $SSH_PORT" SCP_OPTS+=" -P $SSH_PORT" fi if [ -n "${SSH_KEY_PATH:-}" ]; then SSH_OPTS+=" -i $SSH_KEY_PATH" SCP_OPTS+=" -i $SSH_KEY_PATH" fi # Upload build package to server echo "๐Ÿ“ค Uploading package to server..." # shellcheck disable=SC2086 scp $SCP_OPTS out.zip $DEPLOY_USER@$DEPLOY_SERVER:/tmp/ # Run remote deployment (fix: ensure heredoc script actually executes) echo "๐Ÿ”ง Executing remote deployment..." # Inject DEPLOY_PATH and execute heredoc via 'bash -s' on remote host # shellcheck disable=SC2086 ssh $SSH_OPTS $DEPLOY_USER@$DEPLOY_SERVER "DEPLOY_PATH='$DEPLOY_PATH' bash -s" << 'EOF' set -euo pipefail # Create structured backup directory BACKUP_ROOT="/tmp/privydrop_backup" BACKUP_DIR="$BACKUP_ROOT/$(date +%Y%m%d_%H%M%S)" mkdir -p "$BACKUP_DIR/frontend" "$BACKUP_DIR/backend" # Backup current artifacts if present if [ -d "$DEPLOY_PATH/frontend/.next" ]; then echo "๐Ÿ“‹ Backing up current frontend build..." mv "$DEPLOY_PATH/frontend/.next" "$BACKUP_DIR/frontend/.next" fi if [ -d "$DEPLOY_PATH/backend/dist" ]; then echo "๐Ÿ“‹ Backing up current backend build..." mv "$DEPLOY_PATH/backend/dist" "$BACKUP_DIR/backend/dist" fi # Stop PM2 processes echo "โน๏ธ Stopping PM2 apps..." sudo pm2 stop all || true sudo pm2 delete all || true # Extract new version echo "๐Ÿ“‚ Extracting new version..." cd "$DEPLOY_PATH" unzip -o /tmp/out.zip rm -f /tmp/out.zip # Fix ownership sudo chown -R "$(id -un)":"$(id -gn)" "$DEPLOY_PATH/frontend/.next" 2>/dev/null || true sudo chown -R "$(id -un)":"$(id -gn)" "$DEPLOY_PATH/backend/dist" 2>/dev/null || true # Start PM2 apps echo "โ–ถ๏ธ Starting PM2 apps..." sudo pm2 start ecosystem.config.js # Wait for services to start sleep 5 # Check PM2 status echo "๐Ÿ” Checking PM2 status..." sudo pm2 status # Print version identifiers for verification if [ -f "$DEPLOY_PATH/frontend/.next/BUILD_ID" ]; then echo "๐Ÿ“ฆ Frontend BUILD_ID: $(cat "$DEPLOY_PATH/frontend/.next/BUILD_ID")" fi if [ -f "$DEPLOY_PATH/deploy-info.txt" ]; then echo "๐Ÿ“ Deploy info:" cat "$DEPLOY_PATH/deploy-info.txt" || true fi echo "โœ… Deployment completed!" echo "๐Ÿ“‹ Backup saved at: $BACKUP_DIR" EOF echo "๐ŸŽ‰ Deployment finished. Check PM2 status on server:" echo " ssh $DEPLOY_USER@$DEPLOY_SERVER 'sudo pm2 status'" else echo "โŒ Deployment canceled" fi else echo "โŒ out.zip not found" exit 1 fi