173 lines
8.1 KiB
Bash
Executable file
173 lines
8.1 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 + i18n + 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)"
|
|
echo " setup:lan-dns Subscribe this host to black.local dnsmasq (idempotent)"
|
|
echo ""
|
|
echo -e "${YELLOW}Deploy${NC}"
|
|
echo " deploy:guide:next Build dev guide (all episodes) + rsync to mc.next.black.local"
|
|
echo " DEPLOY_BAKE_SCENARIOS=base_no_magic|all bakes sim-cache before rsync"
|
|
echo " bake:simcache [ids|all] Pre-compute sim-cache frames into dist/__sim-cache/"
|
|
}
|
|
|
|
# ── 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
|
|
|
|
# Special cases (subcommand requires alias, multi-arg dispatch, help).
|
|
# Everything else resolves to `cmd_<command-with-[-:]-replaced-by-_>`.
|
|
case "$COMMAND" in
|
|
help|--help|-h|"") usage; exit 0 ;;
|
|
|
|
# Export single-target takes a positional `target` arg.
|
|
export:windows|export:macos|export:linux|export:android|export:ios)
|
|
cmd_export_single "${COMMAND#export:}" "$@"; exit $? ;;
|
|
|
|
# Install dispatches through a shared args parser.
|
|
install:osx|install:macos) _dispatch_install osx "$@"; exit $? ;;
|
|
install:linux) _dispatch_install linux "$@"; exit $? ;;
|
|
install:iphone|install:ios) _dispatch_install iphone "$@"; exit $? ;;
|
|
install:sim) _dispatch_install sim "$@"; exit $? ;;
|
|
install:android) _dispatch_install android "$@"; exit $? ;;
|
|
|
|
# Aliases so `install:macos` → `install:osx` (etc.) dispatch to the canonical fn.
|
|
start:macos) cmd_start_osx "$@"; exit $? ;;
|
|
stop:macos) cmd_stop_osx "$@"; exit $? ;;
|
|
smoke:macos) cmd_smoke_osx "$@"; exit $? ;;
|
|
start:iphone) cmd_start_ios "$@"; exit $? ;;
|
|
|
|
# Legacy space-form aliases: `install osx --dev` → `install:osx --dev`
|
|
install)
|
|
TARGET=""; POS=()
|
|
for arg in "$@"; do
|
|
case "$arg" in
|
|
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[@]}"}"
|
|
exit $?
|
|
;;
|
|
start|stop|smoke|tools)
|
|
VERB="$COMMAND"; TARGET="${1:-}"; shift 2>/dev/null || true
|
|
[ -n "$TARGET" ] || { echo -e "${RED}$VERB requires a target (use $VERB:<target>)${NC}"; exit 1; }
|
|
exec "$0" "$VERB:$TARGET" "$@"
|
|
;;
|
|
esac
|
|
|
|
# Data-driven dispatch: `<verb>:<target>` → `cmd_<verb>_<target>`, `<verb>` → `cmd_<verb>`.
|
|
# New subcommands don't require editing this file — just define `cmd_<name>` in
|
|
# any `scripts/run/*.sh` (or subcommand alias in `scripts/dev-setup/`).
|
|
FUNC="cmd_${COMMAND//[:-]/_}"
|
|
if declare -F "$FUNC" >/dev/null; then
|
|
"$FUNC" "$@"
|
|
exit $?
|
|
fi
|
|
|
|
echo -e "${RED}Unknown command: $COMMAND${NC}"
|
|
echo ""
|
|
usage
|
|
exit 1
|