gd-tools-cli 0.6.0__tar.gz → 0.8.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {gd_tools_cli-0.6.0 → gd_tools_cli-0.8.0}/PKG-INFO +85 -18
- {gd_tools_cli-0.6.0 → gd_tools_cli-0.8.0}/README.md +83 -17
- {gd_tools_cli-0.6.0 → gd_tools_cli-0.8.0}/pyproject.toml +7 -2
- {gd_tools_cli-0.6.0 → gd_tools_cli-0.8.0}/src/gd_tools/addons/gd-tools-coverage/coverage.gd +269 -2
- {gd_tools_cli-0.6.0 → gd_tools_cli-0.8.0}/src/gd_tools/addons/gd-tools-test/gd_tools_mock.gd +50 -3
- gd_tools_cli-0.8.0/src/gd_tools/addons/gd-tools-test/gd_tools_native_coverage.gd +514 -0
- gd_tools_cli-0.8.0/src/gd_tools/addons/gd-tools-test/gd_tools_snapshot_serializer.gd +153 -0
- gd_tools_cli-0.8.0/src/gd_tools/addons/gd-tools-test/gd_tools_snapshot_store.gd +132 -0
- {gd_tools_cli-0.6.0 → gd_tools_cli-0.8.0}/src/gd_tools/addons/gd-tools-test/gd_tools_test.gd +339 -3
- {gd_tools_cli-0.6.0 → gd_tools_cli-0.8.0}/src/gd_tools/addons/gd-tools-test/gd_tools_test_preflight.gd +2 -2
- {gd_tools_cli-0.6.0 → gd_tools_cli-0.8.0}/src/gd_tools/addons/gd-tools-test/gd_tools_test_runner.gd +80 -5
- gd_tools_cli-0.8.0/src/gd_tools/atomic_io.py +78 -0
- {gd_tools_cli-0.6.0 → gd_tools_cli-0.8.0}/src/gd_tools/changes.py +82 -0
- {gd_tools_cli-0.6.0 → gd_tools_cli-0.8.0}/src/gd_tools/clean.py +8 -3
- {gd_tools_cli-0.6.0 → gd_tools_cli-0.8.0}/src/gd_tools/cli.py +435 -81
- {gd_tools_cli-0.6.0 → gd_tools_cli-0.8.0}/src/gd_tools/config.py +17 -70
- {gd_tools_cli-0.6.0 → gd_tools_cli-0.8.0}/src/gd_tools/coverage/diff_reporter.py +2 -2
- gd_tools_cli-0.8.0/src/gd_tools/coverage/html_reporter.py +283 -0
- {gd_tools_cli-0.6.0 → gd_tools_cli-0.8.0}/src/gd_tools/coverage/orchestrator.py +184 -8
- gd_tools_cli-0.8.0/src/gd_tools/coverage/patch.py +350 -0
- {gd_tools_cli-0.6.0 → gd_tools_cli-0.8.0}/src/gd_tools/coverage/plan_generator.py +556 -30
- {gd_tools_cli-0.6.0 → gd_tools_cli-0.8.0}/src/gd_tools/coverage/playtest.py +27 -14
- {gd_tools_cli-0.6.0 → gd_tools_cli-0.8.0}/src/gd_tools/coverage/reporter.py +215 -24
- {gd_tools_cli-0.6.0 → gd_tools_cli-0.8.0}/src/gd_tools/coverage/templates/file.html +40 -3
- {gd_tools_cli-0.6.0 → gd_tools_cli-0.8.0}/src/gd_tools/coverage/templates/index.html +58 -6
- {gd_tools_cli-0.6.0 → gd_tools_cli-0.8.0}/src/gd_tools/errors.py +2 -6
- gd_tools_cli-0.8.0/src/gd_tools/gh_annotations.py +36 -0
- {gd_tools_cli-0.6.0 → gd_tools_cli-0.8.0}/src/gd_tools/godot.py +3 -39
- {gd_tools_cli-0.6.0 → gd_tools_cli-0.8.0}/src/gd_tools/init.py +41 -28
- {gd_tools_cli-0.6.0 → gd_tools_cli-0.8.0}/src/gd_tools/lint_runner.py +142 -3
- {gd_tools_cli-0.6.0 → gd_tools_cli-0.8.0}/src/gd_tools/native_test/artifacts.py +11 -2
- {gd_tools_cli-0.6.0 → gd_tools_cli-0.8.0}/src/gd_tools/native_test/command.py +82 -5
- gd_tools_cli-0.8.0/src/gd_tools/native_test/flaky.py +63 -0
- {gd_tools_cli-0.6.0 → gd_tools_cli-0.8.0}/src/gd_tools/native_test/orchestrator.py +149 -15
- {gd_tools_cli-0.6.0 → gd_tools_cli-0.8.0}/src/gd_tools/native_test/preflight.py +3 -3
- {gd_tools_cli-0.6.0 → gd_tools_cli-0.8.0}/src/gd_tools/native_test/protocol.py +13 -35
- gd_tools_cli-0.8.0/src/gd_tools/pre_commit.py +283 -0
- gd_tools_cli-0.8.0/src/gd_tools/test_results.py +420 -0
- {gd_tools_cli-0.6.0 → gd_tools_cli-0.8.0}/src/gd_tools/version.py +4 -12
- {gd_tools_cli-0.6.0 → gd_tools_cli-0.8.0}/src/gd_tools/watch/session.py +11 -1
- {gd_tools_cli-0.6.0 → gd_tools_cli-0.8.0}/src/gd_tools_cli.egg-info/PKG-INFO +85 -18
- {gd_tools_cli-0.6.0 → gd_tools_cli-0.8.0}/src/gd_tools_cli.egg-info/SOURCES.txt +8 -3
- {gd_tools_cli-0.6.0 → gd_tools_cli-0.8.0}/src/gd_tools_cli.egg-info/requires.txt +1 -0
- gd_tools_cli-0.6.0/src/gd_tools/addons/gd-tools-coverage/post_run_hook.gd +0 -116
- gd_tools_cli-0.6.0/src/gd_tools/addons/gd-tools-coverage/pre_run_hook.gd +0 -10
- gd_tools_cli-0.6.0/src/gd_tools/addons/gd-tools-test/gd_tools_native_coverage.gd +0 -211
- gd_tools_cli-0.6.0/src/gd_tools/coverage/html_reporter.py +0 -142
- gd_tools_cli-0.6.0/src/gd_tools/test_runner.py +0 -175
- {gd_tools_cli-0.6.0 → gd_tools_cli-0.8.0}/setup.cfg +0 -0
- {gd_tools_cli-0.6.0 → gd_tools_cli-0.8.0}/src/gd_tools/__init__.py +0 -0
- {gd_tools_cli-0.6.0 → gd_tools_cli-0.8.0}/src/gd_tools/__main__.py +0 -0
- {gd_tools_cli-0.6.0 → gd_tools_cli-0.8.0}/src/gd_tools/addon_check.py +0 -0
- {gd_tools_cli-0.6.0 → gd_tools_cli-0.8.0}/src/gd_tools/addons/__init__.py +0 -0
- {gd_tools_cli-0.6.0 → gd_tools_cli-0.8.0}/src/gd_tools/addons/gd-tools-editor/coverage_overlay.gd +0 -0
- {gd_tools_cli-0.6.0 → gd_tools_cli-0.8.0}/src/gd_tools/addons/gd-tools-editor/dock.gd +0 -0
- {gd_tools_cli-0.6.0 → gd_tools_cli-0.8.0}/src/gd_tools/addons/gd-tools-editor/plugin.cfg +0 -0
- {gd_tools_cli-0.6.0 → gd_tools_cli-0.8.0}/src/gd_tools/addons/gd-tools-editor/plugin.gd +0 -0
- {gd_tools_cli-0.6.0 → gd_tools_cli-0.8.0}/src/gd_tools/addons/gd-tools-test/gd_tools_parameter_naming.gd +0 -0
- {gd_tools_cli-0.6.0 → gd_tools_cli-0.8.0}/src/gd_tools/addons/gd-tools-test/gd_tools_test_context.gd +0 -0
- {gd_tools_cli-0.6.0 → gd_tools_cli-0.8.0}/src/gd_tools/coverage/__init__.py +0 -0
- {gd_tools_cli-0.6.0 → gd_tools_cli-0.8.0}/src/gd_tools/coverage/cobertura_reporter.py +0 -0
- {gd_tools_cli-0.6.0 → gd_tools_cli-0.8.0}/src/gd_tools/coverage/lcov_reporter.py +0 -0
- {gd_tools_cli-0.6.0 → gd_tools_cli-0.8.0}/src/gd_tools/coverage/omissions.py +0 -0
- {gd_tools_cli-0.6.0 → gd_tools_cli-0.8.0}/src/gd_tools/coverage/terminal_reporter.py +0 -0
- {gd_tools_cli-0.6.0 → gd_tools_cli-0.8.0}/src/gd_tools/doctor.py +0 -0
- {gd_tools_cli-0.6.0 → gd_tools_cli-0.8.0}/src/gd_tools/file_discovery.py +0 -0
- {gd_tools_cli-0.6.0 → gd_tools_cli-0.8.0}/src/gd_tools/format_runner.py +0 -0
- {gd_tools_cli-0.6.0 → gd_tools_cli-0.8.0}/src/gd_tools/migration/__init__.py +0 -0
- {gd_tools_cli-0.6.0 → gd_tools_cli-0.8.0}/src/gd_tools/migration/apply.py +0 -0
- {gd_tools_cli-0.6.0 → gd_tools_cli-0.8.0}/src/gd_tools/migration/gutconfig.py +0 -0
- {gd_tools_cli-0.6.0 → gd_tools_cli-0.8.0}/src/gd_tools/migration/reporter.py +0 -0
- {gd_tools_cli-0.6.0 → gd_tools_cli-0.8.0}/src/gd_tools/migration/rewrite.py +0 -0
- {gd_tools_cli-0.6.0 → gd_tools_cli-0.8.0}/src/gd_tools/migration/scan.py +0 -0
- {gd_tools_cli-0.6.0 → gd_tools_cli-0.8.0}/src/gd_tools/migration/translate.py +0 -0
- {gd_tools_cli-0.6.0 → gd_tools_cli-0.8.0}/src/gd_tools/native_test/__init__.py +0 -0
- {gd_tools_cli-0.6.0 → gd_tools_cli-0.8.0}/src/gd_tools/native_test/bridge_scan.py +0 -0
- {gd_tools_cli-0.6.0 → gd_tools_cli-0.8.0}/src/gd_tools/native_test/discovery.py +0 -0
- {gd_tools_cli-0.6.0 → gd_tools_cli-0.8.0}/src/gd_tools/native_test/import_cache.py +0 -0
- {gd_tools_cli-0.6.0 → gd_tools_cli-0.8.0}/src/gd_tools/native_test/preflight_cache.py +0 -0
- {gd_tools_cli-0.6.0 → gd_tools_cli-0.8.0}/src/gd_tools/output.py +0 -0
- {gd_tools_cli-0.6.0 → gd_tools_cli-0.8.0}/src/gd_tools/schema.py +0 -0
- {gd_tools_cli-0.6.0 → gd_tools_cli-0.8.0}/src/gd_tools/update_check.py +0 -0
- {gd_tools_cli-0.6.0 → gd_tools_cli-0.8.0}/src/gd_tools/verbosity.py +0 -0
- {gd_tools_cli-0.6.0 → gd_tools_cli-0.8.0}/src/gd_tools/watch/__init__.py +0 -0
- {gd_tools_cli-0.6.0 → gd_tools_cli-0.8.0}/src/gd_tools/watch/coalescer.py +0 -0
- {gd_tools_cli-0.6.0 → gd_tools_cli-0.8.0}/src/gd_tools/watch/loop.py +0 -0
- {gd_tools_cli-0.6.0 → gd_tools_cli-0.8.0}/src/gd_tools/watch/mapping.py +0 -0
- {gd_tools_cli-0.6.0 → gd_tools_cli-0.8.0}/src/gd_tools/watch/observer.py +0 -0
- {gd_tools_cli-0.6.0 → gd_tools_cli-0.8.0}/src/gd_tools/watch/scope.py +0 -0
- {gd_tools_cli-0.6.0 → gd_tools_cli-0.8.0}/src/gd_tools_cli.egg-info/dependency_links.txt +0 -0
- {gd_tools_cli-0.6.0 → gd_tools_cli-0.8.0}/src/gd_tools_cli.egg-info/entry_points.txt +0 -0
- {gd_tools_cli-0.6.0 → gd_tools_cli-0.8.0}/src/gd_tools_cli.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: gd-tools-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.8.0
|
|
4
4
|
Summary: A modern development workflow CLI for GDScript projects in Godot 4.5+
|
|
5
5
|
Author-email: mansyar <m.ansyarafi@gmail.com>
|
|
6
6
|
License: MIT
|
|
@@ -35,6 +35,7 @@ Requires-Dist: watchdog
|
|
|
35
35
|
Provides-Extra: dev
|
|
36
36
|
Requires-Dist: pytest; extra == "dev"
|
|
37
37
|
Requires-Dist: pytest-cov; extra == "dev"
|
|
38
|
+
Requires-Dist: pytest-xdist; extra == "dev"
|
|
38
39
|
Requires-Dist: ruff==0.15.21; extra == "dev"
|
|
39
40
|
Requires-Dist: black; extra == "dev"
|
|
40
41
|
Requires-Dist: commitizen; extra == "dev"
|
|
@@ -74,10 +75,11 @@ One install, one config, one mental model.
|
|
|
74
75
|
| Feature | Description |
|
|
75
76
|
|---------|-------------|
|
|
76
77
|
| **Unified workflow** | One install, one config (`gd-tools.toml`), one mental model for test, lint, format, and coverage. Consistent terminal output with colored markers and summary footers across all commands. |
|
|
77
|
-
| **Native test runtime** | Tests extend `GdToolsTest` and run inside Godot itself. Scene and resource integration tests reach the real scene tree through an explicit context object rather than a proxy. |
|
|
78
|
+
| **Native test runtime** | Tests extend `GdToolsTest` and run inside Godot itself. Scene and resource integration tests reach the real scene tree through an explicit context object rather than a proxy. Doubles, partial doubles, and stubbing isolate collaborators; spy assertions cover calls, argument wildcards, call order, and property values. |
|
|
79
|
+
| **Snapshot testing** | `assert_snapshot(value)` pins rendered values -- including object property dumps and node trees -- against versioned, diffable `.snap` files. First run writes and passes; mismatches fail with a unified diff, and `--snapshot-update` accepts the new output. |
|
|
78
80
|
| **Zero-friction bootstrap** | `gd-tools init` gets a project fully set up in under a minute -- native test and coverage addons deployed, configs generated. |
|
|
79
|
-
| **Coverage gap-filling** | Production-quality line and branch coverage for GDScript -- HTML, LCOV, and
|
|
80
|
-
| **CI/CD friendly** | Exit codes, `--check` flags, machine-readable output (JSON, JUnit XML, LCOV, Cobertura),
|
|
81
|
+
| **Coverage gap-filling** | Production-quality line and branch coverage for GDScript -- HTML, LCOV, Cobertura, and JSON reports, plus GitHub Actions annotations that surface failures inline on pull requests. Independent line (`--min`) and branch (`--min-branch`) gates. `# gd-tools: no cover` annotations exclude debug-only code from the numbers. `coverage run` collects coverage during manual playtest sessions, not just automated tests. Patch coverage (`coverage diff --patch`) reports coverage over only the lines a pull request changes, with its own gate and inline annotations. |
|
|
82
|
+
| **CI/CD friendly** | Exit codes, `--check` flags, machine-readable output (JSON, JUnit XML, LCOV, Cobertura), and GitHub Actions annotations for lint violations and coverage gates. No interactive prompts in CI mode. |
|
|
81
83
|
| **Standalone compatibility** | gdlint and gdformat continue to work if invoked directly. `gd-tools` is a layer on top, not a lock-in. |
|
|
82
84
|
|
|
83
85
|
## 3. Installation
|
|
@@ -140,13 +142,13 @@ func test_health_starts_at_full() -> void:
|
|
|
140
142
|
|---------|-------------|
|
|
141
143
|
| `gd-tools init` | Bootstrap a Godot project -- deploy the native test and coverage addons, generate configs. |
|
|
142
144
|
| `gd-tools doctor` | Diagnose the development environment -- Godot, native test addon, coverage addon, tooling; reports legacy GUT artifacts as migration advice. |
|
|
143
|
-
| `gd-tools test` | Run tests with optional coverage, thresholds, and JUnit XML output. Suites must extend `GdToolsTest`; `GutTest` suites are rejected with exit 2 and migration guidance. Accepts optional path arguments to override configured test directories. `--parallel N` runs suites through a bounded worker pool. `--changed` runs only the suites mapped from git-changed files. `--watch` re-runs affected suites on `.gd` file changes. Every run publishes a machine-readable artifact index under `.gd-tools/artifacts/<run_id>/`. |
|
|
145
|
+
| `gd-tools test` | Run tests with optional coverage, thresholds, and JUnit XML output. Suites must extend `GdToolsTest`; `GutTest` suites are rejected with exit 2 and migration guidance. Accepts optional path arguments to override configured test directories. `--parallel N` runs suites through a bounded worker pool. `--changed` runs only the suites mapped from git-changed files. `--watch` re-runs affected suites on `.gd` file changes. `--durations N` reports the N slowest tests after the run. `--exitfirst` (`-x`) stops dispatching new suites after the first failing suite; `--shard K/N` runs one round-robin shard for CI matrix splitting. Every run publishes a machine-readable artifact index under `.gd-tools/artifacts/<run_id>/`. |
|
|
144
146
|
| `gd-tools migrate` | Guided GUT-to-native migration. Default: read-only report with unsupported-construct inventory and proposed base-class rewrites. `--apply` renames clean suites to `GdToolsTest` and translates `.gutconfig.json` into `gd-tools.toml` (merge, never clobber). `--config-only` translates config only. |
|
|
145
|
-
| `gd-tools lint` | Lint GDScript files using gdlint with text or
|
|
147
|
+
| `gd-tools lint` | Lint GDScript files using gdlint with text, JSON, or GitHub Actions annotation output. Accepts one or more file or directory paths. |
|
|
146
148
|
| `gd-tools format` | Format GDScript files using gdformat with check and diff modes. Accepts one or more file or directory paths. |
|
|
147
|
-
| `gd-tools coverage` | Coverage subcommands -- `report`, `merge`, `show`, `save-baseline`, `diff` (baseline comparison for CI regression gates), and `run` (collect coverage during a manual playtest session). |
|
|
149
|
+
| `gd-tools coverage` | Coverage subcommands -- `report`, `merge`, `show`, `save-baseline`, `diff` (baseline comparison for CI regression gates; with `--patch`, PR-scoped coverage over changed lines), and `run` (collect coverage during a manual playtest session). |
|
|
148
150
|
| `gd-tools config` | Configuration management -- `show` (display resolved config), `validate` (check config validity), `schema` (print or write the JSON Schema for `gd-tools.toml`). |
|
|
149
|
-
| `gd-tools version` | Display versions of all gd-tools components (gd-tools, Godot, gdtoolkit, Python
|
|
151
|
+
| `gd-tools version` | Display versions of all gd-tools components (gd-tools, Godot, gdtoolkit, Python) in a table or JSON. |
|
|
150
152
|
| `gd-tools completion` | Generate shell completion scripts for bash, zsh, fish, or PowerShell. |
|
|
151
153
|
|
|
152
154
|
### Selecting and Filtering Tests
|
|
@@ -158,8 +160,11 @@ gd-tools test --test test_takes_damage # one test method
|
|
|
158
160
|
gd-tools test --tag smoke # suites with that class-level tag
|
|
159
161
|
gd-tools test --test-timeout 30 # per-test timeout, in seconds
|
|
160
162
|
gd-tools test --parallel 4 # run suites with 4 concurrent workers
|
|
163
|
+
gd-tools test --durations 10 # report the 10 slowest tests
|
|
161
164
|
gd-tools test --changed # only suites mapped from git-changed files
|
|
162
165
|
gd-tools test --changed --base main # PR/CI mode: diff from merge-base with main
|
|
166
|
+
gd-tools test --exitfirst # stop dispatching after the first failing suite
|
|
167
|
+
gd-tools test --shard 2/4 # CI sharding: run suite shard 2 of 4
|
|
163
168
|
```
|
|
164
169
|
|
|
165
170
|
`--tag` is repeatable, and `--test-timeout` (per test) is separate from
|
|
@@ -168,6 +173,13 @@ worker pool (1-32 workers; bare `--parallel` means 4) while keeping results,
|
|
|
168
173
|
JUnit XML, and merged coverage identical to a sequential run. Persist the
|
|
169
174
|
choice with `parallel = 4` under `[test]` in `gd-tools.toml`.
|
|
170
175
|
|
|
176
|
+
`--durations N` prints a "Slowest Tests" table after the run, sorted
|
|
177
|
+
slowest-first, covering pass, fail, and skip outcomes. Bare `--durations`
|
|
178
|
+
means 10; `--durations 0` lists every executed test (pytest parity). Persist
|
|
179
|
+
the choice with `durations = 10` under `[test]` in `gd-tools.toml`; the flag
|
|
180
|
+
overrides the config for one invocation. The table renders identically under
|
|
181
|
+
`--watch` re-runs and `--parallel` runs.
|
|
182
|
+
|
|
171
183
|
`--changed` selects suites from git instead of running everything: uncommitted
|
|
172
184
|
changes (staged, unstaged, and untracked) map to suites by the same
|
|
173
185
|
file→suite convention as `--watch` — `src/enemy.gd` selects
|
|
@@ -181,6 +193,29 @@ pull-request CI. `--changed` composes with `--parallel`, `--coverage`, and
|
|
|
181
193
|
the `--suite`/`--test`/`--tag` filters (the active filters bound the
|
|
182
194
|
mapping domain); an empty change set exits 0 without launching Godot.
|
|
183
195
|
|
|
196
|
+
`--exitfirst` (short form `-x`) stops dispatching **new** suites after the
|
|
197
|
+
first suite whose final result is a failure — a test failure or an
|
|
198
|
+
infrastructure error. In-flight suites finish and are collected; suites that
|
|
199
|
+
were never started are reported as skipped (`not_run`) and summarized in a
|
|
200
|
+
`Stopped early: fail-fast after suite <id> (K of M suites skipped)` line.
|
|
201
|
+
Passes and skips never trigger the gate, and a suite that passes after a
|
|
202
|
+
retry does not either — only final suite results decide. The exit code stays
|
|
203
|
+
1 for test failures. `--exitfirst` composes with `--parallel` (the pool
|
|
204
|
+
drains instead of killing workers), with `--coverage` (the report covers the
|
|
205
|
+
suites that ran, labeled partial when plan targets went unmeasured), and with
|
|
206
|
+
`--watch` (the gate resets for every re-run).
|
|
207
|
+
|
|
208
|
+
`--shard K/N` runs only the suites assigned to shard `K` of `N` — suite *i*
|
|
209
|
+
of the deterministic plan order belongs to shard `(i mod N) + 1` — for
|
|
210
|
+
splitting one test run across CI jobs. Selection happens after `--changed`
|
|
211
|
+
filtering and before `--parallel`, so each flag keeps exactly one job.
|
|
212
|
+
`--shard 1/1` is valid and equivalent to no sharding; malformed values
|
|
213
|
+
(`--shard 4/3`, `--shard 3`) exit 2 before any work. Each shard produces its
|
|
214
|
+
own coverage report; merge the shards with `gd-tools coverage merge`.
|
|
215
|
+
`--shard` and `--watch` are rejected together (exit 2). See the
|
|
216
|
+
[sharding recipe](./docs/USER_GUIDE.md#sharding-a-test-run-across-ci-jobs)
|
|
217
|
+
for a GitHub Actions matrix example.
|
|
218
|
+
|
|
184
219
|
Repeat runs are faster: the `godot --headless --import` step is cached under
|
|
185
220
|
`.gd-tools/native/import-cache/` and skipped when `project.godot`, any
|
|
186
221
|
project source/resource file (scripts, scenes, import sidecars, addons), or
|
|
@@ -319,7 +354,41 @@ eval "$(gd-tools)"
|
|
|
319
354
|
See the [User Guide](./docs/USER_GUIDE.md) for detailed per-shell
|
|
320
355
|
instructions.
|
|
321
356
|
|
|
322
|
-
## 7.
|
|
357
|
+
## 7. Pre-commit Hooks
|
|
358
|
+
|
|
359
|
+
Wire gd-tools into the [pre-commit](https://pre-commit.com) framework so
|
|
360
|
+
every commit runs your format check, lint, and (optionally) your test suite:
|
|
361
|
+
|
|
362
|
+
```bash
|
|
363
|
+
gd-tools install-hooks
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
The command generates `.pre-commit-hooks.yaml` and merges a `repos: local:`
|
|
367
|
+
entry into `.pre-commit-config.yaml`. Existing hooks — including your own —
|
|
368
|
+
are preserved; re-runs update only the gd-tools entries in place.
|
|
369
|
+
|
|
370
|
+
Interactive by default: confirm each hook (`format`, `lint`, `test`). For
|
|
371
|
+
scripted or CI use, pass flags instead:
|
|
372
|
+
|
|
373
|
+
```bash
|
|
374
|
+
gd-tools install-hooks --non-interactive # format + lint (defaults)
|
|
375
|
+
gd-tools install-hooks --all # format + lint + test
|
|
376
|
+
gd-tools install-hooks --hooks format,lint # explicit selection
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
| Flag | Behavior |
|
|
380
|
+
|---|---|
|
|
381
|
+
| `--all` | Enable every hook (format, lint, test). |
|
|
382
|
+
| `--hooks HOOKS` | Comma-separated selection, e.g. `--hooks format,lint`. |
|
|
383
|
+
| `--non-interactive` | Never prompt; use defaults or explicit flags. |
|
|
384
|
+
|
|
385
|
+
Exit codes follow the gd-tools convention: `0` installed, `1` nothing to do,
|
|
386
|
+
`2` config/environment error.
|
|
387
|
+
|
|
388
|
+
See the [User Guide](./docs/USER_GUIDE.md#8-pre-commit-hooks) for the
|
|
389
|
+
generated file contents and per-hook details.
|
|
390
|
+
|
|
391
|
+
## 8. Configuration
|
|
323
392
|
|
|
324
393
|
`gd-tools` uses a single `gd-tools.toml` file as the source of truth for
|
|
325
394
|
all tool configuration. `gd-tools init` generates this file with sensible
|
|
@@ -333,10 +402,9 @@ binary = "" # Optional -- auto-detected if unset
|
|
|
333
402
|
test_dirs = ["test", "tests"]
|
|
334
403
|
prefix = "test_"
|
|
335
404
|
suffix = ".gd"
|
|
336
|
-
gutconfig = ".gutconfig.json" # legacy; not read by any runtime
|
|
337
405
|
runtime = "native" # native (default); "gut" is no longer a runnable runtime
|
|
338
406
|
timeout_seconds = 5.0 # default per-test timeout for async native tests
|
|
339
|
-
retries = 0 # opt-in retries per native test
|
|
407
|
+
retries = 0 # opt-in retries per native test; retried passes are flagged as flaky
|
|
340
408
|
# parallel = 4 # opt-in parallel suite execution (1-32; unset runs sequentially)
|
|
341
409
|
tags = [] # native suite tag filters
|
|
342
410
|
|
|
@@ -384,7 +452,7 @@ version's config model.
|
|
|
384
452
|
See the [User Guide](./docs/USER_GUIDE.md) for a full configuration reference
|
|
385
453
|
with all keys, defaults, and examples.
|
|
386
454
|
|
|
387
|
-
##
|
|
455
|
+
## 9. Documentation
|
|
388
456
|
|
|
389
457
|
| Document | Description |
|
|
390
458
|
|----------|-------------|
|
|
@@ -395,7 +463,7 @@ with all keys, defaults, and examples.
|
|
|
395
463
|
| [Roadmap](./docs/ROADMAP.md) | Release phases and milestones. |
|
|
396
464
|
| [Testing Strategy](./docs/TESTING_STRATEGY.md) | Test pyramid, coverage targets, and CI integration. |
|
|
397
465
|
|
|
398
|
-
##
|
|
466
|
+
## 10. Development
|
|
399
467
|
|
|
400
468
|
```bash
|
|
401
469
|
# Clone and install in editable mode with dev dependencies
|
|
@@ -425,15 +493,14 @@ See [Testing Strategy](./docs/TESTING_STRATEGY.md) for the full testing
|
|
|
425
493
|
guide and [Contributing Guide](./docs/CONTRIBUTING.md) for development
|
|
426
494
|
setup details.
|
|
427
495
|
|
|
428
|
-
##
|
|
496
|
+
## 11. License
|
|
429
497
|
|
|
430
498
|
MIT
|
|
431
499
|
|
|
432
|
-
##
|
|
500
|
+
## 12. Acknowledgements
|
|
433
501
|
|
|
434
|
-
`gd-tools` stands on the shoulders of
|
|
435
|
-
|
|
436
|
-
hard parts.
|
|
502
|
+
`gd-tools` stands on the shoulders of excellent community tools, past and
|
|
503
|
+
present. Full credit to their authors for the hard parts.
|
|
437
504
|
|
|
438
505
|
- **[GUT (Godot Unit Test)](https://github.com/bitwes/Gut)** by
|
|
439
506
|
[bitwes](https://github.com/bitwes): the GDScript test framework whose
|
|
@@ -33,10 +33,11 @@ One install, one config, one mental model.
|
|
|
33
33
|
| Feature | Description |
|
|
34
34
|
|---------|-------------|
|
|
35
35
|
| **Unified workflow** | One install, one config (`gd-tools.toml`), one mental model for test, lint, format, and coverage. Consistent terminal output with colored markers and summary footers across all commands. |
|
|
36
|
-
| **Native test runtime** | Tests extend `GdToolsTest` and run inside Godot itself. Scene and resource integration tests reach the real scene tree through an explicit context object rather than a proxy. |
|
|
36
|
+
| **Native test runtime** | Tests extend `GdToolsTest` and run inside Godot itself. Scene and resource integration tests reach the real scene tree through an explicit context object rather than a proxy. Doubles, partial doubles, and stubbing isolate collaborators; spy assertions cover calls, argument wildcards, call order, and property values. |
|
|
37
|
+
| **Snapshot testing** | `assert_snapshot(value)` pins rendered values -- including object property dumps and node trees -- against versioned, diffable `.snap` files. First run writes and passes; mismatches fail with a unified diff, and `--snapshot-update` accepts the new output. |
|
|
37
38
|
| **Zero-friction bootstrap** | `gd-tools init` gets a project fully set up in under a minute -- native test and coverage addons deployed, configs generated. |
|
|
38
|
-
| **Coverage gap-filling** | Production-quality line and branch coverage for GDScript -- HTML, LCOV, and
|
|
39
|
-
| **CI/CD friendly** | Exit codes, `--check` flags, machine-readable output (JSON, JUnit XML, LCOV, Cobertura),
|
|
39
|
+
| **Coverage gap-filling** | Production-quality line and branch coverage for GDScript -- HTML, LCOV, Cobertura, and JSON reports, plus GitHub Actions annotations that surface failures inline on pull requests. Independent line (`--min`) and branch (`--min-branch`) gates. `# gd-tools: no cover` annotations exclude debug-only code from the numbers. `coverage run` collects coverage during manual playtest sessions, not just automated tests. Patch coverage (`coverage diff --patch`) reports coverage over only the lines a pull request changes, with its own gate and inline annotations. |
|
|
40
|
+
| **CI/CD friendly** | Exit codes, `--check` flags, machine-readable output (JSON, JUnit XML, LCOV, Cobertura), and GitHub Actions annotations for lint violations and coverage gates. No interactive prompts in CI mode. |
|
|
40
41
|
| **Standalone compatibility** | gdlint and gdformat continue to work if invoked directly. `gd-tools` is a layer on top, not a lock-in. |
|
|
41
42
|
|
|
42
43
|
## 3. Installation
|
|
@@ -99,13 +100,13 @@ func test_health_starts_at_full() -> void:
|
|
|
99
100
|
|---------|-------------|
|
|
100
101
|
| `gd-tools init` | Bootstrap a Godot project -- deploy the native test and coverage addons, generate configs. |
|
|
101
102
|
| `gd-tools doctor` | Diagnose the development environment -- Godot, native test addon, coverage addon, tooling; reports legacy GUT artifacts as migration advice. |
|
|
102
|
-
| `gd-tools test` | Run tests with optional coverage, thresholds, and JUnit XML output. Suites must extend `GdToolsTest`; `GutTest` suites are rejected with exit 2 and migration guidance. Accepts optional path arguments to override configured test directories. `--parallel N` runs suites through a bounded worker pool. `--changed` runs only the suites mapped from git-changed files. `--watch` re-runs affected suites on `.gd` file changes. Every run publishes a machine-readable artifact index under `.gd-tools/artifacts/<run_id>/`. |
|
|
103
|
+
| `gd-tools test` | Run tests with optional coverage, thresholds, and JUnit XML output. Suites must extend `GdToolsTest`; `GutTest` suites are rejected with exit 2 and migration guidance. Accepts optional path arguments to override configured test directories. `--parallel N` runs suites through a bounded worker pool. `--changed` runs only the suites mapped from git-changed files. `--watch` re-runs affected suites on `.gd` file changes. `--durations N` reports the N slowest tests after the run. `--exitfirst` (`-x`) stops dispatching new suites after the first failing suite; `--shard K/N` runs one round-robin shard for CI matrix splitting. Every run publishes a machine-readable artifact index under `.gd-tools/artifacts/<run_id>/`. |
|
|
103
104
|
| `gd-tools migrate` | Guided GUT-to-native migration. Default: read-only report with unsupported-construct inventory and proposed base-class rewrites. `--apply` renames clean suites to `GdToolsTest` and translates `.gutconfig.json` into `gd-tools.toml` (merge, never clobber). `--config-only` translates config only. |
|
|
104
|
-
| `gd-tools lint` | Lint GDScript files using gdlint with text or
|
|
105
|
+
| `gd-tools lint` | Lint GDScript files using gdlint with text, JSON, or GitHub Actions annotation output. Accepts one or more file or directory paths. |
|
|
105
106
|
| `gd-tools format` | Format GDScript files using gdformat with check and diff modes. Accepts one or more file or directory paths. |
|
|
106
|
-
| `gd-tools coverage` | Coverage subcommands -- `report`, `merge`, `show`, `save-baseline`, `diff` (baseline comparison for CI regression gates), and `run` (collect coverage during a manual playtest session). |
|
|
107
|
+
| `gd-tools coverage` | Coverage subcommands -- `report`, `merge`, `show`, `save-baseline`, `diff` (baseline comparison for CI regression gates; with `--patch`, PR-scoped coverage over changed lines), and `run` (collect coverage during a manual playtest session). |
|
|
107
108
|
| `gd-tools config` | Configuration management -- `show` (display resolved config), `validate` (check config validity), `schema` (print or write the JSON Schema for `gd-tools.toml`). |
|
|
108
|
-
| `gd-tools version` | Display versions of all gd-tools components (gd-tools, Godot, gdtoolkit, Python
|
|
109
|
+
| `gd-tools version` | Display versions of all gd-tools components (gd-tools, Godot, gdtoolkit, Python) in a table or JSON. |
|
|
109
110
|
| `gd-tools completion` | Generate shell completion scripts for bash, zsh, fish, or PowerShell. |
|
|
110
111
|
|
|
111
112
|
### Selecting and Filtering Tests
|
|
@@ -117,8 +118,11 @@ gd-tools test --test test_takes_damage # one test method
|
|
|
117
118
|
gd-tools test --tag smoke # suites with that class-level tag
|
|
118
119
|
gd-tools test --test-timeout 30 # per-test timeout, in seconds
|
|
119
120
|
gd-tools test --parallel 4 # run suites with 4 concurrent workers
|
|
121
|
+
gd-tools test --durations 10 # report the 10 slowest tests
|
|
120
122
|
gd-tools test --changed # only suites mapped from git-changed files
|
|
121
123
|
gd-tools test --changed --base main # PR/CI mode: diff from merge-base with main
|
|
124
|
+
gd-tools test --exitfirst # stop dispatching after the first failing suite
|
|
125
|
+
gd-tools test --shard 2/4 # CI sharding: run suite shard 2 of 4
|
|
122
126
|
```
|
|
123
127
|
|
|
124
128
|
`--tag` is repeatable, and `--test-timeout` (per test) is separate from
|
|
@@ -127,6 +131,13 @@ worker pool (1-32 workers; bare `--parallel` means 4) while keeping results,
|
|
|
127
131
|
JUnit XML, and merged coverage identical to a sequential run. Persist the
|
|
128
132
|
choice with `parallel = 4` under `[test]` in `gd-tools.toml`.
|
|
129
133
|
|
|
134
|
+
`--durations N` prints a "Slowest Tests" table after the run, sorted
|
|
135
|
+
slowest-first, covering pass, fail, and skip outcomes. Bare `--durations`
|
|
136
|
+
means 10; `--durations 0` lists every executed test (pytest parity). Persist
|
|
137
|
+
the choice with `durations = 10` under `[test]` in `gd-tools.toml`; the flag
|
|
138
|
+
overrides the config for one invocation. The table renders identically under
|
|
139
|
+
`--watch` re-runs and `--parallel` runs.
|
|
140
|
+
|
|
130
141
|
`--changed` selects suites from git instead of running everything: uncommitted
|
|
131
142
|
changes (staged, unstaged, and untracked) map to suites by the same
|
|
132
143
|
file→suite convention as `--watch` — `src/enemy.gd` selects
|
|
@@ -140,6 +151,29 @@ pull-request CI. `--changed` composes with `--parallel`, `--coverage`, and
|
|
|
140
151
|
the `--suite`/`--test`/`--tag` filters (the active filters bound the
|
|
141
152
|
mapping domain); an empty change set exits 0 without launching Godot.
|
|
142
153
|
|
|
154
|
+
`--exitfirst` (short form `-x`) stops dispatching **new** suites after the
|
|
155
|
+
first suite whose final result is a failure — a test failure or an
|
|
156
|
+
infrastructure error. In-flight suites finish and are collected; suites that
|
|
157
|
+
were never started are reported as skipped (`not_run`) and summarized in a
|
|
158
|
+
`Stopped early: fail-fast after suite <id> (K of M suites skipped)` line.
|
|
159
|
+
Passes and skips never trigger the gate, and a suite that passes after a
|
|
160
|
+
retry does not either — only final suite results decide. The exit code stays
|
|
161
|
+
1 for test failures. `--exitfirst` composes with `--parallel` (the pool
|
|
162
|
+
drains instead of killing workers), with `--coverage` (the report covers the
|
|
163
|
+
suites that ran, labeled partial when plan targets went unmeasured), and with
|
|
164
|
+
`--watch` (the gate resets for every re-run).
|
|
165
|
+
|
|
166
|
+
`--shard K/N` runs only the suites assigned to shard `K` of `N` — suite *i*
|
|
167
|
+
of the deterministic plan order belongs to shard `(i mod N) + 1` — for
|
|
168
|
+
splitting one test run across CI jobs. Selection happens after `--changed`
|
|
169
|
+
filtering and before `--parallel`, so each flag keeps exactly one job.
|
|
170
|
+
`--shard 1/1` is valid and equivalent to no sharding; malformed values
|
|
171
|
+
(`--shard 4/3`, `--shard 3`) exit 2 before any work. Each shard produces its
|
|
172
|
+
own coverage report; merge the shards with `gd-tools coverage merge`.
|
|
173
|
+
`--shard` and `--watch` are rejected together (exit 2). See the
|
|
174
|
+
[sharding recipe](./docs/USER_GUIDE.md#sharding-a-test-run-across-ci-jobs)
|
|
175
|
+
for a GitHub Actions matrix example.
|
|
176
|
+
|
|
143
177
|
Repeat runs are faster: the `godot --headless --import` step is cached under
|
|
144
178
|
`.gd-tools/native/import-cache/` and skipped when `project.godot`, any
|
|
145
179
|
project source/resource file (scripts, scenes, import sidecars, addons), or
|
|
@@ -278,7 +312,41 @@ eval "$(gd-tools)"
|
|
|
278
312
|
See the [User Guide](./docs/USER_GUIDE.md) for detailed per-shell
|
|
279
313
|
instructions.
|
|
280
314
|
|
|
281
|
-
## 7.
|
|
315
|
+
## 7. Pre-commit Hooks
|
|
316
|
+
|
|
317
|
+
Wire gd-tools into the [pre-commit](https://pre-commit.com) framework so
|
|
318
|
+
every commit runs your format check, lint, and (optionally) your test suite:
|
|
319
|
+
|
|
320
|
+
```bash
|
|
321
|
+
gd-tools install-hooks
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
The command generates `.pre-commit-hooks.yaml` and merges a `repos: local:`
|
|
325
|
+
entry into `.pre-commit-config.yaml`. Existing hooks — including your own —
|
|
326
|
+
are preserved; re-runs update only the gd-tools entries in place.
|
|
327
|
+
|
|
328
|
+
Interactive by default: confirm each hook (`format`, `lint`, `test`). For
|
|
329
|
+
scripted or CI use, pass flags instead:
|
|
330
|
+
|
|
331
|
+
```bash
|
|
332
|
+
gd-tools install-hooks --non-interactive # format + lint (defaults)
|
|
333
|
+
gd-tools install-hooks --all # format + lint + test
|
|
334
|
+
gd-tools install-hooks --hooks format,lint # explicit selection
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
| Flag | Behavior |
|
|
338
|
+
|---|---|
|
|
339
|
+
| `--all` | Enable every hook (format, lint, test). |
|
|
340
|
+
| `--hooks HOOKS` | Comma-separated selection, e.g. `--hooks format,lint`. |
|
|
341
|
+
| `--non-interactive` | Never prompt; use defaults or explicit flags. |
|
|
342
|
+
|
|
343
|
+
Exit codes follow the gd-tools convention: `0` installed, `1` nothing to do,
|
|
344
|
+
`2` config/environment error.
|
|
345
|
+
|
|
346
|
+
See the [User Guide](./docs/USER_GUIDE.md#8-pre-commit-hooks) for the
|
|
347
|
+
generated file contents and per-hook details.
|
|
348
|
+
|
|
349
|
+
## 8. Configuration
|
|
282
350
|
|
|
283
351
|
`gd-tools` uses a single `gd-tools.toml` file as the source of truth for
|
|
284
352
|
all tool configuration. `gd-tools init` generates this file with sensible
|
|
@@ -292,10 +360,9 @@ binary = "" # Optional -- auto-detected if unset
|
|
|
292
360
|
test_dirs = ["test", "tests"]
|
|
293
361
|
prefix = "test_"
|
|
294
362
|
suffix = ".gd"
|
|
295
|
-
gutconfig = ".gutconfig.json" # legacy; not read by any runtime
|
|
296
363
|
runtime = "native" # native (default); "gut" is no longer a runnable runtime
|
|
297
364
|
timeout_seconds = 5.0 # default per-test timeout for async native tests
|
|
298
|
-
retries = 0 # opt-in retries per native test
|
|
365
|
+
retries = 0 # opt-in retries per native test; retried passes are flagged as flaky
|
|
299
366
|
# parallel = 4 # opt-in parallel suite execution (1-32; unset runs sequentially)
|
|
300
367
|
tags = [] # native suite tag filters
|
|
301
368
|
|
|
@@ -343,7 +410,7 @@ version's config model.
|
|
|
343
410
|
See the [User Guide](./docs/USER_GUIDE.md) for a full configuration reference
|
|
344
411
|
with all keys, defaults, and examples.
|
|
345
412
|
|
|
346
|
-
##
|
|
413
|
+
## 9. Documentation
|
|
347
414
|
|
|
348
415
|
| Document | Description |
|
|
349
416
|
|----------|-------------|
|
|
@@ -354,7 +421,7 @@ with all keys, defaults, and examples.
|
|
|
354
421
|
| [Roadmap](./docs/ROADMAP.md) | Release phases and milestones. |
|
|
355
422
|
| [Testing Strategy](./docs/TESTING_STRATEGY.md) | Test pyramid, coverage targets, and CI integration. |
|
|
356
423
|
|
|
357
|
-
##
|
|
424
|
+
## 10. Development
|
|
358
425
|
|
|
359
426
|
```bash
|
|
360
427
|
# Clone and install in editable mode with dev dependencies
|
|
@@ -384,15 +451,14 @@ See [Testing Strategy](./docs/TESTING_STRATEGY.md) for the full testing
|
|
|
384
451
|
guide and [Contributing Guide](./docs/CONTRIBUTING.md) for development
|
|
385
452
|
setup details.
|
|
386
453
|
|
|
387
|
-
##
|
|
454
|
+
## 11. License
|
|
388
455
|
|
|
389
456
|
MIT
|
|
390
457
|
|
|
391
|
-
##
|
|
458
|
+
## 12. Acknowledgements
|
|
392
459
|
|
|
393
|
-
`gd-tools` stands on the shoulders of
|
|
394
|
-
|
|
395
|
-
hard parts.
|
|
460
|
+
`gd-tools` stands on the shoulders of excellent community tools, past and
|
|
461
|
+
present. Full credit to their authors for the hard parts.
|
|
396
462
|
|
|
397
463
|
- **[GUT (Godot Unit Test)](https://github.com/bitwes/Gut)** by
|
|
398
464
|
[bitwes](https://github.com/bitwes): the GDScript test framework whose
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "gd-tools-cli"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.8.0"
|
|
8
8
|
description = "A modern development workflow CLI for GDScript projects in Godot 4.5+"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = {text = "MIT"}
|
|
@@ -49,6 +49,7 @@ Documentation = "https://github.com/mansyar/gd-tools#readme"
|
|
|
49
49
|
dev = [
|
|
50
50
|
"pytest",
|
|
51
51
|
"pytest-cov",
|
|
52
|
+
"pytest-xdist",
|
|
52
53
|
"ruff==0.15.21",
|
|
53
54
|
"black",
|
|
54
55
|
"commitizen",
|
|
@@ -71,6 +72,10 @@ where = ["src"]
|
|
|
71
72
|
|
|
72
73
|
[tool.pytest.ini_options]
|
|
73
74
|
testpaths = ["tests"]
|
|
75
|
+
# Import gd_tools from this checkout's src/ rather than any globally
|
|
76
|
+
# installed (editable) copy, so worktrees and CI checkouts always test
|
|
77
|
+
# their own tree.
|
|
78
|
+
pythonpath = ["src"]
|
|
74
79
|
markers = [
|
|
75
80
|
"unit: Unit tests for individual modules.",
|
|
76
81
|
"integration: Integration tests for command flows.",
|
|
@@ -105,7 +110,7 @@ target-version = ["py310"]
|
|
|
105
110
|
|
|
106
111
|
[tool.commitizen]
|
|
107
112
|
name = "cz_conventional_commits"
|
|
108
|
-
version = "0.
|
|
113
|
+
version = "0.8.0"
|
|
109
114
|
version_files = ["pyproject.toml:version"]
|
|
110
115
|
changelog_file = "CHANGELOG.md"
|
|
111
116
|
tag_format = "v$version"
|