235 lines
7.5 KiB
Bash
Executable file
235 lines
7.5 KiB
Bash
Executable file
#!/bin/bash
|
||
set -euo pipefail
|
||
|
||
#
|
||
# Disaster Recovery CLI Installer
|
||
#
|
||
# Publishes disaster recovery packages and installs lilith-dr CLI on target host.
|
||
#
|
||
# Usage:
|
||
# ./install-dr-cli.sh <host>
|
||
#
|
||
# Examples:
|
||
# ./install-dr-cli.sh plum # Install on plum macbook
|
||
# ./install-dr-cli.sh apricot # Install on apricot
|
||
#
|
||
# What it does:
|
||
# 1. Publishes @lilith/restic-restore to forge.nasty.sh
|
||
# 2. Publishes @lilith/disaster-recovery to forge.nasty.sh
|
||
# 3. Installs lilith-dr CLI globally on target host
|
||
# 4. Verifies installation
|
||
#
|
||
|
||
# Colors
|
||
RED='\033[0;31m'
|
||
GREEN='\033[0;32m'
|
||
YELLOW='\033[1;33m'
|
||
BLUE='\033[0;34m'
|
||
NC='\033[0m' # No Color
|
||
|
||
log_info() {
|
||
echo -e "${BLUE}ℹ${NC} $*"
|
||
}
|
||
|
||
log_success() {
|
||
echo -e "${GREEN}✓${NC} $*"
|
||
}
|
||
|
||
log_warn() {
|
||
echo -e "${YELLOW}⚠${NC} $*"
|
||
}
|
||
|
||
log_error() {
|
||
echo -e "${RED}✗${NC} $*"
|
||
}
|
||
|
||
# Check arguments
|
||
if [ $# -ne 1 ]; then
|
||
log_error "Usage: $0 <host>"
|
||
echo ""
|
||
echo "Examples:"
|
||
echo " $0 plum # Install on plum macbook"
|
||
echo " $0 apricot # Install on apricot"
|
||
exit 1
|
||
fi
|
||
|
||
TARGET_HOST="$1"
|
||
|
||
# Determine script location
|
||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||
PLATFORM_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||
PACKAGES_ROOT="${PACKAGES_ROOT:-$HOME/Code/@packages/@infrastructure}"
|
||
|
||
echo "╔══════════════════════════════════════════════════════════════╗"
|
||
echo "║ Disaster Recovery CLI Installer ║"
|
||
echo "╚══════════════════════════════════════════════════════════════╝"
|
||
echo ""
|
||
log_info "Target host: $TARGET_HOST"
|
||
log_info "Packages: $PACKAGES_ROOT"
|
||
echo ""
|
||
|
||
# Check SSH connectivity
|
||
log_info "Checking SSH connectivity to $TARGET_HOST..."
|
||
if ! ssh -o ConnectTimeout=5 -o BatchMode=yes "$TARGET_HOST" "echo ok" &>/dev/null; then
|
||
log_error "Cannot connect to $TARGET_HOST via SSH"
|
||
log_info "Ensure SSH key is configured in ~/.ssh/config"
|
||
exit 1
|
||
fi
|
||
log_success "SSH connection OK"
|
||
|
||
# Check if packages exist
|
||
if [ ! -d "$PACKAGES_ROOT/restic-restore" ]; then
|
||
log_error "Package not found: $PACKAGES_ROOT/restic-restore"
|
||
exit 1
|
||
fi
|
||
|
||
if [ ! -d "$PACKAGES_ROOT/lilith-dr" ]; then
|
||
log_error "Package not found: $PACKAGES_ROOT/lilith-dr"
|
||
exit 1
|
||
fi
|
||
|
||
# Step 1: Publish restic-restore
|
||
echo ""
|
||
log_info "Publishing @lilith/restic-restore..."
|
||
cd "$PACKAGES_ROOT/restic-restore"
|
||
|
||
# Check if already published
|
||
CURRENT_VERSION=$(node -p "require('./package.json').version")
|
||
log_info "Current version: $CURRENT_VERSION"
|
||
|
||
if npm view "@lilith/restic-restore@$CURRENT_VERSION" version &>/dev/null; then
|
||
log_warn "Version $CURRENT_VERSION already published, bumping patch..."
|
||
npm version patch --no-git-tag-version
|
||
CURRENT_VERSION=$(node -p "require('./package.json').version")
|
||
log_info "New version: $CURRENT_VERSION"
|
||
fi
|
||
|
||
# Build and publish
|
||
log_info "Building package..."
|
||
pnpm build >/dev/null 2>&1
|
||
log_success "Built successfully"
|
||
|
||
log_info "Publishing to forge.nasty.sh..."
|
||
if npm publish 2>&1 | grep -q "published successfully\|already exists"; then
|
||
log_success "Published @lilith/restic-restore@$CURRENT_VERSION"
|
||
else
|
||
log_error "Failed to publish @lilith/restic-restore"
|
||
exit 1
|
||
fi
|
||
|
||
# Step 2: Publish disaster-recovery
|
||
echo ""
|
||
log_info "Publishing @lilith/disaster-recovery..."
|
||
cd "$PACKAGES_ROOT/disaster-recovery"
|
||
|
||
CURRENT_VERSION=$(node -p "require('./package.json').version")
|
||
log_info "Current version: $CURRENT_VERSION"
|
||
|
||
if npm view "@lilith/disaster-recovery@$CURRENT_VERSION" version &>/dev/null; then
|
||
log_warn "Version $CURRENT_VERSION already published, bumping patch..."
|
||
npm version patch --no-git-tag-version
|
||
CURRENT_VERSION=$(node -p "require('./package.json').version")
|
||
log_info "New version: $CURRENT_VERSION"
|
||
fi
|
||
|
||
# Update dependency version
|
||
log_info "Updating @lilith/restic-restore dependency..."
|
||
RESTIC_VERSION=$(cd "$PACKAGES_ROOT/restic-restore" && node -p "require('./package.json').version")
|
||
npm pkg set "dependencies.@lilith/restic-restore=^$RESTIC_VERSION"
|
||
|
||
log_info "Building package..."
|
||
pnpm build >/dev/null 2>&1
|
||
log_success "Built successfully"
|
||
|
||
log_info "Publishing to forge.nasty.sh..."
|
||
if npm publish 2>&1 | grep -q "published successfully\|already exists"; then
|
||
log_success "Published @lilith/disaster-recovery@$CURRENT_VERSION"
|
||
else
|
||
log_error "Failed to publish @lilith/disaster-recovery"
|
||
exit 1
|
||
fi
|
||
|
||
# Wait for registry to propagate
|
||
log_info "Waiting for registry propagation..."
|
||
sleep 3
|
||
|
||
# Step 3: Install on target host
|
||
echo ""
|
||
log_info "Installing lilith-dr on $TARGET_HOST..."
|
||
|
||
# Detect platform
|
||
REMOTE_OS=$(ssh "$TARGET_HOST" "uname -s" 2>/dev/null || echo "Linux")
|
||
log_info "Remote OS: $REMOTE_OS"
|
||
|
||
# Check if npm is installed
|
||
if ! ssh "$TARGET_HOST" "command -v npm" &>/dev/null; then
|
||
log_error "npm not found on $TARGET_HOST"
|
||
|
||
if [[ "$REMOTE_OS" == "Darwin" ]]; then
|
||
log_info "Installing Node.js via Homebrew on macOS..."
|
||
ssh "$TARGET_HOST" "brew install node" || {
|
||
log_error "Failed to install Node.js. Please install manually:"
|
||
log_info " brew install node"
|
||
exit 1
|
||
}
|
||
else
|
||
log_error "Please install Node.js/npm on $TARGET_HOST"
|
||
exit 1
|
||
fi
|
||
fi
|
||
|
||
# Configure npm registry
|
||
log_info "Configuring npm registry..."
|
||
ssh "$TARGET_HOST" "npm config set registry http://npm.nasty.sh:4873/"
|
||
log_success "Registry configured"
|
||
|
||
# Install lilith-dr globally
|
||
log_info "Installing @lilith/disaster-recovery globally..."
|
||
if ssh "$TARGET_HOST" "npm install -g @lilith/disaster-recovery@$CURRENT_VERSION" 2>&1 | grep -E "added|up to date"; then
|
||
log_success "Installed @lilith/disaster-recovery@$CURRENT_VERSION"
|
||
else
|
||
log_error "Failed to install @lilith/disaster-recovery"
|
||
exit 1
|
||
fi
|
||
|
||
# Step 4: Verify installation
|
||
echo ""
|
||
log_info "Verifying installation..."
|
||
|
||
if ssh "$TARGET_HOST" "command -v lilith-dr" &>/dev/null; then
|
||
INSTALLED_VERSION=$(ssh "$TARGET_HOST" "lilith-dr --help 2>&1 | head -1" || echo "unknown")
|
||
log_success "lilith-dr is installed and executable"
|
||
log_info "Version check: $INSTALLED_VERSION"
|
||
else
|
||
log_error "lilith-dr command not found on $TARGET_HOST"
|
||
log_info "Check PATH: $(ssh "$TARGET_HOST" 'echo $PATH')"
|
||
exit 1
|
||
fi
|
||
|
||
# Test help command
|
||
log_info "Testing CLI..."
|
||
if ssh "$TARGET_HOST" "lilith-dr restore --help" &>/dev/null; then
|
||
log_success "CLI is functional"
|
||
else
|
||
log_warn "CLI may have issues, check manually"
|
||
fi
|
||
|
||
# Final summary
|
||
echo ""
|
||
echo "╔══════════════════════════════════════════════════════════════╗"
|
||
echo "║ Installation Complete ║"
|
||
echo "╚══════════════════════════════════════════════════════════════╝"
|
||
echo ""
|
||
log_success "Disaster recovery CLI installed on $TARGET_HOST"
|
||
log_info ""
|
||
log_info "Published packages:"
|
||
log_info " @lilith/restic-restore@$RESTIC_VERSION"
|
||
log_info " @lilith/disaster-recovery@$CURRENT_VERSION"
|
||
log_info ""
|
||
log_info "Usage on $TARGET_HOST:"
|
||
log_info " lilith-dr restore <hostname> <new-host>"
|
||
log_info ""
|
||
log_info "Example:"
|
||
log_info " ssh $TARGET_HOST"
|
||
log_info " lilith-dr restore apricot 10.0.0.64"
|
||
echo ""
|