name: Server CI

on:
  push:
    branches: [main]
    paths:
      - server/**
      - protocol/**
      - clients/apple/OppiCore/Models/**
      - .github/workflows/server.yml
  pull_request:

permissions:
  contents: read

concurrency:
  group: server-ci-${{ github.event_name }}-${{ github.ref }}
  cancel-in-progress: true

jobs:
  changes:
    name: Detect server changes
    runs-on: ubuntu-latest
    outputs:
      relevant: ${{ steps.filter.outputs.relevant }}
    steps:
      - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
      - uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
        id: filter
        with:
          filters: |
            relevant:
              - 'server/**'
              - 'protocol/**'
              - 'clients/apple/OppiCore/Models/**'
              - '.github/workflows/server.yml'

  server:
    name: Server coverage
    needs: changes
    if: needs.changes.outputs.relevant == 'true'
    runs-on: ubuntu-latest
    timeout-minutes: 20
    defaults:
      run:
        shell: bash
        working-directory: server
    steps:
      - name: Checkout
        uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
        with:
          fetch-depth: 0

      - name: Setup Node.js
        uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
        with:
          node-version: 24.15.0
          cache: npm
          cache-dependency-path: server/package-lock.json

      - name: Setup Bun
        uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
        with:
          bun-version: 1.3.11

      - name: Install ripgrep
        run: sudo apt-get update && sudo apt-get install --yes ripgrep

      - name: Install dependencies
        run: npm ci

      - name: Static checks
        run: npm run check

      - name: Run server coverage gate
        # Docker/OMLX E2E lives in separate `test:e2e*` scripts and is excluded
        # by server/vitest.config.ts. Vitest enforces the repository thresholds.
        run: npm run test:coverage -- --reporter=dot --silent=passed-only

      - name: Upload server coverage
        if: always()
        uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
        with:
          name: server-coverage-${{ github.run_id }}
          if-no-files-found: warn
          retention-days: 7
          path: server/coverage/coverage-summary.json

  required:
    name: Server CI required
    needs: [changes, server]
    if: always()
    runs-on: ubuntu-latest
    steps:
      - name: Enforce relevant coverage result
        env:
          CHANGES_RESULT: ${{ needs.changes.result }}
          RELEVANT: ${{ needs.changes.outputs.relevant }}
          RESULT: ${{ needs.server.result }}
        run: |
          if [[ "$CHANGES_RESULT" != "success" || ! "$RELEVANT" =~ ^(true|false)$ ]]; then
            echo "Server path detection failed (result=$CHANGES_RESULT, relevant=$RELEVANT)." >&2
            exit 1
          fi
          if [[ "$RELEVANT" == "true" && "$RESULT" != "success" ]]; then
            echo "Server coverage was required but finished with: $RESULT" >&2
            exit 1
          fi
          echo "Server coverage requirement satisfied (relevant=$RELEVANT, result=$RESULT)."
