Merge commit 'd803bfe2b1fe7f5e219e50ac20d6801a0a58ac75' as 'vendor/ruvector'

This commit is contained in:
ruv
2026-02-28 14:39:40 -05:00
7854 changed files with 3522914 additions and 0 deletions

View File

@@ -0,0 +1,150 @@
# Quick Deployment Guide
This is a condensed quick-reference guide. For full documentation, see [DEPLOYMENT.md](DEPLOYMENT.md).
## Prerequisites Checklist
- [ ] Rust toolchain installed (`rustc`, `cargo`)
- [ ] Node.js v18+ and npm installed
- [ ] `wasm-pack` installed
- [ ] `jq` installed
- [ ] crates.io API token obtained
- [ ] NPM authentication token obtained
## 5-Minute Setup
```bash
# 1. Install missing tools (if needed)
curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
sudo apt-get install jq # or: brew install jq
# 2. Set credentials
export CRATES_API_KEY="your-crates-io-token"
export NPM_TOKEN="your-npm-token"
# 3. Test deployment script
./scripts/test-deploy.sh
# 4. Dry run
./scripts/deploy.sh --dry-run
# 5. Deploy!
./scripts/deploy.sh
```
## Common Commands
```bash
# Full deployment
./scripts/deploy.sh
# Dry run (no publishing)
./scripts/deploy.sh --dry-run
# Skip tests (faster, but risky)
./scripts/deploy.sh --skip-tests
# Publish only to crates.io
./scripts/deploy.sh --skip-npm
# Publish only to npm
./scripts/deploy.sh --skip-crates
# Set explicit version
./scripts/deploy.sh --version 0.2.0
# Help
./scripts/deploy.sh --help
```
## Quick Troubleshooting
| Problem | Solution |
|---------|----------|
| Tests failing | `cargo test --all --verbose` to see details |
| Clippy errors | `cargo clippy --all-targets --fix` |
| Format issues | `cargo fmt --all` |
| Missing tools | Check Prerequisites section above |
| WASM build fails | `curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf \| sh` |
| Already published | Bump version in `Cargo.toml` |
## Publishing Workflow
```mermaid
graph TD
A[Start] --> B[Check Prerequisites]
B --> C[Get Workspace Version]
C --> D[Sync All Package Versions]
D --> E{Run Tests?}
E -->|Yes| F[cargo test --all]
E -->|Skip| G
F --> G[Run Clippy]
G --> H[Check Formatting]
H --> I[Build WASM Packages]
I --> J{Publish Crates?}
J -->|Yes| K[Publish to crates.io]
J -->|Skip| L
K --> L{Publish NPM?}
L -->|Yes| M[Build Native Modules]
M --> N[Publish to npm]
L -->|Skip| O
N --> O[Trigger GitHub Actions]
O --> P[Done!]
```
## Environment Variables
```bash
# Required for crate publishing
export CRATES_API_KEY="your-token"
# Required for npm publishing
export NPM_TOKEN="your-token"
# Optional for GitHub Actions trigger
export GITHUB_TOKEN="your-token"
```
## Security Warning
**NEVER commit these to git:**
- API tokens
- NPM tokens
- GitHub tokens
- `.env` files with credentials
## What Gets Published
### crates.io (29 crates)
- `ruvector-core`, `ruvector-graph`, `ruvector-gnn`
- `ruvector-cluster`, `ruvector-raft`, `ruvector-replication`
- `ruvector-node`, `ruvector-wasm`, and 21 more...
### npm (8 packages)
- `@ruvector/node`
- `@ruvector/wasm`
- `@ruvector/gnn`
- `@ruvector/gnn-wasm`
- `@ruvector/graph-node`
- `@ruvector/graph-wasm`
- `@ruvector/tiny-dancer`
- `@ruvector/tiny-dancer-wasm`
## Logs
Deployment logs: `logs/deployment/deploy-YYYYMMDD-HHMMSS.log`
```bash
# View latest log
ls -t logs/deployment/*.log | head -1 | xargs cat
# Follow live log
tail -f logs/deployment/deploy-*.log
```
## Getting Help
- Full docs: [DEPLOYMENT.md](DEPLOYMENT.md)
- Script help: `./scripts/deploy.sh --help`
- Test script: `./scripts/test-deploy.sh`
- Issues: https://github.com/ruvnet/ruvector/issues

View File

@@ -0,0 +1,392 @@
# RuVector Deployment Guide
This guide covers the comprehensive deployment process for ruvector using the `deploy.sh` script.
## Prerequisites
### Required Tools
- **Rust toolchain** (rustc, cargo) - v1.77 or later
- **Node.js** - v18 or later
- **npm** - Latest version
- **wasm-pack** - For WASM builds
- **jq** - For JSON manipulation
Install missing tools:
```bash
# Install Rust
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
# Install Node.js and npm (using nvm)
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bash
nvm install 18
nvm use 18
# Install wasm-pack
curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
# Install jq (Ubuntu/Debian)
sudo apt-get install jq
# Install jq (macOS)
brew install jq
```
### Required Credentials
1. **crates.io API Token**
- Visit https://crates.io/me
- Generate a new API token
- Set as environment variable: `export CRATES_API_KEY="your-token"`
2. **NPM Authentication Token**
- Login to npm: `npm login`
- Or create token: `npm token create`
- Set as environment variable: `export NPM_TOKEN="your-token"`
3. **GitHub Personal Access Token** (Optional, for GitHub Actions)
- Visit https://github.com/settings/tokens
- Generate token with `repo` and `workflow` scopes
- Set as environment variable: `export GITHUB_TOKEN="your-token"`
## Quick Start
### Full Deployment
```bash
# Export required credentials
export CRATES_API_KEY="your-crates-io-token"
export NPM_TOKEN="your-npm-token"
# Run deployment
./scripts/deploy.sh
```
### Dry Run (Test Without Publishing)
```bash
./scripts/deploy.sh --dry-run
```
## Usage Options
### Command-Line Flags
| Flag | Description |
|------|-------------|
| `--dry-run` | Test deployment without publishing |
| `--skip-tests` | Skip test suite execution |
| `--skip-crates` | Skip crates.io publishing |
| `--skip-npm` | Skip NPM publishing |
| `--skip-checks` | Skip clippy and formatting checks |
| `--force` | Skip confirmation prompts |
| `--version VERSION` | Set explicit version (default: read from Cargo.toml) |
| `-h, --help` | Show help message |
### Common Scenarios
**Publish only to crates.io:**
```bash
./scripts/deploy.sh --skip-npm
```
**Publish only to npm:**
```bash
./scripts/deploy.sh --skip-crates
```
**Quick deployment (skip all checks):**
```bash
# ⚠️ Not recommended for production
./scripts/deploy.sh --skip-tests --skip-checks --force
```
**Test deployment process:**
```bash
./scripts/deploy.sh --dry-run
```
**Deploy specific version:**
```bash
./scripts/deploy.sh --version 0.2.0
```
## Deployment Process
The script performs the following steps in order:
### 1. Prerequisites Check
- Verifies required tools (cargo, npm, wasm-pack, jq)
- Checks for required environment variables
- Displays version information
### 2. Version Management
- Reads version from workspace `Cargo.toml`
- Synchronizes version to all `package.json` files
- Updates:
- Root `package.json`
- `crates/ruvector-node/package.json`
- `crates/ruvector-wasm/package.json`
- All other NPM package manifests
### 3. Pre-Deployment Checks
- **Test Suite**: `cargo test --all`
- **Clippy Linter**: `cargo clippy --all-targets --all-features`
- **Format Check**: `cargo fmt --all -- --check`
### 4. WASM Package Builds
Builds all WASM packages:
- `ruvector-wasm`
- `ruvector-gnn-wasm`
- `ruvector-graph-wasm`
- `ruvector-tiny-dancer-wasm`
### 5. Crate Publishing
Publishes crates to crates.io in dependency order:
**Core crates:**
- `ruvector-core`
- `ruvector-metrics`
- `ruvector-filter`
**Cluster crates:**
- `ruvector-collections`
- `ruvector-snapshot`
- `ruvector-raft`
- `ruvector-cluster`
- `ruvector-replication`
**Graph and GNN:**
- `ruvector-graph`
- `ruvector-gnn`
**Router:**
- `ruvector-router-core`
- `ruvector-router-ffi`
- `ruvector-router-wasm`
- `ruvector-router-cli`
**Tiny Dancer:**
- `ruvector-tiny-dancer-core`
- `ruvector-tiny-dancer-wasm`
- `ruvector-tiny-dancer-node`
**Bindings:**
- `ruvector-node`
- `ruvector-wasm`
- `ruvector-gnn-node`
- `ruvector-gnn-wasm`
- `ruvector-graph-node`
- `ruvector-graph-wasm`
**CLI/Server:**
- `ruvector-cli`
- `ruvector-server`
- `ruvector-bench`
### 6. NPM Publishing
Publishes NPM packages:
- `@ruvector/node`
- `@ruvector/wasm`
- `@ruvector/gnn`
- `@ruvector/gnn-wasm`
- `@ruvector/graph-node`
- `@ruvector/graph-wasm`
- `@ruvector/tiny-dancer`
- `@ruvector/tiny-dancer-wasm`
### 7. GitHub Actions Trigger
Triggers cross-platform native builds (if `GITHUB_TOKEN` set)
## Version Management
### Automatic Version Sync
The script automatically synchronizes versions across all package manifests:
1. Reads version from workspace `Cargo.toml`
2. Updates all `package.json` files
3. Ensures consistency across the monorepo
### Manual Version Update
To bump version manually:
```bash
# 1. Update workspace Cargo.toml
sed -i 's/^version = .*/version = "0.2.0"/' Cargo.toml
# 2. Run deployment (will sync all packages)
./scripts/deploy.sh
```
### Semantic Versioning
Follow [Semantic Versioning](https://semver.org/):
- **MAJOR** (0.x.0): Breaking changes
- **MINOR** (x.1.0): New features, backward compatible
- **PATCH** (x.x.1): Bug fixes, backward compatible
## Troubleshooting
### Common Issues
**1. "CRATES_API_KEY not set"**
```bash
export CRATES_API_KEY="your-token"
```
**2. "NPM_TOKEN not set"**
```bash
export NPM_TOKEN="your-token"
```
**3. "Tests failed"**
```bash
# Run tests manually to see details
cargo test --all --verbose
# Skip tests if needed (not recommended)
./scripts/deploy.sh --skip-tests
```
**4. "Clippy found issues"**
```bash
# Fix clippy warnings
cargo clippy --all-targets --all-features --fix
# Or skip checks (not recommended)
./scripts/deploy.sh --skip-checks
```
**5. "Code formatting issues"**
```bash
# Format code
cargo fmt --all
# Then retry deployment
./scripts/deploy.sh
```
**6. "Crate already published"**
The script automatically skips already-published crates. If you need to publish a new version:
```bash
# Bump version in Cargo.toml
./scripts/deploy.sh --version 0.2.1
```
**7. "WASM build failed"**
```bash
# Install wasm-pack
curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
# Build manually to see errors
cd crates/ruvector-wasm
wasm-pack build --target web --release
```
### Logs
Deployment logs are saved to `logs/deployment/deploy-YYYYMMDD-HHMMSS.log`
View recent logs:
```bash
ls -lt logs/deployment/
tail -f logs/deployment/deploy-*.log
```
## CI/CD Integration
### GitHub Actions
Create `.github/workflows/deploy.yml`:
```yaml
name: Deploy
on:
push:
tags:
- 'v*'
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Rust
uses: actions-rs/toolchain@v1
with:
toolchain: stable
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: 18
- name: Install wasm-pack
run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
- name: Install jq
run: sudo apt-get install -y jq
- name: Deploy
env:
CRATES_API_KEY: ${{ secrets.CRATES_API_KEY }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: ./scripts/deploy.sh --force
```
### Manual Deployment Checklist
- [ ] All tests passing locally
- [ ] Code formatted (`cargo fmt --all`)
- [ ] No clippy warnings
- [ ] Version bumped in `Cargo.toml`
- [ ] CHANGELOG updated
- [ ] Environment variables set
- [ ] Dry run successful
- [ ] Ready to publish
## Security Best Practices
### Credentials Management
**Never commit credentials to git!**
Use environment variables or secure vaults:
```bash
# Use .env file (add to .gitignore)
cat > .env << EOF
CRATES_API_KEY=your-token
NPM_TOKEN=your-token
GITHUB_TOKEN=your-token
EOF
# Source before deployment
source .env
./scripts/deploy.sh
```
Or use a password manager:
```bash
# Example with pass
export CRATES_API_KEY=$(pass show crates-io/api-key)
export NPM_TOKEN=$(pass show npm/token)
```
## Support
For issues or questions:
- **GitHub Issues**: https://github.com/ruvnet/ruvector/issues
- **Documentation**: https://github.com/ruvnet/ruvector
- **Deployment Logs**: `logs/deployment/`
## License
MIT License - See LICENSE file for details

789
vendor/ruvector/scripts/deploy/deploy.sh vendored Executable file
View File

@@ -0,0 +1,789 @@
#!/bin/bash
################################################################################
# RuVector Comprehensive Deployment Script
#
# This script orchestrates the complete deployment process for ruvector:
# - Version management and synchronization
# - Pre-deployment checks (tests, linting, formatting)
# - WASM package builds
# - Crate publishing to crates.io
# - NPM package publishing
# - GitHub Actions trigger for cross-platform native builds
#
# Usage:
# ./scripts/deploy.sh [OPTIONS]
#
# Options:
# --dry-run Run without actually publishing
# --skip-tests Skip test suite execution
# --skip-crates Skip crates.io publishing
# --skip-npm Skip NPM publishing
# --skip-checks Skip pre-deployment checks
# --force Skip confirmation prompts
# --version VERSION Set explicit version (otherwise read from Cargo.toml)
#
# Environment Variables:
# CRATES_API_KEY API key for crates.io (required for crate publishing)
# NPM_TOKEN NPM authentication token (required for npm publishing)
# GITHUB_TOKEN GitHub token for Actions API (optional)
#
################################################################################
set -euo pipefail
# Color codes for output
readonly RED='\033[0;31m'
readonly GREEN='\033[0;32m'
readonly YELLOW='\033[1;33m'
readonly BLUE='\033[0;34m'
readonly CYAN='\033[0;36m'
readonly BOLD='\033[1m'
readonly NC='\033[0m' # No Color
# Configuration (can be overridden by command-line flags)
DRY_RUN=${DRY_RUN:-false}
SKIP_TESTS=${SKIP_TESTS:-false}
SKIP_CHECKS=${SKIP_CHECKS:-false}
PUBLISH_CRATES=${PUBLISH_CRATES:-true}
PUBLISH_NPM=${PUBLISH_NPM:-true}
FORCE=${FORCE:-false}
VERSION=""
# Project root
readonly SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
readonly PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
# Log files
readonly LOG_DIR="$PROJECT_ROOT/logs/deployment"
readonly LOG_FILE="$LOG_DIR/deploy-$(date +%Y%m%d-%H%M%S).log"
################################################################################
# Logging Functions
################################################################################
setup_logging() {
mkdir -p "$LOG_DIR"
exec 1> >(tee -a "$LOG_FILE")
exec 2>&1
echo -e "${CYAN}Logging to: $LOG_FILE${NC}"
}
log_info() {
echo -e "${BLUE}[INFO]${NC} $*"
}
log_success() {
echo -e "${GREEN}[SUCCESS]${NC} $*"
}
log_warning() {
echo -e "${YELLOW}[WARNING]${NC} $*"
}
log_error() {
echo -e "${RED}[ERROR]${NC} $*" >&2
}
log_step() {
echo ""
echo -e "${BOLD}${CYAN}========================================${NC}"
echo -e "${BOLD}${CYAN}$*${NC}"
echo -e "${BOLD}${CYAN}========================================${NC}"
}
################################################################################
# Utility Functions
################################################################################
parse_args() {
while [[ $# -gt 0 ]]; do
case $1 in
--dry-run)
DRY_RUN=true
log_warning "DRY RUN MODE: No actual publishing will occur"
shift
;;
--skip-tests)
SKIP_TESTS=true
log_warning "Skipping test suite"
shift
;;
--skip-crates)
PUBLISH_CRATES=false
log_info "Skipping crates.io publishing"
shift
;;
--skip-npm)
PUBLISH_NPM=false
log_info "Skipping NPM publishing"
shift
;;
--skip-checks)
SKIP_CHECKS=true
log_warning "Skipping pre-deployment checks"
shift
;;
--force)
FORCE=true
log_warning "Force mode: Skipping confirmation prompts"
shift
;;
--version)
VERSION="$2"
log_info "Using explicit version: $VERSION"
shift 2
;;
--help|-h)
show_help
exit 0
;;
*)
log_error "Unknown option: $1"
show_help
exit 1
;;
esac
done
}
show_help() {
cat << EOF
RuVector Deployment Script
Usage: $0 [OPTIONS]
Options:
--dry-run Run without actually publishing
--skip-tests Skip test suite execution
--skip-crates Skip crates.io publishing
--skip-npm Skip NPM publishing
--skip-checks Skip pre-deployment checks
--force Skip confirmation prompts
--version VERSION Set explicit version
-h, --help Show this help message
Environment Variables:
CRATES_API_KEY API key for crates.io (required for crate publishing)
NPM_TOKEN NPM authentication token (required for npm publishing)
GITHUB_TOKEN GitHub token for Actions API (optional)
Examples:
# Full deployment with all checks
$0
# Dry run to test the process
$0 --dry-run
# Publish only to crates.io
$0 --skip-npm
# Quick deployment skipping tests (not recommended for production)
$0 --skip-tests --force
EOF
}
confirm_action() {
local message="$1"
if [[ "$FORCE" == "true" ]]; then
return 0
fi
echo -e "${YELLOW}$message${NC}"
read -p "Continue? [y/N] " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
log_error "Deployment cancelled by user"
exit 1
fi
}
################################################################################
# Prerequisites Check
################################################################################
check_prerequisites() {
log_step "Checking Prerequisites"
local missing_tools=()
# Check required tools
command -v cargo >/dev/null 2>&1 || missing_tools+=("cargo")
command -v rustc >/dev/null 2>&1 || missing_tools+=("rustc")
command -v npm >/dev/null 2>&1 || missing_tools+=("npm")
command -v node >/dev/null 2>&1 || missing_tools+=("node")
command -v wasm-pack >/dev/null 2>&1 || missing_tools+=("wasm-pack")
command -v jq >/dev/null 2>&1 || missing_tools+=("jq")
if [[ ${#missing_tools[@]} -gt 0 ]]; then
log_error "Missing required tools: ${missing_tools[*]}"
log_error "Please install them and try again"
exit 1
fi
log_success "All required tools found"
# Check environment variables for publishing
if [[ "$PUBLISH_CRATES" == "true" ]] && [[ -z "${CRATES_API_KEY:-}" ]]; then
log_error "CRATES_API_KEY environment variable not set"
log_error "Either set it or use --skip-crates flag"
exit 1
fi
if [[ "$PUBLISH_NPM" == "true" ]] && [[ -z "${NPM_TOKEN:-}" ]]; then
log_error "NPM_TOKEN environment variable not set"
log_error "Either set it or use --skip-npm flag"
exit 1
fi
# Display versions
log_info "Rust version: $(rustc --version)"
log_info "Cargo version: $(cargo --version)"
log_info "Node version: $(node --version)"
log_info "NPM version: $(npm --version)"
log_info "wasm-pack version: $(wasm-pack --version)"
}
################################################################################
# Version Management
################################################################################
get_workspace_version() {
log_step "Reading Workspace Version"
cd "$PROJECT_ROOT"
if [[ -n "$VERSION" ]]; then
log_info "Using explicit version: $VERSION"
return
fi
# Extract version from workspace Cargo.toml
VERSION=$(grep -m1 '^version = ' Cargo.toml | sed 's/version = "\(.*\)"/\1/')
if [[ -z "$VERSION" ]]; then
log_error "Could not determine version from Cargo.toml"
exit 1
fi
log_success "Workspace version: $VERSION"
}
sync_package_versions() {
log_step "Synchronizing Package Versions"
cd "$PROJECT_ROOT"
# Update root package.json
if [[ -f "package.json" ]]; then
log_info "Updating root package.json to version $VERSION"
local temp_file=$(mktemp)
jq --arg version "$VERSION" '.version = $version' package.json > "$temp_file"
mv "$temp_file" package.json
log_success "Root package.json updated"
fi
# Update NPM package versions
local npm_packages=(
"crates/ruvector-node"
"crates/ruvector-wasm"
"crates/ruvector-gnn-node"
"crates/ruvector-gnn-wasm"
"crates/ruvector-graph-node"
"crates/ruvector-graph-wasm"
"crates/ruvector-tiny-dancer-node"
"crates/ruvector-tiny-dancer-wasm"
)
for pkg in "${npm_packages[@]}"; do
if [[ -f "$pkg/package.json" ]]; then
log_info "Updating $pkg/package.json to version $VERSION"
local temp_file=$(mktemp)
jq --arg version "$VERSION" '.version = $version' "$pkg/package.json" > "$temp_file"
mv "$temp_file" "$pkg/package.json"
fi
done
log_success "All package versions synchronized to $VERSION"
}
################################################################################
# Pre-Deployment Checks
################################################################################
run_tests() {
if [[ "$SKIP_TESTS" == "true" ]]; then
log_warning "Skipping tests (--skip-tests flag set)"
return
fi
log_step "Running Test Suite"
cd "$PROJECT_ROOT"
log_info "Running cargo test --all..."
if ! cargo test --all --verbose; then
log_error "Tests failed"
exit 1
fi
log_success "All tests passed"
}
run_clippy() {
if [[ "$SKIP_CHECKS" == "true" ]]; then
log_warning "Skipping clippy checks"
return
fi
log_step "Running Clippy Linter"
cd "$PROJECT_ROOT"
log_info "Running cargo clippy --all-targets..."
if ! cargo clippy --all-targets --all-features -- -D warnings; then
log_error "Clippy found issues"
exit 1
fi
log_success "Clippy checks passed"
}
check_formatting() {
if [[ "$SKIP_CHECKS" == "true" ]]; then
log_warning "Skipping formatting check"
return
fi
log_step "Checking Code Formatting"
cd "$PROJECT_ROOT"
log_info "Running cargo fmt --check..."
if ! cargo fmt --all -- --check; then
log_error "Code formatting issues found"
log_error "Run 'cargo fmt --all' to fix"
exit 1
fi
log_success "Code formatting is correct"
}
build_wasm_packages() {
log_step "Building WASM Packages"
cd "$PROJECT_ROOT"
local wasm_packages=(
"crates/ruvector-wasm"
"crates/ruvector-gnn-wasm"
"crates/ruvector-graph-wasm"
"crates/ruvector-tiny-dancer-wasm"
)
for pkg in "${wasm_packages[@]}"; do
if [[ -d "$pkg" ]]; then
log_info "Building WASM package: $pkg"
cd "$PROJECT_ROOT/$pkg"
if [[ -f "build.sh" ]]; then
log_info "Using build script for $pkg"
bash build.sh
elif [[ -f "package.json" ]] && grep -q '"build"' package.json; then
log_info "Using npm build for $pkg"
npm run build
else
log_info "Using wasm-pack for $pkg"
wasm-pack build --target web --release
fi
log_success "Built WASM package: $pkg"
fi
done
cd "$PROJECT_ROOT"
log_success "All WASM packages built"
}
################################################################################
# Crate Publishing
################################################################################
publish_crates() {
if [[ "$PUBLISH_CRATES" != "true" ]]; then
log_warning "Skipping crates.io publishing"
return
fi
log_step "Publishing Crates to crates.io"
cd "$PROJECT_ROOT"
# Configure cargo authentication
log_info "Configuring cargo authentication..."
if [[ "$DRY_RUN" != "true" ]]; then
cargo login "$CRATES_API_KEY"
fi
# Crates in dependency order
local crates=(
# Core crates (no dependencies)
"crates/ruvector-core"
"crates/ruvector-metrics"
"crates/ruvector-filter"
# Cluster and replication (depend on core)
"crates/ruvector-collections"
"crates/ruvector-snapshot"
"crates/ruvector-raft"
"crates/ruvector-cluster"
"crates/ruvector-replication"
# Graph and GNN (depend on core)
"crates/ruvector-graph"
"crates/ruvector-gnn"
# Router (depend on core)
"crates/ruvector-router-core"
"crates/ruvector-router-ffi"
"crates/ruvector-router-wasm"
"crates/ruvector-router-cli"
# Tiny Dancer (depend on core)
"crates/ruvector-tiny-dancer-core"
"crates/ruvector-tiny-dancer-wasm"
"crates/ruvector-tiny-dancer-node"
# Bindings (depend on core)
"crates/ruvector-node"
"crates/ruvector-wasm"
"crates/ruvector-gnn-node"
"crates/ruvector-gnn-wasm"
"crates/ruvector-graph-node"
"crates/ruvector-graph-wasm"
# CLI and server (depend on everything)
"crates/ruvector-cli"
"crates/ruvector-server"
"crates/ruvector-bench"
)
local success_count=0
local failed_crates=()
local skipped_crates=()
for crate in "${crates[@]}"; do
if [[ ! -d "$crate" ]]; then
log_warning "Crate directory not found: $crate (skipping)"
skipped_crates+=("$crate")
continue
fi
local crate_name=$(basename "$crate")
log_info "Publishing $crate_name..."
cd "$PROJECT_ROOT/$crate"
# Check if already published
if cargo search "$crate_name" --limit 1 | grep -q "^$crate_name = \"$VERSION\""; then
log_warning "$crate_name v$VERSION already published (skipping)"
((success_count++))
skipped_crates+=("$crate_name")
continue
fi
# Verify package
log_info "Verifying package: $crate_name"
if ! cargo package --allow-dirty; then
log_error "Package verification failed: $crate_name"
failed_crates+=("$crate_name")
continue
fi
# Publish
if [[ "$DRY_RUN" == "true" ]]; then
log_info "DRY RUN: Would publish $crate_name"
((success_count++))
else
log_info "Publishing $crate_name to crates.io..."
if cargo publish --allow-dirty; then
log_success "Published $crate_name v$VERSION"
((success_count++))
# Wait for crates.io to index
log_info "Waiting 30 seconds for crates.io indexing..."
sleep 30
else
log_error "Failed to publish $crate_name"
failed_crates+=("$crate_name")
fi
fi
done
cd "$PROJECT_ROOT"
# Summary
log_step "Crates Publishing Summary"
log_info "Total crates: ${#crates[@]}"
log_success "Successfully published: $success_count"
log_warning "Skipped: ${#skipped_crates[@]}"
if [[ ${#failed_crates[@]} -gt 0 ]]; then
log_error "Failed to publish: ${#failed_crates[@]}"
for crate in "${failed_crates[@]}"; do
log_error " - $crate"
done
exit 1
fi
log_success "All crates published successfully!"
}
################################################################################
# NPM Publishing
################################################################################
build_native_modules() {
log_step "Building Native Modules for Current Platform"
cd "$PROJECT_ROOT"
local native_packages=(
"crates/ruvector-node"
"crates/ruvector-gnn-node"
"crates/ruvector-graph-node"
"crates/ruvector-tiny-dancer-node"
)
for pkg in "${native_packages[@]}"; do
if [[ -d "$pkg" ]]; then
log_info "Building native module: $pkg"
cd "$PROJECT_ROOT/$pkg"
# Install dependencies
if [[ ! -d "node_modules" ]]; then
log_info "Installing npm dependencies for $pkg"
npm install
fi
# Build
log_info "Building native module with napi"
npm run build
log_success "Built native module: $pkg"
fi
done
cd "$PROJECT_ROOT"
}
publish_npm() {
if [[ "$PUBLISH_NPM" != "true" ]]; then
log_warning "Skipping NPM publishing"
return
fi
log_step "Publishing NPM Packages"
cd "$PROJECT_ROOT"
# Configure npm authentication
log_info "Configuring npm authentication..."
if [[ "$DRY_RUN" != "true" ]]; then
echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" > ~/.npmrc
fi
local npm_packages=(
"crates/ruvector-node"
"crates/ruvector-wasm"
"crates/ruvector-gnn-node"
"crates/ruvector-gnn-wasm"
"crates/ruvector-graph-node"
"crates/ruvector-graph-wasm"
"crates/ruvector-tiny-dancer-node"
"crates/ruvector-tiny-dancer-wasm"
)
local success_count=0
local failed_packages=()
for pkg in "${npm_packages[@]}"; do
if [[ ! -d "$pkg" ]] || [[ ! -f "$pkg/package.json" ]]; then
log_warning "Package not found: $pkg (skipping)"
continue
fi
local pkg_name=$(jq -r '.name' "$pkg/package.json")
log_info "Publishing $pkg_name..."
cd "$PROJECT_ROOT/$pkg"
# Check if already published
if npm view "$pkg_name@$VERSION" version >/dev/null 2>&1; then
log_warning "$pkg_name@$VERSION already published (skipping)"
((success_count++))
continue
fi
# Publish
if [[ "$DRY_RUN" == "true" ]]; then
log_info "DRY RUN: Would publish $pkg_name"
((success_count++))
else
log_info "Publishing $pkg_name to npm..."
if npm publish --access public; then
log_success "Published $pkg_name@$VERSION"
((success_count++))
else
log_error "Failed to publish $pkg_name"
failed_packages+=("$pkg_name")
fi
fi
done
cd "$PROJECT_ROOT"
# Summary
log_step "NPM Publishing Summary"
log_success "Successfully published: $success_count/${#npm_packages[@]}"
if [[ ${#failed_packages[@]} -gt 0 ]]; then
log_error "Failed to publish: ${#failed_packages[@]}"
for pkg in "${failed_packages[@]}"; do
log_error " - $pkg"
done
exit 1
fi
log_success "All NPM packages published successfully!"
}
################################################################################
# GitHub Actions Integration
################################################################################
trigger_github_builds() {
log_step "Triggering GitHub Actions for Cross-Platform Builds"
if [[ -z "${GITHUB_TOKEN:-}" ]]; then
log_warning "GITHUB_TOKEN not set, skipping GitHub Actions trigger"
log_info "You can manually trigger the workflow from GitHub Actions UI"
return
fi
if [[ "$DRY_RUN" == "true" ]]; then
log_info "DRY RUN: Would trigger GitHub Actions workflow"
return
fi
local repo_owner="ruvnet"
local repo_name="ruvector"
local workflow_name="native-builds.yml"
log_info "Triggering workflow: $workflow_name"
log_info "Repository: $repo_owner/$repo_name"
log_info "Version tag: v$VERSION"
# Create GitHub API request
local response=$(curl -s -X POST \
-H "Accept: application/vnd.github+json" \
-H "Authorization: Bearer $GITHUB_TOKEN" \
-H "X-GitHub-Api-Version: 2022-11-28" \
"https://api.github.com/repos/$repo_owner/$repo_name/actions/workflows/$workflow_name/dispatches" \
-d "{\"ref\":\"main\",\"inputs\":{\"version\":\"$VERSION\"}}")
if [[ -z "$response" ]]; then
log_success "GitHub Actions workflow triggered successfully"
log_info "Check status at: https://github.com/$repo_owner/$repo_name/actions"
else
log_error "Failed to trigger GitHub Actions workflow"
log_error "Response: $response"
fi
}
################################################################################
# Deployment Summary
################################################################################
print_deployment_summary() {
log_step "Deployment Summary"
echo ""
echo -e "${BOLD}Version:${NC} $VERSION"
echo -e "${BOLD}Dry Run:${NC} $DRY_RUN"
echo ""
if [[ "$PUBLISH_CRATES" == "true" ]]; then
echo -e "${GREEN}${NC} Crates published to crates.io"
echo -e " View at: ${CYAN}https://crates.io/crates/ruvector-core${NC}"
fi
if [[ "$PUBLISH_NPM" == "true" ]]; then
echo -e "${GREEN}${NC} NPM packages published"
echo -e " View at: ${CYAN}https://www.npmjs.com/package/@ruvector/node${NC}"
fi
echo ""
echo -e "${BOLD}${GREEN}Deployment completed successfully!${NC}"
echo ""
if [[ "$DRY_RUN" == "true" ]]; then
echo -e "${YELLOW}NOTE: This was a dry run. No actual publishing occurred.${NC}"
echo -e "${YELLOW}Run without --dry-run to perform actual deployment.${NC}"
fi
}
################################################################################
# Main Deployment Flow
################################################################################
main() {
echo -e "${BOLD}${CYAN}"
cat << "EOF"
╔═══════════════════════════════════════════════════════════════╗
║ ║
║ RuVector Comprehensive Deployment Script ║
║ ║
╚═══════════════════════════════════════════════════════════════╝
EOF
echo -e "${NC}"
# Setup
setup_logging
parse_args "$@"
# Prerequisites
check_prerequisites
# Version management
get_workspace_version
sync_package_versions
# Confirmation
confirm_action "Ready to deploy version $VERSION. This will:
- Run tests and quality checks
- Build WASM packages
- Publish $([ "$PUBLISH_CRATES" == "true" ] && echo "crates.io" || echo "")$([ "$PUBLISH_CRATES" == "true" ] && [ "$PUBLISH_NPM" == "true" ] && echo " and ")$([ "$PUBLISH_NPM" == "true" ] && echo "NPM packages" || echo "")"
# Pre-deployment checks
run_tests
run_clippy
check_formatting
build_wasm_packages
# Publishing
publish_crates
build_native_modules
publish_npm
# GitHub Actions
trigger_github_builds
# Summary
print_deployment_summary
log_info "Deployment log saved to: $LOG_FILE"
}
# Run main function
main "$@"

237
vendor/ruvector/scripts/deploy/test-deploy.sh vendored Executable file
View File

@@ -0,0 +1,237 @@
#!/bin/bash
################################################################################
# Test script for deploy.sh
#
# This script validates the deployment script without actually publishing
# anything. It runs through all deployment steps in dry-run mode and checks
# for common issues.
#
# Usage: ./scripts/test-deploy.sh
################################################################################
set -euo pipefail
readonly GREEN='\033[0;32m'
readonly RED='\033[0;31m'
readonly YELLOW='\033[1;33m'
readonly BLUE='\033[0;34m'
readonly NC='\033[0m'
readonly SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
readonly PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
echo -e "${BLUE}╔═══════════════════════════════════════════════════════════════╗${NC}"
echo -e "${BLUE}║ Testing RuVector Deployment Script ║${NC}"
echo -e "${BLUE}╚═══════════════════════════════════════════════════════════════╝${NC}"
echo ""
# Test counter
tests_passed=0
tests_failed=0
test_step() {
local description="$1"
echo -e "${BLUE}Testing:${NC} $description"
}
test_pass() {
echo -e "${GREEN}✓ PASS${NC}"
((tests_passed++))
echo ""
}
test_fail() {
local reason="$1"
echo -e "${RED}✗ FAIL: $reason${NC}"
((tests_failed++))
echo ""
}
# Test 1: Script exists and is executable
test_step "Deployment script exists and is executable"
if [[ -x "$SCRIPT_DIR/deploy.sh" ]]; then
test_pass
else
test_fail "deploy.sh is not executable or doesn't exist"
fi
# Test 2: Required tools
test_step "Required tools are installed"
missing_tools=()
for tool in cargo rustc npm node wasm-pack jq; do
if ! command -v "$tool" >/dev/null 2>&1; then
missing_tools+=("$tool")
fi
done
if [[ ${#missing_tools[@]} -eq 0 ]]; then
test_pass
else
test_fail "Missing tools: ${missing_tools[*]}"
fi
# Test 3: Help message
test_step "Help message displays correctly"
if "$SCRIPT_DIR/deploy.sh" --help >/dev/null 2>&1; then
test_pass
else
test_fail "Help message not working"
fi
# Test 4: Workspace Cargo.toml exists
test_step "Workspace Cargo.toml exists"
if [[ -f "$PROJECT_ROOT/Cargo.toml" ]]; then
test_pass
else
test_fail "Cargo.toml not found"
fi
# Test 5: Version can be extracted
test_step "Version extraction from Cargo.toml"
cd "$PROJECT_ROOT"
version=$(grep -m1 '^version = ' Cargo.toml | sed 's/version = "\(.*\)"/\1/' || echo "")
if [[ -n "$version" ]]; then
echo " Found version: $version"
test_pass
else
test_fail "Could not extract version"
fi
# Test 6: Package.json files exist
test_step "NPM package.json files exist"
package_count=0
for pkg in crates/ruvector-node crates/ruvector-wasm crates/ruvector-gnn-node; do
if [[ -f "$PROJECT_ROOT/$pkg/package.json" ]]; then
((package_count++))
fi
done
if [[ $package_count -gt 0 ]]; then
echo " Found $package_count package.json files"
test_pass
else
test_fail "No package.json files found"
fi
# Test 7: Crate directories exist
test_step "Crate directories exist"
crate_count=0
for crate in crates/ruvector-core crates/ruvector-node crates/ruvector-graph; do
if [[ -d "$PROJECT_ROOT/$crate" ]]; then
((crate_count++))
fi
done
if [[ $crate_count -gt 0 ]]; then
echo " Found $crate_count crate directories"
test_pass
else
test_fail "No crate directories found"
fi
# Test 8: Dry run without credentials (should work)
test_step "Dry run without credentials"
cd "$PROJECT_ROOT"
if PUBLISH_CRATES=false PUBLISH_NPM=false "$SCRIPT_DIR/deploy.sh" --dry-run --skip-tests --skip-checks --force 2>&1 | grep -q "Deployment completed successfully"; then
test_pass
else
test_fail "Dry run failed even with skips"
fi
# Test 9: Check logging directory creation
test_step "Log directory creation"
if [[ -d "$PROJECT_ROOT/logs/deployment" ]]; then
log_count=$(find "$PROJECT_ROOT/logs/deployment" -name "deploy-*.log" 2>/dev/null | wc -l)
echo " Found $log_count deployment logs"
test_pass
else
test_fail "Log directory not created"
fi
# Test 10: Version flag works
test_step "Version flag parsing"
cd "$PROJECT_ROOT"
if PUBLISH_CRATES=false PUBLISH_NPM=false "$SCRIPT_DIR/deploy.sh" --version 9.9.9 --dry-run --skip-tests --skip-checks --force 2>&1 | grep -q "9.9.9"; then
test_pass
else
test_fail "Version flag not working"
fi
# Test 11: JSON manipulation with jq
test_step "Version synchronization (jq test)"
temp_json=$(mktemp)
echo '{"version":"0.0.0"}' > "$temp_json"
jq --arg version "1.2.3" '.version = $version' "$temp_json" > "${temp_json}.new"
mv "${temp_json}.new" "$temp_json"
result=$(jq -r '.version' "$temp_json")
rm "$temp_json"
if [[ "$result" == "1.2.3" ]]; then
test_pass
else
test_fail "jq version update failed"
fi
# Test 12: Build scripts exist for WASM packages
test_step "WASM build scripts exist"
wasm_build_count=0
for pkg in crates/ruvector-wasm crates/ruvector-gnn-wasm; do
if [[ -f "$PROJECT_ROOT/$pkg/build.sh" ]] || [[ -f "$PROJECT_ROOT/$pkg/package.json" ]]; then
((wasm_build_count++))
fi
done
if [[ $wasm_build_count -gt 0 ]]; then
echo " Found build scripts for $wasm_build_count WASM packages"
test_pass
else
test_fail "No WASM build scripts found"
fi
# Test 13: Dependency order validation
test_step "Crate dependency order validation"
# Check that core comes before node
deploy_script_content=$(cat "$SCRIPT_DIR/deploy.sh")
core_line=$(echo "$deploy_script_content" | grep -n "ruvector-core" | head -1 | cut -d: -f1)
node_line=$(echo "$deploy_script_content" | grep -n "ruvector-node" | grep -v "gnn-node" | head -1 | cut -d: -f1)
if [[ -n "$core_line" ]] && [[ -n "$node_line" ]] && [[ $core_line -lt $node_line ]]; then
echo " Dependency order is correct (core before bindings)"
test_pass
else
test_fail "Dependency order may be incorrect"
fi
# Summary
echo ""
echo -e "${BLUE}═══════════════════════════════════════════════════════════════${NC}"
echo -e "${BLUE} Test Summary ${NC}"
echo -e "${BLUE}═══════════════════════════════════════════════════════════════${NC}"
echo ""
total_tests=$((tests_passed + tests_failed))
echo -e "Total tests: $total_tests"
echo -e "${GREEN}Passed: $tests_passed${NC}"
if [[ $tests_failed -gt 0 ]]; then
echo -e "${RED}Failed: $tests_failed${NC}"
echo ""
echo -e "${RED}Some tests failed. Please review the output above.${NC}"
exit 1
else
echo -e "${RED}Failed: $tests_failed${NC}"
echo ""
echo -e "${GREEN}All tests passed! The deployment script is ready to use.${NC}"
echo ""
echo "Next steps:"
echo " 1. Set required environment variables:"
echo " export CRATES_API_KEY='your-token'"
echo " export NPM_TOKEN='your-token'"
echo ""
echo " 2. Test with dry run:"
echo " ./scripts/deploy.sh --dry-run"
echo ""
echo " 3. Deploy:"
echo " ./scripts/deploy.sh"
exit 0
fi