name: CI — DevOps Dashboard

on:
  push:
    branches: [main]
    paths:
      - 'backend/**'
      - 'web/**'
      - 'shared/**'
      - 'package.json'
      - 'pnpm-lock.yaml'
      - 'pnpm-workspace.yaml'
      - '.pnpmfile.cjs'
      - '.gitea/workflows/ci.yml'
  pull_request:
    paths:
      - 'backend/**'
      - 'web/**'
      - 'shared/**'
      - 'package.json'
      - 'pnpm-lock.yaml'
      - 'pnpm-workspace.yaml'
      - '.pnpmfile.cjs'
      - '.gitea/workflows/ci.yml'

concurrency:
  group: ci-devops-dashboard-${{ github.ref }}
  cancel-in-progress: true

env:
  # Self-contained CI: resolve @bytelyst/* deps from the local Gitea registry
  # rather than a sibling learning_ai_common_plat checkout on the runner.
  BYTELYST_PACKAGE_SOURCE: gitea

jobs:
  build-and-test:
    name: Build, Test & Typecheck
    runs-on: ubuntu-latest
    timeout-minutes: 15
    steps:
      # Check out into the runner workspace (${{ gitea.workspace }}) instead of
      # cd-ing into a hard-coded host path and `git reset --hard` on the live
      # checkout. CI must never mutate an operator's working tree.
      - name: Checkout
        uses: actions/checkout@v4

      - name: Set up Node
        uses: actions/setup-node@v4
        with:
          node-version: 22

      - name: Enable pnpm
        run: |
          corepack enable
          corepack prepare pnpm@10.6.5 --activate

      - name: Secret scan
        run: pnpm secret-scan

      - name: Install dependencies
        run: pnpm install:gitea

      - name: Lint
        run: pnpm lint

      - name: Typecheck
        run: pnpm typecheck

      - name: Build
        run: pnpm build

      - name: Unit tests
        run: pnpm test:run

      # Coverage gate for the backend's tested modules (auth, csrf, health,
      # hermes-ops, deployments/orchestrator, services). Thresholds live in
      # `backend/vitest.config.ts`. Add files there as they gain real tests
      # — ratchet up, never relax.
      - name: Coverage gate (backend)
        run: pnpm --filter @bytelyst/devops-backend test:coverage

      # Playwright browsers are pulled per-CI-run. The web suite (`pnpm
      # test:e2e`) starts its own Next dev server via Playwright's
      # `webServer` config; the backend is intentionally NOT started — the
      # hermes spec intercepts `/api/hermes/ops` (which would otherwise
      # need to shell out to systemctl/git/ps on a live VM) and the
      # dashboard spec mocks every other backend route via `page.route`.
      # See `docs/prompts/ci-e2e-hardening.md` for the design.
      - name: Install Playwright browsers
        run: pnpm --filter @bytelyst/devops-web exec playwright install --with-deps chromium

      - name: E2E tests
        run: pnpm --filter @bytelyst/devops-web test:e2e

  docker-build:
    name: Build Docker Images
    runs-on: ubuntu-latest
    needs: [build-and-test]
    timeout-minutes: 20
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Build backend Docker image
        run: docker build -f backend/Dockerfile -t devops-backend:latest .

      - name: Build web Docker image
        run: docker build -f web/Dockerfile -t devops-web:latest .

      - name: Test Docker Compose
        run: |
          docker compose up -d
          sleep 10
          docker compose down
