name: PR checks

# Enforces the contribution policy on every PR into master — plus the crewing
# stack branches (feat/crewing-*), which collect the stacked, feature-flagged
# crewing phases (foundations → requisitions → candidates → …) before they merge
# to master. Same hard gates:
#   - code changes must ship with tests (docs/config/automation are exempt)
#   - type-check is clean across the whole project (tests included)
#   - unit tests pass
#   - integration tests pass against an ephemeral Postgres (migrate + seed)
# Runs on the pms1 host runner. See automation/README.md > "Contribution policy".
#
# Note: the workflow is evaluated from the branch under test, so the trigger list
# must match it. The feat/crewing-* glob covers every branch in the stack so each
# stacked phase PR is checked without further edits to this file.

on:
  pull_request:
    branches: [master, "feat/crewing-*"]

jobs:
  checks:
    runs-on: host
    steps:
      - name: Checkout PR
        uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: Policy — code changes must include tests
        run: |
          set -uo pipefail
          base="${GITHUB_BASE_REF:-master}"
          git fetch origin "$base" --depth=200 -q
          changed=$(git diff --name-only "origin/$base...HEAD")
          printf 'Changed files:\n%s\n\n' "$changed"

          # "Code" = app source (pages, API routes, lib, components, hooks).
          # Tests, prisma, config, docs, automation and .forgejo are exempt.
          code=$(printf '%s\n' "$changed" | grep -E '^App/(app|lib|components|hooks)/' \
                   | grep -vE '(\.test\.|\.spec\.|/tests/)' || true)
          tests=$(printf '%s\n' "$changed" | grep -E '(\.test\.|\.spec\.|/tests/)' || true)

          if [ -n "$code" ] && [ -z "$tests" ]; then
            echo "::error::Code changed but no test files changed."
            echo "Every code PR must add or update tests (model: the claude/issue-12 integration test)."
            echo "If a test is genuinely not applicable, say why in the PR description so a reviewer can override."
            printf '\nCode files without accompanying tests:\n%s\n' "$code"
            exit 1
          fi
          echo "OK — test-presence policy satisfied."

      - name: Type-check (no errors)
        run: |
          set -e
          export NVM_DIR="$HOME/.nvm"; . "$NVM_DIR/nvm.sh"
          cd App
          pnpm install --frozen-lockfile
          pnpm db:generate          # prisma client types (no DB connection needed)
          pnpm type-check           # whole project, tests included — must be clean

      - name: Unit tests
        run: |
          set -e
          export NVM_DIR="$HOME/.nvm"; . "$NVM_DIR/nvm.sh"
          cd App && pnpm test       # jsdom unit tests, no DB — must pass

  integration:
    runs-on: host
    steps:
      - name: Checkout PR
        uses: actions/checkout@v4

      - name: Integration tests (ephemeral Postgres)
        run: |
          set -euo pipefail
          export NVM_DIR="$HOME/.nvm"; . "$NVM_DIR/nvm.sh"

          # Throwaway Postgres per run — isolated from prod / pelagia_test / staging.
          # A random host port avoids collisions with the host DB and concurrent runs.
          PG="ci-pg-${GITHUB_RUN_ID}-${GITHUB_RUN_ATTEMPT:-1}"
          cleanup() { docker rm -f "$PG" >/dev/null 2>&1 || true; }
          trap cleanup EXIT
          docker rm -f "$PG" >/dev/null 2>&1 || true
          docker run -d --name "$PG" \
            -e POSTGRES_USER=ci -e POSTGRES_PASSWORD=ci -e POSTGRES_DB=pelagia_ci \
            -p 127.0.0.1::5432 postgres:16 >/dev/null

          for i in $(seq 1 30); do
            docker exec "$PG" pg_isready -U ci -d pelagia_ci >/dev/null 2>&1 && break
            sleep 1
          done

          PORT=$(docker inspect --format '{{ (index (index .NetworkSettings.Ports "5432/tcp") 0).HostPort }}' "$PG")
          export DATABASE_URL="postgresql://ci:ci@127.0.0.1:${PORT}/pelagia_ci"
          # Non-secret placeholders so auth.ts (reads these at module load) boots in dev mode.
          export NEXTAUTH_SECRET="ci-secret"
          export NEXTAUTH_URL="http://localhost:3000"
          export AZURE_AD_CLIENT_ID="placeholder"
          export AZURE_AD_CLIENT_SECRET="placeholder"
          export AZURE_AD_TENANT_ID="placeholder"

          cd App
          pnpm install --frozen-lockfile
          pnpm db:generate
          pnpm db:migrate:deploy     # apply migrations to the fresh DB
          pnpm db:seed               # dev seed — integration tests rely on it
          pnpm test:integration      # node + real DB — must pass
