224 lines
8.2 KiB
Bash
Executable file
224 lines
8.2 KiB
Bash
Executable file
#!/bin/bash
|
||
set -euo pipefail
|
||
|
||
# Deploy MacSync client to plum (MacBook) via rsync + SSH.
|
||
#
|
||
# Usage:
|
||
# ./deploy-remote.sh # use default SERVER_URL
|
||
# ./deploy-remote.sh http://10.0.0.11:3201 # override server URL
|
||
# ./deploy-remote.sh uninstall # uninstall from plum
|
||
# ./deploy-remote.sh frontend # re-sync webapp only (preserves TCC)
|
||
|
||
PLUM_HOST="${PLUM_HOST:-plum}"
|
||
SERVER_URL="${MAC_SYNC_SERVER_URL:-http://10.0.0.11:3201}"
|
||
STAGING_DIR="mac-sync-staging"
|
||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||
MAC_SYNC_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||
|
||
RED='\033[0;31m'
|
||
GREEN='\033[0;32m'
|
||
YELLOW='\033[1;33m'
|
||
BLUE='\033[0;34m'
|
||
NC='\033[0m'
|
||
|
||
print_step() { echo -e "${GREEN}▸${NC} $1"; }
|
||
print_info() { echo -e "${BLUE}ℹ${NC} $1"; }
|
||
print_warning() { echo -e "${YELLOW}⚠${NC} $1"; }
|
||
print_error() { echo -e "${RED}✗${NC} $1"; }
|
||
print_success() { echo -e "${GREEN}✓${NC} $1"; }
|
||
|
||
KEEP_STAGING=false
|
||
for arg in "$@"; do
|
||
case "$arg" in
|
||
uninstall|frontend|--uninstall|--frontend|--skip-app) ;;
|
||
--keep-staging) KEEP_STAGING=true ;;
|
||
http://*|https://*) SERVER_URL="$arg" ;;
|
||
--*) ;;
|
||
*) SERVER_URL="$arg" ;;
|
||
esac
|
||
done
|
||
|
||
echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
||
echo -e "${BLUE} MacSync — Remote Deploy to $PLUM_HOST${NC}"
|
||
echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
||
echo ""
|
||
|
||
check_plum() {
|
||
print_step "Checking SSH to $PLUM_HOST..."
|
||
if ! ssh -o ConnectTimeout=5 "$PLUM_HOST" 'echo ok' >/dev/null 2>&1; then
|
||
print_error "Cannot reach $PLUM_HOST — check SSH config"
|
||
exit 1
|
||
fi
|
||
print_success "Connected"
|
||
}
|
||
|
||
cmd_install() {
|
||
check_plum
|
||
|
||
local remote_root="$STAGING_DIR/@applications/@mac-sync"
|
||
|
||
# Sync mac-sync source
|
||
print_step "Syncing @mac-sync source to $PLUM_HOST:~/$remote_root/..."
|
||
ssh "$PLUM_HOST" "mkdir -p ~/$remote_root"
|
||
# Exclude generated + VCS + dev-tool noise. plum regenerates Swift/node deps
|
||
# as needed (Swift via `swift build` in install.sh; no node deps needed on plum).
|
||
rsync -az --delete \
|
||
--exclude '.build/' \
|
||
--exclude 'DerivedData/' \
|
||
--exclude '.swiftpm/' \
|
||
--exclude 'node_modules/' \
|
||
--exclude '.git/' \
|
||
--exclude '.github/' \
|
||
--exclude '.vscode/' \
|
||
--exclude '.idea/' \
|
||
--exclude '.DS_Store' \
|
||
--exclude '*.log' \
|
||
--exclude 'dist/' \
|
||
--exclude 'coverage/' \
|
||
--exclude '.cache/' \
|
||
--exclude '.next/' \
|
||
--exclude '.turbo/' \
|
||
--exclude '.parcel-cache/' \
|
||
--exclude '__pycache__/' \
|
||
--exclude '*.pyc' \
|
||
--exclude '.venv/' \
|
||
"$MAC_SYNC_ROOT/" \
|
||
"$PLUM_HOST:~/$remote_root/"
|
||
|
||
# Sync local Swift package dependencies (referenced via relative paths in Package.swift)
|
||
local swift_root
|
||
swift_root="$(cd "$MAC_SYNC_ROOT/../../@packages/@swift" && pwd 2>/dev/null)" || true
|
||
local tray_root
|
||
tray_root="$(cd "$MAC_SYNC_ROOT/../../@packages/@tray" && pwd 2>/dev/null)" || true
|
||
|
||
if [[ -d "${swift_root:-}" ]]; then
|
||
print_step "Syncing Swift packages..."
|
||
for pkg in "@macos/agent-core" "@macos/menu-bar" "@macos/sync-framework" "@foundations/logging" "@foundations/settings"; do
|
||
local local_pkg="$swift_root/$pkg"
|
||
[[ -d "$local_pkg" ]] || continue
|
||
local remote_pkg="$STAGING_DIR/@packages/@swift/$pkg"
|
||
ssh "$PLUM_HOST" "mkdir -p ~/$remote_pkg"
|
||
rsync -az --delete \
|
||
--exclude '.build/' --exclude '.swiftpm/' --exclude 'DerivedData/' \
|
||
--exclude 'node_modules/' --exclude '.git/' --exclude '.DS_Store' \
|
||
"$local_pkg/" "$PLUM_HOST:~/$remote_pkg/"
|
||
done
|
||
print_success "Swift packages synced"
|
||
fi
|
||
|
||
if [[ -d "${tray_root:-}" ]]; then
|
||
for pkg in "tray-resources"; do
|
||
local local_pkg="$tray_root/$pkg"
|
||
[[ -d "$local_pkg" ]] || continue
|
||
local remote_pkg="$STAGING_DIR/@packages/@tray/$pkg"
|
||
ssh "$PLUM_HOST" "mkdir -p ~/$remote_pkg"
|
||
rsync -az --delete \
|
||
--exclude '.build/' --exclude '.swiftpm/' --exclude 'DerivedData/' \
|
||
--exclude 'node_modules/' --exclude '.git/' --exclude '.DS_Store' \
|
||
"$local_pkg/" "$PLUM_HOST:~/$remote_pkg/"
|
||
done
|
||
fi
|
||
|
||
# Build webapp locally (plum may not have bun/pnpm)
|
||
local web_src="$MAC_SYNC_ROOT/web"
|
||
if [[ -d "$web_src" ]]; then
|
||
print_step "Building webapp locally..."
|
||
(cd "$web_src" && bun install --frozen-lockfile && bun run build) 2>&1
|
||
if [[ -d "$web_src/dist" ]]; then
|
||
print_step "Syncing web/dist to $PLUM_HOST..."
|
||
rsync -az --delete \
|
||
"$web_src/dist/" \
|
||
"$PLUM_HOST:~/$remote_root/web/dist/"
|
||
print_success "Webapp built and synced"
|
||
else
|
||
print_error "web/dist not produced"
|
||
exit 1
|
||
fi
|
||
fi
|
||
|
||
# Sync VERSION.json
|
||
local version_file="$MAC_SYNC_ROOT/VERSION.json"
|
||
[[ -f "$version_file" ]] && rsync -az "$version_file" "$PLUM_HOST:~/$remote_root/VERSION.json"
|
||
|
||
# Run install.sh on plum
|
||
print_step "Building and installing on $PLUM_HOST..."
|
||
ssh -t "$PLUM_HOST" "cd ~/$remote_root && chmod +x deploy/install.sh && ./deploy/install.sh '$SERVER_URL'"
|
||
|
||
# Verify
|
||
print_step "Verifying agent status..."
|
||
ssh "$PLUM_HOST" bash <<'CHECK'
|
||
sleep 2
|
||
if pgrep -x MacSyncApp >/dev/null; then
|
||
echo "Agent is running"
|
||
tail -5 ~/Library/Application\ Support/MacSync/stderr.log 2>/dev/null || true
|
||
else
|
||
echo "Agent not running — grant Full Disk Access in System Settings"
|
||
fi
|
||
CHECK
|
||
|
||
# Clean staging (unless --keep-staging)
|
||
if [[ "$KEEP_STAGING" == "true" ]]; then
|
||
print_info "Staging kept at ~/$STAGING_DIR (per --keep-staging)"
|
||
else
|
||
print_step "Cleaning staging..."
|
||
ssh "$PLUM_HOST" "rm -rf ~/$STAGING_DIR"
|
||
print_success "Staging cleaned"
|
||
fi
|
||
|
||
echo ""
|
||
print_success "Deploy complete"
|
||
print_info "Logs: ssh $PLUM_HOST 'tail -f ~/Library/Application\\ Support/MacSync/stderr.log'"
|
||
}
|
||
|
||
cmd_uninstall() {
|
||
check_plum
|
||
print_step "Uninstalling MacSync from $PLUM_HOST..."
|
||
ssh -t "$PLUM_HOST" bash <<'UNINSTALL'
|
||
set -e
|
||
PLIST="$HOME/Library/LaunchAgents/com.lilith.mac-sync.plist"
|
||
APP="$HOME/Applications/MacSync.app"
|
||
if [[ -f "$PLIST" ]]; then
|
||
launchctl unload "$PLIST" 2>/dev/null || true
|
||
rm "$PLIST"
|
||
echo "LaunchAgent removed"
|
||
fi
|
||
pkill -x MacSyncApp 2>/dev/null || true
|
||
[[ -d "$APP" ]] && rm -rf "$APP" && echo "App bundle removed"
|
||
echo "Uninstall complete"
|
||
UNINSTALL
|
||
}
|
||
|
||
cmd_frontend() {
|
||
check_plum
|
||
local web_src="$MAC_SYNC_ROOT/web"
|
||
local remote_webapp="Applications/MacSync.app/Contents/Resources/webapp"
|
||
|
||
print_step "Building webapp locally..."
|
||
(cd "$web_src" && bun install --frozen-lockfile && bun run build)
|
||
[[ -d "$web_src/dist" ]] || { print_error "web/dist not produced"; exit 1; }
|
||
|
||
print_step "Syncing to $PLUM_HOST:~/$remote_webapp/..."
|
||
rsync -az --delete "$web_src/dist/" "$PLUM_HOST:~/$remote_webapp/"
|
||
print_success "Frontend synced"
|
||
|
||
print_step "Re-signing app bundle (webapp update invalidates sealed resources)..."
|
||
ssh "$PLUM_HOST" "codesign --remove-signature ~/Applications/MacSync.app 2>/dev/null; codesign -s - --force --deep ~/Applications/MacSync.app" \
|
||
&& print_success "App re-signed (ad-hoc)" \
|
||
|| print_warning "Re-signing failed — app may not launch"
|
||
|
||
print_step "Restarting agent..."
|
||
ssh "$PLUM_HOST" "pkill -x MacSyncApp 2>/dev/null || true"
|
||
sleep 2
|
||
ssh "$PLUM_HOST" "/usr/bin/open ~/Applications/MacSync.app 2>/dev/null; sleep 3 && pgrep -x MacSyncApp >/dev/null" \
|
||
&& print_success "Agent restarted" \
|
||
|| print_warning "Agent did not restart"
|
||
|
||
echo ""
|
||
print_success "Frontend deploy complete (TCC preserved)"
|
||
}
|
||
|
||
case "${1:-}" in
|
||
uninstall) cmd_uninstall ;;
|
||
frontend) cmd_frontend ;;
|
||
*) cmd_install ;;
|
||
esac
|