name: Deploy to Production run-name: 🚀 Deploy ${{ github.event.repository.name }} ${{ github.ref_name }} on: workflow_call: push: tags: - "v*" workflow_dispatch: jobs: deploy: runs-on: ubuntu-latest env: VAR_APP_NAME: ${{ vars.VAR_APP_NAME }} steps: - name: 📥 Checkout uses: actions/checkout@v4 - name: 🟢 Setup Node 20 + Cache uses: actions/setup-node@v4 with: node-version: 20 cache: "npm" cache-dependency-path: web/package-lock.json - name: 📦 Install dependencies working-directory: web run: npm ci --include=dev - name: Create Env uses: jakubcieslik99/secrets-vars-to-env-file-action@main with: secrets: ${{ toJSON(secrets) }} vars: ${{ toJSON(vars) }} generate-file: "web/.env" - name: 🏗️ Build Next.js (Standalone) working-directory: web run: | npm run build test -d .next/standalone || (echo "Standalone build missing" && exit 1) test -d .next/static || (echo "Static assets missing" && exit 1) - name: 🚀 Deploy (Atomic Release) run: | set -e DEPLOY_BASE="/var/www/${VAR_APP_NAME}" RELEASE_DIR="$DEPLOY_BASE/releases/$(date +%Y%m%d%H%M%S)" CURRENT_LINK="$DEPLOY_BASE/current" mkdir -p "$RELEASE_DIR" cp -r web/.next/standalone/. "$RELEASE_DIR/" mkdir -p "$RELEASE_DIR/.next/static" cp -r web/.next/static/. "$RELEASE_DIR/.next/static/" if [ -d "web/public" ]; then cp -r web/public "$RELEASE_DIR/" fi cp web/.env "$RELEASE_DIR/" SHARED_LOGS="$DEPLOY_BASE/shared/logs" mkdir -p "$SHARED_LOGS" ln -sfn "$RELEASE_DIR" "$CURRENT_LINK" - name: 🔄 Reload PM2 run: | set -e echo "Restarting $VAR_APP_NAME" sudo -u ansible pm2 restart "$VAR_APP_NAME" sudo -u ansible pm2 save