hallouminate 0.2.3

A markdown corpus indexer for LLMs to build and query their own per-repo wikis.
name: CI

on:
  push:
    branches: [main]
  pull_request:

env:
  CARGO_TERM_COLOR: always

jobs:
  fmt:
    name: fmt
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
      - name: Install Rust toolchain
        # installs the channel pinned in rust-toolchain.toml (the crate's MSRV)
        run: rustup show && rustup component add rustfmt
      - run: cargo fmt --all --check

  clippy:
    name: clippy
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
      - name: Install protoc
        # lance-encoding (via lancedb) runs a build script that needs protoc
        run: sudo apt-get update && sudo apt-get install -y protobuf-compiler
      - name: Install Rust toolchain
        run: rustup show && rustup component add clippy
      - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2
      - name: Clippy
        run: cargo clippy --locked --all-targets --all-features -- -D warnings

  build-test-matrix:
    name: build & test (${{ matrix.os }})
    # Unix only: the crate is unix-only (libc path handling won't compile on
    # Windows — tracked in #48).
    strategy:
      fail-fast: false
      matrix:
        os: [ubuntu-latest, macos-latest]
    runs-on: ${{ matrix.os }}
    steps:
      - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
      - name: Install protoc
        # cross-platform protoc (apt-get is Linux-only); lancedb needs it
        uses: arduino/setup-protoc@c65c819552d16ad3c9b72d9dfd5ba5237b9c906b # v3
        with:
          repo-token: ${{ secrets.GITHUB_TOKEN }}
      - name: Install Rust toolchain
        run: rustup show
      - name: Expose Xcode compiler runtime
        if: runner.os == 'macOS'
        run: |
          set -euo pipefail
          clang_bin="$(xcrun --toolchain XcodeDefault --find clang)"
          clang_usr="$(dirname "$(dirname "$clang_bin")")"
          runtime_dir="$(find "$clang_usr/lib/clang" -type d -path '*/lib/darwin' | sort | tail -n 1)"
          if [ -z "$runtime_dir" ]; then
            echo "::error::could not find Xcode compiler runtime under $clang_usr/lib/clang"
            exit 1
          fi
          echo "LIBRARY_PATH=$runtime_dir${LIBRARY_PATH:+:$LIBRARY_PATH}" >> "$GITHUB_ENV"
      - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2
      - name: Cache Hugging Face tokenizer downloads
        # DaemonState::open hard-loads the HF tokenizer (chunking needs it
        # regardless of embedding mode), so non-ignored tests fetch it from
        # huggingface.co on a cold cache. Persist the hub cache across runs so
        # the tokenizer is downloaded at most once per key.
        uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
        with:
          path: ~/.cache/huggingface
          key: hf-hub-${{ runner.os }}-arctic-embed-s
      - name: Build
        run: cargo build --locked --all-targets
      - name: Warm tokenizer cache
        # Fetch the tokenizer once, serially, with backoff. Without this the
        # parallel test threads each call huggingface.co at startup and trip
        # its rate limiter (HTTP 429) — the failure that reddened the ubuntu leg.
        run: |
          set -euo pipefail
          printf '[embeddings]\nenabled = false\n' > "${RUNNER_TEMP}/hf-warm.toml"
          for attempt in 1 2 3 4 5; do
            if cargo run --locked --quiet -- config download --config "${RUNNER_TEMP}/hf-warm.toml"; then
              exit 0
            fi
            echo "tokenizer warm attempt ${attempt} failed; retrying after backoff"
            sleep $(( attempt * 20 ))
          done
          echo "::error::could not warm the tokenizer cache after 5 attempts"
          exit 1
      - name: Test
        # Offline so the warmed cache is served locally and the parallel test
        # burst makes zero network calls. Safe: every model-downloading test is
        # #[ignore]-gated and is not run here.
        env:
          HF_HUB_OFFLINE: "1"
        run: cargo test --locked

  # Aggregation gate: the branch ruleset requires a single status check named
  # "build & test", but the matrix expands to "build & test (ubuntu-latest)" etc.
  # This job collapses the matrix into one required context and fails unless
  # every matrix leg succeeded — so the required check stays stable when the
  # matrix gains or loses an OS.
  build-test:
    name: build & test
    needs: build-test-matrix
    if: always()
    runs-on: ubuntu-latest
    steps:
      - name: Require all matrix legs to pass
        if: needs.build-test-matrix.result != 'success'
        run: exit 1