fix(python): restore deterministic teardown for async-callback machinery #4140
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] | |
| workflow_call: | |
| permissions: | |
| contents: read | |
| checks: write | |
| env: | |
| CARGO_TERM_COLOR: always | |
| RUST_BACKTRACE: 1 | |
| RG_VERSION: 15.1.0 | |
| jobs: | |
| lint: | |
| name: Lint | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 | |
| - name: Install Rust toolchain | |
| uses: dtolnay/rust-toolchain@e081816240890017053eacbb1bdf337761dc5582 # 1.95.0 | |
| with: | |
| components: rustfmt, clippy | |
| - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 | |
| - name: Check formatting | |
| run: cargo fmt --all -- --check | |
| - name: Run clippy | |
| run: cargo clippy --all-targets --all-features -- -D warnings | |
| - name: Build documentation | |
| run: cargo doc --no-deps --all-features | |
| env: | |
| RUSTDOCFLAGS: "-D warnings" | |
| audit: | |
| name: Audit | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 | |
| - name: Install Rust toolchain | |
| uses: dtolnay/rust-toolchain@e081816240890017053eacbb1bdf337761dc5582 # 1.95.0 | |
| - name: Security audit (cargo-audit) | |
| uses: rustsec/audit-check@69366f33c96575abad1ee0dba8212993eecbe998 # v2.0.0 | |
| with: | |
| token: ${{ secrets.GITHUB_TOKEN }} | |
| ignore: RUSTSEC-2023-0071 | |
| - name: License check (cargo-deny) | |
| uses: EmbarkStudios/cargo-deny-action@bb137d7af7e4fb67e5f82a49c4fce4fad40782fe # v2 | |
| with: | |
| command: check licenses sources | |
| - name: Install cargo-vet | |
| uses: taiki-e/install-action@4bc351f7f2614e48088386e2a0ad917ca3a7e4ba # v2 | |
| with: | |
| tool: cargo-vet | |
| - name: Supply chain audit (cargo-vet) | |
| run: cargo vet --locked | |
| test: | |
| name: Test | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 | |
| - name: Install Rust toolchain | |
| uses: dtolnay/rust-toolchain@e081816240890017053eacbb1bdf337761dc5582 # 1.95.0 | |
| - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 | |
| # Pre-installed on `ubuntu-latest` images, but make the dependency | |
| # explicit so a future runner image change can't silently turn the | |
| # `sqlite_differential_tests` suite into a no-op (it skips when | |
| # `sqlite3` isn't on PATH). | |
| - name: Install host sqlite3 for differential tests | |
| run: | | |
| which sqlite3 || sudo apt-get update && sudo apt-get install -y sqlite3 | |
| sqlite3 --version | |
| # Install the uutils multicall binary for | |
| # `coreutils_differential_tests`. The harness gracefully skips when | |
| # the binary is unavailable, so `continue-on-error` keeps the | |
| # regular Test job green when the upstream install action has a | |
| # bad day — the drift workflow (`coreutils-args-drift.yml`) is the | |
| # authoritative body-drift gate, building uutils from the pinned | |
| # tree before running the harness. | |
| - name: Install uutils coreutils multicall for differential tests | |
| id: install_uutils | |
| continue-on-error: true | |
| uses: taiki-e/install-action@4bc351f7f2614e48088386e2a0ad917ca3a7e4ba # v2 | |
| with: | |
| tool: coreutils | |
| - name: Verify uutils on PATH | |
| if: steps.install_uutils.outcome == 'success' | |
| run: coreutils --version | |
| # `rg` differential tests compare against real ripgrep. Pin the | |
| # binary so upstream formatting/path semantics cannot drift under CI. | |
| - name: Install pinned ripgrep for differential tests | |
| run: scripts/install-ripgrep-ci.sh "$RG_VERSION" | |
| # Examples have a dedicated job below; skipping them here avoids | |
| # duplicated example links that can exhaust runner disk on main. | |
| - name: Run tests | |
| run: cargo test --workspace --lib --bins --tests --features http_client,ssh,sqlite | |
| - name: Run strict bash parity tests | |
| run: cargo test -p bashkit --test integration --features http_client,ssh -- spec_tests::bash_comparison_tests --ignored | |
| - name: Run doc tests | |
| run: cargo test --workspace --doc --features http_client,ssh,sqlite | |
| - name: Run realfs tests | |
| run: cargo test --features realfs -p bashkit --test realfs_tests -p bashkit-cli | |
| - name: Run fail-point tests (single-threaded) | |
| run: cargo test --features failpoints --test security_failpoint_tests -- --test-threads=1 | |
| - name: Run property-based security tests (proptest) | |
| run: cargo test --test proptest_security -- --test-threads=1 | |
| env: | |
| PROPTEST_CASES: 50 | |
| examples: | |
| name: Examples | |
| runs-on: ubuntu-latest | |
| # Secret guard: only expose Doppler/API keys on push to main (trusted | |
| # code). PRs — including same-repo branches — execute PR-controlled | |
| # code (examples, build.rs, scripts) and must never see secrets. | |
| # `github.event_name == 'push'` is the only reliable gate; the old | |
| # `head.repo.fork != true` check passes for same-repo PRs and for | |
| # workflow_call events where pull_request context is absent. | |
| steps: | |
| - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 | |
| - name: Install Rust toolchain | |
| uses: dtolnay/rust-toolchain@e081816240890017053eacbb1bdf337761dc5582 # 1.95.0 | |
| - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 | |
| - name: Build examples | |
| run: cargo build --examples --features "git,http_client,ssh,sqlite" | |
| - name: Run examples | |
| run: | | |
| cargo run --example basic | |
| cargo run --example custom_fs | |
| cargo run --example clap_builtin | |
| cargo run --example clap_builtin_subcommands | |
| cargo run --example resource_limits | |
| cargo run --example text_processing | |
| cargo run --example live_mounts | |
| cargo run --example git_workflow --features git | |
| cargo run --example python_external_functions --features python | |
| cargo run --example typescript_external_functions --features typescript | |
| cargo run --example realfs_readonly --features realfs | |
| cargo run --example realfs_readwrite --features realfs | |
| cargo run --example sqlite_basic --features sqlite | |
| cargo run --example sqlite_workflow --features sqlite | |
| # SSH tests | |
| - name: Run ssh builtin tests (mock handler) | |
| run: cargo test --features ssh -p bashkit --test ssh_builtin_tests | |
| - name: Run ssh supabase.sh example and tests | |
| run: | | |
| cargo run --example ssh_supabase --features ssh | |
| cargo test --features ssh -p bashkit --test ssh_supabase_tests | |
| - name: Run realfs bash example | |
| run: | | |
| cargo build -p bashkit-cli --features realfs | |
| bash examples/realfs_mount.sh | |
| - name: Run ticket CLI example | |
| env: | |
| TICKET_REF: 194b71a8bbc3771da1ce9f579395937c976bbddc | |
| run: bash examples/ticket-cli.sh | |
| # Detect whether DOPPLER_TOKEN is configured. Only set on push to | |
| # main (trusted code); PRs — including same-repo branches — must | |
| # never see the secret. Subsequent Doppler steps gate on | |
| # `env.DOPPLER_AVAILABLE` so this job stays green when unconfigured. | |
| - name: Detect Doppler availability (trusted runs only) | |
| if: github.event_name == 'push' | |
| env: | |
| DOPPLER_TOKEN: ${{ secrets.DOPPLER_TOKEN }} | |
| run: | | |
| if [ -n "$DOPPLER_TOKEN" ]; then | |
| echo "DOPPLER_AVAILABLE=true" >> "$GITHUB_ENV" | |
| fi | |
| - name: Install Doppler CLI | |
| if: github.event_name == 'push' && env.DOPPLER_AVAILABLE == 'true' | |
| env: | |
| DOPPLER_TOKEN: ${{ secrets.DOPPLER_TOKEN }} | |
| uses: dopplerhq/cli-action@4819d808ab99e5cde19a0637a16536a4038fad73 # v4 | |
| # External API dependency — don't block CI on Anthropic outages. | |
| # ANTHROPIC_API_KEY is sourced from Doppler (single source of truth | |
| # for non-GitHub secrets), so this step also requires Doppler to be | |
| # available, which already implies a push to main. | |
| # `--only-secrets` keeps the principle of least privilege: the | |
| # step sees ANTHROPIC_API_KEY only, not every secret in Doppler. | |
| - name: Run LLM agent example | |
| if: github.event_name == 'push' && env.DOPPLER_AVAILABLE == 'true' | |
| continue-on-error: true | |
| env: | |
| DOPPLER_TOKEN: ${{ secrets.DOPPLER_TOKEN }} | |
| run: doppler run --only-secrets ANTHROPIC_API_KEY -- cargo run --example agent_tool --features http_client | |
| - name: Run harness OpenAI joke example | |
| if: github.event_name == 'push' && env.DOPPLER_AVAILABLE == 'true' | |
| env: | |
| DOPPLER_TOKEN: ${{ secrets.DOPPLER_TOKEN }} | |
| run: | | |
| cargo build -p bashkit-cli --features realfs --quiet | |
| doppler run --only-secrets OPENAI_API_KEY -- bash examples/harness-openai-joke.sh | |
| fuzz-check: | |
| name: Fuzz Compile Check | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 | |
| - name: Install Rust nightly | |
| uses: dtolnay/rust-toolchain@5b842231ba77f5c045dba54ac5560fed2db780e2 # nightly | |
| - name: Install cargo-fuzz | |
| uses: taiki-e/cache-cargo-install-action@417450f3c33ee20393705369577571770643d4c7 # v3 | |
| with: | |
| tool: cargo-fuzz | |
| locked: true | |
| - name: Verify fuzz targets compile | |
| working-directory: crates/bashkit | |
| run: cargo +nightly fuzz build | |
| # Gate job for branch protection — name must stay "Check" | |
| check: | |
| name: Check | |
| if: always() | |
| needs: [lint, audit, test, examples, fuzz-check] | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Verify all jobs passed | |
| run: | | |
| if [[ "${{ needs.lint.result }}" != "success" ]] || \ | |
| [[ "${{ needs.audit.result }}" != "success" ]] || \ | |
| [[ "${{ needs.test.result }}" != "success" ]] || \ | |
| [[ "${{ needs.examples.result }}" != "success" ]] || \ | |
| [[ "${{ needs.fuzz-check.result }}" != "success" ]]; then | |
| echo "One or more required jobs failed" | |
| exit 1 | |
| fi |