rsactor 0.14.1

A Simple and Efficient In-Process Actor Model Implementation for Rust.
Documentation
name: Rust CI/CD

# Main CI/CD pipeline for general Rust development workflows
# Covers: quality checks, security audit, testing, cross-compilation, docs, coverage
# MSRV testing is handled separately by msrv.yml workflow

on:
  push:
    branches: [ "main" ]
  pull_request:
    branches: [ "main" ]
  schedule:
    # Weekly dependency check
    - cron: '0 0 * * 0'

env:
  CARGO_TERM_COLOR: always
  RUST_BACKTRACE: 1

jobs:
  # Code quality and formatting checks
  quality:
    name: Code Quality
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v6

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

      - name: Cache cargo dependencies
        uses: actions/cache@v5
        with:
          path: |
            ~/.cargo/bin/
            ~/.cargo/registry/index/
            ~/.cargo/registry/cache/
            ~/.cargo/git/db/
            target/
          key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
          restore-keys: |
            ${{ runner.os }}-cargo-

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

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

  # Security audit
  security:
    name: Security Audit
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v6

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

      - name: Install cargo-audit
        run: |
          if ! command -v cargo-audit &> /dev/null; then
            cargo install cargo-audit
          else
            echo "cargo-audit is already installed"
          fi

      - name: Run security audit
        run: cargo audit

  # Build and test matrix
  test:
    name: Test Suite
    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        os: [ubuntu-latest, windows-latest, macos-latest]
        rust: [stable, beta] # MSRV testing is handled by dedicated msrv.yml workflow
        exclude:
          # Reduce matrix size by excluding some combinations
          - os: windows-latest
            rust: beta
          - os: macos-latest
            rust: beta
    steps:
      - name: Checkout code
        uses: actions/checkout@v6

      - name: Install Rust toolchain
        uses: dtolnay/rust-toolchain@master
        with:
          toolchain: ${{ matrix.rust }}

      - name: Cache cargo dependencies
        uses: actions/cache@v5
        with:
          path: |
            ~/.cargo/bin/
            ~/.cargo/registry/index/
            ~/.cargo/registry/cache/
            ~/.cargo/git/db/
            target/
          key: ${{ runner.os }}-${{ matrix.rust }}-cargo-${{ hashFiles('**/Cargo.lock') }}
          restore-keys: |
            ${{ runner.os }}-${{ matrix.rust }}-cargo-

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

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

      - name: Run examples
        shell: bash
        run: |
          if [ -d "examples" ]; then
            for example in examples/*.rs; do
              if [ -f "$example" ]; then
                example_name=$(basename "$example" .rs)
                echo "Running example: $example_name"
                cargo run --example "$example_name" || echo "Example $example_name failed or requires interaction"
              fi
            done
          else
            echo "No examples directory found"
          fi

  # Android cross-compilation test
  android:
    name: Android Cross-compilation
    runs-on: ubuntu-latest
    strategy:
      matrix:
        target:
          - aarch64-linux-android    # ARM64 Android
          - armv7-linux-androideabi  # ARM Android
          - i686-linux-android       # x86 Android
          - x86_64-linux-android     # x86_64 Android
    steps:
      - name: Checkout code
        uses: actions/checkout@v6

      - name: Install Rust toolchain
        uses: dtolnay/rust-toolchain@stable
        with:
          targets: ${{ matrix.target }}

      - name: Setup Android NDK
        uses: nttld/setup-ndk@v1
        with:
          ndk-version: r26d
          add-to-path: false

      - name: Cache cargo dependencies
        uses: actions/cache@v5
        with:
          path: |
            ~/.cargo/bin/
            ~/.cargo/registry/index/
            ~/.cargo/registry/cache/
            ~/.cargo/git/db/
            target/
          key: ${{ runner.os }}-android-${{ matrix.target }}-cargo-${{ hashFiles('**/Cargo.lock') }}
          restore-keys: |
            ${{ runner.os }}-android-${{ matrix.target }}-cargo-

      - name: Setup Android cross-compilation environment
        run: |
          export ANDROID_NDK_ROOT=$ANDROID_NDK_LATEST_HOME
          echo "ANDROID_NDK_ROOT=$ANDROID_NDK_ROOT" >> $GITHUB_ENV

          # Set up linker for each target
          case "${{ matrix.target }}" in
            aarch64-linux-android)
              echo "CC_aarch64_linux_android=$ANDROID_NDK_ROOT/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android33-clang" >> $GITHUB_ENV
              echo "CXX_aarch64_linux_android=$ANDROID_NDK_ROOT/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android33-clang++" >> $GITHUB_ENV
              echo "AR_aarch64_linux_android=$ANDROID_NDK_ROOT/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ar" >> $GITHUB_ENV
              echo "CARGO_TARGET_AARCH64_LINUX_ANDROID_LINKER=$ANDROID_NDK_ROOT/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android33-clang" >> $GITHUB_ENV
              ;;
            armv7-linux-androideabi)
              echo "CC_armv7_linux_androideabi=$ANDROID_NDK_ROOT/toolchains/llvm/prebuilt/linux-x86_64/bin/armv7a-linux-androideabi33-clang" >> $GITHUB_ENV
              echo "CXX_armv7_linux_androideabi=$ANDROID_NDK_ROOT/toolchains/llvm/prebuilt/linux-x86_64/bin/armv7a-linux-androideabi33-clang++" >> $GITHUB_ENV
              echo "AR_armv7_linux_androideabi=$ANDROID_NDK_ROOT/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ar" >> $GITHUB_ENV
              echo "CARGO_TARGET_ARMV7_LINUX_ANDROIDEABI_LINKER=$ANDROID_NDK_ROOT/toolchains/llvm/prebuilt/linux-x86_64/bin/armv7a-linux-androideabi33-clang" >> $GITHUB_ENV
              ;;
            i686-linux-android)
              echo "CC_i686_linux_android=$ANDROID_NDK_ROOT/toolchains/llvm/prebuilt/linux-x86_64/bin/i686-linux-android33-clang" >> $GITHUB_ENV
              echo "CXX_i686_linux_android=$ANDROID_NDK_ROOT/toolchains/llvm/prebuilt/linux-x86_64/bin/i686-linux-android33-clang++" >> $GITHUB_ENV
              echo "AR_i686_linux_android=$ANDROID_NDK_ROOT/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ar" >> $GITHUB_ENV
              echo "CARGO_TARGET_I686_LINUX_ANDROID_LINKER=$ANDROID_NDK_ROOT/toolchains/llvm/prebuilt/linux-x86_64/bin/i686-linux-android33-clang" >> $GITHUB_ENV
              ;;
            x86_64-linux-android)
              echo "CC_x86_64_linux_android=$ANDROID_NDK_ROOT/toolchains/llvm/prebuilt/linux-x86_64/bin/x86_64-linux-android33-clang" >> $GITHUB_ENV
              echo "CXX_x86_64_linux_android=$ANDROID_NDK_ROOT/toolchains/llvm/prebuilt/linux-x86_64/bin/x86_64-linux-android33-clang++" >> $GITHUB_ENV
              echo "AR_x86_64_linux_android=$ANDROID_NDK_ROOT/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ar" >> $GITHUB_ENV
              echo "CARGO_TARGET_X86_64_LINUX_ANDROID_LINKER=$ANDROID_NDK_ROOT/toolchains/llvm/prebuilt/linux-x86_64/bin/x86_64-linux-android33-clang" >> $GITHUB_ENV
              ;;
          esac

      - name: Build for Android target
        run: |
          echo "Building for target: ${{ matrix.target }}"
          cargo build --target ${{ matrix.target }} --verbose --all-features

      - name: Check if examples can be built for Android
        run: |
          echo "Checking if examples can be built for ${{ matrix.target }}"
          if [ -d "examples" ]; then
            for example in examples/*.rs; do
              if [ -f "$example" ]; then
                example_name=$(basename "$example" .rs)
                echo "Building example: $example_name for ${{ matrix.target }}"
                cargo build --target ${{ matrix.target }} --example "$example_name" || echo "Example $example_name failed to build for ${{ matrix.target }}"
              fi
            done
          else
            echo "No examples directory found"
          fi

      - name: Verify Android compatibility
        run: |
          echo "✓ Successfully built rsactor for Android target: ${{ matrix.target }}"
          echo "  - Target architecture: ${{ matrix.target }}"
          echo "  - Android API level: 33"
          echo "  - NDK version: r26d"

  # Documentation build
  docs:
    name: Documentation
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v6

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

      - name: Cache cargo dependencies
        uses: actions/cache@v5
        with:
          path: |
            ~/.cargo/bin/
            ~/.cargo/registry/index/
            ~/.cargo/registry/cache/
            ~/.cargo/git/db/
            target/
          key: ${{ runner.os }}-docs-cargo-${{ hashFiles('**/Cargo.lock') }}

      - name: Build documentation
        run: cargo doc --no-deps --all-features

      - name: Check for broken doc links
        run: cargo doc --no-deps --all-features
        env:
          RUSTDOCFLAGS: "-D warnings"

  # Code coverage
  coverage:
    name: Code Coverage
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v6

      - name: Install Rust toolchain
        uses: dtolnay/rust-toolchain@stable
        with:
          components: llvm-tools-preview

      - name: Cache cargo dependencies
        uses: actions/cache@v5
        with:
          path: |
            ~/.cargo/bin/
            ~/.cargo/registry/index/
            ~/.cargo/registry/cache/
            ~/.cargo/git/db/
            target/
          key: ${{ runner.os }}-coverage-cargo-${{ hashFiles('**/Cargo.lock') }}

      - name: Install cargo-llvm-cov
        run: |
          if ! command -v cargo-llvm-cov &> /dev/null; then
            cargo install cargo-llvm-cov
          else
            echo "cargo-llvm-cov is already installed"
          fi

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

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

  # Ensure all jobs pass
  ci-success:
    name: CI Success
    runs-on: ubuntu-latest
    needs: [quality, security, test, android, docs, coverage]
    if: always()
    steps:
      - name: Check all jobs
        run: |
          if [[ "${{ needs.quality.result }}" != "success" ]]; then
            echo "Quality check failed"
            exit 1
          fi
          if [[ "${{ needs.security.result }}" != "success" ]]; then
            echo "Security audit failed"
            exit 1
          fi
          if [[ "${{ needs.test.result }}" != "success" ]]; then
            echo "Tests failed"
            exit 1
          fi
          if [[ "${{ needs.android.result }}" != "success" ]]; then
            echo "Android cross-compilation tests failed"
            exit 1
          fi
          if [[ "${{ needs.docs.result }}" != "success" ]]; then
            echo "Documentation build failed"
            exit 1
          fi
          if [[ "${{ needs.coverage.result }}" != "success" ]]; then
            echo "Coverage check failed"
            exit 1
          fi
          echo "All CI jobs passed! (MSRV testing handled by separate msrv.yml workflow)"