platform-codebase/features/image-assistant/macos/deploy.sh

265 lines
7.9 KiB
Bash
Executable file

#!/bin/bash
#
# Deploy ImageAssistant to plum (macOS)
#
# Usage:
# ./deploy.sh # Deploy and install
# ./deploy.sh --sync-only # Just sync files, don't install
# ./deploy.sh --build-only # Sync and build, don't install
# ./deploy.sh --status # Check status on plum
# ./deploy.sh --logs # Tail logs on plum
# ./deploy.sh --stop # Stop the agent on plum
#
# Configuration: deploy.yaml
#
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
CONFIG_FILE="$SCRIPT_DIR/deploy.yaml"
# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'
log_info() { echo -e "${BLUE}${NC} $1"; }
log_success() { echo -e "${GREEN}${NC} $1"; }
log_warn() { echo -e "${YELLOW}${NC} $1"; }
log_error() { echo -e "${RED}${NC} $1"; }
# Read config from deploy.yaml
read_config() {
if [[ ! -f "$CONFIG_FILE" ]]; then
log_error "Config file not found: $CONFIG_FILE"
exit 1
fi
# Parse YAML (simple key: value format)
PLUM_HOST=$(grep '^host:' "$CONFIG_FILE" | sed 's/^host:[[:space:]]*//' | tr -d '"')
REMOTE_DIR=$(grep '^remote_dir:' "$CONFIG_FILE" | sed 's/^remote_dir:[[:space:]]*//' | tr -d '"')
BACKEND_URL=$(grep '^backend_url:' "$CONFIG_FILE" | sed 's/^backend_url:[[:space:]]*//' | tr -d '"')
# Defaults
PLUM_HOST="${PLUM_HOST:-plum-eth}"
REMOTE_DIR="${REMOTE_DIR:-~/Code/@projects/@lilith/lilith-platform/codebase/features/image-assistant/macos}"
BACKEND_URL="${BACKEND_URL:-http://10.0.0.116:3150}"
}
check_plum_reachable() {
log_info "Checking connection to $PLUM_HOST..."
if ! ssh -o ConnectTimeout=5 "$PLUM_HOST" "echo ok" &>/dev/null; then
log_error "Cannot reach plum at $PLUM_HOST"
echo " Check deploy.yaml 'host' setting and SSH config"
exit 1
fi
log_success "Connected to $PLUM_HOST"
}
build_frontend_locally() {
local frontend_dir="$SCRIPT_DIR/../frontend-macos-client"
if [[ ! -d "$frontend_dir" ]]; then
log_warn "Frontend directory not found at $frontend_dir - skipping frontend build"
return 0
fi
log_info "Building frontend locally (to avoid requiring Node.js on plum)..."
cd "$frontend_dir"
# Check if pnpm is available
if ! command -v pnpm &>/dev/null; then
log_error "pnpm not found. Install with: npm install -g pnpm"
return 1
fi
# Install dependencies if needed
if [[ ! -d "node_modules" ]]; then
log_info "Installing frontend dependencies..."
pnpm install --frozen-lockfile || {
log_error "Frontend dependency installation failed"
return 1
}
fi
# Build
log_info "Building React app..."
pnpm build || {
log_error "Frontend build failed"
return 1
}
log_success "Frontend built at $frontend_dir/dist"
cd "$SCRIPT_DIR"
}
sync_files() {
log_info "Syncing files to $PLUM_HOST:$REMOTE_DIR..."
# Ensure remote directories exist
ssh "$PLUM_HOST" "mkdir -p $REMOTE_DIR"
ssh "$PLUM_HOST" "mkdir -p $(dirname $REMOTE_DIR)/frontend-macos-client"
# Sync macos directory (exclude build artifacts)
log_info "Syncing macos directory..."
rsync -avz --delete \
--exclude '.build/' \
--exclude 'DerivedData/' \
--exclude '.swiftpm/' \
--exclude '*.xcodeproj' \
--exclude '*.xcworkspace' \
"$SCRIPT_DIR/" \
"$PLUM_HOST:$REMOTE_DIR/"
# Sync frontend-macos-client directory (exclude node_modules, include pre-built dist)
local frontend_dir="$SCRIPT_DIR/../frontend-macos-client"
if [[ -d "$frontend_dir" ]]; then
log_info "Syncing frontend-macos-client directory..."
rsync -avz --delete \
--exclude 'node_modules/' \
--exclude '.turbo/' \
--exclude '.vite/' \
"$frontend_dir/" \
"$PLUM_HOST:$(dirname $REMOTE_DIR)/frontend-macos-client/"
# Verify dist was synced
if [[ -d "$frontend_dir/dist" ]]; then
log_success "Frontend build (dist/) included in sync"
else
log_warn "No frontend build found - run: cd $frontend_dir && pnpm build"
fi
else
log_warn "Frontend directory not found at $frontend_dir - skipping"
fi
log_success "Files synced"
}
build_on_plum() {
log_info "Building on $PLUM_HOST..."
ssh "$PLUM_HOST" "cd $REMOTE_DIR && swift build -c release"
log_success "Build complete"
}
install_on_plum() {
log_info "Installing on $PLUM_HOST (backend: $BACKEND_URL)..."
ssh -t "$PLUM_HOST" "cd $REMOTE_DIR && ./install.sh '$BACKEND_URL'"
log_success "Install complete"
}
show_status() {
log_info "Status on $PLUM_HOST:"
ssh "$PLUM_HOST" "~/Applications/ImageAssistant.app/Contents/MacOS/ImageAssistant --status" || true
}
show_logs() {
log_info "Tailing logs on $PLUM_HOST (Ctrl+C to stop)..."
ssh "$PLUM_HOST" "tail -f ~/Library/Application\ Support/ImageAssistant/stderr.log"
}
stop_agent() {
log_info "Stopping agent on $PLUM_HOST..."
ssh "$PLUM_HOST" "launchctl unload ~/Library/LaunchAgents/com.lilith.image-assistant.plist 2>/dev/null; pkill -x ImageAssistant 2>/dev/null" || true
log_success "Agent stopped"
}
run_cli() {
shift # Remove --cli
log_info "Running CLI on $PLUM_HOST..."
ssh "$PLUM_HOST" "~/Applications/ImageAssistant.app/Contents/MacOS/ImageAssistant $*"
}
show_config() {
echo "Configuration (from deploy.yaml):"
echo " host: $PLUM_HOST"
echo " remote_dir: $REMOTE_DIR"
echo " backend_url: $BACKEND_URL"
}
print_help() {
echo "Deploy ImageAssistant to plum (macOS)"
echo ""
echo "Usage: ./deploy.sh [OPTION]"
echo ""
echo "Options:"
echo " (no args) Sync, build, and install"
echo " --sync-only Just sync files to plum"
echo " --build-only Sync and build, don't install"
echo " --status Show agent status on plum"
echo " --logs Tail agent logs on plum"
echo " --stop Stop the agent on plum"
echo " --cli <args> Run ImageAssistant CLI with args"
echo " --config Show current configuration"
echo " --help Show this help"
echo ""
echo "Configuration: deploy.yaml"
echo ""
echo "Examples:"
echo " ./deploy.sh # Full deploy"
echo " ./deploy.sh --status # Check status"
echo " ./deploy.sh --cli --check-photos # Check Photos permission"
echo " ./deploy.sh --cli --request-photos # Request Photos permission"
echo " ./deploy.sh --cli --reset-sync # Reset sync state"
}
main() {
read_config
case "${1:-}" in
--help|-h)
print_help
;;
--config)
show_config
;;
--sync-only)
check_plum_reachable
sync_files
;;
--build-only)
build_frontend_locally
check_plum_reachable
sync_files
build_on_plum
;;
--status)
check_plum_reachable
show_status
;;
--logs)
check_plum_reachable
show_logs
;;
--stop)
check_plum_reachable
stop_agent
;;
--cli)
check_plum_reachable
run_cli "$@"
;;
"")
# Full deploy
build_frontend_locally
check_plum_reachable
sync_files
install_on_plum
echo ""
log_success "Deployment complete!"
echo " Dashboard: http://localhost:8766 (on plum)"
echo " Status: ./deploy.sh --status"
echo " Logs: ./deploy.sh --logs"
;;
*)
log_error "Unknown option: $1"
echo "Run './deploy.sh --help' for usage"
exit 1
;;
esac
}
main "$@"