Add integration and stability tests #33
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: CI | |
| on: | |
| pull_request: | |
| branches: [main] | |
| env: | |
| CARGO_TERM_COLOR: always | |
| RUST_BACKTRACE: 1 | |
| # Database URLs for CI | |
| DATABASE_URL: postgres://agentauth:agentauth_dev@localhost:5434/agentauth | |
| DATABASE_REPLICA_URL: postgres://agentauth:agentauth_dev@localhost:5435/agentauth | |
| # Redis URL for CI | |
| REDIS_URL: redis://localhost:6379 | |
| jobs: | |
| # Step 1-5: Rust checks (no external dependencies needed) | |
| rust-checks: | |
| name: Rust Checks | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Install Rust toolchain | |
| uses: dtolnay/rust-toolchain@stable | |
| with: | |
| components: clippy, rustfmt | |
| - name: Cache Rust dependencies | |
| uses: Swatinem/rust-cache@v2 | |
| with: | |
| cache-on-failure: true | |
| cache-all-crates: true | |
| - name: Cache cargo binaries | |
| uses: actions/cache@v4 | |
| with: | |
| path: ~/.cargo/bin | |
| key: ${{ runner.os }}-cargo-bin-${{ hashFiles('.github/workflows/ci.yml') }} | |
| restore-keys: | | |
| ${{ runner.os }}-cargo-bin- | |
| - name: Install cargo tools | |
| run: | | |
| # Only install if not already cached | |
| command -v cargo-nextest >/dev/null 2>&1 || cargo install cargo-nextest --locked | |
| command -v cargo-audit >/dev/null 2>&1 || cargo install cargo-audit --locked | |
| command -v cargo-deny >/dev/null 2>&1 || cargo install cargo-deny --locked | |
| # Step 1: cargo check | |
| - name: Check workspace | |
| run: cargo check --workspace | |
| # Step 2: cargo clippy | |
| - name: Clippy | |
| run: cargo clippy --workspace -- -D warnings | |
| # Step 3: cargo audit | |
| - name: Security audit | |
| run: cargo audit | |
| # Step 4-5: cargo deny | |
| - name: License and dependency check | |
| run: | | |
| cargo deny check licenses || echo "::warning::License check not configured" | |
| cargo deny check bans || echo "::warning::Ban check not configured" | |
| # Step 6-11: Integration tests with services | |
| integration-tests: | |
| name: Integration Tests | |
| runs-on: ubuntu-latest | |
| needs: rust-checks | |
| services: | |
| postgres: | |
| image: postgres:16-alpine | |
| env: | |
| POSTGRES_USER: agentauth | |
| POSTGRES_PASSWORD: agentauth_dev | |
| POSTGRES_DB: agentauth | |
| ports: | |
| - 5434:5432 | |
| options: >- | |
| --health-cmd pg_isready | |
| --health-interval 10s | |
| --health-timeout 5s | |
| --health-retries 5 | |
| redis: | |
| image: redis:7-alpine | |
| ports: | |
| - 6379:6379 | |
| options: >- | |
| --health-cmd "redis-cli ping" | |
| --health-interval 10s | |
| --health-timeout 5s | |
| --health-retries 5 | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Install Rust toolchain | |
| uses: dtolnay/rust-toolchain@stable | |
| - name: Cache Rust dependencies | |
| uses: Swatinem/rust-cache@v2 | |
| with: | |
| cache-on-failure: true | |
| cache-all-crates: true | |
| - name: Cache cargo binaries | |
| uses: actions/cache@v4 | |
| with: | |
| path: ~/.cargo/bin | |
| key: ${{ runner.os }}-cargo-bin-${{ hashFiles('.github/workflows/ci.yml') }} | |
| restore-keys: | | |
| ${{ runner.os }}-cargo-bin- | |
| - name: Install cargo tools | |
| run: | | |
| # Only install if not already cached | |
| command -v cargo-nextest >/dev/null 2>&1 || cargo install cargo-nextest --locked | |
| command -v sqlx >/dev/null 2>&1 || cargo install sqlx-cli --locked --no-default-features --features postgres | |
| # Step 7-8: Database migrations | |
| - name: Run migrations | |
| run: | | |
| sqlx migrate run --source migrations/ || echo "::warning::No migrations found" | |
| - name: Test migration rollback | |
| run: | | |
| sqlx migrate revert --source migrations/ || echo "::warning::No migrations to revert" | |
| sqlx migrate run --source migrations/ || echo "::warning::No migrations found" | |
| # Step 9: Run all tests | |
| - name: Run tests | |
| run: cargo nextest run --workspace | |
| # Step 11: Compliance tests | |
| - name: Run compliance tests | |
| run: cargo nextest run --test compliance || echo "::warning::No compliance tests found" | |
| # Step 12: Banned pattern checks | |
| security-patterns: | |
| name: Security Pattern Checks | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Check for plaintext key backends in production code | |
| run: | | |
| # Check for InMemorySigningBackend outside of #[cfg(test)] blocks | |
| # The struct and impl are properly gated with #[cfg(test)] in backend.rs | |
| # We check that no service code uses it | |
| if grep -rn "InMemorySigningBackend" services/ --include="*.rs" | grep -v "//"; then | |
| echo "::error::Found InMemorySigningBackend in service code" | |
| exit 1 | |
| fi | |
| # Check for PlaintextKeyfile feature in production Dockerfiles and Helm charts | |
| # PlaintextKeyfile is gated behind allow-plaintext-keys feature | |
| if grep -rn "allow-plaintext-keys" Dockerfile* deploy/ --include="*.yml" --include="*.yaml" 2>/dev/null; then | |
| echo "::error::Found allow-plaintext-keys feature in production configs" | |
| exit 1 | |
| fi | |
| echo "No plaintext key backends found in production code" | |
| - name: Check for unwrap() in library crates | |
| run: | | |
| # Count unwraps in non-test code (warning only for now) | |
| count=$(grep -rn "\.unwrap()" crates/ --include="*.rs" | grep -v "#\[cfg(test)\]\|//.*safe because\|test::" | wc -l) | |
| if [ "$count" -gt 0 ]; then | |
| echo "::warning::Found $count uses of unwrap() in library crates" | |
| grep -rn "\.unwrap()" crates/ --include="*.rs" | grep -v "#\[cfg(test)\]\|//.*safe because\|test::" | head -20 | |
| fi | |
| - name: Check for hardcoded secrets | |
| run: | | |
| if grep -rn "secret\|password\|private_key\|api_key" crates/ services/ --include="*.rs" | grep -v "//\|\"\"" | grep "= \"" | grep -v "test\|example\|placeholder"; then | |
| echo "::error::Potential hardcoded secrets found" | |
| exit 1 | |
| fi | |
| echo "No hardcoded secrets found" | |
| - name: Check for SQL string interpolation | |
| run: | | |
| if grep -rn "format!.*SELECT\|format!.*INSERT\|format!.*UPDATE\|format!.*DELETE" crates/ services/ --include="*.rs"; then | |
| echo "::error::SQL string interpolation found - use parameterized queries" | |
| exit 1 | |
| fi | |
| echo "No SQL string interpolation found" | |
| # Step 17: Documentation | |
| docs: | |
| name: Documentation | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Install Rust toolchain | |
| uses: dtolnay/rust-toolchain@stable | |
| - name: Cache Rust dependencies | |
| uses: Swatinem/rust-cache@v2 | |
| with: | |
| cache-on-failure: true | |
| - name: Build documentation | |
| run: cargo doc --no-deps --workspace | |
| env: | |
| RUSTDOCFLAGS: -D warnings | |
| # Step 18: Load test baseline (only on main branch) | |
| load-test: | |
| name: Load Test Baseline | |
| runs-on: ubuntu-latest | |
| needs: integration-tests | |
| if: github.ref == 'refs/heads/main' | |
| services: | |
| postgres: | |
| image: postgres:16-alpine | |
| env: | |
| POSTGRES_USER: agentauth | |
| POSTGRES_PASSWORD: agentauth_dev | |
| POSTGRES_DB: agentauth | |
| ports: | |
| - 5434:5432 | |
| options: >- | |
| --health-cmd pg_isready | |
| --health-interval 10s | |
| --health-timeout 5s | |
| --health-retries 5 | |
| redis: | |
| image: redis:7-alpine | |
| ports: | |
| - 6379:6379 | |
| options: >- | |
| --health-cmd "redis-cli ping" | |
| --health-interval 10s | |
| --health-timeout 5s | |
| --health-retries 5 | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Install k6 | |
| run: | | |
| sudo gpg -k | |
| sudo gpg --no-default-keyring --keyring /usr/share/keyrings/k6-archive-keyring.gpg --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys C5AD17C747E3415A3642D57D77C6C491D6AC1D69 | |
| echo "deb [signed-by=/usr/share/keyrings/k6-archive-keyring.gpg] https://dl.k6.io/deb stable main" | sudo tee /etc/apt/sources.list.d/k6.list | |
| sudo apt-get update | |
| sudo apt-get install k6 | |
| - name: Run load tests | |
| run: | | |
| if [ -f "load-tests/token-verify.js" ]; then | |
| k6 run --vus 10 --duration 30s load-tests/token-verify.js | |
| else | |
| echo "::warning::No load tests found" | |
| fi | |
| # Summary job | |
| ci-success: | |
| name: CI Success | |
| runs-on: ubuntu-latest | |
| needs: [rust-checks, integration-tests, security-patterns, docs] | |
| if: always() | |
| steps: | |
| - name: Check all jobs passed | |
| run: | | |
| if [ "${{ needs.rust-checks.result }}" != "success" ] || \ | |
| [ "${{ needs.integration-tests.result }}" != "success" ] || \ | |
| [ "${{ needs.security-patterns.result }}" != "success" ] || \ | |
| [ "${{ needs.docs.result }}" != "success" ]; then | |
| echo "One or more jobs failed" | |
| exit 1 | |
| fi | |
| echo "All CI checks passed!" |