Skip to content

CI recipes and shards

cdowin edited this page Oct 4, 2026 · 1 revision

CI recipes and shards

The installed godot-toolchain action (.github/actions/godot-toolchain/action.yml) sets up the engine, gdlint, shellcheck and the import in CI. It runs uv run --frozen godot-devkit --version whenever uv.lock names the kit. CI runs make verify.

The runners share an OS-owned, nonblocking admission lease under the account home. Integration owns it across cache repair and worker fanout. Standalone engine boots also require admission. A competing gate exits promptly with its owner's PID and check. Read-only verbs remain available. The lock remains held while any admitted descendant runs, including after a parent dies. GDK_ENGINE_GATE_HOME explicitly selects an isolated admission domain for stub test fixtures. Production callers must share one domain across checkouts.

Import copying prunes registered nested worktrees and explicit Godot-ignored directories before descent. It preserves runtime addons, ordinary Git-cloned addons, and the exact manifest through rsync or the clone-aware fallback.

Sharding the integration tier (3.2.0)

  • integration.sh --all --shard <i>/<n> runs 1 slice of the roster, so a game's CI can fan the integration tier out over a matrix (#67). The env spelling is GDK_SHARD=<i>/<n>; make integration-all GDK_SHARD=<i>/<n> passes it on. The roster is sorted by name, and scenario k (from 1) goes to shard k mod n: the slices differ by at most 1 in size, are the same on every run, and together cover each scenario once. A shard past the end of a short roster has 0 scenarios and passes, with a 0 scenario(s) line. A malformed i/n, i < 1 or i > n exits 2 with a reason, and so does --shard with --diff, --system, --smoke, a name or --list. It composes with GDK_JOBS inside the shard and weighs the engine lease GDK_JOBS, like --all. The run says [INTEGRATION] shard 2/6: 27 scenario(s) of 160 and its SUMMARY ends ; shard 2/6 of 160. The receipt key includes the shard.

Engine lease and parallel lint (3.1.0)

  • The engine gate is a counted lease, not one mutex per user (#47). The host has GDK_ENGINE_GATE_SLOTS slots (default: cores / 2, at least 1). A run holds GDK_ENGINE_GATE_WEIGHT of them (default 1; all is every slot; a weight above the count is the count). integration.sh --all, --system and --diff weigh GDK_JOBS; --smoke and a named scenario weigh 1; unit, parse, warnings, spot and scenario weigh 1; an in-place import-cache rebuild weighs all. A bad count or weight exits 2. GDK_ENGINE_GATE_SLOTS=1 is the 3.0 behavior. Still fcntl.flock from python3, so no flock(1) is needed on macOS. Four concurrent 1 s runs on 8 cores: 4.2 s before, 1.6 s after.
  • lint.sh runs one gdlint per scan dir, in parallel (#50). GDK_LINT_JOBS sets how many at once (default: the core count); a value that is not a whole number above 0 exits 2. The transcript keeps scan-dir order. On a 485-script consumer tree with 8 scan dirs on 8 cores: 8.6 s before, 4.8 s after.

See also: Runners and install-runners, Troubleshooting.

Clone this wiki locally