.PHONY: help up down rebuild logs status clean-data health psql build-engine seed-ui seed-site seed-geoip .DEFAULT_GOAL := help REPO_ROOT := $(realpath $(CURDIR)/../..) ENGINE_IMAGE := galaxy-engine:dev STACK_LABEL := galaxy.stack=dev-deploy ENGINE_LABEL := org.opencontainers.image.title=galaxy-game-engine # Public host the in-front host Caddy serves the single-origin stack on. # Used only by `make health` probes; override for a different domain. GALAXY_DEV_HOST ?= galaxy.lan # Game-state root lives under the invoking user's home by default so # `make up` works without sudo. Override `GALAXY_DEV_GAME_STATE_DIR` # in the environment or `.env` to relocate (e.g. /var/lib/galaxy-dev/ # game-state in a production-shaped host). The value flows through to # both the compose bind-mount and the backend's # `BACKEND_GAME_STATE_ROOT`. export GALAXY_DEV_GAME_STATE_DIR ?= $(HOME)/.galaxy-dev/game-state COMPOSE := docker compose help: @echo "Long-lived Galaxy dev environment (single-origin, e.g. https://galaxy.lan):" @echo " make up Build images, ensure engine image, seed geoip, bring stack up" @echo " make rebuild Force rebuild of backend / gateway images and bring up" @echo " make build-engine Build $(ENGINE_IMAGE) from game/Dockerfile (no-op if present)" @echo " make seed-ui Build ui/frontend and load into galaxy-dev-ui-dist volume" @echo " make seed-site Build site/ (VitePress) and load into galaxy-dev-site-dist volume" @echo " make seed-geoip Copy GeoIP fixture into galaxy-dev-geoip-data volume" @echo " make down Stop containers, keep named volumes" @echo " make logs Tail all logs" @echo " make status docker compose ps" @echo " make health Probe the stack through the host Caddy" @echo " make psql Open a psql shell as galaxy@galaxy_backend" @echo " make clean-data Stop everything and wipe named volumes + game-state" @echo "" @echo "Requires:" @echo " - external Docker network '$${GALAXY_EDGE_NETWORK:-edge}'" @echo " (docker network create edge)" @echo " - host Caddy proxying the public host into that network" @echo " - game-state dir: $(GALAXY_DEV_GAME_STATE_DIR) (auto-created)" up: build-engine seed-geoip mkdir -p "$(GALAXY_DEV_GAME_STATE_DIR)" $(COMPOSE) up -d --wait rebuild: build-engine seed-geoip $(COMPOSE) build --no-cache galaxy-backend galaxy-api mkdir -p "$(GALAXY_DEV_GAME_STATE_DIR)" $(COMPOSE) up -d --wait build-engine: @if docker image inspect $(ENGINE_IMAGE) >/dev/null 2>&1; then \ echo "$(ENGINE_IMAGE) already built; skipping (use 'docker rmi $(ENGINE_IMAGE)' to force a rebuild)."; \ else \ echo "building $(ENGINE_IMAGE)…"; \ docker build -t $(ENGINE_IMAGE) -f $(REPO_ROOT)/game/Dockerfile $(REPO_ROOT); \ fi # Copy the GeoIP fixture into a named volume the backend mounts as # /var/lib/galaxy. Using a volume avoids a bind-mount that would # resolve against an ephemeral workspace path when compose is driven # from the Gitea runner (see tools/dev-deploy/KNOWN-ISSUES.md for the # breakage that bind-mounts caused on `docker restart`). seed-geoip: @echo "seeding GeoIP fixture into galaxy-dev-geoip-data…" docker volume create galaxy-dev-geoip-data >/dev/null docker run --rm \ -v galaxy-dev-geoip-data:/dst \ -v $(REPO_ROOT)/pkg/geoip/test-data/test-data:/src:ro \ alpine sh -c 'cp /src/GeoIP2-Country-Test.mmdb /dst/geoip.mmdb' # Build the UI frontend and load the resulting build/ directory into # the named volume Caddy serves from. Used by the dev-deploy workflow # and by anyone bringing the stack up by hand. seed-ui: @if [ ! -d $(REPO_ROOT)/ui/frontend/node_modules ]; then \ echo "installing UI dependencies…"; \ (cd $(REPO_ROOT)/ui && pnpm install --frozen-lockfile); \ fi @echo "building UI (vite build)…" (cd $(REPO_ROOT)/ui/frontend && \ VITE_GATEWAY_BASE_URL= \ BASE_PATH=/game \ VITE_GALAXY_DEV_AFFORDANCES=true \ VITE_GATEWAY_RESPONSE_PUBLIC_KEY=$$(cat $(REPO_ROOT)/ui/frontend/.env.development \ | sed -n 's/^VITE_GATEWAY_RESPONSE_PUBLIC_KEY=//p') \ pnpm build) @echo "loading build/ into galaxy-dev-ui-dist volume…" docker volume create galaxy-dev-ui-dist >/dev/null docker run --rm \ -v galaxy-dev-ui-dist:/dst \ -v $(REPO_ROOT)/ui/frontend/build:/src:ro \ alpine sh -c 'rm -rf /dst/* /dst/.??* 2>/dev/null; cp -a /src/. /dst/' # Build the project site (VitePress) and load the static output into the # named volume Caddy serves at the root. Used by the dev-deploy workflow # and by anyone bringing the stack up by hand. seed-site: @if [ ! -d $(REPO_ROOT)/site/node_modules ]; then \ echo "installing site dependencies…"; \ (cd $(REPO_ROOT)/site && pnpm install --frozen-lockfile); \ fi @echo "building project site (vitepress build)…" (cd $(REPO_ROOT)/site && pnpm build) @echo "loading site dist into galaxy-dev-site-dist volume…" docker volume create galaxy-dev-site-dist >/dev/null docker run --rm \ -v galaxy-dev-site-dist:/dst \ -v $(REPO_ROOT)/site/.vitepress/dist:/src:ro \ alpine sh -c 'rm -rf /dst/* /dst/.??* 2>/dev/null; cp -a /src/. /dst/' down: $(COMPOSE) down logs: $(COMPOSE) logs -f --tail=100 status: $(COMPOSE) ps health: @echo "Site (https://$(GALAXY_DEV_HOST)/):" @curl -sS -o /dev/null -w " HTTP %{http_code}\n" https://$(GALAXY_DEV_HOST)/ || echo " unreachable" @echo "Game (https://$(GALAXY_DEV_HOST)/game/):" @curl -sS -o /dev/null -w " HTTP %{http_code}\n" https://$(GALAXY_DEV_HOST)/game/ || echo " unreachable" @echo "API healthz (https://$(GALAXY_DEV_HOST)/healthz):" @curl -sS -o /dev/null -w " HTTP %{http_code}\n" https://$(GALAXY_DEV_HOST)/healthz || echo " unreachable" psql: $(COMPOSE) exec galaxy-postgres psql -U galaxy -d galaxy_backend clean-data: @echo "Stopping containers and engines, then wiping volumes + game-state…" $(COMPOSE) down -v @ids=$$(docker ps -aq \ --filter "label=$(STACK_LABEL)" \ --filter "label=$(ENGINE_LABEL)"); \ if [ -n "$$ids" ]; then \ echo "stopping engine containers for $(STACK_LABEL)…"; \ docker rm -f $$ids >/dev/null; \ fi @if [ -d "$(GALAXY_DEV_GAME_STATE_DIR)" ]; then \ echo "wiping $(GALAXY_DEV_GAME_STATE_DIR)…"; \ docker run --rm -v "$(GALAXY_DEV_GAME_STATE_DIR):/state" alpine sh -c 'rm -rf /state/*' 2>/dev/null \ || rm -rf "$(GALAXY_DEV_GAME_STATE_DIR)"/* 2>/dev/null || true; \ fi