# Handoff spec: custom godot-ci image Status: **done, and superseded** — the `godot-ci` repo this spec asked for exists and is built. Its versioning has since moved past what's written below: instead of one Dockerfile pinned to `4.7.1`, it now auto-tracks the newest stable Godot (4.0+) and newest stable Blender on a nightly schedule, with a manual `workflow_dispatch` to (re)build any specific version. See that repo's `README.md` for the current behavior; this file is kept for the original problem statement and scope rationale, not as a source of truth on tags/versions. Decided via wayfinder map [#158](https://git.arthurerlich.de/haylan/Project4x/issues/158), ticket [#162](https://git.arthurerlich.de/haylan/Project4x/issues/162). ## Problem `export-template.yml`'s `export` job runs in `barichello/godot-ci:4.7.1` and, on every single run, `apt-get install`s a from-source Godot export-template toolchain before it can build anything. That install is pure dead time repeated on every release. A custom image extending `barichello/godot-ci:4.7.1` with the toolchain pre-installed removes it. ## What this spec is for A fresh Gitea agent session, given only this file, must be able to: 1. Create a new repo. 2. Add a `Dockerfile` and a publish workflow to it. 3. Get the image published to that repo's Gitea package (container) registry. 4. Report back the final image reference so `export-template.yml` here can be pointed at it. No other context from this repo should be required. ## Scope: what goes in the image Everything `export-template.yml`'s "Update and install dependencies" step currently `apt-get install`s, unconditionally (all of it — see [Decisions](#decisions) below for why the narrower alternative was rejected): ``` libfontconfig1 build-essential scons pkg-config xz-utils curl # Linux leg: libx11-dev libxcursor-dev libxinerama-dev libgl1-mesa-dev \ libasound2-dev libpulse-dev libudev-dev libxi-dev libxrandr-dev libwayland-dev # Windows leg: mingw-w64 # + these two update-alternatives calls, baked in at image build time: update-alternatives --set x86_64-w64-mingw32-gcc /usr/bin/x86_64-w64-mingw32-gcc-posix update-alternatives --set x86_64-w64-mingw32-g++ /usr/bin/x86_64-w64-mingw32-g++-posix # conditionally, when ENABLE_BLENDER is on: blender ``` Current source of truth for this list: `.gitea/workflows/export-template.yml` in `haylan/Project4x`, "Update and install dependencies" step. **Re-check that step before building** — it may have drifted since this spec was written. ### What stays out of the image - **The SCons object cache** (`.scons_cache`, restored via `actions/cache@v3` keyed on `scons-${GODOT_VERSION}-${artifact_name}`). This is build _state_, not a package — baking it into the image would pin it to image-build time instead of the actual release run, going stale immediately. - **`nsis` / `osslsigncode`.** These do NOT belong in this image. They run in `release.yml`'s `create-release` job, which is a plain `ubuntu-latest` runner — it does not use `barichello/godot-ci` or any container at all. (Earlier drafts of this ticket assumed they were part of the export container's toolchain; that was wrong. The NSIS installer has since been removed entirely — see ADR 0001's superseded note — so only `osslsigncode`/`zip` remain in `create-release`, and neither is expensive enough to justify its own image.) ## Registry path and versioning - **Registry:** this Gitea instance's container/package registry (`git.arthurerlich.de`), scoped to the new repo you create — Gitea packages are per-repo/owner, so the path is `git.arthurerlich.de/haylan/`. - **Tag:** pin to the Godot version only, e.g. `git.arthurerlich.de/haylan/:4.7.1`. This mirrors `barichello/godot-ci`'s own tag scheme and `Project4x`'s `GODOT_VERSION` env var. A Godot version bump in `Project4x` means building and pushing a new tag here too — that coupling is intentional, not an oversight. - Pick `` yourself (e.g. `godot-ci-toolchain` or similar); it isn't fixed by this spec. ## Auth: PAT required Confirmed for this Gitea instance: `GITEA_TOKEN` (the automatic per-run Actions token) **cannot** push to the package/container registry. The new repo's publish workflow needs a **Personal Access Token** stored as a repo secret (e.g. `REGISTRY_PUSH_PAT`). - **Scope needed:** `write:package` (add `read:package` too if the publish workflow ever needs to pull the image back, e.g. to test it before tagging `latest`). - Generate it from the account that should own the published packages, under Settings → Applications → Generate New Token, with only that scope checked. - Document the token's owner/scope in the new repo's README once created — this repo (`Project4x`) has no record of it and shouldn't need one; the coupling is one-way (`Project4x` only ever pulls the finished image, never pushes to it). ## Dockerfile skeleton ```dockerfile FROM barichello/godot-ci:4.7.1 RUN apt-get update && apt-get install -y --no-install-recommends \ libfontconfig1 \ build-essential scons pkg-config xz-utils curl \ libx11-dev libxcursor-dev libxinerama-dev libgl1-mesa-dev \ libasound2-dev libpulse-dev libudev-dev libxi-dev libxrandr-dev libwayland-dev \ mingw-w64 \ blender \ && update-alternatives --set x86_64-w64-mingw32-gcc /usr/bin/x86_64-w64-mingw32-gcc-posix \ && update-alternatives --set x86_64-w64-mingw32-g++ /usr/bin/x86_64-w64-mingw32-g++-posix \ && rm -rf /var/lib/apt/lists/* ``` Notes for whoever builds this: - `blender` is baked in unconditionally here even though `Project4x`'s `ENABLE_BLENDER` flag is currently `"false"` — the image can't cheaply branch on a flag it doesn't know about at build time, and the package is small next to the rest of this list. If that turns out to add meaningful image size/pull time for a project that never flips the flag on, split into a second `-blender` tagged variant instead. - Combine into one `RUN` (as above) so it's a single image layer — no benefit to splitting these across layers here. ## Publish workflow skeleton New repo, `.gitea/workflows/publish.yml`: ```yaml name: Publish godot-ci image on: push: branches: [main] paths: [Dockerfile] workflow_dispatch: jobs: publish: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Log in to Gitea registry run: echo "${{ secrets.REGISTRY_PUSH_PAT }}" | docker login git.arthurerlich.de -u --password-stdin - name: Build and push run: | docker build -t git.arthurerlich.de/haylan/:4.7.1 . docker push git.arthurerlich.de/haylan/:4.7.1 ``` Fill in `` and `` once the repo exists. ## How `Project4x` would then reference the new image One-line change in `.gitea/workflows/export-template.yml`: ```diff - container: barichello/godot-ci:4.7.1 + container: git.arthurerlich.de/haylan/:4.7.1 ``` The "Update and install dependencies" step's `apt-get install` calls for the baked-in packages become redundant at that point (harmless no-ops — `apt-get install` on an already-installed package is a fast no-op, so removing them is a cleanup, not a correctness requirement) and can be trimmed in a follow-up ticket once the image is live and proven. ## Decisions - **Bake-in scope:** everything in the current apt-get list, not a narrower "slow packages only" subset — keeps the image and `export-template.yml`'s toolchain description in exact sync, so there's only one place (this spec + the Dockerfile) to update when the list changes, instead of maintaining a second smaller list that drifts from the first. - **Tag scheme:** pinned to `GODOT_VERSION` rather than tracking image/toolchain revisions independently — simpler to reason about, and this repo's own SCons cache is already keyed the same way, so a Godot bump already forces everything else to rebuild in lockstep.