mirror of
https://github.com/exo-explore/exo.git
synced 2026-04-18 04:52:40 -04:00
The existing CI typecheck job used `uv run basedpyright` which depends on a non-hermetic uv sync step. This replaces it with a fully hermetic typecheck as a Nix flake check using the uv2nix virtual environment. Added a `typecheckVenv` with dev dependencies, a `linuxOverlay` to ignore native shared library deps (NVIDIA, torch, triton, mlx) that aren't needed at type-check time, and `passthru` preservation plus `.pyi` stub copying on the `exo-pyo3-bindings` overlay so basedpyright can resolve the Rust bindings types. Also guarded the `mlx` Nix build override to macOS only since it requires Metal. Removed the old non-hermetic `typecheck` CI job since `nix flake check` now covers it. The hermetic check ensures type checking uses exactly the locked dependency versions and catches type errors without requiring a working uv/pip environment. Test plan: - CI (`nix flake check` runs on x86_64-linux, aarch64-linux, aarch64-darwin) - Verified `nix build ".#checks.x86_64-linux.typecheck"` passes with 0 errors
121 lines
4.0 KiB
YAML
121 lines
4.0 KiB
YAML
name: ci-pipeline
|
|
|
|
on:
|
|
push:
|
|
pull_request:
|
|
branches:
|
|
- staging
|
|
- main
|
|
|
|
jobs:
|
|
nix:
|
|
name: Build and check (${{ matrix.system }})
|
|
runs-on: ${{ matrix.runner }}
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
include:
|
|
- runner: macos-26
|
|
system: aarch64-darwin
|
|
- runner: ubuntu-latest
|
|
system: x86_64-linux
|
|
- runner: ubuntu-24.04-arm
|
|
system: aarch64-linux
|
|
steps:
|
|
- name: Checkout repository
|
|
uses: actions/checkout@v4
|
|
with:
|
|
lfs: false
|
|
|
|
- uses: cachix/install-nix-action@v31
|
|
with:
|
|
nix_path: nixpkgs=channel:nixos-unstable
|
|
|
|
- uses: cachix/cachix-action@v14
|
|
name: Configure Cachix
|
|
with:
|
|
name: exo
|
|
authToken: "${{ secrets.CACHIX_AUTH_TOKEN }}"
|
|
|
|
- name: Build Metal packages (macOS only)
|
|
if: runner.os == 'macOS'
|
|
run: |
|
|
# Try to build metal-toolchain first (may succeed via cachix cache hit)
|
|
if nix build .#metal-toolchain 2>/dev/null; then
|
|
echo "metal-toolchain built successfully (likely cache hit)"
|
|
else
|
|
echo "metal-toolchain build failed, extracting from Xcode..."
|
|
|
|
NAR_HASH="sha256-ayR5mXN4sZAddwKEG2OszGRF93k9ZFc7H0yi2xbylQw="
|
|
NAR_NAME="metal-toolchain-17C48.nar"
|
|
|
|
# Use RUNNER_TEMP to avoid /tmp symlink issues on macOS
|
|
WORK_DIR="${RUNNER_TEMP}/metal-work"
|
|
mkdir -p "$WORK_DIR"
|
|
|
|
# Download the Metal toolchain component
|
|
xcodebuild -downloadComponent MetalToolchain
|
|
|
|
# Find and mount the DMG
|
|
DMG_PATH=$(find /System/Library/AssetsV2/com_apple_MobileAsset_MetalToolchain -name '*.dmg' 2>/dev/null | head -1)
|
|
if [ -z "$DMG_PATH" ]; then
|
|
echo "Error: Could not find Metal toolchain DMG"
|
|
exit 1
|
|
fi
|
|
|
|
echo "Found DMG at: $DMG_PATH"
|
|
hdiutil attach "$DMG_PATH" -mountpoint "${WORK_DIR}/metal-dmg"
|
|
|
|
# Copy the toolchain
|
|
cp -R "${WORK_DIR}/metal-dmg/Metal.xctoolchain" "${WORK_DIR}/metal-export"
|
|
hdiutil detach "${WORK_DIR}/metal-dmg"
|
|
|
|
# Create NAR and add to store
|
|
nix nar pack "${WORK_DIR}/metal-export" > "${WORK_DIR}/${NAR_NAME}"
|
|
STORE_PATH=$(nix store add --mode flat "${WORK_DIR}/${NAR_NAME}")
|
|
echo "Added NAR to store: $STORE_PATH"
|
|
|
|
# Verify the hash matches
|
|
ACTUAL_HASH=$(nix hash file "${WORK_DIR}/${NAR_NAME}")
|
|
if [ "$ACTUAL_HASH" != "$NAR_HASH" ]; then
|
|
echo "Warning: NAR hash mismatch!"
|
|
echo "Expected: $NAR_HASH"
|
|
echo "Actual: $ACTUAL_HASH"
|
|
echo "The metal-toolchain.nix may need updating"
|
|
fi
|
|
|
|
# Clean up
|
|
rm -rf "$WORK_DIR"
|
|
|
|
# Retry the build now that NAR is in store
|
|
nix build .#metal-toolchain
|
|
fi
|
|
|
|
# Build mlx (depends on metal-toolchain)
|
|
nix build .#mlx
|
|
|
|
- name: Build all Nix outputs
|
|
run: |
|
|
nix flake show --json | jq -r '
|
|
[
|
|
(.packages."${{ matrix.system }}" // {} | keys[] | ".#packages.${{ matrix.system }}.\(.)"),
|
|
(.devShells."${{ matrix.system }}" // {} | keys[] | ".#devShells.${{ matrix.system }}.\(.)")
|
|
] | .[]
|
|
' | xargs nix build
|
|
|
|
- name: Run nix flake check
|
|
run: nix flake check
|
|
|
|
- name: Run pytest (macOS only)
|
|
if: runner.os == 'macOS'
|
|
run: |
|
|
# Build the test environment (requires relaxed sandbox for uv2nix on macOS)
|
|
TEST_ENV=$(nix build '.#exo-test-env' --option sandbox relaxed --print-out-paths)
|
|
|
|
# Run pytest outside sandbox (needs GPU access for MLX)
|
|
export HOME="$RUNNER_TEMP"
|
|
export EXO_TESTS=1
|
|
export EXO_DASHBOARD_DIR="$PWD/dashboard/"
|
|
export EXO_RESOURCES_DIR="$PWD/resources"
|
|
$TEST_ENV/bin/python -m pytest src -m "not slow" --import-mode=importlib
|