chore(ci): tidy CI/dev infra — drop local-ci, lift migration rule #13

Merged
developer merged 2 commits from feature/ci-tidy-up into development 2026-05-18 23:10:21 +00:00
Owner

Summary

  • Drop tools/local-ci/ — the standalone Gitea + act_runner fallback. Primary CI runs on gitea.lan; no operational dependency on the directory remained. Docs (CLAUDE.md, docs/ARCHITECTURE.md, ui/docs/testing.md, the two tools/*/README.md) are updated in the same change.
  • Lift the pre-production single-migration rule. Future schema deltas land as additive 0000N_*.sql files and goose applies them on backend startup, so the long-lived dev DB no longer needs a manual make clean-data on every breaking change. 00001_init.sql becomes the immutable baseline; the chain may be squashed back into a fresh 00001 as a one-time pre-prod operation.
  • Document the existing deployment cadence, no functional change: dev is single-tenant, autodeploy on push to development, workflow_dispatch available as the PR-time preview path.
  • Container labels. Both compose files now stamp galaxy.stack=<local-dev|dev-deploy> on every service, network, and named volume. Makefiles filter cleanup by AND(galaxy.stack, org.opencontainers.image.title=galaxy-game-engine) so they touch only this stack's engine containers. dev-deploy.yaml gains a pre-compose up step that reaps stale exited/dead containers under the dev-deploy label.
  • BACKEND_STACK_LABEL — backend stamps galaxy.stack=<value> on every engine container it spawns when the env var is set. Compose files set it to their stack name. Contract documented in docs/ARCHITECTURE.md under "Container labels"; new package-level unit test exercises both label-set and label-absent paths.

Test plan

  • go test -short ./backend/internal/{config,runtime,dockerclient} — green locally.
  • docker compose config -q for both compose files — no errors.
  • go build ./backend/... ./gateway/... ./game/... — clean.
  • Gitea CI: go-unit, ui-test, integration green.
  • Optional: workflow_dispatch dev-deploy.yaml against this ref; verify docker ps --filter label=galaxy.stack=dev-deploy shows the six compose containers plus any engine containers spawned by the new backend.
  • After merge: confirm the next push-trigger deploy lands cleanly and engine containers on the dev host inherit the new galaxy.stack=dev-deploy label.
## Summary - **Drop `tools/local-ci/`** — the standalone Gitea + act_runner fallback. Primary CI runs on `gitea.lan`; no operational dependency on the directory remained. Docs (`CLAUDE.md`, `docs/ARCHITECTURE.md`, `ui/docs/testing.md`, the two `tools/*/README.md`) are updated in the same change. - **Lift the pre-production single-migration rule.** Future schema deltas land as additive `0000N_*.sql` files and goose applies them on backend startup, so the long-lived dev DB no longer needs a manual `make clean-data` on every breaking change. `00001_init.sql` becomes the immutable baseline; the chain may be squashed back into a fresh `00001` as a one-time pre-prod operation. - **Document the existing deployment cadence**, no functional change: dev is single-tenant, autodeploy on push to `development`, `workflow_dispatch` available as the PR-time preview path. - **Container labels.** Both compose files now stamp `galaxy.stack=<local-dev|dev-deploy>` on every service, network, and named volume. Makefiles filter cleanup by AND(`galaxy.stack`, `org.opencontainers.image.title=galaxy-game-engine`) so they touch only this stack's engine containers. `dev-deploy.yaml` gains a pre-`compose up` step that reaps stale exited/dead containers under the dev-deploy label. - **`BACKEND_STACK_LABEL`** — backend stamps `galaxy.stack=<value>` on every engine container it spawns when the env var is set. Compose files set it to their stack name. Contract documented in `docs/ARCHITECTURE.md` under "Container labels"; new package-level unit test exercises both label-set and label-absent paths. ## Test plan - [x] `go test -short ./backend/internal/{config,runtime,dockerclient}` — green locally. - [x] `docker compose config -q` for both compose files — no errors. - [x] `go build ./backend/... ./gateway/... ./game/...` — clean. - [ ] Gitea CI: `go-unit`, `ui-test`, `integration` green. - [ ] Optional: `workflow_dispatch dev-deploy.yaml` against this ref; verify `docker ps --filter label=galaxy.stack=dev-deploy` shows the six compose containers plus any engine containers spawned by the new backend. - [ ] After merge: confirm the next push-trigger deploy lands cleanly and engine containers on the dev host inherit the new `galaxy.stack=dev-deploy` label.
developer added 1 commit 2026-05-18 22:05:02 +00:00
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
a9087691a3
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>
developer added 1 commit 2026-05-18 23:00:23 +00:00
fix(compose): keep galaxy.stack label on containers only
Tests · Integration / integration (pull_request) Successful in 1m41s
Tests · Go / test (pull_request) Successful in 2m0s
daed2690c1
The previous commit stamped `galaxy.stack=<value>` on services,
volumes, and networks. Putting it on volumes/networks changes their
compose config-hash on every label revision, so `docker compose up`
tries to recreate them — which on the long-lived dev environment
either destroys the postgres data volume or deadlocks while trying
to remove `galaxy-dev-internal` with containers still bound to it.
Observed live: run #184 hung in compose recreate after the three
stateful services were stopped, with no recovery.

Containers alone are sufficient for the cleanup contract (we filter
containers, not volumes or networks). Roll back the label on volumes
and networks in both compose files and capture the rule in
docs/ARCHITECTURE.md so the next contributor does not reintroduce it.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
developer merged commit f91cf6eb41 into development 2026-05-18 23:10:21 +00:00
Sign in to join this conversation.