name: CI

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

permissions:
  contents: read

env:
  CARGO_TERM_COLOR: always
  CARGO_INCREMENTAL: 0
  SQLX_OFFLINE: true

jobs:
  lint:
    name: Lint
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
      - uses: dtolnay/rust-toolchain@631a55b12751854ce901bb631d5902ceb48146f7 # stable
        with:
          components: rustfmt, clippy
      - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2
        with:
          save-if: false
      - run: cargo fmt --all --check
      - run: cargo clippy --workspace --all-targets --locked -- -D warnings

  test:
    name: Unit Tests
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
      - uses: dtolnay/rust-toolchain@631a55b12751854ce901bb631d5902ceb48146f7 # stable
      - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2
        with:
          save-if: false
      - run: cargo test --workspace --lib --locked

  integration:
    name: Integration Tests
    runs-on: ubuntu-latest
    services:
      postgres:
        image: postgres:16
        env:
          POSTGRES_DB: proxy
          POSTGRES_USER: proxy
          POSTGRES_PASSWORD: testpass
        ports:
          - 5433:5432
        options: >-
          --health-cmd pg_isready
          --health-interval 2s
          --health-timeout 5s
          --health-retries 10
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
      - uses: dtolnay/rust-toolchain@631a55b12751854ce901bb631d5902ceb48146f7 # stable
      - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2
        with:
          save-if: false
      - run: cargo test --features integration --locked
        env:
          DATABASE_URL: postgres://proxy:testpass@127.0.0.1:5433/proxy
          TEST_DATABASE_URL: postgres://proxy:testpass@127.0.0.1:5433/proxy

  build:
    name: Build
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
      - uses: dtolnay/rust-toolchain@631a55b12751854ce901bb631d5902ceb48146f7 # stable
      - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2
        with:
          save-if: ${{ github.ref == 'refs/heads/main' }}
      - run: cargo build --workspace --release --locked

  coverage:
    name: Coverage
    runs-on: ubuntu-latest
    services:
      postgres:
        image: postgres:16
        env:
          POSTGRES_DB: proxy
          POSTGRES_USER: proxy
          POSTGRES_PASSWORD: testpass
        ports:
          - 5433:5432
        options: >-
          --health-cmd pg_isready
          --health-interval 2s
          --health-timeout 5s
          --health-retries 10
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
      - uses: dtolnay/rust-toolchain@631a55b12751854ce901bb631d5902ceb48146f7 # stable
      - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2
        with:
          save-if: false
      - name: Install cargo-tarpaulin
        run: cargo install cargo-tarpaulin --locked --version 0.32.7
      - name: Run coverage
        run: |
          cargo tarpaulin --workspace --lib --features integration \
            --out xml --out html \
            --output-dir coverage \
            --skip-clean \
            --timeout 300 \
            --locked
        env:
          DATABASE_URL: postgres://proxy:testpass@127.0.0.1:5433/proxy
          TEST_DATABASE_URL: postgres://proxy:testpass@127.0.0.1:5433/proxy
      - name: Upload coverage report
        uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4
        with:
          name: coverage-report
          path: coverage/
        if: always()

  frontend:
    name: Frontend Tests
    runs-on: ubuntu-latest
    services:
      postgres:
        image: postgres:16
        env:
          POSTGRES_DB: proxy
          POSTGRES_USER: proxy
          POSTGRES_PASSWORD: testpass
        ports:
          - 5433:5432
        options: >-
          --health-cmd pg_isready
          --health-interval 2s
          --health-timeout 5s
          --health-retries 10
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
      - uses: dtolnay/rust-toolchain@631a55b12751854ce901bb631d5902ceb48146f7 # stable
      - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2
        with:
          save-if: false
      - name: Build gateway
        run: cargo build --bin ccag-server --locked
      - name: Start gateway
        run: |
          DATABASE_URL=postgres://proxy:testpass@127.0.0.1:5433/proxy \
            ADMIN_PASSWORD_ENABLE=true \
            ./target/debug/ccag-server &
          for i in 1 2 3 4 5; do
            curl -sf http://127.0.0.1:8080/health && break || sleep 2
          done
      - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
        with:
          node-version: 20
      - name: Install Playwright
        working-directory: tests/frontend
        run: |
          npm ci
          npx playwright install chromium --with-deps
      - name: Run frontend tests
        working-directory: tests/frontend
        run: npx playwright test
        env:
          GATEWAY_URL: http://localhost:8080
      - name: Upload Playwright report
        uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4
        with:
          name: playwright-report
          path: tests/frontend/playwright-report/
        if: always()

  load-test:
    name: Load Test (Smoke)
    runs-on: ubuntu-latest
    services:
      postgres:
        image: postgres:16
        env:
          POSTGRES_DB: proxy
          POSTGRES_USER: proxy
          POSTGRES_PASSWORD: testpass
        ports:
          - 5433:5432
        options: >-
          --health-cmd pg_isready
          --health-interval 2s
          --health-timeout 5s
          --health-retries 10
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
      - uses: dtolnay/rust-toolchain@631a55b12751854ce901bb631d5902ceb48146f7 # stable
      - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2
        with:
          save-if: false
      - name: Install k6
        run: |
          sudo gpg -k
          sudo gpg --no-default-keyring --keyring /usr/share/keyrings/k6-archive-keyring.gpg --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys C5AD17C747E3415A3642D57D77C6C491D6AC1D69
          echo "deb [signed-by=/usr/share/keyrings/k6-archive-keyring.gpg] https://dl.k6.io/deb stable main" | sudo tee /etc/apt/sources.list.d/k6.list
          sudo apt-get update
          sudo apt-get install -y k6
      - name: Build gateway (mock Bedrock)
        run: cargo build --bin ccag-server --features mock-bedrock --locked
      - name: Start gateway
        run: |
          DATABASE_URL=postgres://proxy:testpass@127.0.0.1:5433/proxy \
            ADMIN_PASSWORD_ENABLE=true \
            ./target/debug/ccag-server &
          for i in 1 2 3 4 5; do
            curl -sf http://127.0.0.1:8080/health && break || sleep 2
          done
      - name: Run k6 smoke test
        run: k6 run tests/load/smoke.js
        env:
          GATEWAY_URL: http://localhost:8080

  audit:
    name: Security Audit
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
      - name: Install cargo-audit
        run: cargo install cargo-audit --locked
      - name: Run cargo-audit
        run: cargo audit --ignore RUSTSEC-2023-0071 --ignore RUSTSEC-2026-0098 --ignore RUSTSEC-2026-0099 --ignore RUSTSEC-2026-0104

  supply-chain:
    name: Supply Chain Policy
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
      - uses: EmbarkStudios/cargo-deny-action@3fd3802e88374d3fe9159b834c7714ec57d6c979 # v2.0.15
