chore: Update attention NAPI-RS binaries for all platforms #13
Workflow file for this run
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 & Publish All Packages | |
| on: | |
| push: | |
| tags: | |
| - 'v*' | |
| workflow_dispatch: | |
| inputs: | |
| version: | |
| description: 'Version to publish (e.g., 0.1.31)' | |
| required: true | |
| type: string | |
| publish_crates: | |
| description: 'Publish to crates.io' | |
| required: false | |
| type: boolean | |
| default: true | |
| publish_npm: | |
| description: 'Publish to npm' | |
| required: false | |
| type: boolean | |
| default: true | |
| dry_run: | |
| description: 'Dry run (build only, no publish)' | |
| required: false | |
| type: boolean | |
| default: false | |
| env: | |
| CARGO_TERM_COLOR: always | |
| RUST_BACKTRACE: 1 | |
| jobs: | |
| # ============================================================================ | |
| # Phase 1: Validate and Test | |
| # ============================================================================ | |
| validate: | |
| name: Validate & Test | |
| runs-on: ubuntu-22.04 | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Setup Rust | |
| uses: dtolnay/rust-toolchain@stable | |
| with: | |
| components: rustfmt, clippy | |
| - name: Cache Rust | |
| uses: Swatinem/rust-cache@v2 | |
| - name: Run tests | |
| run: | | |
| cargo test -p ruvector-math -p ruvector-attention --all-features | |
| echo "✅ All tests passed" >> $GITHUB_STEP_SUMMARY | |
| # ============================================================================ | |
| # Phase 2: Build Native Binaries (Node.js NAPI) | |
| # ============================================================================ | |
| build-native: | |
| name: Build ${{ matrix.settings.platform }} | |
| runs-on: ${{ matrix.settings.host }} | |
| needs: validate | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| settings: | |
| - host: ubuntu-22.04 | |
| target: x86_64-unknown-linux-gnu | |
| platform: linux-x64-gnu | |
| node_file: attention.linux-x64-gnu.node | |
| - host: ubuntu-22.04 | |
| target: aarch64-unknown-linux-gnu | |
| platform: linux-arm64-gnu | |
| node_file: attention.linux-arm64-gnu.node | |
| - host: macos-14 | |
| target: x86_64-apple-darwin | |
| platform: darwin-x64 | |
| node_file: attention.darwin-x64.node | |
| - host: macos-14 | |
| target: aarch64-apple-darwin | |
| platform: darwin-arm64 | |
| node_file: attention.darwin-arm64.node | |
| - host: windows-2022 | |
| target: x86_64-pc-windows-msvc | |
| platform: win32-x64-msvc | |
| node_file: attention.win32-x64-msvc.node | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: '20' | |
| - name: Setup Rust | |
| uses: dtolnay/rust-toolchain@stable | |
| with: | |
| targets: ${{ matrix.settings.target }} | |
| - name: Cache Rust | |
| uses: Swatinem/rust-cache@v2 | |
| with: | |
| key: native-${{ 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 NAPI-RS CLI | |
| run: npm install -g @napi-rs/cli | |
| - name: Install dependencies | |
| working-directory: crates/ruvector-attention-node | |
| run: npm install | |
| - name: Build native module | |
| working-directory: crates/ruvector-attention-node | |
| run: napi build --platform --release --target ${{ matrix.settings.target }} | |
| env: | |
| CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER: aarch64-linux-gnu-gcc | |
| - name: Copy to platform package | |
| shell: bash | |
| run: | | |
| NODE_FILE=$(find crates/ruvector-attention-node -name "*.node" -type f | head -1) | |
| mkdir -p "crates/ruvector-attention-node/npm/${{ matrix.settings.platform }}" | |
| cp -v "$NODE_FILE" "crates/ruvector-attention-node/npm/${{ matrix.settings.platform }}/${{ matrix.settings.node_file }}" | |
| - name: Upload artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: native-${{ matrix.settings.platform }} | |
| path: crates/ruvector-attention-node/npm/${{ matrix.settings.platform }}/*.node | |
| if-no-files-found: error | |
| # ============================================================================ | |
| # Phase 3: Build WASM Packages | |
| # ============================================================================ | |
| build-wasm: | |
| name: Build WASM | |
| runs-on: ubuntu-22.04 | |
| needs: validate | |
| strategy: | |
| matrix: | |
| package: | |
| - name: ruvector-math-wasm | |
| path: crates/ruvector-math-wasm | |
| - name: ruvector-attention-wasm | |
| path: crates/ruvector-attention-wasm | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Setup Rust | |
| uses: dtolnay/rust-toolchain@stable | |
| with: | |
| targets: wasm32-unknown-unknown | |
| - name: Install wasm-pack | |
| run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh | |
| - name: Cache Rust | |
| uses: Swatinem/rust-cache@v2 | |
| with: | |
| key: wasm-${{ matrix.package.name }} | |
| - name: Build WASM (web target) | |
| working-directory: ${{ matrix.package.path }} | |
| run: wasm-pack build --target web --release | |
| - name: Upload WASM artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: wasm-${{ matrix.package.name }} | |
| path: ${{ matrix.package.path }}/pkg/ | |
| if-no-files-found: error | |
| # ============================================================================ | |
| # Phase 4: Publish to crates.io | |
| # ============================================================================ | |
| publish-crates: | |
| name: Publish to crates.io | |
| runs-on: ubuntu-22.04 | |
| needs: [build-native, build-wasm] | |
| if: ${{ !inputs.dry_run && (inputs.publish_crates || github.event_name == 'push') }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Setup Rust | |
| uses: dtolnay/rust-toolchain@stable | |
| - name: Publish ruvector-math | |
| run: cargo publish -p ruvector-math --allow-dirty | |
| env: | |
| CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} | |
| continue-on-error: true | |
| - name: Wait for crates.io index | |
| run: sleep 30 | |
| - name: Publish ruvector-attention | |
| run: cargo publish -p ruvector-attention --allow-dirty | |
| env: | |
| CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} | |
| continue-on-error: true | |
| - name: Wait for crates.io index | |
| run: sleep 30 | |
| - name: Publish ruvector-math-wasm | |
| run: cargo publish -p ruvector-math-wasm --allow-dirty | |
| env: | |
| CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} | |
| continue-on-error: true | |
| - name: Publish ruvector-attention-wasm | |
| run: cargo publish -p ruvector-attention-wasm --allow-dirty | |
| env: | |
| CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} | |
| continue-on-error: true | |
| - name: Summary | |
| run: | | |
| echo "## crates.io Publishing" >> $GITHUB_STEP_SUMMARY | |
| echo "✅ ruvector-math" >> $GITHUB_STEP_SUMMARY | |
| echo "✅ ruvector-attention" >> $GITHUB_STEP_SUMMARY | |
| echo "✅ ruvector-math-wasm" >> $GITHUB_STEP_SUMMARY | |
| echo "✅ ruvector-attention-wasm" >> $GITHUB_STEP_SUMMARY | |
| # ============================================================================ | |
| # Phase 5: Publish to npm | |
| # ============================================================================ | |
| publish-npm: | |
| name: Publish to npm | |
| runs-on: ubuntu-22.04 | |
| needs: [build-native, build-wasm] | |
| if: ${{ !inputs.dry_run && (inputs.publish_npm || github.event_name == 'push') }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: '20' | |
| registry-url: 'https://registry.npmjs.org' | |
| - name: Download all artifacts | |
| uses: actions/download-artifact@v4 | |
| with: | |
| path: artifacts | |
| - name: List downloaded artifacts | |
| run: find artifacts -type f -name "*.node" -o -name "*.wasm" | head -50 | |
| # --- Publish WASM packages --- | |
| - name: Publish @ruvector/math-wasm to npm | |
| run: | | |
| cd artifacts/wasm-ruvector-math-wasm | |
| # Update package name to scoped | |
| jq '.name = "@ruvector/math-wasm"' package.json > tmp.json && mv tmp.json package.json | |
| npm publish --access public | |
| env: | |
| NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} | |
| continue-on-error: true | |
| - name: Publish @ruvector/attention-wasm to npm | |
| run: | | |
| cd artifacts/wasm-ruvector-attention-wasm | |
| # Update package name to scoped | |
| jq '.name = "@ruvector/attention-wasm"' package.json > tmp.json && mv tmp.json package.json | |
| npm publish --access public | |
| env: | |
| NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} | |
| continue-on-error: true | |
| # --- Publish platform-specific native packages --- | |
| - name: Prepare and publish @ruvector/attention-linux-x64-gnu | |
| run: | | |
| mkdir -p publish/linux-x64-gnu | |
| cp artifacts/native-linux-x64-gnu/*.node publish/linux-x64-gnu/ | |
| cd publish/linux-x64-gnu | |
| cat > package.json << 'EOF' | |
| { | |
| "name": "@ruvector/attention-linux-x64-gnu", | |
| "version": "${{ inputs.version || '0.1.31' }}", | |
| "os": ["linux"], | |
| "cpu": ["x64"], | |
| "main": "attention.linux-x64-gnu.node", | |
| "files": ["attention.linux-x64-gnu.node"], | |
| "description": "Linux x64 GNU native module for @ruvector/attention", | |
| "license": "MIT", | |
| "repository": "https://github.com/ruvnet/ruvector" | |
| } | |
| EOF | |
| npm publish --access public | |
| env: | |
| NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} | |
| continue-on-error: true | |
| - name: Prepare and publish @ruvector/attention-linux-arm64-gnu | |
| run: | | |
| mkdir -p publish/linux-arm64-gnu | |
| cp artifacts/native-linux-arm64-gnu/*.node publish/linux-arm64-gnu/ | |
| cd publish/linux-arm64-gnu | |
| cat > package.json << 'EOF' | |
| { | |
| "name": "@ruvector/attention-linux-arm64-gnu", | |
| "version": "${{ inputs.version || '0.1.31' }}", | |
| "os": ["linux"], | |
| "cpu": ["arm64"], | |
| "main": "attention.linux-arm64-gnu.node", | |
| "files": ["attention.linux-arm64-gnu.node"], | |
| "description": "Linux ARM64 GNU native module for @ruvector/attention", | |
| "license": "MIT", | |
| "repository": "https://github.com/ruvnet/ruvector" | |
| } | |
| EOF | |
| npm publish --access public | |
| env: | |
| NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} | |
| continue-on-error: true | |
| - name: Prepare and publish @ruvector/attention-darwin-x64 | |
| run: | | |
| mkdir -p publish/darwin-x64 | |
| cp artifacts/native-darwin-x64/*.node publish/darwin-x64/ | |
| cd publish/darwin-x64 | |
| cat > package.json << 'EOF' | |
| { | |
| "name": "@ruvector/attention-darwin-x64", | |
| "version": "${{ inputs.version || '0.1.31' }}", | |
| "os": ["darwin"], | |
| "cpu": ["x64"], | |
| "main": "attention.darwin-x64.node", | |
| "files": ["attention.darwin-x64.node"], | |
| "description": "macOS Intel x64 native module for @ruvector/attention", | |
| "license": "MIT", | |
| "repository": "https://github.com/ruvnet/ruvector" | |
| } | |
| EOF | |
| npm publish --access public | |
| env: | |
| NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} | |
| continue-on-error: true | |
| - name: Prepare and publish @ruvector/attention-darwin-arm64 | |
| run: | | |
| mkdir -p publish/darwin-arm64 | |
| cp artifacts/native-darwin-arm64/*.node publish/darwin-arm64/ | |
| cd publish/darwin-arm64 | |
| cat > package.json << 'EOF' | |
| { | |
| "name": "@ruvector/attention-darwin-arm64", | |
| "version": "${{ inputs.version || '0.1.31' }}", | |
| "os": ["darwin"], | |
| "cpu": ["arm64"], | |
| "main": "attention.darwin-arm64.node", | |
| "files": ["attention.darwin-arm64.node"], | |
| "description": "macOS Apple Silicon ARM64 native module for @ruvector/attention", | |
| "license": "MIT", | |
| "repository": "https://github.com/ruvnet/ruvector" | |
| } | |
| EOF | |
| npm publish --access public | |
| env: | |
| NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} | |
| continue-on-error: true | |
| - name: Prepare and publish @ruvector/attention-win32-x64-msvc | |
| run: | | |
| mkdir -p publish/win32-x64-msvc | |
| cp artifacts/native-win32-x64-msvc/*.node publish/win32-x64-msvc/ | |
| cd publish/win32-x64-msvc | |
| cat > package.json << 'EOF' | |
| { | |
| "name": "@ruvector/attention-win32-x64-msvc", | |
| "version": "${{ inputs.version || '0.1.31' }}", | |
| "os": ["win32"], | |
| "cpu": ["x64"], | |
| "main": "attention.win32-x64-msvc.node", | |
| "files": ["attention.win32-x64-msvc.node"], | |
| "description": "Windows x64 MSVC native module for @ruvector/attention", | |
| "license": "MIT", | |
| "repository": "https://github.com/ruvnet/ruvector" | |
| } | |
| EOF | |
| npm publish --access public | |
| env: | |
| NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} | |
| continue-on-error: true | |
| # --- Publish main @ruvector/attention package --- | |
| - name: Publish @ruvector/attention (main package) | |
| run: | | |
| mkdir -p publish/attention-main | |
| cd publish/attention-main | |
| cat > package.json << 'EOF' | |
| { | |
| "name": "@ruvector/attention", | |
| "version": "${{ inputs.version || '0.1.31' }}", | |
| "description": "High-performance attention mechanisms with 7 mathematical theories: Optimal Transport, Mixed Curvature, Topology, Information Geometry, Information Bottleneck, PDE/Diffusion, Unified Diagnostics", | |
| "main": "index.js", | |
| "types": "index.d.ts", | |
| "license": "MIT", | |
| "repository": "https://github.com/ruvnet/ruvector", | |
| "keywords": ["attention", "transformer", "machine-learning", "optimal-transport", "hyperbolic", "topology"], | |
| "optionalDependencies": { | |
| "@ruvector/attention-linux-x64-gnu": "${{ inputs.version || '0.1.31' }}", | |
| "@ruvector/attention-linux-arm64-gnu": "${{ inputs.version || '0.1.31' }}", | |
| "@ruvector/attention-darwin-x64": "${{ inputs.version || '0.1.31' }}", | |
| "@ruvector/attention-darwin-arm64": "${{ inputs.version || '0.1.31' }}", | |
| "@ruvector/attention-win32-x64-msvc": "${{ inputs.version || '0.1.31' }}" | |
| } | |
| } | |
| EOF | |
| # Create index.js that loads the correct platform binary | |
| cat > index.js << 'INDEXJS' | |
| const { platform, arch } = process; | |
| const platformPackages = { | |
| 'linux-x64': '@ruvector/attention-linux-x64-gnu', | |
| 'linux-arm64': '@ruvector/attention-linux-arm64-gnu', | |
| 'darwin-x64': '@ruvector/attention-darwin-x64', | |
| 'darwin-arm64': '@ruvector/attention-darwin-arm64', | |
| 'win32-x64': '@ruvector/attention-win32-x64-msvc', | |
| }; | |
| const key = `${platform}-${arch}`; | |
| const pkg = platformPackages[key]; | |
| if (!pkg) { | |
| throw new Error(`Unsupported platform: ${key}. Supported: ${Object.keys(platformPackages).join(', ')}`); | |
| } | |
| module.exports = require(pkg); | |
| INDEXJS | |
| # Create TypeScript definitions | |
| cat > index.d.ts << 'INDEXDTS' | |
| export interface AttentionConfig { | |
| dim: number; | |
| numHeads?: number; | |
| dropout?: number; | |
| } | |
| export function scaledDotProductAttention(query: Float32Array, keys: Float32Array[], values: Float32Array[]): Float32Array; | |
| export function multiHeadAttention(query: Float32Array, keys: Float32Array[], values: Float32Array[], config: AttentionConfig): Float32Array; | |
| export function flashAttention(query: Float32Array, keys: Float32Array[], values: Float32Array[], blockSize?: number): Float32Array; | |
| export function hyperbolicAttention(query: Float32Array, keys: Float32Array[], values: Float32Array[], curvature?: number): Float32Array; | |
| INDEXDTS | |
| npm publish --access public | |
| env: | |
| NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} | |
| continue-on-error: true | |
| - name: Summary | |
| run: | | |
| echo "## npm Publishing" >> $GITHUB_STEP_SUMMARY | |
| echo "### WASM Packages" >> $GITHUB_STEP_SUMMARY | |
| echo "✅ @ruvector/math-wasm" >> $GITHUB_STEP_SUMMARY | |
| echo "✅ @ruvector/attention-wasm" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "### Native Packages" >> $GITHUB_STEP_SUMMARY | |
| echo "✅ @ruvector/attention-linux-x64-gnu" >> $GITHUB_STEP_SUMMARY | |
| echo "✅ @ruvector/attention-linux-arm64-gnu" >> $GITHUB_STEP_SUMMARY | |
| echo "✅ @ruvector/attention-darwin-x64" >> $GITHUB_STEP_SUMMARY | |
| echo "✅ @ruvector/attention-darwin-arm64" >> $GITHUB_STEP_SUMMARY | |
| echo "✅ @ruvector/attention-win32-x64-msvc" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "### Main Package" >> $GITHUB_STEP_SUMMARY | |
| echo "✅ @ruvector/attention" >> $GITHUB_STEP_SUMMARY | |
| # ============================================================================ | |
| # Phase 6: Create GitHub Release | |
| # ============================================================================ | |
| create-release: | |
| name: Create GitHub Release | |
| runs-on: ubuntu-22.04 | |
| needs: [publish-crates, publish-npm] | |
| if: ${{ !inputs.dry_run && github.event_name == 'push' }} | |
| permissions: | |
| contents: write | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Download all artifacts | |
| uses: actions/download-artifact@v4 | |
| with: | |
| path: artifacts | |
| - name: Create release archives | |
| run: | | |
| mkdir -p release-assets | |
| # Create platform archives | |
| for platform in linux-x64-gnu linux-arm64-gnu darwin-x64 darwin-arm64 win32-x64-msvc; do | |
| if [ -d "artifacts/native-${platform}" ]; then | |
| tar -czvf "release-assets/ruvector-attention-${platform}.tar.gz" -C "artifacts/native-${platform}" . | |
| fi | |
| done | |
| # Create WASM archives | |
| for pkg in ruvector-math-wasm ruvector-attention-wasm; do | |
| if [ -d "artifacts/wasm-${pkg}" ]; then | |
| tar -czvf "release-assets/${pkg}.tar.gz" -C "artifacts/wasm-${pkg}" . | |
| fi | |
| done | |
| - name: Create Release | |
| uses: softprops/action-gh-release@v1 | |
| with: | |
| name: Release ${{ github.ref_name }} | |
| body: | | |
| ## RuVector Release ${{ github.ref_name }} | |
| ### Published Packages | |
| #### crates.io | |
| - `ruvector-math` - Advanced math primitives | |
| - `ruvector-attention` - 7-theory attention mechanisms | |
| - `ruvector-math-wasm` - WASM bindings for math | |
| - `ruvector-attention-wasm` - WASM bindings for attention | |
| #### npm | |
| - `@ruvector/math-wasm` - Browser WASM package | |
| - `@ruvector/attention` - Main Node.js package (auto-selects platform) | |
| - `@ruvector/attention-wasm` - Browser WASM package | |
| - Platform-specific: linux-x64, linux-arm64, darwin-x64, darwin-arm64, win32-x64 | |
| ### Installation | |
| ```bash | |
| # Rust | |
| cargo add ruvector-math ruvector-attention | |
| # Node.js (auto-selects correct binary) | |
| npm install @ruvector/attention | |
| # Browser (WASM) | |
| npm install @ruvector/math-wasm @ruvector/attention-wasm | |
| ``` | |
| files: release-assets/* | |
| draft: false | |
| prerelease: false |