Commitizen has two kinds of generated artifacts that look like regular files in git status but are produced by poe tasks:
- Test regression snapshots — used by
pytest-regressions. Stored undertests/next to the tests that produce them. - CLI
--helpscreenshots and demo GIFs — used in the rendered docs. Stored underdocs/images/cli_help/anddocs/images/cli_interactive/.
Both need to be regenerated whenever the underlying behavior changes — test snapshots when output intentionally changes, and CLI screenshots when flags or help text change.
- A test fails with
pytest-regressionscomplaining about a snapshot mismatch, and the new output is the intended output. - A CLI flag was added or renamed (see add-cli-flag playbook).
- A subcommand's
--helptext changed.
pyproject.toml:tool.poe.tasks— see thetest:regen,doc:screenshots, andtest:alltask definitions.scripts/gen_cli_help_screenshots.pyandscripts/gen_cli_interactive_gifs.py— the screenshot generators.docs/images/*.tape—vhstape files that drive the GIF generation.- The failing test, to confirm the snapshot file path and that the diff is intentional.
The test:regen task runs both single-Python and all-Python regenerations because some snapshots are Python-version-specific (their names start with py_):
uv run poe test:regenUnder the hood:
"test:regen".parallel = [
{ ref = "test -k 'not py_' --regen-all" }, # version-agnostic
{ ref = "test:all -- -k py_ --regen-all" }, # per-Python-version via tox
]The test:all half requires tox and the supported Python interpreters to be installed locally. If only the version-agnostic snapshots changed, run just the first half:
uv run pytest -k 'not py_' --regen-all -n autoAfter regeneration:
- Inspect every changed file with
git --no-pager diff. The new content must be what the code was supposed to produce — do not blanket-commit snapshot diffs without reading them. - Stage and commit the snapshots in the same commit as the code change that motivated them. Reviewers need both halves to validate intentionality.
After any flag, help-text, or subcommand change, regenerate the SVGs and GIFs displayed in the docs:
uv run poe doc:screenshotsThis runs two scripts in parallel:
scripts/gen_cli_help_screenshots.py→ updates SVGs underdocs/images/cli_help/.scripts/gen_cli_interactive_gifs.py→ updates GIFs underdocs/images/cli_interactive/usingvhsand the.tapefiles underdocs/images/.
GIF generation requires vhs to be installed on PATH. If it is not available locally, run only the SVG half:
uv run python -m scripts.gen_cli_help_screenshotsand skip the GIFs — surface in the PR description that the GIFs need to be regenerated by a maintainer.
git --no-pager diff # read every snapshot diff before committing
uv run pytest -n auto # snapshots now match
uv run poe doc:build # mkdocs renders new images without broken links
uv run poe all # final pre-push- Regenerating without reading the diff.
--regen-alloverwrites every snapshot the test touches. If a bug in your code changed the output, the snapshot will faithfully record the bug. - Committing snapshots separately from the code change. Reviewers cannot tell intent from a snapshot-only commit.
vhsnot installed. The GIF script silently fails or produces an empty file. Inspectdocs/images/cli_interactive/*.gifafter running and check file sizes are non-zero.- Python-version-specific snapshots. Tests whose names start with
py_(e.g.,tests/test_x.py::test_py_3_12_specific) needtest:allto regenerate across all interpreters. Skipping that step passes locally but breaks CI on the other matrix rows. - Encoding-dependent snapshots. On Windows,
pytest-regressionsmay write CRLF line endings. Configure git or your editor to normalize, or the diff will be all-lines-changed.
- A snapshot regenerates with a diff that does not match what your code change should produce — there is a bug. Do not commit the snapshot.
- The CI failure asks for snapshot regeneration but you cannot reproduce the diff locally — Python-version mismatch is the most likely cause; flag it in the PR.
doc:screenshotsrequires installingvhsand you are running in a sandboxed environment that cannot install system packages.