Merge commit 'd803bfe2b1fe7f5e219e50ac20d6801a0a58ac75' as 'vendor/ruvector'
This commit is contained in:
150
vendor/ruvector/scripts/deploy/DEPLOYMENT-QUICKSTART.md
vendored
Normal file
150
vendor/ruvector/scripts/deploy/DEPLOYMENT-QUICKSTART.md
vendored
Normal 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
|
||||
392
vendor/ruvector/scripts/deploy/DEPLOYMENT.md
vendored
Normal file
392
vendor/ruvector/scripts/deploy/DEPLOYMENT.md
vendored
Normal 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
789
vendor/ruvector/scripts/deploy/deploy.sh
vendored
Executable 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
237
vendor/ruvector/scripts/deploy/test-deploy.sh
vendored
Executable 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
|
||||
Reference in New Issue
Block a user