bbtree 0.1.2

Blessed B-tree.
Documentation
# Named for its README badge, as are miri.yml, sanitizer.yml, shuttle.yml,
# fuzz.yml and verus.yml.
name: test

on:
  push:
    branches: [main]
  pull_request:

# Cancel a pull request's superseded runs. Every commit on main finishes its
# run, so the README badge reports it.
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: ${{ github.event_name == 'pull_request' }}

env:
  CARGO_TERM_COLOR: always
  RUST_BACKTRACE: 1

permissions:
  contents: read
  # For the release fuzzing to fetch the corpora that earlier runs saved.
  actions: read

jobs:
  # Whether this pull request is a release: one that changes the package
  # version (.github/actions/version-change). A release must also pass the
  # `release-` jobs.
  plan:
    name: plan
    runs-on: ubuntu-latest
    outputs:
      release: ${{ steps.version.outputs.changed || 'false' }}
    steps:
      - uses: actions/checkout@v4

      - id: version
        if: github.event_name == 'pull_request'
        uses: ./.github/actions/version-change
        with:
          base: ${{ github.event.pull_request.base.sha }}

  check:
    name: fmt + clippy + test
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      # Keep this exact nightly aligned with flake.nix.
      - name: Install Rust (nightly-2026-10-07)
        uses: dtolnay/rust-toolchain@master
        with:
          toolchain: nightly-2026-10-07
          components: rustfmt, clippy

      - uses: Swatinem/rust-cache@v2

      - name: Format
        run: cargo fmt --all -- --check

      - name: Clippy
        run: cargo clippy --workspace --all-targets --all-features -- -D warnings

      - name: Test
        run: cargo test --workspace --all-features

  bench:
    name: bench (fmt + clippy + test + quick run)
    runs-on: ubuntu-latest
    defaults:
      run:
        working-directory: bench
    steps:
      - uses: actions/checkout@v4

      # Keep this exact nightly aligned with flake.nix.
      - name: Install Rust (nightly-2026-10-07)
        uses: dtolnay/rust-toolchain@master
        with:
          toolchain: nightly-2026-10-07
          components: rustfmt, clippy

      # The bench builds for the runner's CPU (bench/.cargo/config.toml), and
      # runners differ: a build cached on one with AVX-512 dies of SIGILL on
      # one without. So each instruction set gets its own cache.
      - name: Identify the CPU's instruction set
        id: cpu
        run: echo "flags=$(grep -m1 '^flags' /proc/cpuinfo | sha256sum | cut -c1-16)" >> "$GITHUB_OUTPUT"

      - uses: Swatinem/rust-cache@v2
        with:
          workspaces: bench
          key: cpu-${{ steps.cpu.outputs.flags }}

      - name: Format
        run: cargo fmt --all -- --check

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

      - name: Test
        run: cargo test

      # Keeps the suite building and running as the library's API changes;
      # timings on a shared runner mean nothing.
      - name: Quick run
        run: |
          cargo run --release --bin bbtree-bench -- small --quick
          cargo run --release --bin bbtree-bench-memory -- small --quick

      # CI has no datasets: their cells must be reported as missing data
      # while the rest of the suite runs.
      - name: Quick run without datasets
        env:
          BBTREE_BENCH_DATA: ${{ runner.temp }}/no-bench-data
        run: cargo run --release --bin bbtree-bench -- realkeys tiny --quick --map bbtree-unsync

  fuzz:
    name: fuzz harness (fmt + clippy + test)
    runs-on: ubuntu-latest
    defaults:
      run:
        working-directory: fuzz
    steps:
      - uses: actions/checkout@v4

      # Keep this exact nightly aligned with flake.nix.
      - name: Install Rust (nightly-2026-10-07)
        uses: dtolnay/rust-toolchain@master
        with:
          toolchain: nightly-2026-10-07
          components: rustfmt, clippy

      - uses: Swatinem/rust-cache@v2
        with:
          workspaces: fuzz

      # The structural checks that the fuzz targets call, which only fuzzing
      # builds (`--cfg fuzzing`) compile.
      - name: Clippy (library, fuzzing build)
        working-directory: .
        run: cargo clippy --all-features -- -D warnings
        env:
          RUSTFLAGS: --cfg fuzzing

      - name: Format
        run: cargo fmt --all -- --check

      # `fuzz/.cargo/config.toml` builds with `--cfg fuzzing`, as cargo-fuzz
      # does.
      - name: Clippy
        run: cargo clippy --all-targets -- -D warnings

      # The harnesses on pseudo-random inputs, and every crash kept in
      # `regressions/`. The fuzzing itself runs weekly and for every release
      # (fuzz.yml).
      - name: Test
        run: cargo test

  # The library's tests on other platforms. On ARM, the portable code runs
  # where x86 has SIMD. On macOS, Apple's chips run it, with their 128-byte
  # cache lines and 16 KiB pages, and macOS's own allocator. On wasm, pointers
  # are 32 bits, a panic aborts and there are no threads, so tests that
  # assume 64-bit pointers, need unwinding or spawn threads are ignored
  # there.
  test-aarch64:
    name: test (aarch64)
    runs-on: ubuntu-24.04-arm
    steps:
      - uses: actions/checkout@v4

      # Keep this exact nightly aligned with flake.nix.
      - name: Install Rust (nightly-2026-10-07)
        uses: dtolnay/rust-toolchain@master
        with:
          toolchain: nightly-2026-10-07

      - uses: Swatinem/rust-cache@v2

      - name: Test
        run: cargo test --lib --all-features

  test-macos:
    name: test (macOS)
    runs-on: macos-latest
    steps:
      - uses: actions/checkout@v4

      # Keep this exact nightly aligned with flake.nix.
      - name: Install Rust (nightly-2026-10-07)
        uses: dtolnay/rust-toolchain@master
        with:
          toolchain: nightly-2026-10-07

      - uses: Swatinem/rust-cache@v2

      - name: Test
        run: cargo test --workspace --all-features

  test-wasm:
    name: test (wasm32-wasip1)
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      # Keep this exact nightly aligned with flake.nix.
      - name: Install Rust (nightly-2026-10-07)
        uses: dtolnay/rust-toolchain@master
        with:
          toolchain: nightly-2026-10-07
          targets: wasm32-wasip1

      - name: Install wasmtime
        uses: taiki-e/install-action@v2
        with:
          tool: wasmtime

      - uses: Swatinem/rust-cache@v2

      - name: Test
        env:
          CARGO_TARGET_WASM32_WASIP1_RUNNER: wasmtime
          # The tests run on the main thread, whose stack wasm-ld makes 1 MiB,
          # and an overflow there faults far from the cause. Debug builds of
          # walks over page-aligned values need about 1.25 MiB; give the 8 MiB
          # of a native main thread.
          CARGO_TARGET_WASM32_WASIP1_RUSTFLAGS: -C link-arg=-zstack-size=8388608
        run: cargo test --target wasm32-wasip1 --lib --all-features

  # The release checks: the fuzzing takes half an hour on the shared runner,
  # so it runs for releases (and weekly, in fuzz.yml) rather than for every
  # change.
  release-fuzz:
    name: release fuzz
    needs: plan
    if: needs.plan.outputs.release == 'true'
    uses: ./.github/workflows/fuzz.yml
    with:
      minutes: 30

  release-package:
    name: release package
    needs: plan
    if: needs.plan.outputs.release == 'true'
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      # Keep this exact nightly aligned with flake.nix.
      - name: Install Rust (nightly-2026-10-07)
        uses: dtolnay/rust-toolchain@master
        with:
          toolchain: nightly-2026-10-07

      # What `cargo publish` will upload, built from those files alone, so
      # that publishing after the merge doesn't fail on the package.
      - name: Package
        run: cargo publish --dry-run --locked

  # This workflow's one required check (.github/rulesets/main.json), so the
  # jobs above can change without touching the ruleset. It always runs: a
  # required check that is skipped counts as passed. Miri, the sanitizer and
  # Shuttle are required checks of their own (miri.yml, sanitizer.yml,
  # shuttle.yml), as Verus will be.
  merge-gate:
    name: merge gate
    if: always()
    needs: [plan, check, bench, fuzz, test-aarch64, test-macos, test-wasm, release-fuzz, release-package]
    runs-on: ubuntu-latest
    steps:
      - name: Check that every job passed
        env:
          RELEASE: ${{ needs.plan.outputs.release }}
          RESULTS: ${{ toJSON(needs) }}
        run: |
          # A change that isn't a release skips the `release-` jobs; every
          # other result must be a pass.
          not_passed=$(jq -r --arg release "$RELEASE" '
            [ to_entries[]
              | select(.value.result != "success")
              | select(($release == "false"
                  and (.key | startswith("release-"))
                  and .value.result == "skipped") | not)
              | "\(.key): \(.value.result)" ]
            | join(", ")' <<< "$RESULTS")
          if [ -n "$not_passed" ]; then
            echo "::error::Not passed: $not_passed"
            exit 1
          fi