magicciv/run

199 lines
9.7 KiB
Bash
Executable file

#!/usr/bin/env bash
# Magic Civilization — Task Runner
# Usage: ./run <command> [args...]
#
# Naming convention: `<verb>` for global actions; `<verb>:<target>` for subcommands.
# Examples: lint / lint:rust, build / build:wasm, install:osx, smoke:linux.
set -uo pipefail
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# Source all run modules
for _script in "$REPO_ROOT/scripts/run/"*.sh; do
source "$_script"
done
unset _script
usage() {
echo -e "${BLUE}Magic Civilization${NC} — Task Runner"
echo ""
echo "Usage: ./run <command> [args...]"
echo ""
echo -e "${YELLOW}Development${NC}"
echo " play Launch the game locally"
echo " editor Open Godot editor"
echo " guide Start guide dev server (port 5800)"
echo " lint Lint all (GDScript + Rust + TypeScript)"
echo " lint:gd GDScript only (gdlint + gdformat --check)"
echo " lint:rust Rust only (fmt --check + clippy + machete)"
echo " lint:ts TypeScript only (ESLint + tsc typecheck)"
echo " format Format all (GDScript + Rust + TypeScript)"
echo " format:gd GDScript only (gdformat)"
echo " format:rust Rust only (cargo fmt)"
echo " format:ts TypeScript only (ESLint --fix)"
echo " typecheck pnpm -r typecheck (all TS packages)"
echo " validate Validate game data JSON files against schemas"
echo " test Run GUT + Rust (nextest if available) + vitest"
echo " test:golden Cross-language golden-vector parity (Rust + WASM + GDExt)"
echo " coverage Coverage reports (cargo llvm-cov + pnpm test:coverage)"
echo " verify Full pipeline: schemas + build + tests + lint + docs + LOC cap"
echo " screenshot [name] [scene] [delay] Capture screenshot"
echo " autoplay [seed] Run single seeded auto_play game + report (opt-in)"
echo " autoplay-batch [count] Run N seeded games + aggregate report (opt-in)"
echo ""
echo -e "${YELLOW}Build${NC}"
echo " build Build WASM + GDExtension"
echo " build:wasm Build WASM only (src/simulator → pkg/)"
echo " build:gdext Build GDExtension only (src/simulator → src/game/addons/)"
echo ""
echo -e "${YELLOW}Export${NC}"
echo " export [version] Export all platforms (parallel)"
echo " export:macos [version] Export macOS only"
echo " export:linux [version] Export Linux only"
echo " export:windows [version] Export Windows only"
echo " export:android [version] Export Android APK"
echo " export:ios [version] Export iOS Xcode project"
echo ""
echo -e "${YELLOW}Install (deploy + launch on target)${NC}"
echo " install:osx [version] [--dev] Export + install .app on \$OSX_HOST (default: plum)"
echo " install:linux [version] [--dev] Export + install binary on \$LINUX_HOST"
echo " install:iphone [version] [--dev] Export + xcodebuild + devicectl install via \$OSX_HOST"
echo " install:android [version] [--dev] Export + adb install on connected Android device"
echo ""
echo -e "${YELLOW}Remote control${NC}"
echo " start:osx Launch installed app on \$OSX_HOST"
echo " start:linux Launch installed binary on \$LINUX_HOST"
echo " start:ios Launch app on connected iPhone (via \$OSX_HOST)"
echo " stop:osx Kill running app on \$OSX_HOST"
echo " stop:linux Kill running binary on \$LINUX_HOST"
echo " smoke:osx Full smoke test (macOS — export → ship → launch → screenshot)"
echo " smoke:linux [boot-secs] Full smoke test (Linux — default 20s boot wait)"
echo ""
echo -e "${YELLOW}Tools${NC}"
echo " tools:spritegen <cmd> Sprite generation pipeline"
echo " setup Install/verify all dev dependencies (auto-detects OS)"
}
# ── Install args parser (shared by install:* targets) ────────────────
# Separates --dev from positional args; echoes them as
# "DEV_MODE|pos1 pos2 ..." for callers to split.
_parse_install_args() {
local dev_flag=""
local pos=()
for arg in "$@"; do
case "$arg" in
--dev) dev_flag="--dev" ;;
*) pos+=("$arg") ;;
esac
done
echo "$dev_flag|${pos[*]}"
}
_dispatch_install() {
local target="$1"; shift
local parsed dev_flag pos_args
parsed="$(_parse_install_args "$@")"
dev_flag="${parsed%%|*}"
pos_args="${parsed#*|}"
# shellcheck disable=SC2086
case "$target" in
osx) cmd_install_osx $dev_flag $pos_args ;;
linux) cmd_install_linux $dev_flag $pos_args ;;
iphone) cmd_install_ios iphone $dev_flag $pos_args ;;
sim) cmd_install_ios sim $dev_flag $pos_args ;;
android) cmd_install_android $dev_flag $pos_args ;;
*) echo -e "${RED}Unknown install target: $target${NC}"; echo "Available: osx, linux, iphone, android"; return 1 ;;
esac
}
COMMAND="${1:-}"
shift 2>/dev/null || true
case "$COMMAND" in
# ── Development ──────────────────────────────────────────────────
play) cmd_play "$@" ;;
editor) cmd_editor "$@" ;;
guide) cmd_guide "$@" ;;
lint) cmd_lint "$@" ;;
lint:gd) cmd_lint_gd "$@" ;;
lint:rust) cmd_lint_rust "$@" ;;
lint:ts) cmd_lint_ts "$@" ;;
format) cmd_format "$@" ;;
format:gd) cmd_format_gd "$@" ;;
format:rust) cmd_format_rust "$@" ;;
format:ts) cmd_format_ts "$@" ;;
typecheck) cmd_typecheck "$@" ;;
validate) cmd_validate "$@" ;;
test) cmd_test "$@" ;;
test:golden) cmd_test_golden "$@" ;;
coverage) cmd_coverage "$@" ;;
verify) cmd_verify "$@" ;;
screenshot) cmd_screenshot "$@" ;;
autoplay) cmd_autoplay "$@" ;;
autoplay-batch) cmd_autoplay_batch "$@" ;;
# ── Build ────────────────────────────────────────────────────────
build) cmd_build "$@" ;;
build:wasm) cmd_build_wasm "$@" ;;
build:gdext) cmd_build_gdext "$@" ;;
# ── Export ───────────────────────────────────────────────────────
export) cmd_export "$@" ;;
export:windows) cmd_export_single windows "$@" ;;
export:macos) cmd_export_single macos "$@" ;;
export:linux) cmd_export_single linux "$@" ;;
export:android) cmd_export_single android "$@" ;;
export:ios) cmd_export_single ios "$@" ;;
# ── Install (colon form — canonical) ────────────────────────────
install:osx|install:macos) _dispatch_install osx "$@" ;;
install:linux) _dispatch_install linux "$@" ;;
install:iphone|install:ios) _dispatch_install iphone "$@" ;;
install:sim) _dispatch_install sim "$@" ;;
install:android) _dispatch_install android "$@" ;;
# ── Start / Stop / Smoke (colon form — canonical) ───────────────
start:osx|start:macos) cmd_start_osx "$@" ;;
start:linux) cmd_start_linux "$@" ;;
start:ios|start:iphone) cmd_start_ios "$@" ;;
stop:osx|stop:macos) cmd_stop_osx "$@" ;;
stop:linux) cmd_stop_linux "$@" ;;
smoke:osx|smoke:macos) cmd_smoke_osx "$@" ;;
smoke:linux) cmd_smoke_linux "$@" ;;
# ── Tools (colon form — canonical) ──────────────────────────────
tools:spritegen) cmd_tools_spritegen "$@" ;;
# ── Legacy space-form aliases (for muscle memory — undocumented)
# install|start|stop|smoke|tools all accept a positional subtarget.
install)
TARGET=""; POS=()
for arg in "$@"; do
case "$arg" in
--dev) POS+=("$arg") ;;
osx|macos|linux|iphone|ios|sim|android) TARGET="$arg" ;;
*) POS+=("$arg") ;;
esac
done
[ -n "$TARGET" ] || { echo -e "${RED}install requires a target (use install:<target>)${NC}"; exit 1; }
_dispatch_install "${TARGET/macos/osx}" "${POS[@]+"${POS[@]}"}"
;;
start|stop|smoke)
VERB="$COMMAND"
TARGET="${1:-}"; shift 2>/dev/null || true
[ -n "$TARGET" ] || { echo -e "${RED}$VERB requires a target (use $VERB:<target>)${NC}"; exit 1; }
# Recurse using canonical colon form
exec "$0" "$VERB:$TARGET" "$@"
;;
tools)
SUB="${1:-}"; shift 2>/dev/null || true
[ -n "$SUB" ] || { echo -e "${RED}tools requires a subcommand (use tools:<sub>)${NC}"; exit 1; }
exec "$0" "tools:$SUB" "$@"
;;
# ── Misc ─────────────────────────────────────────────────────────
setup) cmd_setup "$@" ;;
help|--help|-h|"") usage ;;
*) echo -e "${RED}Unknown command: $COMMAND${NC}"; echo ""; usage; exit 1 ;;
esac