Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Tune gerenuk

Reference for the knobs. Tune for speed once a run_all reason repeats.

Where the diff comes from. The working tree - staged, unstaged and untracked - is diffed from HEAD~1: the last commit plus what is not committed yet. scope set to "branch" (or --scope branch) diffs the whole branch from its merge-base with origin/main, then main, then master. --base <REF> beats both. --workspace <PATH> names the project root.

Budgets. The walk says run_all at the first limit it hits. A flag beats [tool.gerenuk] in pyproject.toml, which beats the default.

FlagKeyDefaultMeaning
--max-depth <N>max-depth10levels from a changed symbol out to a test
--max-symbols <N>max-symbols500symbols visited before giving up
--budget-ms <MS>budget-ms30000wall clock for the walk; 0 disables it
[tool.gerenuk]
max-depth = 20
suite-ms = 800
ignore-decorators = ["transformation", "celery.task"]
ignore-paths = ["**/*.md", "docs/**"]
docstrings = "code"
pytest-command = ["uv", "run", "pytest", "-o", "addopts="]
fallback-command = ["scripts/pick-subprojects.sh", "--from-gerenuk"]
  • suite-ms: how long the whole suite takes, from pytest’s summary line. A selection costs 1.5-2 s of tyf round-trips, so a suite declared at 2000 ms or under makes run skip the walk and say run_all (fast_suite) whenever the diff would have needed one. impacted-tests ignores it.
  • ignore-decorators: dotted names, suffix-matched syntactically, of decorators that register a function with a runner. A changed symbol carrying one is reported as ignored; import aliases are not resolved.
  • ignore-paths: non-Python files that never force run_all, matched on the repo-relative path (*, ?, **) and listed as ignored_paths; a .py file never is. Leave out anything a test reads, like checked docs.
  • docstrings: ignore (default) selects nothing for a docstring-only edit; code counts it, for code that reads __doc__ (docopt, CLI help text).
  • pytest-command: an argv, never a string, because the common value has arguments. Empty means pytest on PATH; GERENUK_PYTEST beats both. -o addopts= drops a coverage-carrying addopts for the hook run only.
  • fallback-command: what run execs instead of the whole suite on run_all. It gets the reason in GERENUK_FALLBACK_REASON, the changed-symbols report as JSON on stdin, and its exit code is the hook’s. --fallback-command <JSON_ARRAY> and GERENUK_FALLBACK override it, in that order. An empty array anywhere is an error at startup.
  • git-env: isolate (the default) removes GIT_DIR, GIT_INDEX_FILE and the rest of what a hook exports from pytest’s environment, so a test that creates a repository of its own never touches the one being committed; inherit keeps them. --git-env <POLICY> beats it. The fallback inherits.

Binaries. GERENUK_TYF, GERENUK_GIT and GERENUK_PYTEST each name one executable and skip the PATH lookup. Audit. gerenuk audit src/app.py lists symbols nothing references, or only tests reach. Exit 1 on findings.

next: run gerenuk run --dry-run