feat: JSON Schema for commitizen configuration (issue #1565) - #2067
feat: JSON Schema for commitizen configuration (issue #1565)#2067FreakyAdy wants to merge 3 commits into
Conversation
…ools#1565) - Add scripts/gen_json_schema.py: generates schema from 设置/Cz设置 TypedDicts - Add tests/test_json_schema.py: 18 tests validating schema generation, type mapping, defaults, and validation - Add schemas/commitizen-config.schema.json: committed schema (schemastore.org-compatible) - Update pyproject.toml: add jsonschema dependency to test group The schema covers all config keys under [tool.commitizen] including nested customize. All tests pass, ruff clean.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #2067 +/- ##
==========================================
+ Coverage 98.24% 99.07% +0.82%
==========================================
Files 61 61
Lines 2799 2799
==========================================
+ Hits 2750 2773 +23
+ Misses 49 26 -23 ☔ View full report in Codecov by Harness. |
There was a problem hiding this comment.
Pull request overview
Adds JSON Schema generation, validation tests, documentation, and dependencies for Commitizen configuration.
Changes:
- Adds schema generation and drift checking.
- 提交 the generated configuration schema.
- Adds schema validation tests and documentation.
- Adds JSON Schema tooling dependencies.
Reviewed changes
Copilot reviewed 5 out of 6 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Review summary |
|---|---|
uv.lock |
Missing the newly required types-jsonschema dependency, causing frozen CI installs to fail. |
tests/test_json_schema.py |
Adds schema generation and validation coverage. |
scripts/gen_json_schema.py |
Requires wrapper-schema support and stricter validation for question objects. |
schemas/README.md |
Documents the schema location and usage. |
schemas/commitizen-config.schema.json |
Needs wrapper support, broader question types and choices, and an optional confirm default. |
pyproject.toml |
Adds types-jsonschema, which is not reflected in the lockfile. |
Suppressed comments (1)
tests/test_json_schema.py:77
- CI will not run this drift test for schema- or generator-only edits:
pythonpackage.yml's path filter only treatscommitizen/**,tests/**, and.github/workflows/**as relevant (.github/workflows/pythonpackage.yml:23-26), excludingschemas/**andscripts/**. A stale committed schema can therefore bypass the check. Add these paths or an unconditional schema check.
def test_generated_schema_matches_committed_file(gen_module: Any) -> None:
"""The committed schema must be regenerated whenever the models change."""
expected = SCHEMA_PATH.read_text(encoding="utf-8")
actual = json.dumps(gen_module.generate_schema(), indent=2) + "\n"
💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| "types-PyYAML>=5.4.3", | ||
| "types-termcolor>=0.1.1", | ||
| "types-colorama>=0.4.15.20240311", | ||
| "types-jsonschema>=4.26.0", |
| "type": "object", | ||
| "properties": { |
| "type": { | ||
| "enum": [ | ||
| "list" | ||
| ] | ||
| }, |
| "choices": { | ||
| "type": "array", | ||
| "items": { | ||
| "type": "object", | ||
| "properties": { |
| "required": [ | ||
| "default", | ||
| "message", | ||
| "name", | ||
| "type" | ||
| ] |
| "type": "object", | ||
| "properties": settings_schema["properties"], | ||
| "additionalProperties": True, | ||
| } |
| schema: dict[str, Any] = {"type": "object", "properties": properties} | ||
| required = sorted(getattr(typed_dict, "__required_keys__", ())) | ||
| if required: | ||
| schema["required"] = required | ||
| return schema |
Manny7717
left a comment
There was a problem hiding this comment.
Verified locally on head 2b0b64b. Solid implementation overall — one real false-rejection finding in the customize.questions schema worth fixing before this ships to schemastore.
Verified good:
- 18/18 tests in tests/test_json_schema.py pass (jsonschema installed into the repo venv).
- Schema covers ALL 35
设置TypedDict keys — no missing, no extra. - Generator is deterministic; the committed schema matches
gen_json_schema.pyoutput byte-for-byte (--checkpasses). - Unknown top-level keys are allowed (extras/plugin keys — matches the stated scope), and wrong types are rejected (
version: 123,major_version_zero: "yes"→ invalid). - commitizen's own
[tool.commitizen]validates clean.
Finding — customize.questions rejects shapes the project documents as valid:
The schema only accepts question types list/input/confirm with choices as objects ({value,name,key}). But the runtime (questionary 2.1.1, AVAILABLE_PROMPTS) and commitizen's own docs support more:
docs/customization/config_file.md:177: "Valid types:list,select,input, etc." — yet{"type": "select", ...}fails the schema (selectis questionary's canonical name).text,path,editor,checkbox,password,rawselect,autocompleteare all runtime-valid too.docs/customization/config_file.md:41(choices = ["feature", "fix"] # short version) and:180("Either use a list of values or a list of dictionaries") — yet{"type": "list", "choices": ["feat", "fix"]}(plain strings) fails the schema, which requires choice objects.
I reproduced all of these with Draft202012Validator against the committed schema. The restriction is inherited faithfully from the narrow CzQuestion = ListQuestion | InputQuestion | ConfirmQuestion TypedDict (commitizen/question.py:33), so the schema is internally consistent with the typing — but for a schema whose purpose is validating user configs in IDEs, a false INVALID on a config commitizen runs fine is the worst kind of failure (it will send users to questionary docs, find select documented, and distrust the schema).
Suggested direction (either):
- Widen
CzQuestionto the questionary-supported types and makechoicesacceptstring | objectitems (oneOf), regenerating the schema — makes typing and schema match runtime; or - Keep the typed subset but document it explicitly in schemas/README.md so the restriction is a deliberate contract, not a surprise.
Minor: version_provider is a free-form string (no enum) — fine given providers are plugin-like and runtime-validated; not raising.
Happy to re-approve once the questions shapes are addressed — the generator, determinism, and coverage work are excellent.
Implements a JSON Schema for the commitizen configuration ([tool.commitizen] section in pyproject.toml, or commitizen key in .cz.json/.cz.yaml).
Summary:
设置andCz设置TypedDicts incommitizen.defaultsplusDEFAULT_SETTINGSruntime defaultsscripts/gen_json_schema.py(run manually or via CI--checkflag)schemas/commitizen-config.schema.json(points tohttps://json.schemastore.org/commitizen.jsonfor future schemastore.org release)tests/test_json_schema.pyvalidating generation, type mapping, defaults, and validationScope (per maintainer discussion in #1565):
commitizensection:[tool.commitizen]table in pyproject.toml (referenced with#:schema comment) orcommitizenkey in.cz.json/.cz.yaml(referenced with$schemakey)customize(Cz设置)Testing:
uv run ruff check --fix .cleanuv run ruff format .cleanAgent disclosure: This PR was developed with AI assistance (Hermes Agent).