aprender-graph 0.32.0

GPU-first embedded graph database for code analysis (call graphs, dependencies, AST traversals)
name: Quality Checks

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

env:
  CARGO_TERM_COLOR: always
  RUST_BACKTRACE: 1

jobs:
  lint:
    name: Lint (Clippy + Rustfmt)
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Install Rust
        uses: dtolnay/rust-toolchain@stable
        with:
          components: rustfmt, clippy

      - name: Cache cargo registry
        uses: actions/cache@v4
        with:
          path: ~/.cargo/registry
          key: ${{ runner.os }}-cargo-registry-${{ hashFiles('**/Cargo.lock') }}

      - name: Cache cargo build
        uses: actions/cache@v4
        with:
          path: target
          key: ${{ runner.os }}-cargo-build-${{ hashFiles('**/Cargo.lock') }}

      - name: Run rustfmt check
        run: cargo fmt --all -- --check

      - name: Run clippy
        run: cargo clippy --all-features --all-targets -- -D warnings

  bashrs:
    name: bashrs Shell Safety
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Install bashrs
        run: cargo install bashrs --version ">=6.0.0" || cargo install bashrs

      - name: Lint Makefile
        run: bashrs make lint Makefile

      - name: Lint shell scripts
        run: |
          for script in $(find . -type f -name "*.sh" ! -path "./target/*" ! -path "./.git/*"); do
            echo "Linting $script..."
            bashrs lint "$script" || true
          done

  test:
    name: Test Suite
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Install Rust
        uses: dtolnay/rust-toolchain@stable

      - name: Cache cargo registry
        uses: actions/cache@v4
        with:
          path: ~/.cargo/registry
          key: ${{ runner.os }}-cargo-registry-${{ hashFiles('**/Cargo.lock') }}

      - name: Cache cargo build
        uses: actions/cache@v4
        with:
          path: target
          key: ${{ runner.os }}-cargo-test-${{ hashFiles('**/Cargo.lock') }}

      - name: Run tests
        run: cargo test --all-features --verbose

  coverage:
    name: Code Coverage
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Install Rust
        uses: dtolnay/rust-toolchain@stable

      - name: Install cargo-llvm-cov
        uses: taiki-e/install-action@cargo-llvm-cov

      - name: Cache cargo registry
        uses: actions/cache@v4
        with:
          path: ~/.cargo/registry
          key: ${{ runner.os }}-cargo-registry-${{ hashFiles('**/Cargo.lock') }}

      - name: Cache cargo build
        uses: actions/cache@v4
        with:
          path: target
          key: ${{ runner.os }}-cargo-coverage-${{ hashFiles('**/Cargo.lock') }}

      - name: Generate coverage
        run: cargo llvm-cov --all-features --lcov --output-path lcov.info

      - name: Upload coverage to Codecov
        uses: codecov/codecov-action@v4
        with:
          files: lcov.info
          fail_ci_if_error: false

      - name: Check coverage threshold
        run: |
          COVERAGE=$(cargo llvm-cov --all-features | grep -oP '\d+\.\d+(?=%)' | head -1)
          echo "Coverage: ${COVERAGE}%"
          if (( $(echo "$COVERAGE < 90.0" | bc -l) )); then
            echo "❌ Coverage ${COVERAGE}% is below 90% threshold"
            exit 1
          fi
          echo "✅ Coverage ${COVERAGE}% meets ≥90% threshold"

  pmat:
    name: PMAT Quality Analysis
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: Install Rust
        uses: dtolnay/rust-toolchain@stable

      - name: Install PMAT
        run: cargo install pmat || echo "Using existing pmat"

      - name: Check for SATD
        run: |
          pmat analyze satd --path . --fail-on-any || exit 1

      - name: Complexity Analysis
        run: |
          pmat analyze complexity --fail-above 20 --path . || exit 1

      - name: Dead Code Analysis
        run: |
          pmat analyze dead-code --path . || true

  build:
    name: Build (Debug + Release)
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Install Rust
        uses: dtolnay/rust-toolchain@stable

      - name: Cache cargo registry
        uses: actions/cache@v4
        with:
          path: ~/.cargo/registry
          key: ${{ runner.os }}-cargo-registry-${{ hashFiles('**/Cargo.lock') }}

      - name: Cache cargo build
        uses: actions/cache@v4
        with:
          path: target
          key: ${{ runner.os }}-cargo-build-${{ hashFiles('**/Cargo.lock') }}

      - name: Build debug
        run: cargo build --all-features --verbose

      - name: Build release
        run: cargo build --all-features --release --verbose

  quality-gate:
    name: Quality Gate
    runs-on: ubuntu-latest
    needs: [lint, bashrs, test, coverage, pmat, build]
    if: always()
    steps:
      - name: Check all jobs passed
        run: |
          if [[ "${{ needs.lint.result }}" != "success" ]] ||
             [[ "${{ needs.bashrs.result }}" != "success" ]] ||
             [[ "${{ needs.test.result }}" != "success" ]] ||
             [[ "${{ needs.coverage.result }}" != "success" ]] ||
             [[ "${{ needs.pmat.result }}" != "success" ]] ||
             [[ "${{ needs.build.result }}" != "success" ]]; then
            echo "❌ One or more quality checks failed"
            exit 1
          fi
          echo "✅ All quality gates passed"