ci: ensure ubuntu ownership before writing env and starting pm2 #165
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: 🚀 Build & Deploy | |
| on: | |
| push: | |
| branches: [ main ] | |
| workflow_dispatch: | |
| concurrency: | |
| group: production_deploy | |
| cancel-in-progress: false | |
| jobs: | |
| deploy: | |
| runs-on: [self-hosted, linux, x64] | |
| environment: | |
| name: production | |
| steps: | |
| - name: 📥 Checkout repository | |
| uses: actions/checkout@v4 | |
| - name: 🟩 Set up Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: '20' | |
| - name: 📦 Install pnpm | |
| run: npm install -g pnpm@latest-10 | |
| - name: 📥 Install dependencies | |
| # On self-hosted, this is lightning fast because the store is local | |
| run: pnpm install --frozen-lockfile | |
| - name: 🧪 Run backend tests | |
| run: | | |
| echo "🧪 Running backend test suite with coverage..." | |
| COVERAGE_REPORTERS=text pnpm --filter backend test:coverage | |
| echo "✅ All backend tests passed with coverage!" | |
| continue-on-error: false | |
| - name: 🏗️ Build frontend | |
| run: pnpm build:frontend | |
| env: | |
| VITE_TURNSTILE_SITE_KEY: ${{ secrets.VITE_TURNSTILE_SITE_KEY }} | |
| - name: 🚀 Deploy backend | |
| run: | | |
| BACKEND_PATH="${{ secrets.BACKEND_PATH }}" | |
| echo "📤 Copying backend files to $BACKEND_PATH ..." | |
| # 1. Ensure directory exists and is owned by ubuntu | |
| mkdir -p "$BACKEND_PATH" | |
| chown -R ubuntu:ubuntu "$BACKEND_PATH" | |
| # 2. Sync files | |
| rsync -az --delete --exclude 'node_modules' --exclude '.git' backend/ "$BACKEND_PATH/" | |
| echo "🔑 Setting up environment variables..." | |
| # 3. Create .env as the ubuntu user directly | |
| sudo -u ubuntu bash -c "cat > '$BACKEND_PATH/.env' << ENVEOF | |
| GEMINI_API_KEY=${{ secrets.GEMINI_API_KEY }} | |
| TURNSTILE_SECRET_KEY=${{ secrets.TURNSTILE_SECRET_KEY }} | |
| PORT=5000 | |
| NODE_ENV=production | |
| ENVEOF" | |
| sudo -u ubuntu chmod 600 "$BACKEND_PATH/.env" | |
| echo "🚀 Starting backend with PM2..." | |
| cd "$BACKEND_PATH" | |
| # 4. Run everything else as ubuntu | |
| sudo -u ubuntu pnpm install --prod | |
| sudo -u ubuntu pm2 restart "stackconverter-backend" --update-env || sudo -u ubuntu pm2 start index.js --name "stackconverter-backend" | |
| sudo -u ubuntu pm2 save | |
| - name: 🚀 Deploy frontend | |
| run: | | |
| FRONTEND_PATH="${{ secrets.FRONTEND_PATH }}" | |
| echo "📤 Copying frontend build to $FRONTEND_PATH ..." | |
| mkdir -p "$FRONTEND_PATH" | |
| rsync -az --delete frontend/dist/ "$FRONTEND_PATH/" | |
| - name: ✅ Run health check | |
| run: | | |
| echo "🔍 Checking PM2 status and backend health..." | |
| # Check the list specifically for the ubuntu user | |
| sudo -u ubuntu pm2 status | grep stackconverter-backend | |
| sleep 5 | |
| curl -s http://localhost:5000/ > /dev/null && echo "✅ Backend healthy" || (echo "❌ Backend not responding" && exit 1) | |
| echo "🎉 Deployment Summary:" | |
| echo "✅ Frontend: https://amiroff.org/stackconverter/" | |
| echo "✅ Backend: http://localhost:5000" | |
| echo "✅ PM2 managing backend process" | |
| echo "✅ Environment variables configured" | |
| echo "" | |
| echo "Check PM2 logs: pm2 logs stackconverter-backend" | |
| echo "Monitor with: pm2 monit" |