Files
galaxy-game/tools/dev-deploy
Ilia Denisov 81917acc3e
Tests · UI / test (push) Has been cancelled
Tests · Integration / integration (pull_request) Successful in 1m47s
Tests · Go / test (pull_request) Successful in 2m4s
Tests · UI / test (pull_request) Successful in 2m23s
dev-deploy: enable Dev Sandbox bootstrap and synthetic-report loader
Two long-standing dev-environment ergonomics had not survived the
move from the bespoke local-dev stack to the CI-driven dev-deploy:

1. `BACKEND_DEV_SANDBOX_EMAIL` defaulted to an empty string in the
   dev-deploy compose, so the auto-provisioned "Dev Sandbox" game
   never appeared on `https://www.galaxy.lan`. Bake `dev@galaxy.lan`
   as the default — matches `.env.example` and lets a developer who
   logs in with that email find a ready-to-play game in the lobby.

2. The lobby's synthetic-report loader was gated on
   `import.meta.env.DEV`, which is true only for `vite dev` (the
   tools/local-dev path). The long-lived dev environment builds
   with `vite build` (production mode), so the section was always
   stripped from its bundle. Gate it on an explicit
   `VITE_GALAXY_DEV_AFFORDANCES` flag instead and set it both in
   `.env.development` (preserves `pnpm dev` behaviour) and in the
   `dev-deploy.yaml` build step. The `prod-build.yaml` build path
   leaves the flag unset, so production stays clean.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-16 21:46:24 +02:00
..

tools/dev-deploy/ — long-lived Galaxy dev environment

A docker-compose stack that runs the Galaxy backend, gateway, supporting services, and a small Caddy in front of them, reachable through the host Caddy at https://www.galaxy.lan and https://api.galaxy.lan. Used by the dev-deploy.yaml Gitea Actions workflow as the canonical dev target on every merge into the development branch, and runnable by hand through this Makefile for local debugging of the deploy plumbing itself.

This stack is not the developer's primary playground for UI work — that role still belongs to tools/local-dev/, which is faster (Vite HMR, host-side dev server) and isolated to one developer. The two stacks coexist on the same host because every name is distinct:

tools/local-dev/ tools/dev-deploy/
Compose project local-dev galaxy-dev
Container prefix galaxy-local-dev-* galaxy-dev-*
Network galaxy-local-dev-net galaxy-dev-internal, edge
Volumes galaxy-local-dev-* galaxy-dev-*
Host ports 5433/6380/8025/8080/9090 none (only edge network)
Game state /tmp/galaxy-game-state /var/lib/galaxy-dev/game-state
Engine image galaxy-engine:local-dev galaxy-engine:dev

Prerequisites

The host must already provide:

  • Docker daemon reachable as the user running make (member of the docker group, no sudo).

  • An external bridge network named edge (or whatever GALAXY_EDGE_NETWORK overrides to):

    docker network create edge
    
  • A host Caddy listening on :80/:443, attached to the edge network, and proxying www.galaxy.lan and api.galaxy.lan to galaxy-caddy:80. Example fragment for the host Caddyfile:

    www.galaxy.lan, api.galaxy.lan {
        tls internal
        reverse_proxy galaxy-caddy:80
    }
    
  • Game-state directory writable by the user running make. Default is ${HOME}/.galaxy-dev/game-state; make up creates it on demand. Override by exporting GALAXY_DEV_GAME_STATE_DIR (e.g. to /var/lib/galaxy-dev/game-state once the host is provisioned for it).

Bring it up

make -C tools/dev-deploy up

up (re)builds the local-dev backend and gateway images, makes sure the engine image galaxy-engine:dev exists, and waits for healthchecks. It does not seed the UI volume — that is normally done by CI. The first time you run by hand:

make -C tools/dev-deploy seed-ui
make -C tools/dev-deploy up
make -C tools/dev-deploy health

seed-ui runs pnpm build in ui/frontend/, then copies the resulting build/ tree into the galaxy-dev-ui-dist volume. Subsequent CI deploys overwrite this volume automatically.

Daily flow

make -C tools/dev-deploy rebuild   # rebuild backend/gateway images + up
make -C tools/dev-deploy logs      # tail compose logs
make -C tools/dev-deploy health    # probe https://*.galaxy.lan
make -C tools/dev-deploy down      # stop, keep state

State persists in named volumes between up/down cycles. The development branch keeps the dev environment continuously usable — games created last week survive into this week unless somebody calls make clean-data.

Logging in

The same dev-mode email-code override as tools/local-dev/ applies, and the dev-deploy compose ships with it enabled by default:

  1. Enter dev@galaxy.lan (or whatever BACKEND_DEV_SANDBOX_EMAIL resolves to) in the login form.
  2. Submit 123456 as the code — the docker-compose default for BACKEND_AUTH_DEV_FIXED_CODE is 123456, so the bcrypt-hashed email code stays a fallback. To force real Mailpit codes (e.g. for mail-flow QA), set BACKEND_AUTH_DEV_FIXED_CODE= (empty) in a local .env and make rebuild.

The fixed-code override is rejected by production env loaders, so it cannot leak into the prod environment.

Networking

Browser
   │  https://www.galaxy.lan, https://api.galaxy.lan
   ▼
host-Caddy (:80, :443, TLS, attached to `edge` network)
   │  reverse_proxy *.galaxy.lan → galaxy-caddy:80
   ▼
galaxy-caddy  (networks: edge + galaxy-dev-internal)
   │  www.galaxy.lan → file_server /srv/galaxy-ui (volume galaxy-dev-ui-dist)
   │  api.galaxy.lan → reverse_proxy galaxy-api:8080
   ▼
galaxy-dev-internal
   ├─ galaxy-api      (gateway:   :8080 REST, :9090 gRPC)
   ├─ galaxy-backend  (backend:   :8080 HTTP, :8081 gRPC push)
   ├─ galaxy-postgres (postgres:  :5432)
   ├─ galaxy-redis    (redis:     :6379)
   ├─ galaxy-mailpit  (mailpit:   :8025 UI, :1025 SMTP)
   └─ engine containers (spawned by backend on demand)

The compose project deliberately exposes no host ports. Diagnostics that used to go through localhost:8025 etc. now go through the container network: docker compose -f tools/dev-deploy/docker-compose.yml exec galaxy-mailpit wget -qO- localhost:8025/messages and similar.

Persistent state and schema changes

The dev Postgres volume galaxy-dev-postgres-data survives redeploys. Until the pre-production migration rule is lifted, every backward-incompatible change to backend/internal/postgres/migrations/00001_init.sql needs a manual wipe before the next deploy succeeds:

make -C tools/dev-deploy clean-data
make -C tools/dev-deploy up

This is the same caveat as tools/local-dev/, just with a different volume name.

Make targets

make up             Build images, ensure engine image, bring stack up (waits for health)
make rebuild        Rebuild backend / gateway images (ignores cache), then up
make seed-ui        pnpm build + load build/ into galaxy-dev-ui-dist volume
make build-engine   Build galaxy-engine:dev (no-op if image already present)
make down           Stop containers, keep named volumes
make logs           Tail compose logs
make status         docker compose ps
make health         curl https://www.galaxy.lan + https://api.galaxy.lan/healthz
make psql           psql as galaxy@galaxy_backend
make clean-data     Stop everything and wipe volumes + game-state dir

Files

  • docker-compose.yml — six services: postgres, redis, mailpit, galaxy-backend, galaxy-api, galaxy-caddy. Reuses the alpine-runtime Dockerfiles from ../local-dev/ so the backend healthcheck can run wget. Reuses the dev keypair from ../local-dev/keys/.
  • Caddyfile.dev — the application-routing Caddy config, mounted into galaxy-caddy at /etc/caddy/Caddyfile.
  • Caddyfile.prod — placeholder for a future prod deployment; not used by this compose.
  • Makefile — wrapper over docker compose with helpers for engine, UI seeding, health probes, and full wipe.
  • .env.example — non-secret defaults for the compose ${VAR:-} expansions. Copy to .env if you want host-local overrides.

Relationship to other infrastructure

  • tools/local-dev/ — single-developer playground, host-port mapped, Vite dev server on the side. Recommended for active UI work.
  • tools/local-ci/ — Gitea + act runner for fallback workflow testing without gitea.lan. Optional, not part of the per-stage CI gate anymore.
  • .gitea/workflows/dev-deploy.yaml — the CI side of this stack: builds images, seeds the UI volume, runs docker compose up -d on every merge into development. The Makefile in this directory is what that workflow ultimately calls into.