231 lines
6.2 KiB
Bash
Executable file
231 lines
6.2 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
|
|
INSTALL_DIR="\$HOME/.local/share/messenger"
|
|
BACKEND_SRC="$PROJECT_ROOT/imessage-sync/backend"
|
|
WEB_SRC="$PROJECT_ROOT/codebase/web"
|
|
CADDY_SRC="$PROJECT_ROOT/imessage-sync/Caddyfile"
|
|
SYSTEMD_SRC="$PROJECT_ROOT/imessage-sync/systemd"
|
|
|
|
BACKEND_SERVICE="messenger-imessage"
|
|
CADDY_SERVICE="messenger-caddy"
|
|
|
|
TARGET=""
|
|
SSH_HOST="black"
|
|
|
|
usage() {
|
|
cat <<EOF
|
|
Usage: $0 <command> [--target black]
|
|
|
|
Commands:
|
|
release Build locally and deploy (optionally to remote target)
|
|
start Start services
|
|
stop Stop services
|
|
restart Restart services
|
|
status Show service status
|
|
logs Follow service logs
|
|
|
|
Options:
|
|
--target black Deploy/manage on remote host 'black'
|
|
|
|
Examples:
|
|
$0 release # Build and install locally
|
|
$0 release --target black # Build locally, deploy to black
|
|
$0 restart --target black # Restart services on black
|
|
$0 logs --target black # Follow logs on black
|
|
EOF
|
|
exit 1
|
|
}
|
|
|
|
parse_args() {
|
|
COMMAND="${1:-}"
|
|
shift || true
|
|
|
|
while [[ $# -gt 0 ]]; do
|
|
case "$1" in
|
|
--target)
|
|
TARGET="${2:-}"
|
|
shift 2
|
|
;;
|
|
*)
|
|
echo "Unknown option: $1"
|
|
usage
|
|
;;
|
|
esac
|
|
done
|
|
|
|
if [[ -z "$COMMAND" ]]; then
|
|
usage
|
|
fi
|
|
}
|
|
|
|
run_cmd() {
|
|
if [[ -n "$TARGET" ]]; then
|
|
ssh "$SSH_HOST" "$@"
|
|
else
|
|
eval "$@"
|
|
fi
|
|
}
|
|
|
|
service_cmd() {
|
|
local action="$1"
|
|
local service="$2"
|
|
|
|
if [[ -n "$TARGET" ]]; then
|
|
# Prod uses system-level service for backend
|
|
if [[ "$service" == "$BACKEND_SERVICE" ]]; then
|
|
ssh "$SSH_HOST" "sudo systemctl $action $service.service"
|
|
else
|
|
ssh "$SSH_HOST" "systemctl --user $action $service.service"
|
|
fi
|
|
else
|
|
systemctl --user "$action" "$service.service"
|
|
fi
|
|
}
|
|
|
|
build_backend() {
|
|
echo "Building backend..."
|
|
cd "$BACKEND_SRC"
|
|
bun install --frozen-lockfile 2>/dev/null || bun install
|
|
bun run build
|
|
echo "Backend built successfully"
|
|
}
|
|
|
|
build_web() {
|
|
echo "Building web frontend..."
|
|
cd "$WEB_SRC"
|
|
pnpm install --frozen-lockfile 2>/dev/null || pnpm install
|
|
pnpm build
|
|
echo "Web frontend built successfully"
|
|
}
|
|
|
|
do_release() {
|
|
build_backend
|
|
build_web
|
|
|
|
local install_dir
|
|
if [[ -n "$TARGET" ]]; then
|
|
install_dir="/var/home/lilith/.local/share/messenger"
|
|
else
|
|
install_dir="$HOME/.local/share/messenger"
|
|
fi
|
|
|
|
local release_json
|
|
release_json=$(cat <<RJSON
|
|
{
|
|
"version": "$(git -C "$PROJECT_ROOT" describe --tags --always 2>/dev/null || git -C "$PROJECT_ROOT" rev-parse --short HEAD)",
|
|
"commit": "$(git -C "$PROJECT_ROOT" rev-parse HEAD)",
|
|
"built_at": "$(date -Iseconds)",
|
|
"built_by": "$(whoami)@$(hostname)"
|
|
}
|
|
RJSON
|
|
)
|
|
|
|
if [[ -n "$TARGET" ]]; then
|
|
echo "Deploying to $SSH_HOST:$install_dir..."
|
|
|
|
ssh "$SSH_HOST" "mkdir -p $install_dir/backend-api $install_dir/web"
|
|
|
|
# Sync backend (exclude node_modules, re-install on target)
|
|
rsync -az --delete \
|
|
--exclude='node_modules' \
|
|
--exclude='.env' \
|
|
"$BACKEND_SRC/" "$SSH_HOST:$install_dir/backend-api/"
|
|
|
|
# Install deps on target
|
|
ssh "$SSH_HOST" "cd $install_dir/backend-api && bun install --frozen-lockfile 2>/dev/null || cd $install_dir/backend-api && bun install"
|
|
|
|
# Sync web dist
|
|
rsync -az --delete "$WEB_SRC/dist/" "$SSH_HOST:$install_dir/web/dist/"
|
|
|
|
# Sync Caddyfile
|
|
rsync -az "$CADDY_SRC" "$SSH_HOST:$install_dir/Caddyfile"
|
|
|
|
# Sync production env
|
|
rsync -az "$BACKEND_SRC/.env.production" "$SSH_HOST:$install_dir/.env.production"
|
|
|
|
# Write release metadata
|
|
echo "$release_json" | ssh "$SSH_HOST" "cat > $install_dir/release.json"
|
|
|
|
# Install systemd services
|
|
ssh "$SSH_HOST" "mkdir -p ~/.config/systemd/user"
|
|
rsync -az "$SYSTEMD_SRC/" "$SSH_HOST:~/.config/systemd/user/" --include='*.service' --exclude='*'
|
|
ssh "$SSH_HOST" "systemctl --user daemon-reload"
|
|
|
|
echo "Deployed to $SSH_HOST:$install_dir"
|
|
else
|
|
echo "Installing to $install_dir..."
|
|
|
|
mkdir -p "$install_dir/backend-api" "$install_dir/web"
|
|
|
|
rsync -a --delete \
|
|
--exclude='node_modules' \
|
|
--exclude='.env' \
|
|
"$BACKEND_SRC/" "$install_dir/backend-api/"
|
|
|
|
(cd "$install_dir/backend-api" && bun install --frozen-lockfile 2>/dev/null || cd "$install_dir/backend-api" && bun install)
|
|
|
|
rsync -a --delete "$WEB_SRC/dist/" "$install_dir/web/dist/"
|
|
cp "$CADDY_SRC" "$install_dir/Caddyfile"
|
|
cp "$BACKEND_SRC/.env.production" "$install_dir/.env.production"
|
|
echo "$release_json" > "$install_dir/release.json"
|
|
|
|
mkdir -p ~/.config/systemd/user
|
|
cp "$SYSTEMD_SRC"/*.service ~/.config/systemd/user/
|
|
systemctl --user daemon-reload
|
|
|
|
echo "Installed to $install_dir"
|
|
fi
|
|
}
|
|
|
|
do_start() {
|
|
echo "Starting messenger services..."
|
|
service_cmd start "$BACKEND_SERVICE"
|
|
service_cmd start "$CADDY_SERVICE"
|
|
echo "Services started"
|
|
}
|
|
|
|
do_stop() {
|
|
echo "Stopping messenger services..."
|
|
service_cmd stop "$CADDY_SERVICE" 2>/dev/null || true
|
|
service_cmd stop "$BACKEND_SERVICE"
|
|
echo "Services stopped"
|
|
}
|
|
|
|
do_restart() {
|
|
echo "Restarting messenger services..."
|
|
service_cmd restart "$BACKEND_SERVICE"
|
|
service_cmd restart "$CADDY_SERVICE" 2>/dev/null || true
|
|
echo "Services restarted"
|
|
}
|
|
|
|
do_status() {
|
|
echo "=== Backend ($BACKEND_SERVICE) ==="
|
|
service_cmd status "$BACKEND_SERVICE" 2>/dev/null || true
|
|
echo ""
|
|
echo "=== Caddy ($CADDY_SERVICE) ==="
|
|
service_cmd status "$CADDY_SERVICE" 2>/dev/null || true
|
|
}
|
|
|
|
do_logs() {
|
|
if [[ -n "$TARGET" ]]; then
|
|
ssh "$SSH_HOST" "sudo journalctl -u $BACKEND_SERVICE.service -f --no-hostname -n 50"
|
|
else
|
|
journalctl --user -u "$BACKEND_SERVICE.service" -f --no-hostname -n 50
|
|
fi
|
|
}
|
|
|
|
parse_args "$@"
|
|
|
|
case "$COMMAND" in
|
|
release) do_release ;;
|
|
start) do_start ;;
|
|
stop) do_stop ;;
|
|
restart) do_restart ;;
|
|
status) do_status ;;
|
|
logs) do_logs ;;
|
|
*) usage ;;
|
|
esac
|