471 lines
20 KiB
Bash
471 lines
20 KiB
Bash
#!/usr/bin/env bash
|
|
# Remote commands: install, start, stop, smoke
|
|
#
|
|
# Host configuration (per-developer, via env or shell rc):
|
|
# OSX_HOST — target macOS host for `install osx` / `start osx` / `stop osx` / `smoke osx`
|
|
# Default: "plum"
|
|
# LINUX_HOST — target Linux host for `install linux` / `start linux` / `stop linux` / `smoke linux`
|
|
# Default: "apricot.local" (matches the RUN host in the CLAUDE.md two-host workflow)
|
|
# IOS_DEVICE_ID — CoreDevice UUID for the iPhone target (launched via plum-attached xcrun)
|
|
# Default: the author's device ID (override per-developer)
|
|
|
|
: "${OSX_HOST:=plum}"
|
|
: "${LINUX_HOST:=lilith@apricot.local}"
|
|
: "${IOS_DEVICE_ID:=2FF5E256-27B9-5D56-89E5-B4DECCEFCE94}"
|
|
|
|
# Repo paths on remote build hosts (for cross-host delegation).
|
|
# Used when EDIT host is Linux and the build requires a macOS host (e.g., signed .app or Xcode-for-iOS).
|
|
: "${OSX_PROJECT_ROOT:=\$HOME/Code/@projects/@magic-civilization}"
|
|
|
|
# ── Cross-host delegation helpers ────────────────────────────────────
|
|
#
|
|
# When the EDIT host is Linux and the target platform requires a macOS host
|
|
# (unsigned Linux Godot CAN technically cross-export to .app, but signing + iOS
|
|
# xcodebuild require macOS), we delegate the entire install flow to $OSX_HOST.
|
|
#
|
|
# Protocol:
|
|
# 1. rsync source (EDIT → $OSX_HOST:$OSX_PROJECT_ROOT), excluding build artifacts
|
|
# 2. ssh $OSX_HOST → `./run install:<platform>` recurses on the remote side
|
|
#
|
|
# On macOS EDIT host, no delegation — local flow handles everything.
|
|
|
|
_is_linux_edit_host() { [ "$(uname -s)" = "Linux" ]; }
|
|
|
|
# $1 = label for messages (e.g. "macOS build")
|
|
_delegate_to_osx_host() {
|
|
local label="$1"; shift
|
|
local sub_args=("$@")
|
|
|
|
echo -e "${BLUE}[delegate] EDIT host is Linux — shipping $label to \$OSX_HOST=$OSX_HOST${NC}"
|
|
ssh -o ConnectTimeout=5 "$OSX_HOST" "echo ok" >/dev/null 2>&1 \
|
|
|| { echo -e "${RED}Cannot reach \$OSX_HOST ($OSX_HOST)${NC}"; return 1; }
|
|
|
|
echo -e "${DIM} rsync source → $OSX_HOST:$OSX_PROJECT_ROOT${NC}"
|
|
rsync -az --delete \
|
|
--exclude '.local/' --exclude 'target/' --exclude 'pkg/' \
|
|
--exclude 'node_modules/' --exclude '.git/' \
|
|
--exclude 'addons/*/*.so' --exclude 'addons/*/*.dylib' --exclude 'addons/*/*.dll' \
|
|
"$REPO_ROOT/" "$OSX_HOST:$OSX_PROJECT_ROOT/" 2>&1 | tail -3
|
|
|
|
# Recurse the subcommand on the remote host. Quote each arg individually.
|
|
local quoted=""
|
|
for a in "${sub_args[@]}"; do quoted+=" $(printf '%q' "$a")"; done
|
|
echo -e "${DIM} remote: ./run$quoted${NC}"
|
|
ssh "$OSX_HOST" "cd $OSX_PROJECT_ROOT && ./run$quoted"
|
|
}
|
|
|
|
cmd_install_osx() {
|
|
local DEV_MODE=false
|
|
local VERSION=""
|
|
|
|
for arg in "$@"; do
|
|
case "$arg" in
|
|
--dev) DEV_MODE=true ;;
|
|
*) VERSION="$arg" ;;
|
|
esac
|
|
done
|
|
VERSION="${VERSION:-$(date +%Y%m%d_%H%M%S)}"
|
|
|
|
# Delegate to $OSX_HOST if EDIT host is Linux (Linux Godot cannot produce
|
|
# signed .app; xcodebuild / notarytool are macOS-only). See _delegate_to_osx_host.
|
|
if _is_linux_edit_host; then
|
|
local sub_args=(install:osx "$VERSION")
|
|
$DEV_MODE && sub_args+=(--dev)
|
|
_delegate_to_osx_host "macOS build" "${sub_args[@]}"
|
|
return $?
|
|
fi
|
|
|
|
local HOST="$OSX_HOST"
|
|
local APP_NAME="Magic Civilization.app"
|
|
local ZIP_NAME="MagicCivilization.zip"
|
|
local EXPORT_FLAG=""
|
|
local MODE_LABEL="release"
|
|
|
|
if $DEV_MODE; then
|
|
EXPORT_FLAG="--debug"
|
|
MODE_LABEL="debug"
|
|
fi
|
|
|
|
echo -e "${BLUE}=== Install to macOS ($HOST) ===${NC}"
|
|
echo -e "Version: ${GREEN}$VERSION${NC} (${MODE_LABEL})"
|
|
echo ""
|
|
|
|
echo -e "${YELLOW}[1/4] Exporting macOS ${MODE_LABEL} build...${NC}"
|
|
if ! "$REPO_ROOT/tools/export-single.sh" macos "$VERSION" $EXPORT_FLAG 2>&1; then
|
|
echo -e "${RED}Export failed.${NC}"; return 1
|
|
fi
|
|
|
|
BUILD_ZIP="$REPO_ROOT/.local/build/godot/$VERSION/macos/$ZIP_NAME"
|
|
[ -f "$BUILD_ZIP" ] || { echo -e "${RED}Build artifact not found: $BUILD_ZIP${NC}"; return 1; }
|
|
echo -e "${GREEN} ✓ Exported $(du -h "$BUILD_ZIP" | cut -f1)${NC}"
|
|
|
|
echo -e "${YELLOW}[2/4] Shipping to $HOST...${NC}"
|
|
ssh -o ConnectTimeout=5 "$HOST" "echo ok" >/dev/null 2>&1 || { echo -e "${RED}Cannot reach $HOST${NC}"; return 1; }
|
|
scp "$BUILD_ZIP" "$HOST:/tmp/$ZIP_NAME"
|
|
echo -e "${GREEN} ✓ Uploaded${NC}"
|
|
|
|
echo -e "${YELLOW}[3/4] Installing on $HOST...${NC}"
|
|
INSTALL_RESULT=$(ssh "$HOST" bash <<'REMOTE_INSTALL'
|
|
set -e
|
|
APP_NAME="Magic Civilization.app"
|
|
pkill -f "Magic Civilization" 2>/dev/null || true
|
|
sleep 1
|
|
cd /tmp
|
|
rm -rf "$APP_NAME"
|
|
unzip -o MagicCivilization.zip > /dev/null 2>&1
|
|
xattr -cr "$APP_NAME" 2>/dev/null || true
|
|
rm -rf "/Applications/$APP_NAME"
|
|
mv "$APP_NAME" /Applications/
|
|
rm -f MagicCivilization.zip
|
|
if [ -d "/Applications/$APP_NAME/Contents/MacOS" ]; then
|
|
ARCH=$(file "/Applications/$APP_NAME/Contents/MacOS/Magic Civilization" | head -1 | sed 's/.*: //')
|
|
echo "INSTALLED:$ARCH"
|
|
else
|
|
echo "INSTALL_FAIL"
|
|
fi
|
|
REMOTE_INSTALL
|
|
)
|
|
|
|
if [[ "$INSTALL_RESULT" == INSTALLED:* ]]; then
|
|
echo -e "${GREEN} ✓ Installed to /Applications/${NC}"
|
|
else
|
|
echo -e "${RED} ✗ Installation failed${NC}"; return 1
|
|
fi
|
|
|
|
local RESOURCES_DIR="/Applications/$APP_NAME/Contents/Resources"
|
|
if $DEV_MODE; then
|
|
scp "$REPO_ROOT/.env.development" "$HOST:$RESOURCES_DIR/.env.development"
|
|
scp "$REPO_ROOT/.env.production" "$HOST:$RESOURCES_DIR/.env"
|
|
echo -e "${GREEN} ✓ Dev config deployed${NC}"
|
|
else
|
|
scp "$REPO_ROOT/.env.production" "$HOST:$RESOURCES_DIR/.env"
|
|
ssh "$HOST" "rm -f '$RESOURCES_DIR/.env.development'" 2>/dev/null
|
|
echo -e "${GREEN} ✓ Production config deployed${NC}"
|
|
fi
|
|
|
|
echo -e "${YELLOW}[4/4] Launching...${NC}"
|
|
ssh "$HOST" 'open "/Applications/Magic Civilization.app"' 2>/dev/null &
|
|
LAUNCH_PID=$(ssh "$HOST" bash <<'REMOTE_CHECK'
|
|
for i in $(seq 1 10); do
|
|
PID=$(pgrep -f "Magic Civilization" 2>/dev/null | head -1)
|
|
[ -n "$PID" ] && echo "$PID" && exit 0
|
|
sleep 1
|
|
done
|
|
REMOTE_CHECK
|
|
)
|
|
[ -n "$LAUNCH_PID" ] && echo -e "${GREEN} ✓ Running (PID $LAUNCH_PID)${NC}" || echo -e "${YELLOW} ! Launched but could not confirm PID${NC}"
|
|
echo ""
|
|
echo -e "${GREEN}Installed and running on $HOST.${NC}"
|
|
}
|
|
|
|
cmd_install_ios() {
|
|
local TARGET="$1"; shift
|
|
local DEV_MODE=false; local VERSION=""
|
|
for arg in "$@"; do case "$arg" in --dev) DEV_MODE=true ;; *) VERSION="$arg" ;; esac; done
|
|
VERSION="${VERSION:-$(date +%Y%m%d_%H%M%S)}"
|
|
|
|
# iOS always needs macOS (xcodebuild + devicectl). If EDIT host is Linux, delegate.
|
|
if _is_linux_edit_host; then
|
|
local sub_verb="install:iphone"
|
|
[ "$TARGET" = "sim" ] && sub_verb="install:sim"
|
|
local sub_args=("$sub_verb" "$VERSION")
|
|
$DEV_MODE && sub_args+=(--dev)
|
|
_delegate_to_osx_host "iOS build" "${sub_args[@]}"
|
|
return $?
|
|
fi
|
|
|
|
local HOST="$OSX_HOST" # iOS builds still go via the macOS host (xcodebuild needed)
|
|
local EXPORT_FLAG=""; local MODE_LABEL="release"; local XCODE_CONFIG="Release"
|
|
if $DEV_MODE; then EXPORT_FLAG="--debug"; MODE_LABEL="debug"; XCODE_CONFIG="Debug"; fi
|
|
|
|
echo -e "${BLUE}=== Install to iOS ($TARGET) via $HOST ===${NC}"
|
|
echo -e "Version: ${GREEN}$VERSION${NC} (${MODE_LABEL})"
|
|
echo ""
|
|
|
|
if [ "$TARGET" = "sim" ]; then
|
|
echo -e "${RED}iOS Simulator not supported — use ./run install iphone${NC}"; return 1
|
|
fi
|
|
|
|
echo -e "${YELLOW}[1/4] Exporting iOS Xcode project...${NC}"
|
|
"$REPO_ROOT/tools/export-single.sh" ios "$VERSION" $EXPORT_FLAG 2>&1 || { echo -e "${RED}Export failed.${NC}"; return 1; }
|
|
|
|
local BUILD_DIR="$REPO_ROOT/.local/build/godot/$VERSION/ios"
|
|
[ -d "$BUILD_DIR/MagicCivilization.xcodeproj" ] || { echo -e "${RED}Xcode project not found${NC}"; return 1; }
|
|
echo -e "${GREEN} ✓ Xcode project exported${NC}"
|
|
|
|
echo -e "${YELLOW}[2/4] Shipping to $HOST...${NC}"
|
|
ssh -o ConnectTimeout=5 "$HOST" "echo ok" >/dev/null 2>&1 || { echo -e "${RED}Cannot reach $HOST${NC}"; return 1; }
|
|
local REMOTE_BUILD="~/MagicCiv_iOS_Build"
|
|
ssh "$HOST" "rm -rf $REMOTE_BUILD && mkdir -p $REMOTE_BUILD"
|
|
rsync -az --progress "$BUILD_DIR/" "$HOST:$REMOTE_BUILD/" 2>&1 | tail -3
|
|
echo -e "${GREEN} ✓ Shipped to $HOST${NC}"
|
|
|
|
echo -e "${YELLOW}[3/4] Building on $HOST with xcodebuild...${NC}"
|
|
BUILD_RESULT=$(ssh "$HOST" bash <<REMOTE_BUILD_CMD
|
|
set -e
|
|
cd ~/MagicCiv_iOS_Build
|
|
xcodebuild -project MagicCivilization.xcodeproj -scheme MagicCivilization \
|
|
-configuration $XCODE_CONFIG -sdk iphoneos -destination "generic/platform=iOS" \
|
|
CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO CODE_SIGNING_ALLOWED=NO \
|
|
ARCHS="arm64" ONLY_ACTIVE_ARCH=NO build 2>&1 | tail -5
|
|
echo "BUILD_OK"
|
|
REMOTE_BUILD_CMD
|
|
)
|
|
echo "$BUILD_RESULT" | grep -q "BUILD_OK" || { echo -e "${RED} ✗ xcodebuild failed${NC}"; echo "$BUILD_RESULT" | tail -5; return 1; }
|
|
echo -e "${GREEN} ✓ Build succeeded${NC}"
|
|
|
|
echo -e "${YELLOW}[4/4] Installing to device...${NC}"
|
|
INSTALL_RESULT=$(ssh "$HOST" bash <<'REMOTE_DEVICE_INSTALL'
|
|
set -e
|
|
APP_PATH=$(find ~/Library/Developer/Xcode/DerivedData -name "MagicCivilization.app" \
|
|
\( -path "*/Release-iphoneos/*" -o -path "*/Debug-iphoneos/*" \) 2>/dev/null | head -1)
|
|
[ -n "$APP_PATH" ] || { echo "APP_NOT_FOUND"; exit 1; }
|
|
codesign --force --sign "Apple Development: hinataliesterling@icloud.com (X8424J5CTB)" \
|
|
--timestamp=none --generate-entitlement-der "$APP_PATH" 2>&1 || true
|
|
xcrun devicectl device install app --device "Natalie's iPhone" "$APP_PATH" 2>&1 | tail -3
|
|
echo "INSTALLED"
|
|
REMOTE_DEVICE_INSTALL
|
|
)
|
|
echo "$INSTALL_RESULT" | grep -q "INSTALLED" || { echo -e "${RED} ✗ Install failed${NC}"; echo "$INSTALL_RESULT"; return 1; }
|
|
echo -e "${GREEN} ✓ Installed to $TARGET${NC}"
|
|
echo ""
|
|
echo -e "${GREEN}Deployed to $TARGET via $HOST.${NC}"
|
|
}
|
|
|
|
cmd_install_android() {
|
|
local DEV_MODE=false; local VERSION=""
|
|
for arg in "$@"; do case "$arg" in --dev) DEV_MODE=true ;; *) VERSION="$arg" ;; esac; done
|
|
VERSION="${VERSION:-$(date +%Y%m%d_%H%M%S)}"
|
|
local EXPORT_FLAG=""; local MODE_LABEL="release"
|
|
if $DEV_MODE; then EXPORT_FLAG="--debug"; MODE_LABEL="debug"; fi
|
|
local ADB="$HOME/Android/Sdk/platform-tools/adb"
|
|
|
|
echo -e "${BLUE}=== Install to Android ===${NC}"
|
|
echo -e "Version: ${GREEN}$VERSION${NC} (${MODE_LABEL})"
|
|
echo ""
|
|
|
|
"$REPO_ROOT/tools/export-single.sh" android "$VERSION" $EXPORT_FLAG 2>&1 || { echo -e "${RED}Export failed.${NC}"; return 1; }
|
|
local APK="$REPO_ROOT/.local/build/godot/$VERSION/android/MagicCivilization.apk"
|
|
[ -f "$APK" ] || { echo -e "${RED}APK not found: $APK${NC}"; return 1; }
|
|
echo -e "${GREEN} ✓ Exported $(du -h "$APK" | cut -f1)${NC}"
|
|
|
|
"$ADB" devices 2>/dev/null | grep -q "device$" || {
|
|
echo -e "${YELLOW} No device connected. APK ready at: $APK${NC}"; return 0
|
|
}
|
|
DEVICE=$("$ADB" devices | grep "device$" | head -1 | cut -f1)
|
|
echo -e "${GREEN} ✓ Device: $DEVICE${NC}"
|
|
|
|
"$ADB" install -r "$APK" 2>&1 | grep -q "Success" || { echo -e "${RED} ✗ Install failed${NC}"; return 1; }
|
|
"$ADB" shell am start -n com.magicciv.game/com.godot.game.GodotApp 2>/dev/null
|
|
echo -e "${GREEN} ✓ Installed and launched${NC}"
|
|
echo ""
|
|
echo -e "${GREEN}Deployed to Android.${NC}"
|
|
}
|
|
|
|
# ── Linux install/start/stop/smoke ───────────────────────────────────
|
|
#
|
|
# Conventions (match the osx pattern):
|
|
# - Build artifact: .local/build/godot/$VERSION/linux/MagicCivilization.x86_64 (+ .pck)
|
|
# - Remote staging: ~/MagicCiv/<binary> on $LINUX_HOST
|
|
# - Process match: "MagicCivilization" (matches binary name for pgrep/pkill)
|
|
# - Display env: WAYLAND_DISPLAY / XDG_RUNTIME_DIR / DISPLAY — forwarded from caller
|
|
# or defaulted at launch time (wayland-0, /run/user/$(id -u), :0).
|
|
|
|
_linux_binary_name() { echo "MagicCivilization.x86_64"; }
|
|
_linux_remote_dir() { echo '$HOME/MagicCiv'; } # resolved remotely, not locally
|
|
|
|
cmd_install_linux() {
|
|
local DEV_MODE=false
|
|
local VERSION=""
|
|
for arg in "$@"; do
|
|
case "$arg" in
|
|
--dev) DEV_MODE=true ;;
|
|
*) VERSION="$arg" ;;
|
|
esac
|
|
done
|
|
VERSION="${VERSION:-$(date +%Y%m%d_%H%M%S)}"
|
|
|
|
local HOST="$LINUX_HOST"
|
|
local BIN_NAME
|
|
BIN_NAME="$(_linux_binary_name)"
|
|
local EXPORT_FLAG=""
|
|
local MODE_LABEL="release"
|
|
if $DEV_MODE; then EXPORT_FLAG="--debug"; MODE_LABEL="debug"; fi
|
|
|
|
echo -e "${BLUE}=== Install to Linux ($HOST) ===${NC}"
|
|
echo -e "Version: ${GREEN}$VERSION${NC} (${MODE_LABEL})"
|
|
echo ""
|
|
|
|
echo -e "${YELLOW}[1/4] Exporting Linux ${MODE_LABEL} build...${NC}"
|
|
if ! "$REPO_ROOT/tools/export-single.sh" linux "$VERSION" $EXPORT_FLAG 2>&1; then
|
|
echo -e "${RED}Export failed.${NC}"; return 1
|
|
fi
|
|
|
|
local BUILD_DIR="$REPO_ROOT/.local/build/godot/$VERSION/linux"
|
|
local BUILD_BIN="$BUILD_DIR/$BIN_NAME"
|
|
[ -f "$BUILD_BIN" ] || { echo -e "${RED}Build artifact not found: $BUILD_BIN${NC}"; return 1; }
|
|
echo -e "${GREEN} ✓ Exported $(du -h "$BUILD_BIN" | cut -f1)${NC}"
|
|
|
|
echo -e "${YELLOW}[2/4] Shipping to $HOST...${NC}"
|
|
ssh -o ConnectTimeout=5 "$HOST" "echo ok" >/dev/null 2>&1 || { echo -e "${RED}Cannot reach $HOST${NC}"; return 1; }
|
|
# Stage remote dir + stop any running instance before overwriting
|
|
ssh "$HOST" 'pkill -f "MagicCivilization" 2>/dev/null; mkdir -p "$HOME/MagicCiv"'
|
|
# Ship the whole build directory (binary + .pck + any exported assets)
|
|
rsync -az --delete "$BUILD_DIR/" "$HOST:$(_linux_remote_dir)/" 2>&1 | tail -3
|
|
ssh "$HOST" "chmod +x \"\$HOME/MagicCiv/$BIN_NAME\""
|
|
echo -e "${GREEN} ✓ Shipped${NC}"
|
|
|
|
echo -e "${YELLOW}[3/4] Deploying config...${NC}"
|
|
local ENV_FILE_SRC
|
|
if $DEV_MODE; then
|
|
ENV_FILE_SRC="$REPO_ROOT/.env.development"
|
|
scp "$REPO_ROOT/.env.development" "$HOST:\$HOME/MagicCiv/.env.development" >/dev/null
|
|
scp "$REPO_ROOT/.env.production" "$HOST:\$HOME/MagicCiv/.env" >/dev/null
|
|
echo -e "${GREEN} ✓ Dev config deployed${NC}"
|
|
else
|
|
scp "$REPO_ROOT/.env.production" "$HOST:\$HOME/MagicCiv/.env" >/dev/null
|
|
ssh "$HOST" 'rm -f "$HOME/MagicCiv/.env.development"' 2>/dev/null
|
|
echo -e "${GREEN} ✓ Production config deployed${NC}"
|
|
fi
|
|
|
|
echo -e "${YELLOW}[4/4] Launching...${NC}"
|
|
cmd_start_linux || echo -e "${YELLOW} ! Installed but launch did not confirm${NC}"
|
|
echo ""
|
|
echo -e "${GREEN}Installed on $HOST.${NC}"
|
|
}
|
|
|
|
cmd_start_linux() {
|
|
local HOST="$LINUX_HOST"
|
|
local BIN_NAME
|
|
BIN_NAME="$(_linux_binary_name)"
|
|
ssh -o ConnectTimeout=5 "$HOST" "echo ok" >/dev/null 2>&1 || { echo -e "${RED}Cannot reach $HOST${NC}"; return 1; }
|
|
|
|
local EXISTING
|
|
EXISTING=$(ssh "$HOST" 'pgrep -f "MagicCivilization" 2>/dev/null | head -1')
|
|
[ -n "$EXISTING" ] && { echo -e "${YELLOW}Already running on $HOST (PID $EXISTING)${NC}"; return 0; }
|
|
|
|
# Verify installed
|
|
ssh "$HOST" "[ -x \"\$HOME/MagicCiv/$BIN_NAME\" ]" \
|
|
|| { echo -e "${RED}Not installed on $HOST. Run: ./run install linux${NC}"; return 1; }
|
|
|
|
# Launch detached with forwarded display env; rely on systemd-login's XDG_RUNTIME_DIR default.
|
|
ssh "$HOST" bash <<REMOTE_LAUNCH
|
|
cd "\$HOME/MagicCiv"
|
|
export WAYLAND_DISPLAY="\${WAYLAND_DISPLAY:-wayland-0}"
|
|
export XDG_RUNTIME_DIR="\${XDG_RUNTIME_DIR:-/run/user/\$(id -u)}"
|
|
export DISPLAY="\${DISPLAY:-:0}"
|
|
nohup "./$BIN_NAME" >/tmp/magic_civ_linux.log 2>&1 &
|
|
disown
|
|
REMOTE_LAUNCH
|
|
|
|
local i PID
|
|
for i in $(seq 1 10); do
|
|
PID=$(ssh "$HOST" 'pgrep -f "MagicCivilization" 2>/dev/null | head -1')
|
|
[ -n "$PID" ] && { echo -e "${GREEN}Running on $HOST (PID $PID)${NC}"; return 0; }
|
|
sleep 1
|
|
done
|
|
echo -e "${YELLOW}Launched on $HOST but could not confirm PID. Log: /tmp/magic_civ_linux.log${NC}"
|
|
return 1
|
|
}
|
|
|
|
cmd_stop_linux() {
|
|
local HOST="$LINUX_HOST"
|
|
ssh -o ConnectTimeout=5 "$HOST" "echo ok" >/dev/null 2>&1 || { echo -e "${RED}Cannot reach $HOST${NC}"; return 1; }
|
|
|
|
local PID
|
|
PID=$(ssh "$HOST" 'pgrep -f "MagicCivilization" 2>/dev/null | head -1')
|
|
[ -z "$PID" ] && { echo -e "${YELLOW}Not running on $HOST.${NC}"; return 0; }
|
|
ssh "$HOST" 'pkill -f "MagicCivilization"' 2>/dev/null
|
|
echo -e "${GREEN}Stopped on $HOST (was PID $PID)${NC}"
|
|
}
|
|
|
|
cmd_smoke_linux() {
|
|
# Minimal inline smoke test — no external smoke-test-linux.sh needed.
|
|
# Install → wait for boot → screenshot via tools/screenshot.sh → stop.
|
|
local HOST="$LINUX_HOST"
|
|
local BOOT_WAIT="${1:-20}"
|
|
|
|
echo -e "${BLUE}=== Linux smoke test ($HOST, ${BOOT_WAIT}s boot) ===${NC}"
|
|
cmd_install_linux || { echo -e "${RED}Install failed — smoke aborted${NC}"; return 1; }
|
|
|
|
echo -e "${YELLOW}Waiting ${BOOT_WAIT}s for boot...${NC}"
|
|
sleep "$BOOT_WAIT"
|
|
|
|
# Is it still running?
|
|
local PID
|
|
PID=$(ssh "$HOST" 'pgrep -f "MagicCivilization" 2>/dev/null | head -1')
|
|
if [ -z "$PID" ]; then
|
|
echo -e "${RED}✗ Process exited during boot — check /tmp/magic_civ_linux.log on $HOST${NC}"
|
|
ssh "$HOST" 'tail -20 /tmp/magic_civ_linux.log' 2>/dev/null | head -20
|
|
return 1
|
|
fi
|
|
echo -e "${GREEN} ✓ Running (PID $PID) after ${BOOT_WAIT}s${NC}"
|
|
|
|
# Capture screenshot via the existing helper (host-aware via SCREENSHOT_HOST)
|
|
"$REPO_ROOT/tools/screenshot.sh" "smoke_linux_$(date +%Y%m%d_%H%M%S)" || {
|
|
echo -e "${YELLOW}Screenshot step reported non-zero — check tool output${NC}"
|
|
}
|
|
|
|
cmd_stop_linux
|
|
echo -e "${GREEN}Linux smoke test complete.${NC}"
|
|
}
|
|
|
|
cmd_start_osx() {
|
|
local HOST="$OSX_HOST"
|
|
ssh -o ConnectTimeout=5 "$HOST" "echo ok" >/dev/null 2>&1 || { echo -e "${RED}Cannot reach $HOST${NC}"; return 1; }
|
|
EXISTING=$(ssh "$HOST" 'pgrep -f "Magic Civilization" 2>/dev/null | head -1')
|
|
[ -n "$EXISTING" ] && { echo -e "${YELLOW}Already running (PID $EXISTING)${NC}"; return 0; }
|
|
ssh "$HOST" '[ -d "/Applications/Magic Civilization.app" ]' || { echo -e "${RED}Not installed. Run: ./run install osx${NC}"; return 1; }
|
|
ssh "$HOST" 'open "/Applications/Magic Civilization.app"' 2>/dev/null
|
|
for i in $(seq 1 10); do
|
|
PID=$(ssh "$HOST" 'pgrep -f "Magic Civilization" 2>/dev/null | head -1')
|
|
[ -n "$PID" ] && { echo -e "${GREEN}Running (PID $PID)${NC}"; return 0; }
|
|
sleep 1
|
|
done
|
|
echo -e "${YELLOW}Launched but could not confirm PID${NC}"
|
|
}
|
|
|
|
cmd_start_ios() {
|
|
local HOST="$OSX_HOST"
|
|
ssh -o ConnectTimeout=5 "$HOST" "echo ok" >/dev/null 2>&1 || { echo -e "${RED}Cannot reach $HOST${NC}"; return 1; }
|
|
RESULT=$(ssh "$HOST" "xcrun devicectl device process launch --device $IOS_DEVICE_ID com.magicciv.game 2>&1")
|
|
echo "$RESULT" | grep -q "launched" && echo -e "${GREEN}Launched on iPhone${NC}" || { echo -e "${RED}Launch failed${NC}"; echo "$RESULT" | grep -E "error:|NSLocalizedFailureReason" | head -3; return 1; }
|
|
}
|
|
|
|
cmd_stop_osx() {
|
|
local HOST="$OSX_HOST"
|
|
ssh -o ConnectTimeout=5 "$HOST" "echo ok" >/dev/null 2>&1 || { echo -e "${RED}Cannot reach $HOST${NC}"; return 1; }
|
|
PID=$(ssh "$HOST" 'pgrep -f "Magic Civilization" 2>/dev/null | head -1')
|
|
[ -z "$PID" ] && { echo -e "${YELLOW}Not running.${NC}"; return 0; }
|
|
ssh "$HOST" 'pkill -f "Magic Civilization"' 2>/dev/null
|
|
echo -e "${GREEN}Stopped (was PID $PID)${NC}"
|
|
}
|
|
|
|
cmd_smoke_osx() {
|
|
# Minimal inline smoke test — mirrors cmd_smoke_linux.
|
|
# Install → wait for boot → screenshot → stop.
|
|
local HOST="$OSX_HOST"
|
|
local BOOT_WAIT="${1:-20}"
|
|
|
|
echo -e "${BLUE}=== macOS smoke test ($HOST, ${BOOT_WAIT}s boot) ===${NC}"
|
|
cmd_install_osx || { echo -e "${RED}Install failed — smoke aborted${NC}"; return 1; }
|
|
|
|
echo -e "${YELLOW}Waiting ${BOOT_WAIT}s for boot...${NC}"
|
|
sleep "$BOOT_WAIT"
|
|
|
|
local PID
|
|
PID=$(ssh "$HOST" 'pgrep -f "Magic Civilization" 2>/dev/null | head -1')
|
|
if [ -z "$PID" ]; then
|
|
echo -e "${RED}✗ Process exited during boot on $HOST${NC}"
|
|
ssh "$HOST" "log show --predicate 'process == \"Magic Civilization\"' --last 30s 2>/dev/null | tail -20" | head -20
|
|
return 1
|
|
fi
|
|
echo -e "${GREEN} ✓ Running (PID $PID) after ${BOOT_WAIT}s${NC}"
|
|
|
|
"$REPO_ROOT/tools/screenshot.sh" "smoke_osx_$(date +%Y%m%d_%H%M%S)" || {
|
|
echo -e "${YELLOW}Screenshot step reported non-zero${NC}"
|
|
}
|
|
|
|
cmd_stop_osx
|
|
echo -e "${GREEN}macOS smoke test complete.${NC}"
|
|
}
|