feat(cel): bind request.body_json + on_match.deny (ADR-0030 prereqs) #332
Workflow file for this run
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: | |
| push: | |
| branches: [main] | |
| pull_request: | |
| branches: [main] | |
| issue_comment: | |
| types: [created] | |
| env: | |
| CARGO_TERM_COLOR: always | |
| RUST_BACKTRACE: 1 | |
| jobs: | |
| # Detect what files changed to skip unnecessary jobs | |
| changes: | |
| name: Detect Changes | |
| if: github.event_name != 'issue_comment' | |
| runs-on: ubuntu-latest | |
| outputs: | |
| code: ${{ steps.filter.outputs.code }} | |
| plugins: ${{ steps.filter.outputs.plugins }} | |
| ui: ${{ steps.filter.outputs.ui }} | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - uses: dorny/paths-filter@v4 | |
| id: filter | |
| with: | |
| filters: | | |
| code: | |
| - '**/*.rs' | |
| - '**/Cargo.toml' | |
| - '**/Cargo.lock' | |
| - 'plugins/**' | |
| - '.github/workflows/ci.yml' | |
| plugins: | |
| - 'plugins/**' | |
| - 'crates/barbacane-plugin-sdk/**' | |
| - 'crates/barbacane-plugin-macros/**' | |
| ui: | |
| - 'ui/**' | |
| - '.github/workflows/ci.yml' | |
| # Fast checks first (format, clippy) for quick feedback | |
| fmt: | |
| name: Format | |
| runs-on: ubuntu-latest | |
| needs: [changes] | |
| if: needs.changes.outputs.code == 'true' | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Install Rust toolchain | |
| uses: dtolnay/rust-toolchain@stable | |
| with: | |
| components: rustfmt | |
| - name: Check formatting | |
| run: cargo fmt --all -- --check | |
| clippy: | |
| name: Clippy | |
| runs-on: ubuntu-latest | |
| needs: [changes] | |
| if: needs.changes.outputs.code == 'true' | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Install Rust toolchain | |
| uses: dtolnay/rust-toolchain@stable | |
| with: | |
| components: clippy | |
| - name: Cache cargo registry | |
| uses: actions/cache@v5 | |
| with: | |
| path: | | |
| ~/.cargo/registry | |
| ~/.cargo/git | |
| target | |
| key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} | |
| restore-keys: | | |
| ${{ runner.os }}-cargo- | |
| - name: Run Clippy | |
| run: cargo clippy --workspace --lib --bins -- -D warnings | |
| # Security audit via cargo-deny (advisories configured in deny.toml) | |
| audit: | |
| name: Security Audit | |
| runs-on: ubuntu-latest | |
| needs: [changes] | |
| if: needs.changes.outputs.code == 'true' | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Install cargo-deny | |
| run: cargo install cargo-deny --locked | |
| - name: Run security audit | |
| run: cargo deny check advisories | |
| # Build workspace and plugins, upload artifacts for test job | |
| build: | |
| name: Build | |
| runs-on: ubuntu-latest | |
| needs: [changes] | |
| if: needs.changes.outputs.code == 'true' | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Install Rust toolchain | |
| uses: dtolnay/rust-toolchain@stable | |
| with: | |
| targets: wasm32-unknown-unknown | |
| - name: Cache cargo registry | |
| uses: actions/cache@v5 | |
| with: | |
| path: | | |
| ~/.cargo/registry | |
| ~/.cargo/git | |
| target | |
| key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} | |
| restore-keys: | | |
| ${{ runner.os }}-cargo- | |
| - name: Cache WASM plugins | |
| uses: actions/cache@v5 | |
| id: plugin-cache | |
| with: | |
| path: | | |
| plugins/*/*.wasm | |
| plugins/*/target | |
| key: ${{ runner.os }}-plugins-${{ hashFiles('plugins/**/Cargo.toml', 'plugins/**/Cargo.lock', 'plugins/**/*.rs', 'crates/barbacane-plugin-sdk/**') }} | |
| - name: Build workspace | |
| run: cargo build --workspace --all-targets | |
| - name: Build WASM plugins | |
| if: steps.plugin-cache.outputs.cache-hit != 'true' | |
| run: make plugins | |
| - name: Upload build artifacts | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: build-artifacts | |
| path: | | |
| target/debug/barbacane | |
| plugins/*/*.wasm | |
| retention-days: 1 | |
| # Unit tests (fast, no external dependencies) | |
| unit-tests: | |
| name: Unit Tests | |
| runs-on: ubuntu-latest | |
| needs: [changes, fmt, clippy, build] | |
| if: needs.changes.outputs.code == 'true' | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Install Rust toolchain | |
| uses: dtolnay/rust-toolchain@stable | |
| - name: Cache cargo registry | |
| uses: actions/cache@v5 | |
| with: | |
| path: | | |
| ~/.cargo/registry | |
| ~/.cargo/git | |
| target | |
| key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} | |
| restore-keys: | | |
| ${{ runner.os }}-cargo- | |
| - name: Run unit tests | |
| # Exclude barbacane-test as it contains integration tests requiring gateway binary | |
| run: cargo test --workspace --lib --bins --exclude barbacane-test -- --test-threads=4 | |
| # Control plane API tests (require PostgreSQL) | |
| control-plane-tests: | |
| name: Control Plane Tests | |
| runs-on: ubuntu-latest | |
| needs: [changes, fmt, clippy, build] | |
| if: needs.changes.outputs.code == 'true' | |
| services: | |
| postgres: | |
| image: postgres:16 | |
| env: | |
| POSTGRES_USER: barbacane | |
| POSTGRES_PASSWORD: barbacane | |
| POSTGRES_DB: barbacane | |
| options: >- | |
| --health-cmd pg_isready | |
| --health-interval 5s | |
| --health-timeout 5s | |
| --health-retries 5 | |
| ports: | |
| - 5432:5432 | |
| env: | |
| DATABASE_URL: postgres://barbacane:barbacane@localhost:5432/barbacane | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Install Rust toolchain | |
| uses: dtolnay/rust-toolchain@stable | |
| - name: Cache cargo registry | |
| uses: actions/cache@v5 | |
| with: | |
| path: | | |
| ~/.cargo/registry | |
| ~/.cargo/git | |
| target | |
| key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} | |
| restore-keys: | | |
| ${{ runner.os }}-cargo- | |
| - name: Run control plane tests | |
| run: cargo test -p barbacane-control -- --test-threads=4 | |
| # Plugin unit tests (only when plugin or SDK code changes) | |
| plugin-tests: | |
| name: Plugin Tests | |
| runs-on: ubuntu-latest | |
| needs: [changes, fmt] | |
| if: needs.changes.outputs.plugins == 'true' | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Install Rust toolchain | |
| uses: dtolnay/rust-toolchain@stable | |
| - name: Cache cargo registry | |
| uses: actions/cache@v5 | |
| with: | |
| path: | | |
| ~/.cargo/registry | |
| ~/.cargo/git | |
| key: ${{ runner.os }}-cargo-plugins-${{ hashFiles('plugins/**/Cargo.lock') }} | |
| restore-keys: | | |
| ${{ runner.os }}-cargo-plugins- | |
| - name: Run plugin tests | |
| run: | | |
| failed=0 | |
| for p in plugins/*/; do | |
| name=$(basename "$p") | |
| echo "::group::$name" | |
| if ! (cd "$p" && cargo test 2>&1); then | |
| echo "::error::Plugin $name tests failed" | |
| failed=1 | |
| fi | |
| echo "::endgroup::" | |
| done | |
| exit $failed | |
| # Integration tests (slower, requires gateway binary and plugins) | |
| integration-tests: | |
| name: Integration Tests | |
| runs-on: ubuntu-latest | |
| needs: [changes, unit-tests] | |
| if: needs.changes.outputs.code == 'true' | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Install Rust toolchain | |
| uses: dtolnay/rust-toolchain@stable | |
| - name: Cache cargo registry | |
| uses: actions/cache@v5 | |
| with: | |
| path: | | |
| ~/.cargo/registry | |
| ~/.cargo/git | |
| target | |
| key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} | |
| restore-keys: | | |
| ${{ runner.os }}-cargo- | |
| - name: Download build artifacts | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: build-artifacts | |
| - name: Make binary executable | |
| run: chmod +x target/debug/barbacane | |
| - name: Run integration tests | |
| # Run gateway integration tests from barbacane-test crate | |
| run: cargo test -p barbacane-test --lib -- --test-threads=2 | |
| # Benchmark regression check | |
| # Triggered by: adding the "run-benchmarks" label, or commenting "/bench" on a PR. | |
| benchmarks: | |
| name: Benchmark Check | |
| runs-on: ubuntu-latest | |
| if: >- | |
| (github.event_name == 'pull_request' && contains(github.event.pull_request.labels.*.name, 'run-benchmarks')) | |
| || (github.event_name == 'issue_comment' && github.event.issue.pull_request | |
| && contains(github.event.comment.body, '/bench')) | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| # For issue_comment events, check out the PR head | |
| ref: ${{ github.event_name == 'issue_comment' && format('refs/pull/{0}/head', github.event.issue.number) || '' }} | |
| - name: Install Rust toolchain | |
| uses: dtolnay/rust-toolchain@stable | |
| - name: Cache cargo registry | |
| uses: actions/cache@v5 | |
| with: | |
| path: | | |
| ~/.cargo/registry | |
| ~/.cargo/git | |
| target | |
| key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} | |
| restore-keys: | | |
| ${{ runner.os }}-cargo- | |
| - name: Cache benchmark baselines | |
| uses: actions/cache@v5 | |
| with: | |
| path: target/criterion | |
| key: ${{ runner.os }}-criterion-${{ github.base_ref }} | |
| restore-keys: | | |
| ${{ runner.os }}-criterion-main | |
| - name: Run benchmarks | |
| run: | | |
| cargo bench -p barbacane -p barbacane-compiler -p barbacane-wasm 2>&1 | tee /tmp/bench-output.txt | |
| - name: Parse benchmark results | |
| run: | | |
| # Extract benchmark results into a GitHub Step Summary table. | |
| # Criterion output format (name and stats on separate lines): | |
| # bench_group/bench_name/size | |
| # time: [low est high] | |
| # change: [low% mid% high%] (p = ...) | |
| # Performance has regressed/improved. | |
| echo "## Benchmark Results" >> "$GITHUB_STEP_SUMMARY" | |
| echo "" >> "$GITHUB_STEP_SUMMARY" | |
| regressed=$(grep -c "Performance has regressed" /tmp/bench-output.txt || true) | |
| improved=$(grep -c "Performance has improved" /tmp/bench-output.txt || true) | |
| no_change=$(grep -c "No change in performance" /tmp/bench-output.txt || true) | |
| if [ "$regressed" -gt 0 ]; then | |
| echo "> [!WARNING]" >> "$GITHUB_STEP_SUMMARY" | |
| echo "> **$regressed** benchmark(s) regressed, **$improved** improved, **$no_change** unchanged" >> "$GITHUB_STEP_SUMMARY" | |
| else | |
| echo "> **$improved** improved, **$no_change** unchanged, no regressions" >> "$GITHUB_STEP_SUMMARY" | |
| fi | |
| echo "" >> "$GITHUB_STEP_SUMMARY" | |
| echo "| Benchmark | Time (est) | Change | Verdict |" >> "$GITHUB_STEP_SUMMARY" | |
| echo "|-----------|-----------|--------|---------|" >> "$GITHUB_STEP_SUMMARY" | |
| # Parse criterion output into table rows. | |
| # Criterion uses two formats depending on benchmark name length: | |
| # Multi-line: bench_name\n time: [low est high] | |
| # Single-line: bench_name time: [low est high] | |
| # Both followed by change: and verdict lines. | |
| perl -ne ' | |
| if (/^[A-Za-z_]/ && /\// && !/time:/ && !/^(?:Benchmarking|Found |Gnuplot)/) { | |
| chomp; $name = $_; $name =~ s/^\s+|\s+$//g; | |
| } | |
| if (/^[A-Za-z_]/ && /\// && /time:/ && !/^Benchmarking/) { | |
| chomp; $name = $_; $name =~ s/\s*time:.*//; $name =~ s/^\s+|\s+$//g; | |
| } | |
| if (/time:/ && /\[/) { | |
| /\[([^\]]+)\]/; @t = split(/\s+/, $1); | |
| $time_est = "$t[2] $t[3]"; | |
| } | |
| if (/change:/ && /\[/) { | |
| /\[([^\]]+)\]/; @p = split(/\s+/, $1); | |
| $change = $p[1]; | |
| } | |
| if (/Performance has regressed/) { | |
| printf "| \x60%s\x60 | %s | %s | :red_circle: regressed |\n", $name, $time_est, $change; | |
| } | |
| if (/Performance has improved/) { | |
| printf "| \x60%s\x60 | %s | %s | :green_circle: improved |\n", $name, $time_est, $change; | |
| } | |
| if (/No change in performance/) { | |
| printf "| \x60%s\x60 | %s | %s | :white_circle: no change |\n", $name, $time_est, $change; | |
| } | |
| ' /tmp/bench-output.txt >> "$GITHUB_STEP_SUMMARY" | |
| echo "" >> "$GITHUB_STEP_SUMMARY" | |
| if [ "$regressed" -gt 0 ]; then | |
| echo "::warning::$regressed benchmark(s) regressed — see job summary for details" | |
| fi | |
| # UI unit tests (build + vitest) | |
| ui-tests: | |
| name: UI Tests | |
| runs-on: ubuntu-latest | |
| needs: [changes] | |
| if: needs.changes.outputs.ui == 'true' | |
| defaults: | |
| run: | |
| working-directory: ui | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v6 | |
| with: | |
| node-version: 22 | |
| cache: npm | |
| cache-dependency-path: ui/package-lock.json | |
| - name: Install dependencies | |
| run: npm ci | |
| - name: Type check & build | |
| run: npm run build | |
| - name: Run unit tests | |
| run: npm test | |
| # UI E2E tests (Playwright) | |
| ui-e2e: | |
| name: UI E2E Tests | |
| runs-on: ubuntu-latest | |
| needs: [changes, ui-tests] | |
| if: needs.changes.outputs.ui == 'true' | |
| defaults: | |
| run: | |
| working-directory: ui | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v6 | |
| with: | |
| node-version: 22 | |
| cache: npm | |
| cache-dependency-path: ui/package-lock.json | |
| - name: Install dependencies | |
| run: npm ci | |
| - name: Install Playwright browsers | |
| run: npx playwright install --with-deps chromium | |
| - name: Run E2E tests | |
| run: npx playwright test --project=chromium | |
| - name: Upload test report | |
| uses: actions/upload-artifact@v7 | |
| if: failure() | |
| with: | |
| name: playwright-report | |
| path: ui/playwright-report/ | |
| retention-days: 7 |