name: Deploy release to production

# Pushing a release tag (vX.Y.Z) deploys that tag to the portal at
# pms.pelagiamarine.com. Runs on the pms1 host runner (label: host),
# which executes as shad0w with direct access to the pm2-managed app.

on:
  push:
    tags:
      - "v*"

jobs:
  deploy:
    runs-on: host
    steps:
      - name: Deploy tag to ~/pms and restart ppms
        run: |
          set -euo pipefail
          export NVM_DIR="$HOME/.nvm"
          . "$NVM_DIR/nvm.sh"

          TAG="${GITHUB_REF_NAME}"
          echo "=== Deploying $TAG ==="

          cd "$HOME/pms"
          git fetch origin --tags --force
          git checkout -f "refs/tags/$TAG"

          cd App
          pnpm install --frozen-lockfile
          pnpm build                 # includes prisma generate
          pnpm db:migrate:deploy

          # NOT --update-env: this job runs inside the Forgejo Actions runner, whose
          # environment includes an ephemeral FORGEJO_TOKEN (the per-job token, revoked
          # when the job ends). --update-env would inject it into ppms, where it shadows
          # the real PAT from .env (Next.js does not override an already-set process.env
          # var) and breaks the Report Issue button once the job token expires. A plain
          # restart re-execs ppms from the pm2 daemon's clean env, so .env wins.
          pm2 restart ppms
          echo "=== Deployed $TAG ==="

      - name: Build & (re)start microservices
        run: |
          set -euo pipefail
          export NVM_DIR="$HOME/.nvm"
          . "$NVM_DIR/nvm.sh"

          cd "$HOME/pms"

          # ~/pms has historically been a SPARSE checkout limited to App/ (only the
          # app deployed), so the service folders + ecosystem.config.js never landed
          # on disk. Expand the working tree to the full repo, then re-materialise
          # the tag. Idempotent: a no-op once sparse is disabled / if never sparse.
          git sparse-checkout disable 2>/dev/null || true
          git config --unset core.sparseCheckout 2>/dev/null || true
          rm -f .git/info/sparse-checkout 2>/dev/null || true
          git checkout -f "refs/tags/${GITHUB_REF_NAME}"

          # Pull only the few keys the services need out of the app's .env (the
          # single source of truth on the host). Never import PORT (each service's
          # port is fixed in ecosystem.config.js) or the runner's ephemeral
          # FORGEJO_TOKEN. Missing keys → empty, which the services tolerate.
          envget() { grep -E "^$1=" App/.env 2>/dev/null | head -1 | sed -E 's/^[^=]+=//; s/^"//; s/"$//'; }
          export PDF_SERVICE_TOKEN="$(envget PDF_SERVICE_TOKEN)"
          export ALLOWED_ORIGIN="$(envget ALLOWED_ORIGIN)"
          export EPFO_LIVE="$(envget EPFO_LIVE)"

          # Build each present service (skip any not yet in the tree, e.g. before
          # its feature PR has merged). npm install (not ci) — not every service
          # carries a lockfile. Playwright's postinstall fetches the browser; the
          # explicit install is a cached, idempotent backstop.
          for svc in GstService EpfoService PdfService; do
            [ -f "$svc/package.json" ] || { echo "skip $svc (absent)"; continue; }
            echo "=== Building $svc ==="
            ( cd "$svc" && npm install --no-audit --no-fund && npx playwright install chromium && npm run build )
          done

          # Create on first release, zero-downtime reload thereafter. The
          # ecosystem registers only services whose dirs exist.
          if [ ! -f ecosystem.config.js ]; then
            echo "ERROR: ecosystem.config.js absent in $(pwd) after checkout — sparse-checkout not expanded?"
            git sparse-checkout list 2>/dev/null || true
            exit 1
          fi
          pm2 startOrReload ecosystem.config.js --update-env
          pm2 save
          pm2 list
          echo "=== Microservices up ==="

      - name: Verify services respond
        run: |
          sleep 3
          cd "$HOME/pms"
          check() {
            local dir="$1" port="$2"
            [ -f "$dir/package.json" ] || { echo "skip $dir (absent)"; return 0; }
            local code
            code=$(curl -s -o /dev/null -w "%{http_code}" "http://127.0.0.1:$port/health" || echo "000")
            echo "$dir on :$port /health → HTTP $code"
            test "$code" = "200"
          }
          check GstService 3003
          check EpfoService 3004
          check PdfService 3005

      - name: Verify portal responds
        run: |
          sleep 5
          code=$(curl -s -o /dev/null -w "%{http_code}" http://127.0.0.1:3000/login)
          echo "Portal /login returned HTTP $code"
          test "$code" = "200"
