diff --git a/.gitignore b/.gitignore index a3dd3fd..80d07ce 100644 --- a/.gitignore +++ b/.gitignore @@ -23,6 +23,7 @@ crash_handler* *.log # Local environment and secrets +.venv/ .env .env.* !.env.example diff --git a/AGENTS.md b/AGENTS.md index 5856181..86177bf 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -25,21 +25,31 @@ systems project, not a content dump. The expected working style is: Only Godot 4.7 matters for this project. -Use the project quality gate from PowerShell: +Use the project quality gate for the current platform: + +```bash +# macOS / Linux +./tools/quality.sh +``` ```powershell +# Windows powershell -ExecutionPolicy Bypass -File .\tools\quality.ps1 ``` For changed-file quick checks: +```bash +./tools/quality.sh --changed +``` + ```powershell powershell -ExecutionPolicy Bypass -File .\tools\quality.ps1 -Changed ``` The quality scripts isolate Godot's user profile under `logs/quality/godot_profile` -so headless Godot 4.7 can run without crashing on blocked Windows app-data paths. -Do not remove that behavior. +so headless Godot 4.7 can run without crashing when platform user-data paths +are unavailable. Do not remove that behavior. Useful extra checks: diff --git a/docs/local_quality_gate.md b/docs/local_quality_gate.md index 5788476..e9af141 100644 --- a/docs/local_quality_gate.md +++ b/docs/local_quality_gate.md @@ -5,12 +5,20 @@ parser errors, and LLM-generated garbage before committing. ## Requirements -- **Python 3** with `gdtoolkit` (gdscript-toolkit): +- **Python 3** with the pinned `gdtoolkit` (gdscript-toolkit). The recommended + setup uses `uv` and a project-local environment: + ```bash - pip install gdtoolkit + uv venv .venv + uv pip install --python .venv/bin/python -r requirements-dev.txt ``` + + On Windows, use `.venv/Scripts/python.exe` for the `--python` value. - **Godot 4** binary on `PATH`, or set the `GODOT_BIN` environment variable +The quality and format scripts discover `.venv` automatically; activating it +is optional. + ## Usage ### Full project check @@ -102,7 +110,7 @@ to the terminal. To add this to CI, install the dependencies and run: ```bash -pip install gdtoolkit +python -m pip install -r requirements-dev.txt ./tools/quality.sh ``` diff --git a/requirements-dev.txt b/requirements-dev.txt new file mode 100644 index 0000000..a11100f --- /dev/null +++ b/requirements-dev.txt @@ -0,0 +1 @@ +gdtoolkit==4.5.0 diff --git a/tools/fix_format.sh b/tools/fix_format.sh index 885eb8b..1fe40b0 100644 --- a/tools/fix_format.sh +++ b/tools/fix_format.sh @@ -8,14 +8,16 @@ cd "$ROOT" # detect gdformat FMT="" -if command -v gdformat &>/dev/null; then +if [[ -x "$ROOT/.venv/bin/gdformat" ]]; then + FMT="$ROOT/.venv/bin/gdformat" +elif command -v gdformat &>/dev/null; then FMT="gdformat" elif python -m gdtoolkit.formatter --help &>/dev/null 2>&1; then FMT="python -m gdtoolkit.formatter" fi if [[ -z "$FMT" ]]; then - echo "ERROR: gdformat not found. Install: pip install gdtoolkit" + echo "ERROR: gdformat not found. Install requirements-dev.txt; see docs/local_quality_gate.md." exit 1 fi diff --git a/tools/quality.ps1 b/tools/quality.ps1 index d0e9b92..7589b5a 100644 --- a/tools/quality.ps1 +++ b/tools/quality.ps1 @@ -59,6 +59,7 @@ function Find-Godot { } function Test-GdFormat { + if (Test-Path "$ROOT/.venv/Scripts/gdformat.exe") { return $true } if (Get-Command gdformat -ErrorAction SilentlyContinue) { return $true } try { $null = & python -m gdtoolkit.formatter --help 2>&1 @@ -72,6 +73,7 @@ function Test-GdFormat { } function Test-GdLint { + if (Test-Path "$ROOT/.venv/Scripts/gdlint.exe") { return $true } if (Get-Command gdlint -ErrorAction SilentlyContinue) { return $true } try { $null = & python -m gdtoolkit.linter --help 2>&1 @@ -86,7 +88,10 @@ function Test-GdLint { function Invoke-GdFormat { $args = $args - if (Get-Command gdformat -ErrorAction SilentlyContinue) { + $localTool = "$ROOT/.venv/Scripts/gdformat.exe" + if (Test-Path $localTool) { + & $localTool @args 2>&1 + } elseif (Get-Command gdformat -ErrorAction SilentlyContinue) { & gdformat @args 2>&1 } else { & python -m gdtoolkit.formatter @args 2>&1 @@ -95,7 +100,10 @@ function Invoke-GdFormat { function Invoke-GdLint { $args = $args - if (Get-Command gdlint -ErrorAction SilentlyContinue) { + $localTool = "$ROOT/.venv/Scripts/gdlint.exe" + if (Test-Path $localTool) { + & $localTool @args 2>&1 + } elseif (Get-Command gdlint -ErrorAction SilentlyContinue) { & gdlint @args 2>&1 } else { & python -m gdtoolkit.linter @args 2>&1 @@ -161,7 +169,7 @@ $fmtResult = "PASS" Set-Content -Path "$LOG/gdformat.log" -Value "" -Encoding utf8 if (-not $fmtAvail) { $fmtResult = "SKIPPED" - Add-Content -Path "$LOG/gdformat.log" -Value "gdformat not found -- install: pip install gdtoolkit" -Encoding utf8 + Add-Content -Path "$LOG/gdformat.log" -Value "gdformat not found -- install requirements-dev.txt (see docs/local_quality_gate.md)" -Encoding utf8 } else { if ($Changed) { $files = Get-ChangedGd @@ -203,7 +211,7 @@ $lintResult = "PASS" Set-Content -Path "$LOG/gdlint.log" -Value "" -Encoding utf8 if (-not $lintAvail) { $lintResult = "SKIPPED" - Add-Content -Path "$LOG/gdlint.log" -Value "gdlint not found -- install: pip install gdtoolkit" -Encoding utf8 + Add-Content -Path "$LOG/gdlint.log" -Value "gdlint not found -- install requirements-dev.txt (see docs/local_quality_gate.md)" -Encoding utf8 } else { if ($Changed) { $files = Get-ChangedGd diff --git a/tools/quality.sh b/tools/quality.sh index 72783fc..09b1154 100755 --- a/tools/quality.sh +++ b/tools/quality.sh @@ -54,12 +54,14 @@ find_godot() { } find_gdformat() { + if [[ -x "$ROOT/.venv/bin/gdformat" ]]; then echo "$ROOT/.venv/bin/gdformat"; return 0; fi if command -v gdformat &>/dev/null; then echo "gdformat"; return 0; fi if python -m gdtoolkit.formatter --help &>/dev/null 2>&1; then echo "python -m gdtoolkit.formatter"; return 0; fi return 1 } find_gdlint() { + if [[ -x "$ROOT/.venv/bin/gdlint" ]]; then echo "$ROOT/.venv/bin/gdlint"; return 0; fi if command -v gdlint &>/dev/null; then echo "gdlint"; return 0; fi if python -m gdtoolkit.linter --help &>/dev/null 2>&1; then echo "python -m gdtoolkit.linter"; return 0; fi return 1 @@ -99,7 +101,7 @@ fmt_result="PASS" : > "$LOG/gdformat.log" if [[ -z "$fmt_tool" ]]; then fmt_result="SKIPPED" - echo "gdformat not found — install: pip install gdtoolkit" > "$LOG/gdformat.log" + echo "gdformat not found — install requirements-dev.txt (see docs/local_quality_gate.md)" > "$LOG/gdformat.log" else if $CHANGED; then files=$(changed_gd) @@ -137,7 +139,7 @@ lint_result="PASS" : > "$LOG/gdlint.log" if [[ -z "$lint_tool" ]]; then lint_result="SKIPPED" - echo "gdlint not found — install: pip install gdtoolkit" > "$LOG/gdlint.log" + echo "gdlint not found — install requirements-dev.txt (see docs/local_quality_gate.md)" > "$LOG/gdlint.log" else if $CHANGED; then files=$(changed_gd)