fmt: atlas_data_proxy.rs test code. godot-cold-parse: the cold parse re-seeds the class cache WITHOUT addon classes (gdUnit4's GdUnitTestCIRunner missing), leaving tests/run-godot unable to start (0 tests / 355ms — caught by the pre-push gate running the suite right after this script). The script now restores a full cache via a final --import pass before exiting; the cold verdict is unaffected. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
97 lines
4.2 KiB
Bash
Executable File
97 lines
4.2 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# tooling/godot-cold-parse [--run-menu] — cold-cache headless parse check.
|
|
#
|
|
# Used by /pr-process step 1c before push. Deletes the cached script-class
|
|
# registry so the parse simulates the cold-start ordering CI / fresh clones
|
|
# see: Sprint 36 close caught a new `class_name MetaScreen` base class and
|
|
# six extending scripts that parsed fine on warm developer caches but hit
|
|
# `Could not find base class "MetaScreen"` post-merge, because the
|
|
# autoload-vs-class_name registration order only resolves correctly once the
|
|
# class cache is seeded (see CLAUDE.md -> GDScript conventions -> Autoload
|
|
# parse-order rule).
|
|
#
|
|
# Godot's resource scanner emits category errors (e.g. "Export type can only
|
|
# be built-in, a resource, a node, or an enum") that do NOT always prefix
|
|
# with SCRIPT ERROR — they appear as plain ERROR lines. The filter below
|
|
# catches both, then drops known pre-existing noise from the autoload
|
|
# class_name parse-order trap. Sprint 36 shipped a scanner error the old
|
|
# narrower grep missed; this is why the filter stays wide.
|
|
#
|
|
# --run-menu: also launch main_menu.tscn briefly (for branches with UI changes).
|
|
#
|
|
# Exit 0 + "clean" if no matches. Exit 1 + the matched lines if any are found.
|
|
set -euo pipefail
|
|
|
|
REPO_ROOT="$(git rev-parse --show-toplevel)"
|
|
RUN_MENU=false
|
|
[ "${1:-}" = "--run-menu" ] && RUN_MENU=true
|
|
|
|
rm -f "$REPO_ROOT/client/.godot/global_script_class_cache.cfg"
|
|
|
|
# A truly cold checkout (fresh clone or worktree — .godot/ is gitignored) has
|
|
# no resource-import cache, and every imported asset (fonts, ogg) then "fails
|
|
# loading" during the parse run: a wall of false positives. Seed the cache
|
|
# with an import pass first; source assets are tracked, so this is always
|
|
# reconstructible. (Found live: first run in a fresh worktree, 2026-07-13.)
|
|
if [ ! -d "$REPO_ROOT/client/.godot/imported" ] || [ -z "$(ls -A "$REPO_ROOT/client/.godot/imported" 2>/dev/null)" ]; then
|
|
echo "godot-cold-parse: no import cache — running one-time import pass..." >&2
|
|
set +e
|
|
IMPORT_OUT=$(godot --headless --path "$REPO_ROOT/client" --import 2>&1)
|
|
IMPORT_EXIT=$?
|
|
set -e
|
|
if [ "$IMPORT_EXIT" -ne 0 ]; then
|
|
echo "godot-cold-parse: import pass exited $IMPORT_EXIT" >&2
|
|
printf '%s\n' "$IMPORT_OUT" | tail -20 >&2
|
|
exit "$IMPORT_EXIT"
|
|
fi
|
|
fi
|
|
|
|
FILTER='^(SCRIPT )?ERROR|Parse Error|Export type'
|
|
|
|
# Capture the godot run separately from the filter pipeline: with the
|
|
# trailing `|| true` on the greps, a nonzero exit from godot itself (crash,
|
|
# missing binary, corrupted install) would otherwise report "clean". Nothing
|
|
# downstream re-reads the raw output now that this is scripted, so fail loud.
|
|
set +e
|
|
RAW=$(godot --headless --path "$REPO_ROOT/client" --quit 2>&1)
|
|
GODOT_EXIT=$?
|
|
set -e
|
|
if [ "$GODOT_EXIT" -ne 0 ]; then
|
|
echo "godot-cold-parse: godot itself exited $GODOT_EXIT — not a parse verdict" >&2
|
|
printf '%s\n' "$RAW" | tail -20 >&2
|
|
exit "$GODOT_EXIT"
|
|
fi
|
|
|
|
MATCHES=$(printf '%s\n' "$RAW" \
|
|
| grep -iE "$FILTER" \
|
|
| grep -v "Failed loading resource: res://assets" \
|
|
| grep -v "Cannot infer the type" \
|
|
| grep -vE '(Messagepack|LocalBridge|ServerProcess|Constants)" not declared' || true)
|
|
|
|
if [ "$RUN_MENU" = true ]; then
|
|
# Deliberately no exit-code check here: `timeout` kills the menu after
|
|
# 10s by design (exit 124 is the expected shutdown path); only the
|
|
# scraped error lines carry signal for this bounded run.
|
|
MENU_MATCHES=$(timeout 10 godot --path "$REPO_ROOT/client" res://scenes/main_menu.tscn 2>&1 \
|
|
| grep -iE "$FILTER" || true)
|
|
if [ -n "$MENU_MATCHES" ]; then
|
|
MATCHES="$MATCHES
|
|
$MENU_MATCHES"
|
|
fi
|
|
fi
|
|
|
|
if [ -n "$MATCHES" ]; then
|
|
echo "$MATCHES"
|
|
exit 1
|
|
fi
|
|
|
|
# Restore a FULL class cache before exiting: the cold parse run re-seeds
|
|
# global_script_class_cache.cfg only partially — addon classes (e.g. gdUnit4's
|
|
# GdUnitTestCIRunner) are missing, which leaves tests/run-godot unable to even
|
|
# start (0 tests in ~350ms; found live when the pre-push gate ran the suite
|
|
# right after this script, 2026-07-14). The cold verdict above is already
|
|
# decided; this restore just returns the tree to a runnable state.
|
|
godot --headless --path "$REPO_ROOT/client" --import > /dev/null 2>&1 || true
|
|
|
|
echo "godot-cold-parse: clean"
|