feat: add first-class Windows release support #8
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: macOS smoke | |
| # Validates native Apple Silicon builds, Metal index/search acceleration, and | |
| # the CPU fallback path. | |
| on: | |
| push: | |
| branches: [main] | |
| pull_request: | |
| branches: [main] | |
| permissions: | |
| contents: read | |
| env: | |
| MACOSX_DEPLOYMENT_TARGET: "11.0" | |
| GRAPHIQ_GPU_TRACE: "1" | |
| jobs: | |
| smoke: | |
| runs-on: macos-14 | |
| timeout-minutes: 30 | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Assert native Apple Silicon runner | |
| run: test "$(uname -m)" = "arm64" | |
| - name: Install Rust | |
| uses: dtolnay/rust-toolchain@stable | |
| - name: Build release (gpu feature) | |
| run: cargo build --release --features gpu | |
| - name: Run Metal parity tests | |
| run: cargo test -p graphiq-core --features gpu gpu_compute::tests -- --nocapture | |
| - name: Prove the binaries start with Metal available | |
| run: | | |
| set -euo pipefail | |
| ./target/release/graphiq --version | |
| ./target/release/graphiq-mcp --help >/dev/null | |
| - name: Build a sufficiently large fixture and index it with Metal | |
| run: | | |
| set -euo pipefail | |
| export PATH="$PWD/target/release:$PATH" | |
| mkdir -p fixture/src | |
| cat > fixture/src/lib.rs <<'RUST' | |
| pub struct RateLimiter { max: u32 } | |
| impl RateLimiter { | |
| pub fn check_rate(&self) -> bool { true } | |
| pub fn reset(&self) {} | |
| } | |
| pub fn handle_request(rl: &RateLimiter) -> bool { rl.check_rate() } | |
| RUST | |
| for i in $(seq 1 96); do | |
| cat >> fixture/src/lib.rs <<RUST | |
| pub fn request_handler_${i}(cache: bool, retry: bool, rate: u32) -> bool { cache && retry && rate > 0 } | |
| RUST | |
| done | |
| (cd fixture && git init -q && git config user.email t@t && git config user.name t && git add -A && git commit -qm init) | |
| graphiq index fixture --db fixture/.graphiq/graphiq.db >index.out 2>index.err | |
| cat index.out | |
| cat index.err | |
| grep -Eq 'Symbols: [0-9]+' index.out | |
| - name: Verify reported Metal capability | |
| run: | | |
| set -euo pipefail | |
| export PATH="$PWD/target/release:$PATH" | |
| out="$(graphiq status --db fixture/.graphiq/graphiq.db)" | |
| echo "$out" | |
| echo "$out" | grep -q 'GPU: initialized OK (Metal' | |
| - name: Run GPU-backed search and verify CPU parity | |
| run: | | |
| set -euo pipefail | |
| export PATH="$PWD/target/release:$PATH" | |
| DB=fixture/.graphiq/graphiq.db | |
| QUERY='request handler cache retry rate' | |
| GRAPHIQ_GPU_MIN_SEARCH_CANDIDATES=24 \ | |
| GRAPHIQ_GPU_MIN_SEARCH_WORK_ITEMS=128 \ | |
| graphiq search "$QUERY" --db "$DB" --top 10 >gpu.out 2>gpu.err | |
| cat gpu.out | |
| cat gpu.err | |
| grep -q 'GPU: initialized Metal' gpu.err | |
| grep -q 'gpu acceleration: 3/3 phases on GPU' gpu.err | |
| grep -q 'Search: GPU term scoring' gpu.err | |
| grep -q 'request_handler_1' gpu.out | |
| GRAPHIQ_DISABLE_GPU=1 graphiq search "$QUERY" --db "$DB" --top 10 >cpu.out 2>cpu.err | |
| cat cpu.out | |
| cat cpu.err | |
| if grep -q 'Search: GPU term scoring' cpu.err; then | |
| echo 'CPU fallback unexpectedly used GPU scoring' >&2 | |
| exit 1 | |
| fi | |
| grep -q 'request_handler_1' cpu.out | |
| grep '^#' gpu.out | awk '{print $NF}' >gpu.names | |
| grep '^#' cpu.out | awk '{print $NF}' >cpu.names | |
| diff -u cpu.names gpu.names | |
| echo 'GPU and CPU ranked symbol names match' | |
| - name: Run the remaining command surface | |
| run: | | |
| set -euo pipefail | |
| export PATH="$PWD/target/release:$PATH" | |
| DB=fixture/.graphiq/graphiq.db | |
| echo "--- search ---" | |
| out="$(graphiq search 'rate limit' --db "$DB" --top 3)" | |
| echo "$out" | grep -q "RateLimiter" || { echo "search did not find RateLimiter: $out" >&2; exit 1; } | |
| echo "--- blast ---" | |
| out="$(graphiq blast RateLimiter --db "$DB" --depth 2)" | |
| echo "$out" | grep -Eq "check_rate|reset" || { echo "blast missing members: $out" >&2; exit 1; } | |
| echo "--- empty-index no-panic regression ---" | |
| mkdir -p empty_proj && (cd empty_proj && git init -q) | |
| graphiq index empty_proj --db empty_proj/g.db >/dev/null 2>&1 | |
| out="$(graphiq search anything --db empty_proj/g.db)" | |
| echo "$out" | grep -q "No results" || { echo "empty search did not say No results: $out" >&2; exit 1; } | |
| echo "--- clear ---" | |
| out="$(graphiq clear --db empty_proj/g.db --yes)" | |
| echo "$out" | grep -Eq "fresh empty|Cleared" || { echo "clear failed: $out" >&2; exit 1; } | |
| echo "--- discover (JSON, must report a count) ---" | |
| out="$(graphiq discover --json)" | |
| echo "$out" | grep -q '"count"' || { echo "discover no count: $out" >&2; exit 1; } | |
| echo "--- git scope (fixture is a repo) ---" | |
| out="$(graphiq git --project fixture --json)" | |
| echo "$out" | grep -q '"branch"' || { echo "git no branch: $out" >&2; exit 1; } | |
| echo "--- projects (registry) ---" | |
| out="$(HOME="$PWD/fake-home" graphiq projects --json)" | |
| echo "$out" | grep -q '"projects"' || { echo "projects no key: $out" >&2; exit 1; } | |
| echo "--- sync verify ---" | |
| out="$(HOME="$PWD/fake-home" graphiq sync --project fixture)" | |
| echo "$out" | grep -Eq "connected:|No harnesses" || { echo "sync no result: $out" >&2; exit 1; } | |
| echo "--- explicit SIGPIPE behavior ---" | |
| set +e | |
| graphiq discover 2>/dev/null | head -1 >/dev/null | |
| rc=${PIPESTATUS[0]} | |
| set -e | |
| [ "$rc" -eq 141 ] || [ "$rc" -eq 0 ] || { echo "unexpected exit $rc from discover|head (want 141 SIGPIPE or 0)" >&2; exit 1; } | |
| echo "discover|head exit $rc (SIGPIPE handled, no panic)" | |
| echo "ALL MACOS SMOKE CHECKS PASSED" | |
| - name: Upload binaries (for inspection) | |
| if: always() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: graphiq-macos-build | |
| path: | | |
| target/release/graphiq | |
| target/release/graphiq-mcp |