1 Reference Modules
picklemustard edited this page 2026-09-07 15:49:27 -04:00

Registering a module

A module is a git repository containing a standard Godot engine module: an SCsub, a config.py, and sources. The builder clones it and copies it into the engine tree before SCons runs, so anything that compiles when dropped into godot/modules/ will compile here.

Modules live in the database, not in a file. There is no configs/modules.yaml to edit — registering a module is an API call, and privileged users can make it from the UI. See admin.md for the operator's side.

Add a module

curl -X POST https://gbb.example/api/v1/admin/modules \
  -H "Authorization: Bearer $GBB_ADMIN_TOKEN" \
  -d '{
        "name": "deep_engine_tool",
        "endpoint": "ssh://git@git.picklemustard.dev:2222/StudioTeal/deep-engine-tool.git",
        "path": "modules/deep_engine_tool",
        "description": "Core-level instrumentation hooks."
      }'
Field Required Meaning
name yes Module identifier and directory name. Must match ^[a-z][a-z0-9_]{0,63}$, the same rule Godot applies.
endpoint yes Any git URL the build host can clone.
path no Destination inside the engine tree. Defaults to modules/<name>. Must be relative and contain no ...
description no Shown in the UI's module picker.

A module on its own is not buildable. It becomes buildable when it has at least one version.

Add a version

curl -X POST https://gbb.example/api/v1/admin/modules/deep_engine_tool/versions \
  -H "Authorization: Bearer $GBB_ADMIN_TOKEN" \
  -d '{
        "version": "v0.3.1",
        "ref": "v0.3.1",
        "min_godot_major": 4,
        "min_godot_minor": 3,
        "requires": []
      }'
Field Required Meaning
version yes The label operators and users see, e.g. v0.3.1. Unique per module.
ref yes Tag, branch, or commit SHA to clone. Pin it.
min_godot_major / min_godot_minor yes The oldest Godot this release supports.
requires no Other module names that must also be selected.

requires belongs to the version, not the module: v0.3 may need deep_engine_tool and v0.4 may not, and an older Godot's frozen list must keep seeing the dependency set that shipped with it.

Pin to a commit, not a branch

ref may be a branch, but a branch moves, and two builds of "the same" version then produce different binaries. That breaks build deduplication and makes a bug report impossible to reproduce. Tag your releases and point the version at the tag.

How compatibility works

Compatibility is a property of a Godot version, not of a module. Each Godot major/minor has a stored list of the modules it offers and, for each, which version of that module. The picker shows that list; the build gates on it.

The list is generated once, when the Godot version is added, by this rule:

For Godot X.Y, a module is offered at its newest version whose min_godot_major.min_godot_minor is at or below X.Y. A module with no qualifying version is not offered.

That is the "use the current version for every Godot at or above the declared minimum" half. The other half is that the list then freezes:

  • Adding a new version of a module updates only the newest Godot major/minor.
  • Every older Godot version keeps the list it had. A module shipping a 4.5-targeting release does not change what 4.3 offers.

That is deliberate. Godot 4.3's list records what was true while 4.3 was current; only the newest Godot minor is still accumulating module updates, because it is the only one where a module can still ship an update before Godot does.

An operator can pin an exception by hand, and can force a regenerate when the automatic answer is wrong. Hand-pinned entries survive regeneration. See admin.md.

Forks and branches

A Godot version's major and minor are columns an operator sets, not something parsed out of the ref. So studioteal/4.4 — a branch name no version parser can read — is recorded as 4, 4 and shares 4.4's list.

Private repositories

The build host clones over the deploy key configured in modules.ssh_key_path, with modules.known_hosts_path supplying the host keys:

modules:
  ssh_key_path: "/etc/gbb/ssh/id_ed25519"
  known_hosts_path: "/etc/gbb/ssh/known_hosts"

Both come from a Kubernetes Secret mounted at mode 0400 — ssh refuses a group- or world-readable key, and the default 0644 fails. known_hosts is required whenever a key is set: without it every private clone fails with an opaque host-key error, or hangs waiting for a prompt that no worker can answer.

docs/deployment.md has the Secret.

Selecting modules in a build

Selection is per build, not global, and is drawn from the chosen Godot version's list:

gbb build --godot 4.4-stable --modules deep_engine_tool,telemetry_bridge@v0.2.0

name@ref overrides which commit is cloned for that one build, which is how you test an unreleased module branch without registering a version. It does not override membership: a module the selected Godot version does not offer cannot be smuggled in by naming a ref. Register a version with the right minimum instead.

Two failures are distinct because they need different fixes:

  • unknown module: nope — no such module is registered.
  • Godot 4.2 does not offer telemetry_bridge (needs 4.4 or newer) — the module exists, this engine does not offer it.

Both are reported before anything is cloned, and all offenders in one message.

To build an engine with only the selected modules and none of Godot's defaults, add --only-selected. This passes modules_enabled_by_default=no. It produces a much smaller binary but disables a great deal of engine functionality; expect to re-enable some defaults explicitly.