mirror of
https://github.com/lancedb/lancedb.git
synced 2026-08-18 20:18:37 +00:00
ff50e698cf
Standard GitHub-hosted runners are free on public repos, so all Actions spend here is on the `*-8x-*` / `4x` larger runners. Measured over 30 days at current (post-Jan-2026) larger-runner rates, that is ~$1,400/mo, and `npm-publish` is ~70% of it. ## Changes **Fat LTO was forcing builds onto large runners.** `[profile.release]` in `.cargo/config.toml` sets `lto = "fat"` with `codegen-units = 1`, which is single-threaded and the peak-memory step. The macOS `npm-publish` build was 111 of its 113 minutes in one `napi build` step, making it the critical path of the whole publish pipeline. The ThinLTO override already applied to Windows now covers macOS too, and both Windows builds move from `windows-2025-8x-x64` to the free standard `windows-2025`. **The npm-publish cargo cache never existed.** There are zero caches with its key prefix. The key was static, so `actions/cache` (which only writes on a miss) could never refresh it, and a multi-GB release `target/` per target could never fit the repo's 10 GB budget anyway. Now caches only the crate registry, keyed on `Cargo.lock`. The docker builds also mounted `.cargo/registry/*` while the cache saved `.cargo-cache`, so containers re-downloaded the registry every run. **Cache eviction thrash.** Repo cache usage is 10.4 GB against GitHub's 10 GB cap, so every PR run evicted main's warm entries. `rust.yml` and `nodejs.yml` now restore everywhere but only save from `main`. **npm-publish moves to nightly + tags** instead of every push to main (~90/month). The cross-compiled targets do need watching, so `report-failure` now fires on scheduled runs, and dedupes onto an existing open issue rather than filing one per night. **rust.yml aarch64-pc-windows-msvc** cross-compiled its tests and then skipped them, paying full codegen and link cost for a compile check. `windows-11-arm` is now GA and free on public repos, so it builds and tests natively. Its test step also passes `--target` — without it cargo used `target/ci/` rather than `target/<triple>/ci/` and rebuilt the entire dependency graph a second time. **pypi-publish.yml had no concurrency group**, so force-pushes left a ~74 minute Windows job running. ## What is cost vs. wall-clock | Change | Cost | Wall-clock | |---|---|---| | Windows npm-publish → free runners | **−$570/mo** | slower per job (8→4 cores) | | npm-publish nightly | **−$125/mo** | — | | pypi-publish concurrency | small | — | | macOS ThinLTO | $0 (already free) | **−~50 min** per release | | rust aarch64 Windows native | $0 (already free) | **−~25 min** | | rust `--target` on test step | $0 | large, avoids a second full build | | rust-cache `save-if` | small | faster via real cache hits | ## Risks - The two Windows builds now have 4 cores instead of 8 and ~14 GB of free disk. If they fail, it is most likely disk rather than memory; fallback is `windows-2025-4x-x64`, which still halves that line. - `windows-11-arm` has a thinner toolset (choco/vcpkg/protoc under emulation) and this enables a test step that has never run, so it may surface real aarch64 failures. That is the point, but it is the change most likely to need iteration. - ThinLTO applies to published macOS and Windows binaries, typically within a few percent of fat LTO. Linux release builds are untouched. ## Follow-ups - `python.yml` `pydantic1x` (37 min) and `Doctest` (33 min) each rebuild the extension from source via `pip install -e .` with no Rust cache; they should consume the wheel the `linux` job already builds. Worth ~$235/mo and ~70 min of compute per run. Separate PR. - The three `ubuntu-2404-8x-x64` npm-publish builds (~$420/mo at the old cadence) are the remaining large-runner spend; `aarch64-unknown-linux-gnu` could run natively on free `ubuntu-24.04-arm`. Worth doing after this lands so the ThinLTO change can be validated first. - The wheel composite actions declare `python-minor-version` as required but never use it, and every caller omits it (actionlint warns). 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
315 lines
12 KiB
YAML
315 lines
12 KiB
YAML
name: Rust
|
|
|
|
on:
|
|
push:
|
|
branches:
|
|
- main
|
|
pull_request:
|
|
paths:
|
|
- Cargo.toml
|
|
- Cargo.lock
|
|
- rust-toolchain.toml
|
|
- deny.toml
|
|
- rust/**
|
|
- nodejs/Cargo.toml
|
|
- python/Cargo.toml
|
|
- .github/workflows/rust.yml
|
|
|
|
permissions:
|
|
contents: read
|
|
|
|
concurrency:
|
|
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
|
cancel-in-progress: true
|
|
|
|
env:
|
|
# This env var is used by Swatinem/rust-cache@v2 for the cache
|
|
# key, so we set it to make sure it is always consistent.
|
|
CARGO_TERM_COLOR: always
|
|
RUST_BACKTRACE: "1"
|
|
|
|
jobs:
|
|
lint:
|
|
timeout-minutes: 30
|
|
runs-on: ubuntu-24.04
|
|
defaults:
|
|
run:
|
|
shell: bash
|
|
env:
|
|
# Need up-to-date compilers for kernels
|
|
CC: clang-18
|
|
CXX: clang++-18
|
|
steps:
|
|
- uses: actions/checkout@v6
|
|
with:
|
|
fetch-depth: 0
|
|
lfs: true
|
|
- uses: actions-rust-lang/setup-rust-toolchain@v1
|
|
with:
|
|
components: rustfmt, clippy
|
|
- uses: Swatinem/rust-cache@v2
|
|
with:
|
|
# Restore everywhere, but only save from main. Per-PR saves are
|
|
# unreadable outside their own branch anyway, since GitHub scopes
|
|
# caches to the creating ref.
|
|
save-if: ${{ github.ref == 'refs/heads/main' }}
|
|
- name: Install dependencies
|
|
run: |
|
|
sudo apt update
|
|
sudo apt install -y protobuf-compiler libssl-dev
|
|
- name: Run format
|
|
run: cargo fmt --all -- --check
|
|
- name: Run clippy
|
|
run: cargo clippy --profile ci --workspace --tests --all-features -- -D warnings
|
|
- name: Run clippy (without remote feature)
|
|
run: cargo clippy --profile ci --workspace --tests -- -D warnings
|
|
|
|
deny:
|
|
# Supply-chain checks: advisories, licenses, banned crates, and source
|
|
# restrictions. Configuration lives in `deny.toml` at the workspace root.
|
|
timeout-minutes: 10
|
|
runs-on: ubuntu-24.04
|
|
steps:
|
|
- uses: actions/checkout@v6
|
|
- uses: EmbarkStudios/cargo-deny-action@v2
|
|
with:
|
|
command: check advisories bans licenses sources
|
|
|
|
build-no-lock:
|
|
runs-on: ubuntu-24.04
|
|
timeout-minutes: 30
|
|
env:
|
|
# Need up-to-date compilers for kernels
|
|
CC: clang
|
|
CXX: clang++
|
|
steps:
|
|
- uses: actions/checkout@v6
|
|
# Building without a lock file often requires the latest Rust version since downstream
|
|
# dependencies may have updated their minimum Rust version.
|
|
- uses: actions-rust-lang/setup-rust-toolchain@v1
|
|
with:
|
|
toolchain: "stable"
|
|
# Remove cargo.lock to force a fresh build
|
|
- name: Remove Cargo.lock
|
|
run: rm -f Cargo.lock
|
|
- uses: rui314/setup-mold@v1
|
|
- uses: Swatinem/rust-cache@v2
|
|
with:
|
|
# Restore everywhere, but only save from main. Per-PR saves are
|
|
# unreadable outside their own branch anyway, since GitHub scopes
|
|
# caches to the creating ref.
|
|
save-if: ${{ github.ref == 'refs/heads/main' }}
|
|
- name: Install dependencies
|
|
run: |
|
|
sudo apt update
|
|
sudo apt install -y protobuf-compiler libssl-dev
|
|
- name: Build all
|
|
run: |
|
|
cargo build --profile ci --benches --all-features --tests
|
|
|
|
linux:
|
|
timeout-minutes: 60
|
|
# To build all features, we need more disk space than is available
|
|
# on the free OSS github runner. This is mostly due to the the
|
|
# sentence-transformers feature.
|
|
runs-on: ubuntu-2404-4x-x64
|
|
defaults:
|
|
run:
|
|
shell: bash
|
|
working-directory: rust
|
|
env:
|
|
# Need up-to-date compilers for kernels
|
|
CC: clang-18
|
|
CXX: clang++-18
|
|
GH_TOKEN: ${{ secrets.SOPHON_READ_TOKEN }}
|
|
steps:
|
|
- uses: actions/checkout@v6
|
|
with:
|
|
fetch-depth: 0
|
|
lfs: true
|
|
- uses: Swatinem/rust-cache@v2
|
|
with:
|
|
# Restore everywhere, but only save from main. Per-PR saves are
|
|
# unreadable outside their own branch anyway, since GitHub scopes
|
|
# caches to the creating ref.
|
|
save-if: ${{ github.ref == 'refs/heads/main' }}
|
|
- name: Install dependencies
|
|
run: |
|
|
sudo apt update
|
|
sudo apt install -y protobuf-compiler libssl-dev
|
|
- uses: rui314/setup-mold@v1
|
|
- name: Make Swap
|
|
run: |
|
|
swapfile=/swapfile
|
|
min_swap_bytes=$((15 * 1024 * 1024 * 1024))
|
|
active_swap_bytes="$(sudo swapon --show=NAME,SIZE --bytes --noheadings | awk '$1 == "/swapfile" { print $2 }')"
|
|
if [ -n "$active_swap_bytes" ]; then
|
|
if [ "$active_swap_bytes" -ge "$min_swap_bytes" ]; then
|
|
echo "/swapfile is already active with enough space; skipping swap creation"
|
|
exit 0
|
|
fi
|
|
echo "/swapfile is already active but smaller than 16G; using /mnt/lancedb-swapfile"
|
|
swapfile=/mnt/lancedb-swapfile
|
|
fi
|
|
if sudo swapon --show=NAME --noheadings | grep -Fxq "$swapfile"; then
|
|
echo "$swapfile is already active; skipping swap creation"
|
|
exit 0
|
|
fi
|
|
sudo rm -f "$swapfile"
|
|
sudo fallocate -l 16G "$swapfile"
|
|
sudo chmod 600 "$swapfile"
|
|
sudo mkswap "$swapfile"
|
|
sudo swapon "$swapfile"
|
|
- name: Build
|
|
run: cargo build --profile ci --all-features --tests --locked --examples
|
|
- name: Run feature tests
|
|
run: CARGO_ARGS="--profile ci" make -C ./lancedb feature-tests
|
|
- name: Run examples
|
|
run: cargo run --profile ci --example simple --locked
|
|
- name: Run remote tests
|
|
# Running this requires access to secrets, so skip if this is
|
|
# a PR from a fork.
|
|
if: github.event_name != 'pull_request' || !github.event.pull_request.head.repo.fork
|
|
run: CARGO_ARGS="--profile ci" make -C ./lancedb remote-tests
|
|
|
|
macos:
|
|
timeout-minutes: 60
|
|
strategy:
|
|
matrix:
|
|
mac-runner: ["macos-14", "macos-15"]
|
|
runs-on: "${{ matrix.mac-runner }}"
|
|
defaults:
|
|
run:
|
|
shell: bash
|
|
working-directory: rust
|
|
steps:
|
|
- uses: actions/checkout@v6
|
|
with:
|
|
fetch-depth: 0
|
|
lfs: true
|
|
- name: CPU features
|
|
run: sysctl -a | grep cpu
|
|
- uses: Swatinem/rust-cache@v2
|
|
with:
|
|
# Restore everywhere, but only save from main. Per-PR saves are
|
|
# unreadable outside their own branch anyway, since GitHub scopes
|
|
# caches to the creating ref.
|
|
save-if: ${{ github.ref == 'refs/heads/main' }}
|
|
- name: Install dependencies
|
|
run: brew install protobuf
|
|
- name: Run tests
|
|
run: |
|
|
# Don't run the s3 integration tests since docker isn't available
|
|
# on this image.
|
|
ALL_FEATURES=`cargo metadata --format-version=1 --no-deps \
|
|
| jq -r '.packages[] | .features | keys | .[]' \
|
|
| grep -v s3-test | sort | uniq | paste -s -d "," -`
|
|
cargo test --profile ci --features $ALL_FEATURES --locked
|
|
|
|
windows:
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
include:
|
|
- target: x86_64-pc-windows-msvc
|
|
runner: windows-2022
|
|
# windows-11-arm is a standard runner, so it is free on public repos.
|
|
# Running natively lets the aarch64 tests actually execute -- this
|
|
# job used to cross-compile them and then skip the test step, paying
|
|
# full codegen and link cost for a compile check.
|
|
- target: aarch64-pc-windows-msvc
|
|
runner: windows-11-arm
|
|
runs-on: ${{ matrix.runner }}
|
|
defaults:
|
|
run:
|
|
working-directory: rust/lancedb
|
|
steps:
|
|
- uses: actions/checkout@v6
|
|
- name: Set target
|
|
run: rustup target add ${{ matrix.target }}
|
|
- uses: Swatinem/rust-cache@v2
|
|
with:
|
|
# Restore everywhere, but only save from main. Per-PR saves are
|
|
# unreadable outside their own branch anyway, since GitHub scopes
|
|
# caches to the creating ref.
|
|
save-if: ${{ github.ref == 'refs/heads/main' }}
|
|
- name: Install Protoc v21.12
|
|
run: choco install --no-progress protoc
|
|
- name: Build
|
|
run: |
|
|
$env:VCPKG_ROOT = $env:VCPKG_INSTALLATION_ROOT
|
|
cargo build --profile ci --features aws,remote --tests --locked --target ${{ matrix.target }}
|
|
- name: Run tests
|
|
run: |
|
|
$env:VCPKG_ROOT = $env:VCPKG_INSTALLATION_ROOT
|
|
# `--target` has to match the build step above. Without it cargo uses
|
|
# target/ci/ rather than target/<triple>/ci/ and rebuilds the entire
|
|
# dependency graph a second time.
|
|
cargo test --profile ci --features aws,remote --locked --target ${{ matrix.target }}
|
|
|
|
msrv:
|
|
# Check the minimum supported Rust version
|
|
name: MSRV Check - Rust v${{ matrix.msrv }}
|
|
runs-on: ubuntu-24.04
|
|
strategy:
|
|
matrix:
|
|
msrv: ["1.91.0"] # This should match up with rust-version in Cargo.toml
|
|
env:
|
|
# Need up-to-date compilers for kernels
|
|
CC: clang-18
|
|
CXX: clang++-18
|
|
steps:
|
|
- uses: actions/checkout@v6
|
|
with:
|
|
submodules: true
|
|
- name: Install dependencies
|
|
run: |
|
|
sudo apt update
|
|
sudo apt install -y protobuf-compiler libssl-dev
|
|
- name: Install ${{ matrix.msrv }}
|
|
uses: dtolnay/rust-toolchain@master
|
|
with:
|
|
toolchain: ${{ matrix.msrv }}
|
|
- uses: Swatinem/rust-cache@v2
|
|
with:
|
|
# Restore everywhere, but only save from main. Per-PR saves are
|
|
# unreadable outside their own branch anyway, since GitHub scopes
|
|
# caches to the creating ref.
|
|
save-if: ${{ github.ref == 'refs/heads/main' }}
|
|
- name: Downgrade dependencies
|
|
# These packages have newer requirements for MSRV
|
|
run: |
|
|
cargo update -p aws-sdk-bedrockruntime --precise 1.77.0
|
|
cargo update -p aws-sdk-dynamodb --precise 1.68.0
|
|
cargo update -p aws-config --precise 1.6.0
|
|
cargo update -p aws-sdk-kms --precise 1.63.0
|
|
cargo update -p aws-sdk-s3 --precise 1.79.0
|
|
cargo update -p aws-sdk-sso --precise 1.62.0
|
|
cargo update -p aws-sdk-ssooidc --precise 1.63.0
|
|
cargo update -p aws-sdk-sts --precise 1.63.0
|
|
# aws-runtime/sigv4/credential-types/types and the aws-smithy-*
|
|
# crates bumped their MSRV to 1.91.1 in late 2026; pin to the last
|
|
# 1.91.0-compatible versions. The order matters — each downgrade
|
|
# only succeeds once everything that still pins it at a higher
|
|
# version has itself been downgraded.
|
|
cargo update -p aws-runtime --precise 1.5.12
|
|
cargo update -p aws-types --precise 1.3.9
|
|
cargo update -p aws-sigv4 --precise 1.3.5
|
|
cargo update -p aws-credential-types --precise 1.2.8
|
|
cargo update -p aws-smithy-checksums --precise 0.63.9
|
|
cargo update -p aws-smithy-runtime --precise 1.9.3
|
|
cargo update -p aws-smithy-http --precise 0.62.4
|
|
cargo update -p aws-smithy-eventstream --precise 0.60.12
|
|
cargo update -p aws-smithy-http-client --precise 1.1.3
|
|
cargo update -p aws-smithy-observability --precise 0.1.4
|
|
cargo update -p aws-smithy-query --precise 0.60.8
|
|
cargo update -p aws-smithy-runtime-api --precise 1.9.1
|
|
cargo update -p aws-smithy-async --precise 1.2.6
|
|
cargo update -p aws-smithy-types --precise 1.3.5
|
|
cargo update -p aws-smithy-xml --precise 0.60.11
|
|
cargo update -p home --precise 0.5.9
|
|
- name: cargo +${{ matrix.msrv }} check
|
|
env:
|
|
RUSTUP_TOOLCHAIN: ${{ matrix.msrv }}
|
|
run: cargo check --profile ci --workspace --tests --benches --all-features
|