Skip to content

feat: add first-class Windows release support #8

feat: add first-class Windows release support

feat: add first-class Windows release support #8

Workflow file for this run

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