diff --git a/scripts/websites-agent/deploy.sh b/scripts/websites-agent/deploy.sh index b0dc91a..f9e1832 100755 --- a/scripts/websites-agent/deploy.sh +++ b/scripts/websites-agent/deploy.sh @@ -10,6 +10,7 @@ fi ROOT="/var/www/sites/$SLUG" LOG="/var/log/websites/deploy-$SLUG.log" STATUS="/var/log/websites/deploy-$SLUG.status.json" +ECOSYSTEM="/var/www/sites/ecosystem.config.cjs" exec >>"$LOG" 2>&1 write_status() { @@ -78,7 +79,97 @@ fi npm ci npm run build -pm2 restart "$SLUG" --update-env || pm2 start /var/www/sites/ecosystem.config.cjs --only "$SLUG" + +# Next.js standalone: copy static assets Next does not place in standalone/, then +# point PM2 at server.js and drop the full node_modules tree. +if [[ -f .next/standalone/server.js ]]; then + echo "standalone build detected — preparing runtime bundle" + mkdir -p .next/standalone/.next + rm -rf .next/standalone/.next/static + cp -a .next/static .next/standalone/.next/static + if [[ -d public ]]; then + rm -rf .next/standalone/public + cp -a public .next/standalone/public + fi + + SLUG="$SLUG" ROOT="$ROOT" ECOSYSTEM="$ECOSYSTEM" node <<'NODE' +const fs = require('fs'); +const path = process.env.ECOSYSTEM; +const slug = process.env.SLUG; +const root = process.env.ROOT; +let cfg = { apps: [] }; +try { + delete require.cache[require.resolve(path)]; + cfg = require(path); + if (!Array.isArray(cfg.apps)) cfg.apps = []; +} catch (_) { + cfg = { apps: [] }; +} + +const app = cfg.apps.find((a) => a.name === slug); +if (!app) { + console.error('ecosystem entry missing for', slug); + process.exit(1); +} + +const port = + (app.env && Number(app.env.PORT)) || + (String(app.args || '').match(/--port\s+(\d+)/) || [])[1] || + 3005; + +app.cwd = root + '/.next/standalone'; +app.script = 'server.js'; +app.args = ''; +app.env = { + NODE_ENV: 'production', + PORT: String(port), + HOSTNAME: '127.0.0.1', +}; + +const lines = ['module.exports = {', ' apps: [']; +cfg.apps.forEach((entry, idx) => { + lines.push(' {'); + lines.push(` name: ${JSON.stringify(entry.name)},`); + lines.push(` cwd: ${JSON.stringify(entry.cwd)},`); + lines.push(` script: ${JSON.stringify(entry.script)},`); + if (entry.args) { + lines.push(` args: ${JSON.stringify(entry.args)},`); + } + lines.push(' env: {'); + lines.push(` NODE_ENV: ${JSON.stringify(entry.env.NODE_ENV)},`); + lines.push(` PORT: ${JSON.stringify(entry.env.PORT)},`); + if (entry.env.HOSTNAME) { + lines.push(` HOSTNAME: ${JSON.stringify(entry.env.HOSTNAME)},`); + } + lines.push(' },'); + lines.push(` error_file: ${JSON.stringify(entry.error_file)},`); + lines.push(` out_file: ${JSON.stringify(entry.out_file)},`); + lines.push(' time: true,'); + lines.push(idx === cfg.apps.length - 1 ? ' }' : ' },'); +}); +lines.push(' ],'); +lines.push('};'); +lines.push(''); +fs.writeFileSync(path, lines.join('\n')); +console.log('ecosystem updated for standalone:', slug, 'port', port); +NODE + + # Full delete+start so PM2 picks up new cwd/script (restart alone keeps old path). + pm2 delete "$SLUG" || true + pm2 start "$ECOSYSTEM" --only "$SLUG" + pm2 save || true + + echo "removing full node_modules (standalone runtime keeps its own minimal copy)" + rm -rf node_modules + + echo "==== $(date -u +%Y-%m-%dT%H:%M:%SZ) deploy ok (standalone): $SLUG ====" + write_status "success" "Deployed origin/$BRANCH (standalone)" + trap - ERR + exit 0 +fi + +echo "no standalone output — using next start (legacy)" +pm2 restart "$SLUG" --update-env || pm2 start "$ECOSYSTEM" --only "$SLUG" pm2 save || true echo "==== $(date -u +%Y-%m-%dT%H:%M:%SZ) deploy ok: $SLUG ===="