mode=max was re-uploading the bun install cache mount (~40–60s per
build, ~90s combined for api-core + web) to the Gitea OCI registry
on every push, even when source hadn't changed. That single export
accounts for most of the delta between 1-minute and 3-minute deploys.
mode=min only exports the final stage's layers. The trade-off is a
few-second tax on cold buildkitd starts (the installer stage no
longer warms from registry cache), but the per-push savings dwarf it.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Three reliability+speed changes to the reusable build-deploy-game workflow:
- Pin actions/checkout, docker/setup-buildx-action, docker/build-push-action
to immutable patch tags (v4.2.2, v3.10.0, v6.16.0). Moving major-version
tags (`@v3`/`@v6`) gave the act-runner non-deterministic cache hashes; the
remplir 1541 failure was act re-using a partial cache dir for `@v3` of
docker/login-action with only `.gitignore` present and no `dist/index.js`.
- Replace docker/login-action with an inline `docker login --password-stdin`
shell step in both build jobs. One less remote-action download per job =
one less surface for the act partial-cache failure mode that broke 1541.
- Decouple build-web from deploy-api-core. Web build only needs the git
checkout, not a running api-core (vite build is offline). deploy-web now
gates on [build-web, deploy-api-core] so the runtime ordering is still
api-core-before-web while the two image builds can run in parallel if the
runner has any concurrency.
Also: drop the shared played/bun-cache references (was causing thrashing
between games writing to the same `:latest` tag) and flip per-game cache
to mode=max so the expensive bun-install + turbo-build layers are
actually reused on subsequent runs.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Drives the standard four-stage build-api-core → deploy-api-core → build-web
→ deploy-web pipeline for a played game. Game repos invoke via:
jobs:
deploy:
uses: played/workflows/.gitea/workflows/build-deploy-game.yml@main
with:
game-id: <slug>
secrets: inherit
The caller's BUILD_ENV / NPMRC / REGISTRY_* / PLAYED_* /
STEP_CA_PROVISIONER_PASSWORD are inherited; `game-id` parameterizes the
VM paths (~/<id>, ~/<id>-secrets) and the docker tag context.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>