chore(ci): tidy CI/dev infra — drop local-ci, lift migration rule, scope by galaxy.stack label
Tests · Go / test (push) Successful in 2m6s
Tests · Go / test (pull_request) Successful in 3m1s
Tests · Integration / integration (pull_request) Successful in 1m42s

Five connected cleanups across the dev/CI infrastructure:

1. Drop tools/local-ci/. The standalone Gitea + act_runner stack was
   the legacy "offline workflow validator"; the per-stage CI gate now
   runs on gitea.lan and the directory was only retained as a
   fallback. Removing it leaves no operational dependency: backend,
   gateway, and game code have no references; documentation that
   pointed at it (CLAUDE.md, docs/ARCHITECTURE.md, ui/docs/testing.md,
   tools/dev-deploy/README.md, tools/local-dev/README.md) is updated
   in this same change. Historical "Verified on local-ci run N"
   markers in ui/PLAN.md are preserved unchanged.

2. Lift the pre-production single-migration rule. The rule forced
   every schema delta into 00001_init.sql and required a manual
   make clean-data wipe on every backward-incompatible change in
   tools/dev-deploy/. Future schema deltas now land as additive
   sequence-numbered files (00002_*.sql, …) that goose applies
   automatically on backend startup; 00001_init.sql becomes an
   immutable baseline. Authoring conventions live in
   backend/internal/postgres/migrations/README.md. The chain may be
   squashed back into a fresh 00001 as a deliberate one-time
   operation before the first production deployment.

3. Document the deployment cadence. The dev environment is
   single-tenant: pushes to feature/* run the test workflows
   (go-unit, ui-test, integration) only; dev-deploy.yaml fires on
   push to development. A workflow_dispatch override on
   dev-deploy.yaml lets a developer preview a feature branch on the
   shared dev environment before merge; the next merge into
   development overwrites the manual deploy idempotently.

4. Scope compose-managed resources by an explicit
   galaxy.stack=<local-dev|dev-deploy> label. Both compose files
   stamp the label on every service, network, and named volume.
   Makefiles in tools/local-dev/ and tools/dev-deploy/ filter their
   engine-cleanup operations by (stack-label AND engine OCI title)
   so they never touch unrelated workloads on the same daemon.
   dev-deploy.yaml gains a pre-`compose up` step that reaps stale
   exited/dead containers under the dev-deploy stack label.

5. Backend now stamps the same galaxy.stack=<value> label on every
   engine container it spawns, sourced from a new BACKEND_STACK_LABEL
   env var (empty → label not applied; legacy-safe). Both compose
   files set it to their stack name (local-dev / dev-deploy). The
   contract is recorded in docs/ARCHITECTURE.md under
   "Container labels". A package-level test in
   backend/internal/runtime exercises both the label-present and
   label-absent paths.

No tests intentionally regressed: go test ./backend/internal/{config,
runtime,dockerclient} is green, both compose files validate cleanly,
and the backend, gateway, and game modules all build.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Ilia Denisov
2026-05-18 23:32:42 +02:00
parent 5eec7013ba
commit a9087691a3
23 changed files with 325 additions and 532 deletions
+13 -12
View File
@@ -15,10 +15,10 @@ This stack is **not** a CI gate (the per-stage CI gate now lives on
the **long-lived dev environment** at
[`tools/dev-deploy/`](../dev-deploy/README.md), which is redeployed on
every merge into `development` and is reachable as
`https://www.galaxy.lan` / `https://api.galaxy.lan`. The three stacks
(`tools/local-dev/`, `tools/dev-deploy/`, and the fallback
`tools/local-ci/`) coexist on the same host because every name —
compose project, container, network, volume — is distinct.
`https://www.galaxy.lan` / `https://api.galaxy.lan`. The two stacks
(`tools/local-dev/` and `tools/dev-deploy/`) coexist on the same host
because every name — compose project, container, network, volume — is
distinct.
## Bring it up
@@ -203,8 +203,8 @@ make status docker compose ps
images built on alpine (so `wget` is available for the compose
healthchecks). The build stage mirrors `backend/Dockerfile` and
`gateway/Dockerfile` exactly.
- `Makefile` — wrapper over `docker compose` that keeps the muscle
memory close to `tools/local-ci/`'s Makefile.
- `Makefile` — wrapper over `docker compose` with thin targets for the
most common dev cycles.
- `.env` — committed defaults for the compose `${VAR:-}`
expansions. Edit per-developer or override via your shell.
- `keys/gateway-response.pem`, `keys/gateway-response.pub` — dev-only
@@ -290,12 +290,13 @@ make status docker compose ps
## Relationship to other infrastructure
- `tools/local-ci/` — Gitea + Actions runner, replays
`.gitea/workflows/*` against a pushed branch. Different stack,
different purpose; coexists with local-dev on the same machine.
- `tools/dev-deploy/` — long-lived dev environment redeployed on every
merge into `development`; reachable at `https://www.galaxy.lan` /
`https://api.galaxy.lan`. Distinct compose project, container names,
network and volumes.
- `integration/testenv/` — testcontainers harness used by
`make -C integration integration`. Uses the same images
(`backend/Dockerfile`, `gateway/Dockerfile`) at production
defaults; do not confuse with this local-dev stack, which carries
`make -C integration integration`. Uses the canonical
`backend/Dockerfile` / `gateway/Dockerfile` at production defaults;
do not confuse with this local-dev stack, which carries
alpine-runtime images for ergonomics and the dev-mode auth
override.