rpcnet 0.1.0

RPC library based on QUIC+TLS encryption
Documentation
name: PR Checks

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

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

permissions:
  contents: read
  pull-requests: write
  issues: write

env:
  CARGO_TERM_COLOR: always
  RUST_BACKTRACE: 1

jobs:
  # Quick checks that fail fast
  format:
    name: Format Check
    runs-on: ubuntu-latest
    steps:
    - name: Checkout code
      uses: actions/checkout@v4
    
    - name: Install Rust
      uses: dtolnay/rust-toolchain@stable
      with:
        components: rustfmt
    
    - name: Check formatting
      run: cargo fmt --all -- --check

  lint:
    name: Clippy Lint
    runs-on: ubuntu-latest
    steps:
    - name: Checkout code
      uses: actions/checkout@v4
    
    - name: Install Rust
      uses: dtolnay/rust-toolchain@stable
      with:
        components: clippy
    
    - name: Cache cargo registry
      uses: actions/cache@v4
      with:
        path: ~/.cargo/registry/index
        key: ${{ runner.os }}-cargo-registry-${{ hashFiles('**/Cargo.lock') }}
        restore-keys: ${{ runner.os }}-cargo-registry-
    
    - name: Cache cargo build
      uses: actions/cache@v4
      with:
        path: target
        key: ${{ runner.os }}-cargo-build-${{ hashFiles('**/Cargo.lock') }}
        restore-keys: ${{ runner.os }}-cargo-build-
    
    - name: Generate test certificates
      run: |
        mkdir -p certs
        openssl req -x509 -newkey rsa:4096 -keyout certs/test_key.pem -out certs/test_cert.pem -days 365 -nodes -subj "/CN=localhost"
    
    - name: Run Clippy
      run: make ci-lint

  # Main test suite
  test:
    name: Test Suite
    runs-on: ${{ matrix.os }}
    strategy:
      fail-fast: false
      matrix:
        os: [ubuntu-latest, macos-latest]
        rust: [stable, beta]
        exclude:
          - os: macos-latest
            rust: beta
    
    steps:
    - name: Checkout code
      uses: actions/checkout@v4
    
    - name: Install Rust ${{ matrix.rust }}
      uses: dtolnay/rust-toolchain@master
      with:
        toolchain: ${{ matrix.rust }}
    
    - name: Cache cargo registry
      uses: actions/cache@v4
      with:
        path: ~/.cargo/registry/index
        key: ${{ runner.os }}-${{ matrix.rust }}-cargo-registry-${{ hashFiles('**/Cargo.lock') }}
        restore-keys: ${{ runner.os }}-${{ matrix.rust }}-cargo-registry-
    
    - name: Cache cargo build
      uses: actions/cache@v4
      with:
        path: target
        key: ${{ runner.os }}-${{ matrix.rust }}-cargo-build-${{ hashFiles('**/Cargo.lock') }}
        restore-keys: ${{ runner.os }}-${{ matrix.rust }}-cargo-build-
    
    - name: Generate test certificates
      run: |
        mkdir -p certs
        openssl req -x509 -newkey rsa:4096 -keyout certs/test_key.pem -out certs/test_cert.pem -days 365 -nodes -subj "/CN=localhost"
    
    - name: Run tests
      run: make ci-test
    
    - name: Run doctests
      run: cargo test --doc

  # Coverage analysis (only on ubuntu with stable)
  coverage:
    name: Coverage Analysis
    runs-on: ubuntu-latest
    steps:
    - name: Checkout code
      uses: actions/checkout@v4
    
    - name: Install Rust
      uses: dtolnay/rust-toolchain@stable
      with:
        components: llvm-tools-preview
    
    - name: Install cargo-tarpaulin
      run: cargo install cargo-tarpaulin
    
    - name: Install dependencies
      run: |
        sudo apt-get update
        sudo apt-get install -y jq bc
    
    - name: Cache cargo registry
      uses: actions/cache@v4
      with:
        path: ~/.cargo/registry/index
        key: ${{ runner.os }}-cargo-registry-${{ hashFiles('**/Cargo.lock') }}
        restore-keys: ${{ runner.os }}-cargo-registry-
    
    - name: Cache cargo build
      uses: actions/cache@v4
      with:
        path: target
        key: ${{ runner.os }}-cargo-coverage-${{ hashFiles('**/Cargo.lock') }}
        restore-keys: ${{ runner.os }}-cargo-coverage-
    
    - name: Generate test certificates
      run: |
        mkdir -p certs
        openssl req -x509 -newkey rsa:4096 -keyout certs/test_key.pem -out certs/test_cert.pem -days 365 -nodes -subj "/CN=localhost"
    
    - name: Run coverage analysis
      run: make ci-coverage
    
    - name: Generate coverage report
      run: |
        echo "## Coverage Report" >> $GITHUB_STEP_SUMMARY
        echo "" >> $GITHUB_STEP_SUMMARY
        if [ -f "scripts/analyze-coverage.sh" ]; then
          ./scripts/analyze-coverage.sh >> $GITHUB_STEP_SUMMARY || true
        fi
    
    - name: Upload coverage to Codecov
      uses: codecov/codecov-action@v4
      with:
        files: target/coverage/tarpaulin-report.xml
        flags: unittests
        name: codecov-umbrella
        fail_ci_if_error: false
      env:
        CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
    
    - name: Archive coverage results
      uses: actions/upload-artifact@v4
      with:
        name: coverage-report
        path: |
          target/coverage/tarpaulin-report.html
          target/coverage/tarpaulin-report.json
        retention-days: 30
    
    - name: Comment coverage on PR
      if: github.event_name == 'pull_request'
      uses: actions/github-script@v7
      with:
        script: |
          const fs = require('fs');
          try {
            const coverage = JSON.parse(fs.readFileSync('target/coverage/tarpaulin-report.json', 'utf8'));
            const coveragePercent = coverage.coverage.toFixed(1);
            const threshold = 65.0;
            const status = coveragePercent >= threshold ? '✅' : '⚠️';
            
            const body = `## ${status} Coverage Report
            
            **Overall Coverage: ${coveragePercent}%** (Threshold: ${threshold}%)
            
            ${coveragePercent >= threshold ? '✅ Coverage meets requirements!' : '⚠️ Coverage is below threshold. Consider adding more tests.'}
            
            📊 [View detailed coverage report](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }})
            `;
            
            github.rest.issues.createComment({
              issue_number: context.issue.number,
              owner: context.repo.owner,
              repo: context.repo.repo,
              body: body
            });
          } catch (error) {
            console.log('Could not post coverage comment:', error.message);
          }

  # Security audit
  security:
    name: Security Audit
    runs-on: ubuntu-latest
    steps:
    - name: Checkout code
      uses: actions/checkout@v4
    
    - name: Install Rust
      uses: dtolnay/rust-toolchain@stable
    
    - name: Install cargo-audit
      run: cargo install cargo-audit
    
    - name: Run security audit
      run: make ci-security

  # Build documentation
  docs:
    name: Documentation
    runs-on: ubuntu-latest
    steps:
    - name: Checkout code
      uses: actions/checkout@v4
    
    - name: Install Rust
      uses: dtolnay/rust-toolchain@stable
    
    - name: Cache cargo registry
      uses: actions/cache@v4
      with:
        path: ~/.cargo/registry/index
        key: ${{ runner.os }}-cargo-registry-${{ hashFiles('**/Cargo.lock') }}
        restore-keys: ${{ runner.os }}-cargo-registry-
    
    - name: Cache cargo build
      uses: actions/cache@v4
      with:
        path: target
        key: ${{ runner.os }}-cargo-doc-${{ hashFiles('**/Cargo.lock') }}
        restore-keys: ${{ runner.os }}-cargo-doc-
    
    - name: Build documentation
      run: make doc
      env:
        RUSTDOCFLAGS: -D warnings
    
    - name: Check for broken links
      run: |
        cargo install cargo-deadlinks || true
        cargo deadlinks --check-http || true

  # Verify examples compile
  examples:
    name: Examples
    runs-on: ubuntu-latest
    steps:
    - name: Checkout code
      uses: actions/checkout@v4
    
    - name: Install Rust
      uses: dtolnay/rust-toolchain@stable
    
    - name: Cache cargo registry
      uses: actions/cache@v4
      with:
        path: ~/.cargo/registry/index
        key: ${{ runner.os }}-cargo-registry-${{ hashFiles('**/Cargo.lock') }}
        restore-keys: ${{ runner.os }}-cargo-registry-
    
    - name: Cache cargo build
      uses: actions/cache@v4
      with:
        path: target
        key: ${{ runner.os }}-cargo-examples-${{ hashFiles('**/Cargo.lock') }}
        restore-keys: ${{ runner.os }}-cargo-examples-
    
    - name: Generate test certificates
      run: |
        mkdir -p certs
        openssl req -x509 -newkey rsa:4096 -keyout certs/test_key.pem -out certs/test_cert.pem -days 365 -nodes -subj "/CN=localhost"
    
    - name: Build examples
      run: make examples

  # Summary job that depends on all checks
  pr-checks-complete:
    name: All PR Checks Passed
    runs-on: ubuntu-latest
    needs: [format, lint, test, coverage, security, docs, examples]
    if: always()
    steps:
    - name: Check results
      run: |
        if [[ "${{ needs.format.result }}" == "failure" ]] || \
           [[ "${{ needs.lint.result }}" == "failure" ]] || \
           [[ "${{ needs.test.result }}" == "failure" ]] || \
           [[ "${{ needs.coverage.result }}" == "failure" ]] || \
           [[ "${{ needs.security.result }}" == "failure" ]] || \
           [[ "${{ needs.docs.result }}" == "failure" ]] || \
           [[ "${{ needs.examples.result }}" == "failure" ]]; then
          echo "❌ One or more checks failed"
          exit 1
        fi
        echo "✅ All PR checks passed!"