allframe 0.1.28

Complete Rust web framework with built-in HTTP/2 server, REST/GraphQL/gRPC, compile-time DI, CQRS - TDD from day zero
Documentation
name: Offline Quality Gates

# Ensures AllFrame works correctly in offline-first and offline-only
# desktop/embedded deployments (GitHub Issue #36).
#
# Linux jobs run inside ghcr.io/all-source-os/all-frame-ci:latest which
# has Tauri 2 system dependencies pre-installed (GTK, WebKit, etc.).
# See .github/Dockerfile.ci and .github/workflows/ci-image.yml.

on:
  push:
    branches: [main]
  pull_request:

permissions:
  contents: read
  packages: read

jobs:
  # ── Gate 1: Offline feature combinations compile ─────────────────────
  offline-feature-matrix:
    name: Offline Features (${{ matrix.profile.name }}, ${{ matrix.os }})
    runs-on: ${{ matrix.os }}
    container: ${{ matrix.os == 'ubuntu-latest' && 'ghcr.io/all-source-os/all-frame-ci:latest' || '' }}
    strategy:
      fail-fast: false
      matrix:
        os: [ubuntu-latest, macos-latest]
        profile:
          - name: "offline-only-minimal"
            features: "cqrs,di"
          - name: "offline-first-desktop"
            features: "cqrs,di,resilience,security"
          - name: "offline-with-router"
            features: "router,cqrs,di"
          - name: "offline-with-auth"
            features: "cqrs,di,auth,auth-jwt,security"
          - name: "offline-with-cache"
            features: "cqrs,di,cache-memory"
    steps:
      - uses: actions/checkout@v4
      - uses: dtolnay/rust-toolchain@stable
        if: matrix.os == 'macos-latest'
      - uses: Swatinem/rust-cache@v2

      - name: Build & test allframe-core (${{ matrix.profile.name }})
        run: |
          cargo build -p allframe-core --no-default-features --features "${{ matrix.profile.features }}"
          cargo test  -p allframe-core --no-default-features --features "${{ matrix.profile.features }}"

  # ── Gate 2: allframe-tauri crate ─────────────────────────────────────
  tauri-crate:
    name: allframe-tauri (${{ matrix.os }})
    runs-on: ${{ matrix.os }}
    container: ${{ matrix.os == 'ubuntu-latest' && 'ghcr.io/all-source-os/all-frame-ci:latest' || '' }}
    strategy:
      fail-fast: false
      matrix:
        os: [ubuntu-latest, macos-latest]
    steps:
      - uses: actions/checkout@v4
      - uses: dtolnay/rust-toolchain@stable
        if: matrix.os == 'macos-latest'
      - uses: Swatinem/rust-cache@v2

      - name: Check, test, clippy
        run: |
          cargo check  -p allframe-tauri
          cargo test   -p allframe-tauri
          cargo clippy -p allframe-tauri -- -D warnings

  # ── Gate 3: No network deps in offline builds ────────────────────────
  dependency-tree-validation:
    name: Dep Tree (${{ matrix.profile.name }})
    runs-on: ubuntu-latest
    container: ghcr.io/all-source-os/all-frame-ci:latest
    strategy:
      fail-fast: false
      matrix:
        profile:
          - name: "offline-only-minimal"
            features: "cqrs,di"
            banned: "reqwest|redis|opentelemetry-otlp|tonic|hyper"

          - name: "offline-first-desktop"
            features: "cqrs,di,resilience,security"
            banned: "reqwest|redis|opentelemetry-otlp|tonic|hyper"

          - name: "allframe-tauri"
            package: "allframe-tauri"
            # hyper is a legitimate transitive dep of tauri (internal IPC)
            banned: "reqwest|redis|opentelemetry-otlp|tonic"

    steps:
      - uses: actions/checkout@v4
      - uses: Swatinem/rust-cache@v2

      - name: Validate no network deps
        run: |
          PACKAGE="${{ matrix.profile.package || 'allframe-core' }}"
          FEATURES="${{ matrix.profile.features || '' }}"
          BANNED="${{ matrix.profile.banned }}"

          # Capture only stdout (dependency tree). Stderr has "Adding"/"Locking"
          # metadata lines that can false-match banned crate names.
          if [ -n "$FEATURES" ]; then
            TREE=$(cargo tree -p "$PACKAGE" --no-default-features --features "$FEATURES" 2>/dev/null)
          else
            TREE=$(cargo tree -p "$PACKAGE" 2>/dev/null)
          fi

          if echo "$TREE" | grep -qE "$BANNED"; then
            echo "$TREE"
            echo ""
            echo "Matched:"
            echo "$TREE" | grep -E "$BANNED"
            echo ""
            echo "::error::Network dependencies found in ${{ matrix.profile.name }}!"
            exit 1
          else
            echo "PASS: No banned deps in ${{ matrix.profile.name }}"
          fi

  # ── Gate 4: Offline quality gate integration tests ───────────────────
  offline-quality-gate-tests:
    name: Quality Gate Tests (${{ matrix.os }})
    runs-on: ${{ matrix.os }}
    container: ${{ matrix.os == 'ubuntu-latest' && 'ghcr.io/all-source-os/all-frame-ci:latest' || '' }}
    strategy:
      fail-fast: false
      matrix:
        os: [ubuntu-latest, macos-latest]
    steps:
      - uses: actions/checkout@v4
      - uses: dtolnay/rust-toolchain@stable
        if: matrix.os == 'macos-latest'
      - uses: Swatinem/rust-cache@v2

      - name: Run offline quality gate tests
        run: >
          cargo test -p allframe
          --test 09_offline_quality_gates
          --features "cqrs,di,resilience,security,openapi"

  # ── Gate 5: Binary size for offline profile ──────────────────────────
  offline-binary-size:
    name: Binary Size (offline)
    runs-on: ubuntu-latest
    container: ghcr.io/all-source-os/all-frame-ci:latest
    steps:
      - uses: actions/checkout@v4
      - uses: Swatinem/rust-cache@v2

      - name: Build & measure
        run: |
          cargo build --release -p allframe-core \
            --no-default-features --features "cqrs,di,resilience,security"

          SIZE=$(stat -c%s "target/release/liballframe_core.rlib" 2>/dev/null || echo "0")
          SIZE_MB=$(echo "scale=2; $SIZE / 1048576" | bc)

          echo "## Offline Profile Binary Size" >> $GITHUB_STEP_SUMMARY
          echo "Features: \`cqrs,di,resilience,security\`" >> $GITHUB_STEP_SUMMARY
          echo "**Size: ${SIZE_MB}MB** (limit: 5.0MB)" >> $GITHUB_STEP_SUMMARY

          if (( $(echo "$SIZE_MB > 5.0" | bc -l) )); then
            echo "::error::Offline binary ${SIZE_MB}MB exceeds 5.0MB"
            exit 1
          fi
          echo "PASS: ${SIZE_MB}MB"

  # ── Gate 6: Full workspace regression ────────────────────────────────
  workspace-regression:
    name: Workspace Regression
    runs-on: ubuntu-latest
    container: ghcr.io/all-source-os/all-frame-ci:latest
    needs: [offline-feature-matrix, tauri-crate]
    steps:
      - uses: actions/checkout@v4
      - uses: Swatinem/rust-cache@v2

      - name: Full workspace test + clippy
        run: |
          cargo test
          cargo clippy -- -D warnings