553 lines
20 KiB
YAML
553 lines
20 KiB
YAML
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
|