# CI Requirements — Minstrel > Copy of [the template](https://git.fabledsword.com/bvandeusen/CI-runner/src/branch/main/docs/requirements-sheet.template.md). > Family-wide policy: `ci-runners.md` in the FabledRulebook. ## Runtime images Minstrel's four workflows consume two CI images: ``` git.fabledsword.com/bvandeusen/ci-go:1.26 git.fabledsword.com/bvandeusen/ci-flutter:3.44 ``` - `ci-go:1.26` — Go server tests (`.gitea/workflows/test-go.yml`), web SPA tests (`.gitea/workflows/test-web.yml`), and the release container build (`.gitea/workflows/release.yml`). - `ci-flutter:3.44` — Flutter client tests + debug/release APK builds (`.gitea/workflows/flutter.yml`). ## Image deps used ### From `ci-go:1.26` - **Go** (1.26 toolchain) — `go vet`, `go test -race`, `go build`, `go mod`. - **Node + npm** — `npm ci` and `npm test` / `npm run check` in `test-web.yml`. - **golangci-lint** — lint pass in `test-go.yml`. - **docker CLI** — bridge-IP discovery of the per-job Postgres service container in `test-go.yml` integration job (via the runner's shared `/var/run/docker.sock`). - **docker buildx** — release container build + push in `release.yml`. - **curl** — release-asset polling / upload in `release.yml`. ### From `ci-flutter:3.44` - **Flutter** (3.44 stable channel) — `flutter pub get`, `flutter analyze --fatal-infos`, `flutter test`, `flutter build apk` (debug + signed release). - **Dart** — `dart run tool/gen_tokens.dart`, `dart run build_runner build` (drift codegen). - **Android SDK + NDK + cmdline-tools + build-tools** — APK assembly + signing. - **Java 25** — Gradle / Android build. - **git** — `actions/checkout@v4` baseline (and any shell git operations). - **base64 + curl** — keystore decode + release-asset upload in the tag-build path. ## Per-job tool installs None. ## Notes - **Label/image split.** Workflows keep `runs-on: go-ci` / `runs-on: flutter-ci` as the scheduling label per the [`ci-runners.md`](https://…/FabledRulebook/ci-runners.md) "label = scheduling handle, image = `container.image`" pattern. The labels are intentional handles, not toolchain assertions. - **Integration-job docker-socket dependency.** `test-go.yml`'s integration job uses the runner's shared docker socket (`/var/run/docker.sock`) to bridge-IP-discover the per-job Postgres service container by name + network intersection — the dev compose's `minstrel-postgres-*` containers are explicitly skipped as belt-and-suspenders. Depends on `act_runner.valid_volumes` whitelisting the socket; if that ever stops auto-mounting, integration tests fail at the `docker inspect` step. - **Go toolchain pin.** `go.mod` is on `go 1.25.0` because `golang.org/x/crypto v0.51.0` declares 1.25 as its minimum. `ci-go:1.26` satisfies this with headroom. Future `x/crypto` bumps that move the Go floor should be paired with an image-tag bump in this file + the workflows. - **In-app update channel polling.** `release.yml` polls Gitea's release-asset API for up to 15 min on tag pushes to fetch the APK that `flutter.yml` is concurrently attaching to the same release. The asset eventually appears because `flutter.yml` and `release.yml` run in parallel on the same tag; if the polling times out, the server image ships without the bundled update channel (graceful degradation, not a build failure). - **Cache server reachability.** `test-web.yml` does NOT use `cache: 'npm'` on `actions/setup-node` — the Gitea Actions cache server isn't reachable from this runner's container network and `setup-node` was burning ~4m41s on ETIMEDOUT before failing open. With the migration to `ci-go:1.26`, `setup-node` is removed entirely (Node is in the image). The cache concern reappears if a future change re-introduces a network-dependent action. - **Friction asks.** None pending. The two images cover everything Minstrel needs.