feat(@projects/@magic-civilization): ✨ enable multi-episode guide deployment
Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
This commit is contained in:
parent
066d75f418
commit
3d9d385615
4 changed files with 97 additions and 3 deletions
|
|
@ -36,6 +36,15 @@ import {
|
|||
|
||||
const DEFAULT_PREFS: PlayerPreferences = { race: 'random', gender: 'random', name: '', colorMode: 'dark', dyslexicFont: false, fontSize: 'md' }
|
||||
|
||||
// Episode scope for the EpisodeProvider. Default: 1 (Age of Dwarves — Game 1
|
||||
// Early Access only). Set `VITE_DEV_GUIDE=1` at build time to render every
|
||||
// <EpisodeGate min={N}> subtree — used for the contributor-facing dev
|
||||
// deploy at https://mc.next.black.local, where Game 2/3 work-in-progress
|
||||
// content should be visible alongside the shipping Game 1 scope.
|
||||
const DEV_GUIDE_ALL_EPISODES = 999
|
||||
const ACTIVE_EPISODE: number =
|
||||
import.meta.env.VITE_DEV_GUIDE === '1' ? DEV_GUIDE_ALL_EPISODES : 1
|
||||
|
||||
export default function App(): ReactElement {
|
||||
const { preferences, isFirstVisit, save } = usePlayerPreferences()
|
||||
const [searchParams] = useSearchParams()
|
||||
|
|
@ -171,7 +180,7 @@ export default function App(): ReactElement {
|
|||
|
||||
if (noGui) {
|
||||
return (
|
||||
<EpisodeProvider episode={1}>
|
||||
<EpisodeProvider episode={ACTIVE_EPISODE}>
|
||||
<GuideDataProvider data={guideData}>
|
||||
<PreferencesProvider preferences={activePrefs} races={allRaces}>
|
||||
<RaceThemeProvider
|
||||
|
|
@ -189,7 +198,7 @@ export default function App(): ReactElement {
|
|||
}
|
||||
|
||||
return (
|
||||
<EpisodeProvider episode={1}>
|
||||
<EpisodeProvider episode={ACTIVE_EPISODE}>
|
||||
<GuideDataProvider data={guideData}>
|
||||
<PreferencesProvider preferences={activePrefs} races={allRaces}>
|
||||
<AppShell save={save} showWelcome={showWelcome} setShowWelcome={setShowWelcome} preferences={activePrefs}>
|
||||
|
|
|
|||
3
run
3
run
|
|
@ -73,6 +73,9 @@ usage() {
|
|||
echo -e "${YELLOW}Tools${NC}"
|
||||
echo " tools:spritegen <cmd> Sprite generation pipeline"
|
||||
echo " setup Install/verify all dev dependencies (auto-detects OS)"
|
||||
echo ""
|
||||
echo -e "${YELLOW}Deploy${NC}"
|
||||
echo " deploy:guide:next Build dev guide (all episodes) + rsync to mc.next.black.local"
|
||||
}
|
||||
|
||||
# ── Install args parser (shared by install:* targets) ────────────────
|
||||
|
|
|
|||
74
scripts/run/deploy.sh
Normal file
74
scripts/run/deploy.sh
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
#!/usr/bin/env bash
|
||||
# Deploy commands: guide:next (dev guide to mc.next.black.local).
|
||||
#
|
||||
# This module is Tourguide-owned (see .project/team-leads/tourguide.md).
|
||||
#
|
||||
# Host configuration (from .env or shell rc):
|
||||
# NEXT_DEPLOY_HOST — SSH target for mc.next.black.local static root.
|
||||
# Default: "lilith@black.local".
|
||||
# NEXT_DEPLOY_PATH — destination directory on the remote host.
|
||||
# Default: "/bigdisk/next/mc/".
|
||||
#
|
||||
# The target host-nginx vhost + bind-mount are set up in
|
||||
# `/bigdisk/nginx/nginx.conf` + `/bigdisk/nginx/docker-compose.yml` on
|
||||
# black.local. Infra + objective: p1-15.
|
||||
|
||||
: "${NEXT_DEPLOY_HOST:=lilith@black.local}"
|
||||
: "${NEXT_DEPLOY_PATH:=/bigdisk/next/mc/}"
|
||||
|
||||
cmd_deploy_guide_next() {
|
||||
# Build the dev bundle (all EpisodeGate subtrees visible) + rsync to black.
|
||||
# Safe to run repeatedly — rsync --delete replaces the target dir with dist/.
|
||||
|
||||
# Prerequisite: WASM artifact present locally. The Vite build imports from
|
||||
# the @magic-civ/physics-rs alias which resolves to .local/build/wasm/.
|
||||
if [ ! -f "$REPO_ROOT/.local/build/wasm/magic_civ_physics.js" ]; then
|
||||
echo -e "${RED}✗ .local/build/wasm/magic_civ_physics.js missing — can't build guide.${NC}"
|
||||
echo -e "${RED} Build locally: (cd src/simulator && bash build-wasm.sh)${NC}"
|
||||
echo -e "${RED} Or rsync from apricot:${NC}"
|
||||
echo -e "${RED} rsync -a \"\$AUTOPLAY_HOST\":\"\$PROJECT_ROOT_REMOTE\"/.local/build/wasm/ .local/build/wasm/${NC}"
|
||||
return 1
|
||||
fi
|
||||
|
||||
echo -e "${BLUE}[1/4] Building dev bundle (VITE_DEV_GUIDE=1 pnpm build)...${NC}"
|
||||
if ! (cd "$GUIDE_DIR" && VITE_DEV_GUIDE=1 pnpm build 2>&1); then
|
||||
echo -e "${RED}✗ pnpm build failed${NC}"
|
||||
return 1
|
||||
fi
|
||||
|
||||
local dist="$GUIDE_DIR/dist"
|
||||
if [ ! -f "$dist/index.html" ]; then
|
||||
echo -e "${RED}✗ $dist/index.html not produced — build reported success but emitted no bundle.${NC}"
|
||||
return 1
|
||||
fi
|
||||
local size
|
||||
size="$(du -sh "$dist" | cut -f1)"
|
||||
echo -e "${GREEN}✓ dist/ ready ($size)${NC}"
|
||||
|
||||
echo -e "${BLUE}[2/4] Verifying SSH to $NEXT_DEPLOY_HOST...${NC}"
|
||||
if ! ssh -o ConnectTimeout=5 -o BatchMode=yes "$NEXT_DEPLOY_HOST" "test -d $NEXT_DEPLOY_PATH && echo ok" >/dev/null 2>&1; then
|
||||
echo -e "${RED}✗ can't reach $NEXT_DEPLOY_HOST:$NEXT_DEPLOY_PATH (VPN or permissions).${NC}"
|
||||
return 1
|
||||
fi
|
||||
echo -e "${GREEN}✓ reachable${NC}"
|
||||
|
||||
echo -e "${BLUE}[3/4] Rsyncing dist/ → $NEXT_DEPLOY_HOST:$NEXT_DEPLOY_PATH${NC}"
|
||||
if ! rsync -az --delete "$dist/" "$NEXT_DEPLOY_HOST:$NEXT_DEPLOY_PATH"; then
|
||||
echo -e "${RED}✗ rsync failed${NC}"
|
||||
return 1
|
||||
fi
|
||||
echo -e "${GREEN}✓ deployed${NC}"
|
||||
|
||||
echo -e "${BLUE}[4/4] Probing https://mc.next.black.local ...${NC}"
|
||||
local http_status
|
||||
http_status="$(curl -sk -o /dev/null -w "%{http_code}" --max-time 10 https://mc.next.black.local)"
|
||||
if [ "$http_status" = "200" ]; then
|
||||
echo -e "${GREEN}✓ https://mc.next.black.local → HTTP 200${NC}"
|
||||
else
|
||||
echo -e "${YELLOW}! https://mc.next.black.local → HTTP $http_status (expected 200)${NC}"
|
||||
echo -e "${YELLOW} Deploy may still be correct; check the vhost config on $NEXT_DEPLOY_HOST.${NC}"
|
||||
return 1
|
||||
fi
|
||||
|
||||
echo -e "${GREEN}Deployed dev guide to https://mc.next.black.local${NC}"
|
||||
}
|
||||
|
|
@ -25,16 +25,24 @@ TEAM_LEADS_DIR = REPO / ".project" / "team-leads"
|
|||
OUT = OBJ_DIR / "README.md"
|
||||
JSON_OUT = REPO / "public" / "games" / "age-of-dwarves" / "data" / "objectives.json"
|
||||
|
||||
VALID_STATUS = {"done", "partial", "stub", "missing", "oos"}
|
||||
VALID_STATUS = {"done", "partial", "stub", "missing", "oos", "superseded"}
|
||||
VALID_PRIORITY = {"p0", "p1", "p2", "p3"}
|
||||
VALID_SCOPE = {"game1", "game2", "game3"}
|
||||
|
||||
# Statuses that appear in the totals tables, Left-To-Do-by-Lead, priority
|
||||
# groups, and in the structured JSON export consumed by the guide's
|
||||
# ProgressReportPage. `superseded` is intentionally excluded — those files are
|
||||
# index stubs that redirect to child objectives; counting them would double-
|
||||
# count the children and the guide's ObjectiveStatus union would widen.
|
||||
ACTIVE_STATUSES = {"done", "partial", "stub", "missing", "oos"}
|
||||
|
||||
STATUS_ICON = {
|
||||
"done": "✅",
|
||||
"partial": "🟡",
|
||||
"stub": "🔴",
|
||||
"missing": "❌",
|
||||
"oos": "⚫",
|
||||
"superseded": "♻️",
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue