Hello, Realm: why BallOrcs builds everything from source
BallOrcs is a colourful 3D platformer about round little creatures. Day one went on building the factory that will make the game.
In plain words
BallOrcs is a colourful 3D platformer about round little creatures — think "build your own bouncy ball with eyes, a hat, and superpowers." Before writing any of the fun stuff, we spent day one building the factory that will make the game: our own copy of the game engine, our own build machines, and a rulebook that guarantees the game we ship is exactly the game we tested. It's like pouring the foundations before decorating the house.
Under the hood
The repo opened with a deterministic build pipeline, not gameplay. Choices worth defending:
- Godot built from pinned source, not downloaded binaries. A single
versions.lockis the source of truth for every dependency — engine commit, bindings, SDKs, container images — andcheck_pinsfails closed when a build touches an unpinned value. - One entry point:
build/build.sh <platform>dispatches to per-platform scripts sharing a common library. C++ gameplay lives in a GDExtension, so the engine stays unmodified upstream code. - Self-hosted GitLab CE + CI (localhost, memory-tuned for a 10 GB WSL box) rather than cloud CI: the whole studio runs on one Windows machine with WSL, and nothing about the pipeline should assume internet-hosted services exist.
- Day-one hygiene that paid off immediately:
.gitattributesforces LF repo-wide (the system gitconfig hasautocrlf=true, and CRLF scripts break inside Linux build containers and change artifact hashes), and shellcheck runs in CI with a clean exit — several findings were real bugs, like a top-level[[ cond ]] && warnthat aborted whole builds underset -ewhenever the condition was false.
Pinning surprises from the very first day: upstream publishes build-container
Dockerfiles but no images (the ghcr packages don't exist), so we pin their
repo commit and build/push images to our own registry; and godot-cpp has no
godot-4.7-stable tag because since v10 it versions independently of the
engine — more on the fallout from that in the next post.