Commit ccb0e11
authored
feat(tests): Cover
### Description of your changes
#### What
<sub>This section was generated by AI.</sub>
- Add `tests/pytest/tool_version_test.py`: black-box pytest suite for `--hook-config=--tool-version=` / `--tool-version-mode=` / `--tf-path` resolution added on `downloadable_and_version_controlled_hooks`. Tests invoke real `hooks/*.sh` scripts as subprocesses and assert only on exit code / cache filesystem state / output - never on bash-internal function names - so they need minimal changes if a hook is ever rewritten in another language.
- **Assertions prove which binary actually ran.** Each stub echoes a unique marker; every network-free test asserts that marker plus the absence of the losing candidate's. `--tool-version-mode=strict` in particular logs its NOTE *before* choosing a binary.
- Hooks now run against a coreutils-only `PATH` (no wrapped CLI tool) and an allowlisted environment (`PRE_COMMIT_COLOR=never`, `LC_ALL=C`, no inherited `PCT_TFPATH`/`TERRAGRUNT_TFPATH`/`TF_*`), so a host install or an exported variable cannot change what a test resolves. The temp repo is created with `git init --template=` and committed with `--no-verify`, because this project's own README tells users to point `init.templateDir` at a directory with pre-commit installed.
- Coverage: cache-hit reuse, `strict` vs `prefer-local`, the `--tf-path=terraform|opentofu|tofu` selector and its invalid-value error, `--tf-path` auto-detect **including Terraform winning when both binaries are on `$PATH`**, `--tf-path` literal passthrough when `--tool-version` is *not* set, the `XDG_CACHE_HOME` and `$HOME/.cache` cache roots, the documented `checkov` no-op, the actionable "tool not found" error, the `tool_name` wired by **each of the 14 resolving hooks**, and one real end-to-end download on a cache miss.
- `fix(hooks)`: resolve a pinned tool **once** per run. `common::per_dir_hook` now takes the already-resolved `tool_path` instead of re-resolving it, so hooks that need it before the per-dir loop (`tflint --init`; the terragrunt hooks choosing `hcl format` vs `hclfmt`) no longer trigger a duplicate NOTE log and, on a cache miss, a duplicate download.
- `fix(hooks)`: reject an unrecognized `--tool-version-mode` instead of treating it as `strict`, so a typo like `prefer_local` no longer silently does the opposite of what was asked. Documented in README.
- Package `hooks/`, `lib_getopt` and `tools/install/` into the sdist (`hatch.toml`), since the CI `tests` job runs pytest against a built sdist and needs the hook scripts this suite subprocesses into.
- Fix bash 3.2 (macOS default) `${var^^}` usage in `hooks/_common.sh` / `tools/install/_common.sh` (portable `tr` pipeline) and an OpenTofu release-asset version-regex bug.
- Wire `GITHUB_TOKEN` into the tox test job so the real-download test authenticates its `api.github.com` call instead of sharing the unauthenticated per-IP rate limit across the whole CI matrix.
- Mark the download test `network` (registered in `pytest.ini`, which `--strict-markers` requires) so `-m 'not network'` runs the suite offline.
- Flat test functions rather than test classes, matching this repo's existing `_cli_test.py` / `terraform_docs_replace_test.py` convention; parametrized cases are bundled into `NamedTuple`s to satisfy `PLR0913`/`WPS211` without suppressions. `.flake8` ignores `WPS226` (string-literal overuse, same precedent as `_cli_test.py`) plus `WPS202`/`WPS204`, which a wide table-driven suite trips by construction. Windows-skip coverage pragmas satisfy the `covdefaults` 100% coverage gate.
- Merge `stderr` into `stdout` in `_run_hook`, because `common::colorify` writes every diagnostic to stderr while a wrapped tool's own output goes to stdout - one ready-to-grep string per caller.
#### Why
> [!IMPORTANT]
> Somehow related/conflicts with #990. So far - I can't say what will be chosen, waiting for python-guru's review
Main idea - make some black-box testing for bash hooks on pytest, which then can be applied on hooks reimplementation on Python, when/if it time comes
Or if that's a shity approach - then just make some black-box testing, not in pytest
### How can we test changes
<sub>This section was generated by AI.</sub>
- Offline: `pytest tests/pytest/ -m 'not network'` - 43 passed, 1 deselected.
- Full suite: `pytest tests/pytest/` - 44 passed, coverage 100.00% (the `covdefaults` gate). Network test alone: `pytest -m network` - 1 passed.
- **Mutation-tested.** Each of these, applied on its own, turns the suite red: strict mode falling back to `$PATH`; inverting the `--tf-path` auto-detect precedence; dropping the `XDG_CACHE_HOME` fallback; a `terraform-docs` -> `terraform_docs` `tool_name` typo; `--tf-path` passthrough hijacked by the pinning code; `prefer-local` ignored; the `opentofu` -> `tofu` binary rename forgotten; the `--tool-version-mode` validation removed; and re-introducing the duplicate resolution inside `common::per_dir_hook`.
- Each new commit was checked out into a separate `git worktree` and its test suite run there, to confirm no intermediate commit is broken.
- This PR targets `downloadable_and_version_controlled_hooks` (not `master`) so this repo's GH Actions matrix runs the suite for real, including the network-dependent download test.
- All pre-commit hooks pass locally: `shellcheck`, `shfmt`, `ruff check`, `ruff format`, `wemake-python-styleguide`, `mypy` (py3.10/3.12/3.14).--hook-config=--tool-version resolution with pytest (#1004)1 parent cc08a68 commit ccb0e11
19 files changed
Lines changed: 1106 additions & 36 deletions
File tree
- .github/workflows
- hooks
- tests/pytest
- tools/install
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
78 | 78 | | |
79 | 79 | | |
80 | 80 | | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
81 | 88 | | |
82 | 89 | | |
83 | 90 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
311 | 311 | | |
312 | 312 | | |
313 | 313 | | |
| 314 | + | |
| 315 | + | |
| 316 | + | |
| 317 | + | |
| 318 | + | |
| 319 | + | |
| 320 | + | |
314 | 321 | | |
315 | 322 | | |
316 | 323 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
2 | 2 | | |
3 | 3 | | |
4 | 4 | | |
| 5 | + | |
| 6 | + | |
5 | 7 | | |
6 | 8 | | |
| 9 | + | |
7 | 10 | | |
8 | 11 | | |
9 | 12 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
309 | 309 | | |
310 | 310 | | |
311 | 311 | | |
312 | | - | |
| 312 | + | |
| 313 | + | |
| 314 | + | |
| 315 | + | |
| 316 | + | |
| 317 | + | |
313 | 318 | | |
314 | 319 | | |
315 | 320 | | |
316 | 321 | | |
317 | 322 | | |
318 | 323 | | |
319 | | - | |
| 324 | + | |
320 | 325 | | |
321 | 326 | | |
322 | 327 | | |
| |||
330 | 335 | | |
331 | 336 | | |
332 | 337 | | |
333 | | - | |
334 | | - | |
335 | | - | |
336 | | - | |
337 | | - | |
338 | 338 | | |
339 | 339 | | |
340 | 340 | | |
| |||
616 | 616 | | |
617 | 617 | | |
618 | 618 | | |
| 619 | + | |
| 620 | + | |
| 621 | + | |
| 622 | + | |
| 623 | + | |
| 624 | + | |
| 625 | + | |
| 626 | + | |
| 627 | + | |
| 628 | + | |
| 629 | + | |
| 630 | + | |
| 631 | + | |
619 | 632 | | |
620 | 633 | | |
621 | 634 | | |
| |||
664 | 677 | | |
665 | 678 | | |
666 | 679 | | |
667 | | - | |
| 680 | + | |
| 681 | + | |
668 | 682 | | |
669 | 683 | | |
670 | 684 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
20 | 20 | | |
21 | 21 | | |
22 | 22 | | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
23 | 28 | | |
24 | | - | |
| 29 | + | |
25 | 30 | | |
26 | 31 | | |
27 | 32 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
17 | 17 | | |
18 | 18 | | |
19 | 19 | | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
20 | 25 | | |
21 | | - | |
| 26 | + | |
22 | 27 | | |
23 | 28 | | |
24 | 29 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
17 | 17 | | |
18 | 18 | | |
19 | 19 | | |
20 | | - | |
21 | | - | |
22 | | - | |
23 | 20 | | |
24 | 21 | | |
25 | 22 | | |
| |||
39 | 36 | | |
40 | 37 | | |
41 | 38 | | |
42 | | - | |
| 39 | + | |
43 | 40 | | |
44 | 41 | | |
45 | 42 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
23 | 23 | | |
24 | 24 | | |
25 | 25 | | |
26 | | - | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
27 | 32 | | |
28 | 33 | | |
29 | 34 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
15 | 15 | | |
16 | 16 | | |
17 | 17 | | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
18 | 23 | | |
19 | | - | |
| 24 | + | |
20 | 25 | | |
21 | 26 | | |
22 | 27 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
24 | 24 | | |
25 | 25 | | |
26 | 26 | | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
27 | 32 | | |
28 | | - | |
| 33 | + | |
29 | 34 | | |
30 | 35 | | |
31 | 36 | | |
| |||
0 commit comments