Build Router Native Modules #93
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: Build Router Native Modules | |
| on: | |
| push: | |
| branches: [main] | |
| paths: | |
| - 'crates/ruvector-router-core/**' | |
| - 'crates/ruvector-router-ffi/**' | |
| - 'npm/packages/router/**' | |
| - '.github/workflows/build-router.yml' | |
| tags: | |
| - 'v*' | |
| pull_request: | |
| branches: [main] | |
| paths: | |
| - 'crates/ruvector-router-core/**' | |
| - 'crates/ruvector-router-ffi/**' | |
| - 'npm/packages/router/**' | |
| workflow_dispatch: | |
| inputs: | |
| publish: | |
| description: 'Publish to npm after build' | |
| required: false | |
| type: boolean | |
| default: false | |
| env: | |
| CARGO_TERM_COLOR: always | |
| jobs: | |
| build: | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| settings: | |
| - host: ubuntu-22.04 | |
| target: x86_64-unknown-linux-gnu | |
| platform: linux-x64-gnu | |
| - host: ubuntu-22.04 | |
| target: aarch64-unknown-linux-gnu | |
| platform: linux-arm64-gnu | |
| - host: macos-14 | |
| target: x86_64-apple-darwin | |
| platform: darwin-x64 | |
| - host: macos-14 | |
| target: aarch64-apple-darwin | |
| platform: darwin-arm64 | |
| - host: windows-2022 | |
| target: x86_64-pc-windows-msvc | |
| platform: win32-x64-msvc | |
| name: Build Router ${{ matrix.settings.platform }} | |
| runs-on: ${{ matrix.settings.host }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: '18' | |
| - name: Setup Rust | |
| uses: dtolnay/rust-toolchain@stable | |
| with: | |
| toolchain: stable | |
| targets: ${{ matrix.settings.target }} | |
| - name: Cache Rust | |
| uses: Swatinem/rust-cache@v2 | |
| with: | |
| key: router-${{ matrix.settings.target }} | |
| - name: Install cross-compilation tools (Linux ARM64) | |
| if: matrix.settings.platform == 'linux-arm64-gnu' | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y gcc-aarch64-linux-gnu g++-aarch64-linux-gnu | |
| - name: Install dependencies | |
| working-directory: npm/packages/router | |
| run: npm install --ignore-scripts --omit=optional --force | |
| - name: Build native module | |
| working-directory: npm/packages/router | |
| run: | | |
| npx napi build --platform --release --cargo-cwd ../../../crates/ruvector-router-ffi --target ${{ matrix.settings.target }} | |
| env: | |
| CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER: aarch64-linux-gnu-gcc | |
| - name: Find built .node files (debug) | |
| shell: bash | |
| run: | | |
| echo "=== Searching for Router .node files ===" | |
| find npm/packages/router -name "*.node" -type f 2>/dev/null || true | |
| find crates/ruvector-router-ffi -name "*.node" -type f 2>/dev/null || true | |
| - name: Prepare artifact | |
| shell: bash | |
| run: | | |
| mkdir -p router-artifacts/${{ matrix.settings.platform }} | |
| # Find the built .node file | |
| NODE_FILE=$(find npm/packages/router -name "*.node" -type f | head -1) | |
| if [ -z "$NODE_FILE" ]; then | |
| NODE_FILE=$(find crates/ruvector-router-ffi -name "*.node" -type f | head -1) | |
| fi | |
| if [ -z "$NODE_FILE" ]; then | |
| echo "ERROR: No .node file found" | |
| exit 1 | |
| fi | |
| echo "Found: $NODE_FILE" | |
| cp -v "$NODE_FILE" "router-artifacts/${{ matrix.settings.platform }}/" | |
| - name: Test native module (native platform only) | |
| if: | | |
| (matrix.settings.platform == 'linux-x64-gnu' && runner.os == 'Linux') || | |
| (matrix.settings.platform == 'darwin-x64' && runner.os == 'macOS' && runner.arch == 'X64') || | |
| (matrix.settings.platform == 'darwin-arm64' && runner.os == 'macOS' && runner.arch == 'ARM64') || | |
| (matrix.settings.platform == 'win32-x64-msvc' && runner.os == 'Windows') | |
| continue-on-error: true | |
| working-directory: npm/packages/router | |
| run: npm test | |
| - name: Upload artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: router-${{ matrix.settings.platform }} | |
| path: router-artifacts/${{ matrix.settings.platform }}/*.node | |
| if-no-files-found: error | |
| publish: | |
| name: Publish Router Platform Packages | |
| runs-on: ubuntu-22.04 | |
| needs: build | |
| if: inputs.publish == true || startsWith(github.ref, 'refs/tags/v') | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: '18' | |
| registry-url: 'https://registry.npmjs.org' | |
| - name: Download all artifacts | |
| uses: actions/download-artifact@v4 | |
| with: | |
| path: artifacts | |
| - name: Create and publish platform packages | |
| env: | |
| NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} | |
| run: | | |
| VERSION=$(node -p "require('./npm/packages/router/package.json').version") | |
| echo "Publishing version: $VERSION" | |
| for dir in artifacts/router-*/; do | |
| platform=$(basename "$dir" | sed 's/router-//') | |
| NODE_FILE=$(find "$dir" -name "*.node" | head -1) | |
| if [ -z "$NODE_FILE" ]; then | |
| echo "No .node file found in $dir" | |
| continue | |
| fi | |
| echo "=== Publishing @ruvector/router-${platform}@${VERSION} ===" | |
| # Create package directory | |
| PKG_DIR="npm-pkg/router-${platform}" | |
| mkdir -p "$PKG_DIR" | |
| # Determine OS and CPU | |
| case "$platform" in | |
| linux-x64-gnu) | |
| OS="linux"; CPU="x64"; LIBC='"libc": ["glibc"],' | |
| NODE_NAME="ruvector-router.linux-x64-gnu.node" | |
| ;; | |
| linux-arm64-gnu) | |
| OS="linux"; CPU="arm64"; LIBC='"libc": ["glibc"],' | |
| NODE_NAME="ruvector-router.linux-arm64-gnu.node" | |
| ;; | |
| darwin-x64) | |
| OS="darwin"; CPU="x64"; LIBC="" | |
| NODE_NAME="ruvector-router.darwin-x64.node" | |
| ;; | |
| darwin-arm64) | |
| OS="darwin"; CPU="arm64"; LIBC="" | |
| NODE_NAME="ruvector-router.darwin-arm64.node" | |
| ;; | |
| win32-x64-msvc) | |
| OS="win32"; CPU="x64"; LIBC="" | |
| NODE_NAME="ruvector-router.win32-x64-msvc.node" | |
| ;; | |
| esac | |
| # Copy and rename binary | |
| cp "$NODE_FILE" "$PKG_DIR/$NODE_NAME" | |
| # Create package.json | |
| cat > "$PKG_DIR/package.json" << EOF | |
| { | |
| "name": "@ruvector/router-${platform}", | |
| "version": "${VERSION}", | |
| "os": ["${OS}"], | |
| "cpu": ["${CPU}"], | |
| ${LIBC} | |
| "main": "${NODE_NAME}", | |
| "files": ["${NODE_NAME}"], | |
| "description": "Semantic router for AI agents - ${platform} platform", | |
| "keywords": ["ruvector", "router", "semantic-router", "napi-rs"], | |
| "author": "ruv.io Team <info@ruv.io>", | |
| "license": "MIT", | |
| "repository": {"type": "git", "url": "https://github.com/ruvnet/ruvector"}, | |
| "engines": {"node": ">= 18"}, | |
| "publishConfig": {"registry": "https://registry.npmjs.org/", "access": "public"} | |
| } | |
| EOF | |
| # Publish | |
| cd "$PKG_DIR" | |
| npm publish --access public || echo "Failed to publish @ruvector/router-${platform}" | |
| cd ../.. | |
| done | |
| - name: Copy binaries to main package | |
| run: | | |
| for dir in artifacts/router-*/; do | |
| platform=$(basename "$dir" | sed 's/router-//') | |
| NODE_FILE=$(find "$dir" -name "*.node" | head -1) | |
| if [ -n "$NODE_FILE" ]; then | |
| cp -v "$NODE_FILE" "npm/packages/router/ruvector-router.${platform}.node" | |
| fi | |
| done | |
| ls -la npm/packages/router/*.node || true | |
| - name: Publish main package | |
| working-directory: npm/packages/router | |
| env: | |
| NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} | |
| run: npm publish --access public || echo "Package may already exist" |