# Lint, format-check, and unit-test GDScript (Godot 4.6). gdtoolkit: https://github.com/Scony/godot-gdscript-toolkit # GDUnit4 v6.1.2 under client/addons/gdUnit4; tests in client/test/ # # PRs: workflow always runs so "GDScript / lint_and_test" can be a required check. Path-sensitive # work uses step-level `if` — skipped steps still leave the job successful (unlike a workflow # skipped via `on.paths`, which leaves the required check missing/pending). # push: path filter on `on` avoids redundant runs on unrelated commits to main. name: GDScript on: push: branches: [main] paths: - "client/scripts/**" - "client/test/**" - "client/addons/**" - "client/project.godot" - ".github/workflows/gdscript.yml" pull_request: branches: [main] # dorny/paths-filter reads the PR file list from the GitHub API; needs pull-requests:read. permissions: contents: read pull-requests: read jobs: lint_and_test: runs-on: ubuntu-latest # Folder is addons/gdUnit4 (capital U). Lowercase gdunit4 fails on Linux (case-sensitive res://). env: GDUNIT_CMDTOOL: res://addons/gdUnit4/bin/GdUnitCmdTool.gd steps: - uses: actions/checkout@v4 - name: Detect GDScript-relevant changes (PR only) id: paths if: github.event_name == 'pull_request' uses: dorny/paths-filter@v3 with: filters: | gdscript: - "client/scripts/**" - "client/test/**" - "client/addons/**" - "client/project.godot" - ".github/workflows/gdscript.yml" - name: Skip GDScript lint and tests (no client GDScript paths in this PR) if: github.event_name == 'pull_request' && steps.paths.outputs.gdscript != 'true' run: echo "Skipping gdlint, gdformat, and GDUnit4." - uses: actions/setup-python@v5 if: github.event_name == 'push' || steps.paths.outputs.gdscript == 'true' with: python-version: "3.x" - name: Install gdtoolkit if: github.event_name == 'push' || steps.paths.outputs.gdscript == 'true' run: pip install "gdtoolkit==4.5.0" - name: gdlint if: github.event_name == 'push' || steps.paths.outputs.gdscript == 'true' run: gdlint client/scripts client/test - name: gdformat (check only) if: github.event_name == 'push' || steps.paths.outputs.gdscript == 'true' run: gdformat --check client/scripts client/test - name: Cache Godot 4.6 if: github.event_name == 'push' || steps.paths.outputs.gdscript == 'true' uses: actions/cache@v4 id: godot-cache with: path: ~/godot/Godot_v4.6-stable_linux.x86_64 key: godot-4.6-stable-linux-x86_64 - name: Download Godot 4.6 if: (github.event_name == 'push' || steps.paths.outputs.gdscript == 'true') && steps.godot-cache.outputs.cache-hit != 'true' run: | mkdir -p ~/godot wget -q "https://github.com/godotengine/godot/releases/download/4.6-stable/Godot_v4.6-stable_linux.x86_64.zip" -O /tmp/godot.zip unzip -q /tmp/godot.zip -d ~/godot chmod +x ~/godot/Godot_v4.6-stable_linux.x86_64 - name: Import project (.godot) if: github.event_name == 'push' || steps.paths.outputs.gdscript == 'true' working-directory: client run: ~/godot/Godot_v4.6-stable_linux.x86_64 --headless --import --path . --quit-after 10 - name: Verify GDUnit path (Linux res:// is case-sensitive) if: github.event_name == 'push' || steps.paths.outputs.gdscript == 'true' working-directory: client run: | test -f addons/gdUnit4/bin/GdUnitCmdTool.gd || { echo "::error::Missing GdUnit CLI script. Use addons/gdUnit4 (capital U), not gdunit4." ls -la addons/ || true exit 1 } # GdUnit returns 0 if *executed* tests pass, even when Godot logs SCRIPT ERROR during suite # discovery (broken test files are skipped). Fail the job if those errors appear in output. - name: GDUnit4 (headless) if: github.event_name == 'push' || steps.paths.outputs.gdscript == 'true' working-directory: client shell: bash run: | set -euo pipefail LOG="$(mktemp)" trap 'rm -f "$LOG"' EXIT ~/godot/Godot_v4.6-stable_linux.x86_64 --headless --path . -s "$GDUNIT_CMDTOOL" --ignoreHeadlessMode -a res://test 2>&1 | tee "$LOG" godot_ec="${PIPESTATUS[0]}" if [[ "$godot_ec" -ne 0 ]]; then echo "::error::Godot/GdUnit exited with code ${godot_ec}" exit "$godot_ec" fi if grep -E 'SCRIPT ERROR:|ERROR: Failed to load script' "$LOG"; then echo "::error::Godot reported script parse/load errors (suites may have been skipped). Fix the test scripts." exit 1 fi