#!/usr/bin/env bash # CI test script — runs fmt, clippy (all targets + feature matrix), tests, # Python interop suites, bench compilation, and no_std checks. # # Usage: # ./scripts/ci-test.sh # # Environment: # CLAWHDF5_REQUIRE_INTEROP=1 Fail (instead of skip) when python3 with # h5py/netCDF4/xarray is missing. CI sets this. # Unset locally, the interop steps are skipped # if python3+h5py is not importable. # CLAWHDF5_FUZZ_SECONDS=N Run each cargo-fuzz target for N seconds # (needs nightly + cargo-fuzz). Default: skip. # # Exit codes: # 0 — all checks passed # 1 — one or more checks failed set -uo pipefail SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" PASS=0 FAIL=0 STEPS=() run_step() { local name="$1" shift echo "" echo "==> [$name]" if "$@" 2>&1; then echo " ✓ PASS: $name" PASS=$((PASS + 1)) STEPS+=("PASS: $name") else echo " ✗ FAIL: $name" FAIL=$((FAIL + 1)) STEPS+=("FAIL: $name") fi } # All steps always run so one failure doesn't hide the others; the summary # and the exit code at the end are the verdict. # 1. Format check run_step "cargo fmt --check" cargo fmt --check # 2. Clippy over every target (lib, bins, tests, benches, examples). Without # --all-targets, test and bench code is never linted. clawhdf5-py is # excluded because it needs PyO3/Python headers. run_step "cargo clippy --all-targets" cargo clippy \ --workspace \ --exclude clawhdf5-py \ --all-targets \ -- -D warnings # 3. Clippy over clawhdf5-format's optional features, which the default # workspace build never compiles (szip is left out: it needs libaec). run_step "cargo clippy (format feature matrix)" cargo clippy \ -p clawhdf5-format \ --all-targets \ --features parallel,lz4,zstd,pcodec,fast-checksum \ -- -D warnings # The HNSW index's parallel bulk build is feature-gated too. run_step "cargo clippy (ann parallel)" cargo clippy \ -p clawhdf5-ann \ --all-targets \ --features parallel \ -- -D warnings # 4. Tests (exclude clawhdf5-py) run_step "cargo test" cargo test \ --workspace \ --exclude clawhdf5-py run_step "cargo test (format feature matrix)" cargo test \ -p clawhdf5-format \ --features parallel,lz4,zstd,pcodec,fast-checksum run_step "cargo test (ann parallel)" cargo test \ -p clawhdf5-ann \ --features parallel # 5. Python interop suites. The h5py writer tests are #[ignore]d so a plain # `cargo test` stays hermetic; run them explicitly here. if python3 -c "import h5py" >/dev/null 2>&1 || [ "${CLAWHDF5_REQUIRE_INTEROP:-0}" = "1" ]; then run_step "h5py interop (format, ignored tests)" cargo test \ -p clawhdf5-format --test writer_h5py_tests -- --include-ignored else echo "" echo "==> [h5py interop] SKIPPED: python3 with h5py not available" STEPS+=("SKIP: h5py interop (format, ignored tests)") fi # 6. Benches must keep compiling (they are not run). run_step "cargo bench --no-run" cargo bench \ --workspace \ --exclude clawhdf5-py \ --no-run # 7. no_std check run_step "check-nostd.sh" "$SCRIPT_DIR/check-nostd.sh" # 8. Optional fuzz smoke run if [ -n "${CLAWHDF5_FUZZ_SECONDS:-}" ]; then fuzz_smoke() { local crate target for crate in clawhdf5-format clawhdf5-agent; do cd "$SCRIPT_DIR/../crates/$crate" || return 1 for target in $(cargo +nightly fuzz list); do echo "--- fuzz: $crate/$target" cargo +nightly fuzz run "$target" -- \ -max_total_time="$CLAWHDF5_FUZZ_SECONDS" || return 1 done done } run_step "fuzz smoke (${CLAWHDF5_FUZZ_SECONDS}s/target)" fuzz_smoke fi # Summary echo "" echo "========================================" echo " CI Summary" echo "========================================" for s in "${STEPS[@]}"; do echo " $s" done echo "----------------------------------------" echo " $PASS passed, $FAIL failed" echo "========================================" if [ "$FAIL" -gt 0 ]; then exit 1 fi exit 0