# ─────────────────────────────────────────────────────────────────────────────
# GitHub Actions CI Pipeline – Claude Code Agent Monitor
#
# Triggers on push to main and PRs. Runs linting, tests, builds Docker
# images, and scans for security vulnerabilities.
# ─────────────────────────────────────────────────────────────────────────────
name: CI

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

permissions:
  contents: read
  packages: write
  security-events: write

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

env:
  NODE_VERSION: "22"
  REGISTRY: ghcr.io
  IMAGE_NAME: ${{ github.repository }}/agent-monitor
  MCP_IMAGE_NAME: ${{ github.repository }}/agent-monitor-mcp

jobs:
  # ── Lint & Format Check ─────────────────────────────────────────────────
  lint:
    name: Lint & Format
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: ${{ env.NODE_VERSION }}
          cache: "npm"

      - name: Install dependencies
        run: npm ci

      - name: Check formatting
        run: npm run format:check

  # ── Server Tests ────────────────────────────────────────────────────────
  test-server:
    name: Server Tests
    runs-on: ubuntu-latest
    needs: lint
    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: ${{ env.NODE_VERSION }}
          cache: "npm"

      - name: Install dependencies
        run: npm ci

      - name: Run server tests
        run: npm run test:server

  # ── Client Tests ────────────────────────────────────────────────────────
  test-client:
    name: Client Tests
    runs-on: ubuntu-latest
    needs: lint
    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: ${{ env.NODE_VERSION }}
          cache: "npm"

      - name: Install root dependencies
        run: npm ci

      - name: Install client dependencies
        run: cd client && npm ci

      - name: Run client tests
        run: npm run test:client

  # ── MCP Tests ───────────────────────────────────────────────────────────
  test-mcp:
    name: MCP Sidecar Tests
    runs-on: ubuntu-latest
    needs: lint
    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: ${{ env.NODE_VERSION }}
          cache: "npm"

      - name: Install MCP dependencies
        run: npm run mcp:install

      - name: Type check MCP
        run: npm run mcp:typecheck

      - name: Run MCP tests
        run: npm run mcp:test

  # ── Build Docker Images ────────────────────────────────────────────────
  build-image:
    name: Build Docker Images
    runs-on: ubuntu-latest
    needs: [test-server, test-client, test-mcp]
    # Only push images on main branch
    if: github.event_name == 'push' && github.ref == 'refs/heads/main'
    outputs:
      image-tag: ${{ steps.meta.outputs.version }}
      image-digest: ${{ steps.build-app.outputs.digest }}
    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3

      - name: Login to Container Registry
        uses: docker/login-action@v3
        with:
          registry: ${{ env.REGISTRY }}
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: Extract metadata (app)
        id: meta
        uses: docker/metadata-action@v5
        with:
          images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
          tags: |
            type=ref,event=branch
            type=sha,prefix=sha-
            type=raw,value=latest,enable={{is_default_branch}}
            type=semver,pattern={{version}},enable=${{ startsWith(github.ref, 'refs/tags/v') }}

      - name: Build & push app image
        id: build-app
        uses: docker/build-push-action@v5
        with:
          context: .
          file: ./Dockerfile
          push: true
          tags: ${{ steps.meta.outputs.tags }}
          labels: ${{ steps.meta.outputs.labels }}
          cache-from: type=gha
          cache-to: type=gha,mode=max
          platforms: linux/amd64,linux/arm64

      - name: Extract metadata (MCP)
        id: meta-mcp
        uses: docker/metadata-action@v5
        with:
          images: ${{ env.REGISTRY }}/${{ env.MCP_IMAGE_NAME }}
          tags: |
            type=ref,event=branch
            type=sha,prefix=sha-
            type=raw,value=latest,enable={{is_default_branch}}

      - name: Build & push MCP image
        id: build-mcp
        uses: docker/build-push-action@v5
        with:
          context: .
          file: ./mcp/Dockerfile
          push: true
          tags: ${{ steps.meta-mcp.outputs.tags }}
          labels: ${{ steps.meta-mcp.outputs.labels }}
          cache-from: type=gha
          cache-to: type=gha,mode=max
          platforms: linux/amd64,linux/arm64

  # ── Security Scan ──────────────────────────────────────────────────────
  security-scan:
    name: Security Scan
    runs-on: ubuntu-latest
    needs: build-image
    if: github.event_name == 'push' && github.ref == 'refs/heads/main'
    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Login to Container Registry
        uses: docker/login-action@v3
        with:
          registry: ${{ env.REGISTRY }}
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: Run Trivy vulnerability scanner (app)
        uses: aquasecurity/trivy-action@master
        with:
          image-ref: "${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ needs.build-image.outputs.image-tag }}"
          format: "sarif"
          output: "trivy-app-results.sarif"
          severity: "CRITICAL,HIGH"
          exit-code: "1"

      - name: Run Trivy vulnerability scanner (MCP)
        uses: aquasecurity/trivy-action@master
        with:
          image-ref: "${{ env.REGISTRY }}/${{ env.MCP_IMAGE_NAME }}:${{ needs.build-image.outputs.image-tag }}"
          format: "sarif"
          output: "trivy-mcp-results.sarif"
          severity: "CRITICAL,HIGH"
          exit-code: "1"

      - name: Upload Trivy SARIF (app)
        uses: github/codeql-action/upload-sarif@v3
        if: always()
        with:
          sarif_file: "trivy-app-results.sarif"
          category: "trivy-app"

      - name: Upload Trivy SARIF (MCP)
        uses: github/codeql-action/upload-sarif@v3
        if: always()
        with:
          sarif_file: "trivy-mcp-results.sarif"
          category: "trivy-mcp"

      - name: Run npm audit
        run: npm audit --production --audit-level=high

      - name: Trivy filesystem scan (IaC)
        uses: aquasecurity/trivy-action@master
        with:
          scan-type: "fs"
          scan-ref: "./deployments"
          format: "table"
          severity: "CRITICAL,HIGH"
          exit-code: "1"
