name: Deploy Staging

# ─────────────────────────────────────────────────────────────────────────────
# Build + Deploy-Pipeline fuer rebreak-staging.
#
# Warum GitHub-Actions statt Server-Build:
#   - Hetzner CX23 (4 GB RAM) gerissen am 2026-05-06 das 1.5 GB Heap-Limit
#     waehrend `pnpm build` (OOM, "ineffective mark-compacts near heap limit").
#   - GitHub Actions Runner haben 7 GB RAM und sind frei (public-repo) bzw.
#     monatliches Free-Quota (private-repo).
#   - Server bleibt unangetastet -- nur Artifact-Extract + pm2 restart.
#
# Pattern (uebernommen aus trucko-monorepo .github/workflows/android.yml):
#   - SSH-Key in GitHub-Secret (HETZNER_SSH_KEY)
#   - ssh-keyscan + scp + ssh fuer Server-Side-Trigger
#   - Concurrency-Group verhindert parallele Deploys
#
# Coexistence: scripts/deploy.sh + scripts/deploy-webhook/server.mjs laufen
#   parallel auf dem Server (Failsafe). User entscheidet wann der Webhook
#   abgeschaltet wird (siehe ops/GITHUB_ACTIONS_PIPELINE.md).
# ─────────────────────────────────────────────────────────────────────────────

on:
  push:
    branches: [main]
  workflow_dispatch:

concurrency:
  group: deploy-staging
  cancel-in-progress: false  # parallele deploys queueen, nicht canceln

permissions:
  contents: read

jobs:
  # ── 1. Build auf GitHub-Runner (7 GB RAM, kein OOM-Risiko) ──────────────────
  build:
    name: Build backend (Nitro)
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0  # full history fuer migrate-detection im Server-Script

      - uses: pnpm/action-setup@v4
        # version is read from package.json's "packageManager" field (pnpm@10.23.0)

      - uses: actions/setup-node@v4
        with:
          node-version: 24.11.1  # MATCH Hetzner-Node-Version exakt
          cache: pnpm

      - name: Install dependencies
        run: pnpm install --frozen-lockfile

      - name: Build backend (prisma generate + nitro build)
        working-directory: backend
        run: pnpm build

      - name: Tar artifact
        run: tar czf backend-output.tar.gz -C backend/.output .

      - name: Upload artifact
        uses: actions/upload-artifact@v4
        with:
          name: backend-output
          path: backend-output.tar.gz
          retention-days: 7

  # ── 2. Deploy: Artifact zum Hetzner pushen + extract + pm2 restart ──────────
  deploy:
    name: Deploy zu Hetzner
    needs: build
    runs-on: ubuntu-latest
    environment: staging  # GitHub-Environment fuer Secret-Isolation
    steps:
      - name: Download artifact
        uses: actions/download-artifact@v4
        with:
          name: backend-output

      - name: Setup SSH
        env:
          SSH_PRIVATE_KEY: ${{ secrets.HETZNER_SSH_KEY }}
          SSH_HOST: ${{ vars.HETZNER_HOST }}
        run: |
          if [ -z "$SSH_PRIVATE_KEY" ] || [ -z "$SSH_HOST" ]; then
            echo "FATAL: HETZNER_SSH_KEY (secret) oder HETZNER_HOST (var) nicht gesetzt"
            exit 1
          fi
          echo "Deploying to host: $SSH_HOST"
          mkdir -p ~/.ssh
          printf '%s\n' "$SSH_PRIVATE_KEY" > ~/.ssh/id_ed25519
          chmod 600 ~/.ssh/id_ed25519
          ssh-keyscan -H "$SSH_HOST" >> ~/.ssh/known_hosts

      - name: Upload artifact zu Hetzner
        env:
          SSH_HOST: ${{ vars.HETZNER_HOST }}
          SSH_USER: ${{ vars.HETZNER_USER }}
        run: |
          scp -i ~/.ssh/id_ed25519 backend-output.tar.gz \
            "$SSH_USER@$SSH_HOST:/srv/rebreak/backend/.output-incoming.tar.gz"

      - name: Server-side deploy (extract + migrate + pm2 restart)
        env:
          SSH_HOST: ${{ vars.HETZNER_HOST }}
          SSH_USER: ${{ vars.HETZNER_USER }}
        run: |
          ssh -i ~/.ssh/id_ed25519 "$SSH_USER@$SSH_HOST" \
            'bash /srv/rebreak/scripts/deploy-from-artifact.sh'

      - name: Health-Check (HTTP 401 = Server erreichbar + auth-protected)
        run: |
          sleep 5
          STATUS=$(curl -sS -o /dev/null -w '%{http_code}' \
            https://staging.rebreak.org/api/auth/me || echo "000")
          echo "staging.rebreak.org/api/auth/me -> HTTP $STATUS"
          if [ "$STATUS" != "401" ] && [ "$STATUS" != "200" ]; then
            echo "FAIL: erwartet 401/200, bekommen $STATUS"
            exit 1
          fi
