Skip to content

Migrating from 3.x to 4.0

Chris Dowin edited this page Oct 18, 2026 · 1 revision

Migrating from 3.x to 4.0

4.0 uses Godot's import and compile behavior and direct GUT tests. The Python scene CLI remains an engine-free text parser and editor. Installed shell runners boot Godot with a sandboxed user://. The tested runner baseline is Godot 4.7.2 with GUT 9.6.1; older combinations are unverified.

Pin and reinstall

  1. Pin godot-devkit==4.0.0 in pyproject.toml and update uv.lock from the explicit devkit index. If using GODOT_DEVKIT_VERSION, change it to v4.0.0 instead; keep one pin.
  2. Preview uv run godot-devkit install-gates --diff, install-runners --diff and install-skills --runtime codex --diff (or claude). The installed files are project-owned. --force replaces a whole file, including edited runner headers; carry local settings forward before using it.
  3. Reinstall the godot-101, godot-native-first and godot-ui skills. Route Godot design work to them. Prefer class_name types, scene-owned nodes, typed signals, Resource catalogs and static helpers. Autoloads need a concrete app-wide lifecycle requirement.
  4. Run make help, then the adopted make check, make parse, make unit, make integration and make verify tiers. The former make milestone alias and GDK_MILESTONE_TIERS/GDK_MILESTONE_SKIP knobs are removed.

Port tests to GUT

Put test_*.gd unit tests under tests/unit/ and integration tests under tests/integration/. The installer writes .gutconfig.json and .gutconfig.integration.json, plus integration_test_template.gd and measure_test_template.gd. These are examples; copy and adapt the templates to a real test_*.gd file to make GUT discover them. The measure example must load a valid target scene, sample Performance monitors and assert project budgets; a blank scene would prove nothing.

make unit uses GDK_GUT_CONFIG (default res://.gutconfig.json). make integration uses GDK_GUT_INTEGRATION_CONFIG (default res://.gutconfig.integration.json). ARGS passes GUT options in single-process mode, for example make integration ARGS="-gtest=res://tests/integration/test_boot.gd". GDK_GUT_CONFIG= disables the unit config file when calling the unit runner directly. The runner requests JUnit XML at GDK_GATE_REPORT_DIR/{unit,integration}.xml and checks actual JUnit results against discovered tests. Do not pass a competing JUnit path or GUT config option through ARGS.

For isolation, set GDK_INTEGRATION_PER_FILE=1; this runs each integration test file in its own sandboxed engine process, with GDK_JOBS concurrent files (default 2). ARGS applies only to single-process integration. The 3.x custom scenario base and result protocol, scenario, smoke, integration-all, integration-diff, integration-list, SYS, warm workers and shards are removed. GDK_SHARD now errors. Port scenario assertions into GUT tests using its waiting, input and orphan checks where needed. make capture NAME=eyes runs headed GUT for tests/capture/test_eyes.gd and expects res://.capture-reports/eyes.png (the test and report directories are configurable).

Reconfigure checks and CI

check all now defaults to warnings, props, defaults, rng, tres-comment and unit-disk. uid, tres, canonical, patterns and test-shape are opt-in. Move the removed [checks] godot alias to [roster] checks; the old key is refused. The editor owns UID generation. make parse fails on invalid UID output and runs a sandboxed import, retained compile sweep and main-scene boot. A Godot 4.7.2 probe showed that import alone missed an unloaded script syntax error, which is why the sweep remains.

check warnings requires every name in [warnings] errors to have gdscript/warnings/<name>=2 under [debug] in project.godot. An empty list is refused, and gdscript/warnings/enable=false fails. Omit warnings from [roster] checks to opt out. The 3.x warnings shell runner is retired.

test-shape now uses [test_shape] integration_root, unit_root, cap and ledger for tracked integration scripts. The old scenario_root, runner, header, header_ledger and infra keys are refused. It does not depend on GUT headers or a runner roster. Rename make import-cache to make import in CI. Replace scenario shards with whole-suite GUT or per-file mode, and inspect .gate-reports/ logs and JUnit results.

See Installing and pinning, Configuration reference, Runners and install-runners and CI recipes and shards.

Clone this wiki locally