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>
176 lines
6.9 KiB
Markdown
176 lines
6.9 KiB
Markdown
# UI Testing Tiers
|
|
|
|
UI client test toolchain. Project-wide testing layers (service /
|
|
inter-service / system) live in [`../../docs/TESTING.md`](../../docs/TESTING.md);
|
|
this doc only covers the UI-specific tiers added in Phase 2 of
|
|
[`../PLAN.md`](../PLAN.md).
|
|
|
|
## Tier 1 — per-PR
|
|
|
|
Triggered by `.gitea/workflows/ui-test.yaml` on every push and pull
|
|
request that touches `ui/**`, `backend/**`, `gateway/**`, `game/**`,
|
|
`pkg/**`, `go.work`, or `go.work.sum`. Linux runner only.
|
|
|
|
The `actions/checkout@v4` step uses `submodules: recursive`, so the
|
|
runner pulls every git submodule the suite depends on (today only
|
|
`pkg/geoip/test-data`, the MaxMind-DB fixtures used by `pkg/geoip`).
|
|
|
|
Runs:
|
|
|
|
- `go test` over the monorepo Go modules, excluding two areas:
|
|
- `integration/` — needs Docker + testcontainers and is the
|
|
project's `make -C integration integration` gate.
|
|
- `client/` — the deprecated Fyne client (see `../PLAN.md` §74) is
|
|
frozen; its tests are not run in CI.
|
|
|
|
The `pkg/<name>/` modules are listed one by one in the workflow
|
|
because they are independent go.work modules and `./pkg/...` does
|
|
not recurse into separate modules. The exact command lives in
|
|
`.gitea/workflows/ui-test.yaml`.
|
|
- `pnpm test` (Vitest + `@testing-library/svelte` +
|
|
`@testing-library/jest-dom`) — component / unit tests under
|
|
`ui/frontend/tests/**/*.test.ts`.
|
|
- `pnpm exec playwright test` — end-to-end smoke against `pnpm run
|
|
dev` on port 5173. Four projects:
|
|
- `chromium-desktop` (Desktop Chrome)
|
|
- `webkit-desktop` (Desktop Safari)
|
|
- `chromium-mobile-iphone-13` (iPhone 13 viewport, Chromium engine)
|
|
- `chromium-mobile-pixel-5` (Pixel 5 viewport, Chromium engine)
|
|
|
|
Playwright traces and screenshots are retained on failure and uploaded
|
|
as Gitea Actions artefacts (`playwright-report` and `playwright-traces`,
|
|
14-day retention).
|
|
|
|
## Tier 2 — release
|
|
|
|
Triggered by `.gitea/workflows/ui-release.yaml` on tag push (`v*`).
|
|
Currently mirrors the Tier 1 step set; the dedicated release-only
|
|
checks land in later phases:
|
|
|
|
- **Visual regression baseline check** — Phase 33. Snapshots live in
|
|
`ui/frontend/tests/__snapshots__/` until the project shifts to
|
|
Argos or another visual-diff service.
|
|
- **iOS smoke (Capacitor + Appium)** — Phase 32. Runs on a `macos-13`
|
|
runner once the Capacitor mobile wrapper exists.
|
|
|
|
Both blocks are present as commented sections in
|
|
`.gitea/workflows/ui-release.yaml` with the phase number that
|
|
re-enables them.
|
|
|
|
## Local execution
|
|
|
|
From `ui/frontend/`:
|
|
|
|
```sh
|
|
pnpm test # Vitest
|
|
pnpm exec playwright install # one-time
|
|
pnpm exec playwright test # all projects
|
|
pnpm exec playwright test --project=chromium-desktop
|
|
pnpm exec playwright show-report # open last HTML report
|
|
```
|
|
|
|
From the repository root, the same scope CI uses (backend serially
|
|
because most packages spawn their own Postgres testcontainer and
|
|
parallel bootstraps starve each other on constrained runners):
|
|
|
|
```sh
|
|
go test -count=1 -p 1 ./backend/...
|
|
go test -count=1 \
|
|
./gateway/... ./game/... \
|
|
./pkg/calc/... ./pkg/connector/... ./pkg/cronutil/... \
|
|
./pkg/error/... ./pkg/geoip/... ./pkg/model/... \
|
|
./pkg/postgres/... ./pkg/redisconn/... ./pkg/schema/... \
|
|
./pkg/storage/... ./pkg/transcoder/... ./pkg/util/...
|
|
```
|
|
|
|
## Local development stack
|
|
|
|
For UI work that needs a real authenticated stack (verifying the
|
|
FlatBuffers wire end-to-end, exercising a real lobby flow, hitting
|
|
real Mailpit), bring up `tools/local-dev/`:
|
|
|
|
```sh
|
|
make -C tools/local-dev up # postgres + redis + mailpit + backend + gateway
|
|
pnpm -C ui/frontend dev # Vite on the host, talks to the stack
|
|
```
|
|
|
|
`ui/frontend/.env.development` already targets the stack
|
|
(`http://localhost:8080`) and pins the matching response-signing
|
|
public key from `tools/local-dev/keys/`. Per-developer overrides go
|
|
into `.env.development.local` (gitignored).
|
|
|
|
The stack honours `BACKEND_AUTH_DEV_FIXED_CODE` (default `123456` in
|
|
`tools/local-dev/.env`) so the login form takes that literal in
|
|
addition to the real Mailpit code; see
|
|
[`../../tools/local-dev/README.md`](../../tools/local-dev/README.md)
|
|
for the full runbook (regenerating the dev keypair, switching the
|
|
mode off, troubleshooting common boot issues).
|
|
|
|
|
|
## Synthetic reports for visual testing (DEV)
|
|
|
|
For visual checks of the map, inspectors and order-overlay against
|
|
rich game states, the lobby exposes a DEV-only "Load synthetic
|
|
report" affordance (`import.meta.env.DEV`). The flow is:
|
|
|
|
1. Convert a legacy text report (`tools/local-dev/reports/{dg,gplus}/`)
|
|
to JSON with the Go CLI:
|
|
|
|
```sh
|
|
go run ./tools/local-dev/legacy-report/cmd/legacy-report-to-json \
|
|
--in tools/local-dev/reports/dg/KNNTS039.REP \
|
|
--out /tmp/dg39.json
|
|
```
|
|
|
|
See [`../../tools/local-dev/legacy-report/README.md`](../../tools/local-dev/legacy-report/README.md)
|
|
for what the parser populates today and how to extend it when a
|
|
new UI phase decodes a new `Report` field.
|
|
|
|
2. Run the UI dev server (`pnpm -C ui/frontend dev`), open the lobby,
|
|
and use the "Load JSON…" file picker in the **Synthetic test
|
|
reports (DEV)** section. The page navigates to
|
|
`/games/synthetic-<uuid>/map` with the report wired into the
|
|
in-game shell.
|
|
|
|
In synthetic mode:
|
|
|
|
- The map view, inspectors and races view render against the loaded
|
|
report exactly as they would for a real game.
|
|
- Composing orders works locally (overlay applies through
|
|
`applyOrderOverlay` as usual), but **nothing is sent to the
|
|
gateway** — `OrderDraftStore.scheduleSync` short-circuits because
|
|
the synthetic id is not a UUID and the layout deliberately does
|
|
not bind a `GalaxyClient` for this game.
|
|
- The order draft is persisted into the platform `Cache` under the
|
|
same `order-drafts` namespace as real games, keyed by the
|
|
synthetic id, so navigating back into the same synthetic session
|
|
restores the draft. The cache is cleared with
|
|
`__galaxyDebug.clearOrderDraft(gameId)` (DEV debug surface).
|
|
- A page reload loses the in-memory report registry; opening the
|
|
same synthetic id afterwards redirects to /lobby. Re-load the JSON
|
|
to reseed.
|
|
|
|
The synthetic-report parity rule (see [`../PLAN.md`](../PLAN.md) §
|
|
Assumptions and Defaults) requires every UI phase that extends
|
|
`decodeReport` to also extend the legacy parser in lockstep, or to
|
|
record in the parser's `README.md` that the new field cannot be
|
|
derived from legacy text. This keeps the synthetic-mode coverage in
|
|
step with the contract as the UI grows.
|
|
|
|
## CI verification
|
|
|
|
Workflow changes are exercised on the primary CI host (`gitea.lan`).
|
|
Push the branch (`git push gitea …`), then open the run in the Gitea
|
|
UI to inspect the status and logs. See `CLAUDE.md` (`## Per-stage CI
|
|
gate`) for the per-stage workflow.
|
|
|
|
For a sub-second syntax check of a workflow YAML without pulling
|
|
images or running anything:
|
|
|
|
```sh
|
|
act -W .gitea/workflows/ui-test.yaml -n push
|
|
```
|
|
|
|
`act` doesn't honour Gitea-specific behaviours (artifact storage,
|
|
secrets, run triggers); use it only for syntax checks.
|