name: CI

on:
  push:
    branches: [main, "001-*"]
  pull_request:
    branches: [main]

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

permissions: {}

env:
  CARGO_TERM_COLOR: always
  RUST_BACKTRACE: 1
  RUMDL_VERSION: "0.1.42"

jobs:
  check:
    name: Check & Lint
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd  # v6
        with:
          persist-credentials: false
      - uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8  # stable
        with:
          components: rustfmt, clippy
      - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32  # v2
        with:
          shared-key: cargo-${{ runner.os }}
          save-if: ${{ github.ref == 'refs/heads/main' }}

      - name: Check formatting
        run: cargo fmt --check

      - name: Cache rumdl
        uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae  # v5
        with:
          path: ~/.cargo/bin/rumdl
          key: rumdl-${{ env.RUMDL_VERSION }}
      - name: Install rumdl
        run: command -v rumdl || cargo install rumdl@${{ env.RUMDL_VERSION }}

      - name: Check Markdown
        run: rumdl check *.md

      - name: Clippy
        run: cargo clippy -- -D warnings

      - name: Build
        run: cargo build --release

  audit:
    name: Security Audit
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd  # v6
        with:
          persist-credentials: false
      - uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8  # stable
      - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32  # v2
        with:
          shared-key: cargo-${{ runner.os }}
          save-if: ${{ github.ref == 'refs/heads/main' }}
      - name: Install cargo-audit
        uses: taiki-e/install-action@b651345a718c8f44efa2460560b3dbf29cbd7ee1  # v2
        with:
          tool: cargo-audit
      - name: Run cargo audit
        run: cargo audit

  test:
    name: Test
    runs-on: ${{ matrix.os }}
    needs: check
    strategy:
      matrix:
        os: [ubuntu-latest, macos-latest, windows-latest]
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd  # v6
        with:
          persist-credentials: false
      - uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8  # stable
      - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32  # v2
        with:
          shared-key: cargo-${{ runner.os }}
          save-if: ${{ github.ref == 'refs/heads/main' }}

      - name: Run tests
        run: cargo test

  bench:
    name: Benchmark
    runs-on: ubuntu-latest
    needs: check
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd  # v6
        with:
          persist-credentials: false
      - uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8  # stable
      - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32  # v2
        with:
          shared-key: cargo-${{ runner.os }}
          save-if: ${{ github.ref == 'refs/heads/main' }}

      - name: Run benchmarks
        run: cargo bench

  coverage:
    name: Coverage
    runs-on: ubuntu-latest
    needs: test
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd  # v6
        with:
          persist-credentials: false
      - uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8  # stable
        with:
          components: llvm-tools-preview
      - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32  # v2
        with:
          shared-key: cargo-${{ runner.os }}
          save-if: ${{ github.ref == 'refs/heads/main' }}

      - name: Install cargo-tarpaulin
        uses: taiki-e/install-action@b651345a718c8f44efa2460560b3dbf29cbd7ee1  # v2
        with:
          tool: cargo-tarpaulin

      - name: Generate coverage
        run: cargo tarpaulin --out xml --fail-under 65

      - name: Upload coverage to Codecov
        uses: codecov/codecov-action@57e3a136b779b570ffcdbf80b3bdc90e7fab3de2  # v6
        with:
          files: cobertura.xml
          fail_ci_if_error: false
