Files
galaxy-game/tools/local-ci
Ilia Denisov 7450006ed3 phase 2: ui testing infrastructure
Vitest + @testing-library/jest-dom matchers wired through tests/setup.ts.
Playwright with four projects: chromium-desktop, webkit-desktop,
chromium-mobile-iphone-13, chromium-mobile-pixel-5; traces and
screenshots retained on failure.

.gitea/workflows/ui-test.yaml runs Tier 1 on every push and pull
request: monorepo Go service tests (backend with -p 1 to dodge
testcontainer contention; gateway, game, every pkg/<name> module),
pnpm install --frozen-lockfile, playwright install --with-deps,
pnpm test, pnpm exec playwright test. Uploads playwright-report
and test-results on failure. Integration suite stays gated behind
make -C integration integration; deprecated client/ excluded.

.gitea/workflows/ui-release.yaml mirrors Tier 1 on v* tag push and
keeps commented placeholders for visual regression (Phase 33) and
macOS iOS smoke (Phase 32).

ui/docs/testing.md documents both tiers and the local invocations
that mirror what CI runs. ui/PLAN.md Phase 2 marked done; Phase 3
gains a bullet to extend the go test command with ./ui/core/...;
Phase 36 has the renamed release workflow path.

tools/local-ci/ ships a self-contained docker-compose for verifying
workflows against a local Gitea + arm64 act_runner before pushing
to a real instance.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-07 08:24:44 +02:00
..
2026-05-07 08:24:44 +02:00
2026-05-07 08:24:44 +02:00
2026-05-07 08:24:44 +02:00
2026-05-07 08:24:44 +02:00

Local Gitea CI

Self-contained Gitea + Actions runner for verifying .gitea/workflows/* honestly before pushing to a real Gitea instance. Runs natively on arm64 (Apple Silicon) — every image below has an arm64 variant, so Docker pulls the right architecture and the runner executes workflow steps without QEMU emulation.

Prerequisites

  • Docker (Colima or Docker Desktop)
  • python3, curl, bash — all built into macOS

First time

make -C tools/local-ci up

This:

  1. brings up the Gitea container;
  2. creates an admin user (galaxy / galaxy-dev);
  3. creates the galaxy/galaxy repo;
  4. fetches a runner registration token from the Gitea API;
  5. brings up the runner with that token (the runner persists its credentials in a Docker volume and ignores the token on subsequent restarts).

The script is idempotent — re-running it is safe.

Pushing a branch

make -C tools/local-ci push

This adds a local-gitea remote on the first run and then pushes the current HEAD. Equivalent manual flow:

git remote add local-gitea \
    http://galaxy:galaxy-dev@localhost:3000/galaxy/galaxy.git
git push local-gitea HEAD

The Tier 1 workflow fires on push to any branch and the Tier 2 workflow fires on tags matching v*. Watch runs at:

http://localhost:3000/galaxy/galaxy/actions

Operational targets

Target What it does
make up Bring up Gitea + runner (idempotent)
make down Stop both containers (state preserved)
make logs Tail logs from both containers
make status Show container status
make push Push current HEAD to local Gitea
make clean Stop and wipe all local state (full reset)

What's in the box

Component Image Role
Gitea gitea/gitea:1.23 Server with SQLite backend
act_runner gitea/act_runner:0.6.1 Single-capacity runner registered on boot
Workflow catthehacker/ubuntu:act-latest Image spawned per job (multi-arch)

The runner mounts the host Docker socket and spawns workflow containers on the same Docker network as Gitea, so actions/checkout reaches the server at http://gitea:3000 from inside spawned containers.

Caveats

  • Gitea's ROOT_URL is set to http://gitea:3000/ so spawned workflow containers reach the server through the compose network. The web UI works at http://localhost:3000 via port mapping, but copy-paste URLs in the UI may show gitea:3000 instead of localhost:3000. Harmless for local dev; switch the host part by hand when copying.
  • The runner is single-capacity (runner.capacity: 1 in config.yaml). Concurrent jobs queue. Bump if you need parallel jobs.
  • First push from a fresh checkout uploads the full repo history (~tens of MB). Subsequent pushes are deltas.
  • actions/upload-artifact@v4 requires Gitea ≥ 1.21 — we pin 1.23 to stay above the cutoff.
  • Workflow steps run as root inside the spawned container; this matches the upstream catthehacker behaviour. Keep that in mind if you add steps that touch host-mounted directories.
  • On Apple Silicon the runner image and its catthehacker child run natively as arm64. Some pre-built tools that ship in the image are amd64-only and would fall back to QEMU; setup-go, setup-node, and pnpm/action-setup all download arm64 binaries themselves, so the workflow steps we care about stay native.