name: CI

on:
  push:
    branches:
        - main
        - dev
        - "feat/**"
        - "fix/**"
  pull_request:
    branches: [ "main", "dev" ]

env:
  CARGO_TERM_COLOR: always
  RUSTFLAGS: "-Dwarnings"
  DATABASE_URL: "postgres://postgres:postgres@localhost/oxicloud_test"

jobs:

  # Detect which parts of the codebase changed
  changes:
    runs-on: ubuntu-latest
    outputs:
      frontend: ${{ steps.filter.outputs.frontend }}
      backend: ${{ steps.filter.outputs.backend }}
    steps:
      - uses: actions/checkout@v4
      - uses: dorny/paths-filter@v3
        id: filter
        with:
          filters: |
            frontend:
              - 'static/**'
              - 'biome.json'
              - '.grit'
              - '.stylelintrc.json'
              - 'jsconfig.json'
            backend:
              - 'src/**'
              - 'Cargo.toml'
              - 'Cargo.lock'

  frontend-linter:
    name: Frontend — CSS and JS checks (format, lint, rules, etc)
    needs: changes
    if: needs.changes.outputs.frontend == 'true'
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Install Biome
        uses: biomejs/setup-biome@v2

      - name: Run Biome check
        run: biome ci static/

      - name: Setup Node
        uses: actions/setup-node@v4
        with:
          node-version: 25

      # because we are not using package.json
      - name: Install Stylelint and plugins
        run: |
            npm install --global \
                stylelint@17 \
                postcss@8 \
                stylelint-value-no-unknown-custom-properties@6

      - name: Run Stylelint
        run: npx stylelint "static/css/**/*.{css,scss}"

  rust-fmt:
    name: Rustfmt
    needs: changes
    if: needs.changes.outputs.backend == 'true'
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6
      - uses: dtolnay/rust-toolchain@stable
        with:
          components: rustfmt
      - run: cargo fmt --all --check

  rust-clippy:
    name: Clippy
    needs: changes
    if: needs.changes.outputs.backend == 'true'
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6
      - uses: dtolnay/rust-toolchain@stable
        with:
          components: clippy
      - uses: Swatinem/rust-cache@v2
      - run: cargo clippy --all-targets --all-features -- -D warnings

  rust-test:
    name: Tests
    needs: changes
    if: needs.changes.outputs.backend == 'true'
    runs-on: ubuntu-latest
    services:
      postgres:
        image: postgres:16-alpine
        env:
          POSTGRES_USER: postgres
          POSTGRES_PASSWORD: postgres
          POSTGRES_DB: oxicloud_test
        ports:
          - 5432:5432
        options: >-
          --health-cmd "pg_isready -U postgres"
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5
    steps:
      - uses: actions/checkout@v6
      - uses: dtolnay/rust-toolchain@stable
      - uses: Swatinem/rust-cache@v2

      - name: Initialize test database
        run: psql -h localhost -U postgres -d oxicloud_test -f migrations/20260307000000_initial_schema.sql
        env:
          PGPASSWORD: postgres

      - name: Run tests
        run: cargo test --all-features --workspace
        env:
          DATABASE_URL: "postgres://postgres:postgres@localhost/oxicloud_test"

  rust-audit:
    name: Security Audit
    needs: changes
    if: needs.changes.outputs.backend == 'true'
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6
      # RUSTSEC-2023-0071 (Marvin Attack): rsa crate is a transitive dependency from jsonwebtoken.
      # Not affected: This application uses HS256 for internal JWT signing and only performs
      # RSA public key verification (not private key operations) for OIDC/OAuth2 tokens.
      - uses: rustsec/audit-check@v2.0.0
        with:
          token: ${{ secrets.GITHUB_TOKEN }}
          ignore: RUSTSEC-2023-0071

  build:
    name: Build Check
    runs-on: ubuntu-latest
    needs: [frontend-linter, rust-fmt, rust-clippy, rust-test]
    steps:
      - uses: actions/checkout@v6
      - uses: dtolnay/rust-toolchain@stable
      - uses: Swatinem/rust-cache@v2
      - run: cargo build --release
