fix(cz_customize): set commit_parser default that captures change_type#1970
Open
bearomorphism wants to merge 2 commits intocommitizen-tools:masterfrom
Open
Conversation
CustomizeCommitsCz previously inherited the `commit_parser =
r"(?P<message>.*)"` default from `BaseCommitizen`. That default
matches everything but does not capture a `change_type` named group,
so even when a `cz_customize` user configured `changelog_pattern`,
`change_type_map` and `change_type_order`, the changelog generator
could not group commits and emitted a single ungrouped bullet list.
Set a conventional-commits-style default that captures
`change_type`, `scope`, `breaking` and `message` named groups.
Users with a different commit format can still override via
`customize.commit_parser`.
End-to-end check on the exact reproducer from the issue now produces a
properly grouped changelog:
## Unreleased
### feat
- **DL-4567**: new feature test
### fix
- **DL-1234**: qweqwe
### chore
- update deps
Closes commitizen-tools#466
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #1970 +/- ##
=======================================
Coverage 98.23% 98.23%
=======================================
Files 61 61
Lines 2779 2780 +1
=======================================
+ Hits 2730 2731 +1
Misses 49 49 ☔ View full report in Codecov by Sentry. |
15 tasks
Contributor
There was a problem hiding this comment.
Pull request overview
This PR addresses cz_customize changelog grouping by providing a default commit_parser that extracts change_type, enabling sectioned changelog output when users configure changelog_pattern but don’t explicitly set customize.commit_parser.
Changes:
- Add a conventional-commits-shaped
commit_parserdefault toCustomizeCommitsCzsochange_typecan be derived for grouping. - Add a regression test asserting the default parser extracts
change_type,scope,breaking, andmessagewithout explicit config.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| commitizen/cz/customize/customize.py | Adds a new class-level default commit_parser intended to extract change_type for changelog grouping. |
| tests/test_cz_customize.py | Adds a regression test verifying the new default parser extracts the expected named groups. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Wrap the conventional-commits prefix in an optional group so subjects that don't follow the format (e.g. 'bug fix: x', 'ticket-123 do stuff', '✨ feature: x') are still captured under <message> with change_type=None instead of being silently dropped by generate_tree_from_commits. Also broaden <change_type> from \w+ to [\w-]+ to accommodate hyphenated types. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Closes #466.
Why
cz_customizelets users define their own commit schema viachangelog_pattern,change_type_order, andchange_type_map— all the ingredients for a grouped changelog. However, until now, runningcz changelogwith those settings produced a single flat bullet list with no### Feat/### Fixheadings, making the feature effectively unusable without an extra, non-obvious step.The root cause is the
commit_parserdefault inherited fromBaseCommitizen.BaseCommitizen.commit_parserisr"(?P<message>.*)"(commitizen/cz/base.py:58) — a catch-all with nochange_typenamed group. The changelog generator incommitizen/changelog.py:195callsmsg.pop("change_type", None)to key commits into sections; without that group, every commit yieldschange_type = Noneand lands in an ungrouped bucket (changelog.py:198).A maintainer confirmed the gap in December 2021 (issue comment by @woile): "I think the
commit_parserregex is not exposed in the customize… and it looks like the customize is using the default from the base." Users who stumbled across the fix documented it in later comments — e.g. a community workaround posted in 2025 showing the exact four-group regex that had to be copy-pasted into everycz_customizeconfig. Triage against master (v4.15.1) in #1964 verified the bug is still present:cz changelog --dry-runwithchangelog_patternset still produces an ungrouped list.The fix gives
CustomizeCommitsCzits owncommit_parserclass attribute — a conventional-commits-shaped default that works for any schema following the<type>[(scope)][!]: <message>convention — so users who only setchangelog_patternget grouping for free.What changed
commitizen/cz/customize/customize.pycommit_parserclass attribute (conventional-commits-shaped default withchange_type,scope,breaking, andmessagenamed groups)tests/test_cz_customize.pytest_commit_parser_default_extracts_change_type— regression test verifying all four named groups are extracted without anycustomize.commit_parserconfig keyHow it works
commitizen/cz/customize/customize.py:32–45after the PR is applied) sits between the existingchange_type_orderdefault and__init__. It is a four-group regex:__init__override loop (commitizen/cz/customize/customize.py:40–50) already iterates over"commit_parser"and callssetattrif the user provided their own value. The class-level default is therefore transparently superseded by anycustomize.commit_parserkey — zero behaviour change for existing configs that already set one.\w+instead of a fixed alternation?cz_customizeis format-agnostic: it cannot know which types a project has defined. Hard-codingfeat|fix|chore|…would silently drop commits whose types aren't in the list.\w+captures any single-token type, which matches every conventional-commits derivative. An alternative — deriving the alternation fromchangelog_patternat runtime — was considered but is fragile:changelog_patternis a broad filter regex, not a structured grammar, so parsing it reliably would require a regex-of-regexes approach.commit_parseryourself"? The three other customisable attributes (changelog_pattern,change_type_order,change_type_map) all have sensible inherited defaults; a user who sets only those reasonably expects changelog grouping to work.generate_tree_from_commits(commitizen/changelog.py:92–171) compilescommit_parserwithre.MULTILINEand callsmap_pat.match(commit.message)per commit.process_commit_message(changelog.py:174–198) then callsparsed.groupdict()— so the named groups flow directly into thechangesdict that drives section headings.Backward compatibility
customize.commit_parserexplicitly are unaffected — the__init__loop (customize.py:40–50) overwrites the class default with their value viasetattr.commit_parserknowing it would match everything toNone) will now see headings. This is the desired fix; the old behaviour was a bug, not a feature.test_cz_customize.pytests still pass — the new default only changes what happens when nocommit_parseris configured.BaseCommitizen.commit_parser(commitizen/cz/base.py:58) is unchanged; other built-incz_*plugins are unaffected.Checklist
Was generative AI tooling used to co-author this PR?
Generated-by: Claude following the guidelines
Code Changes
uv run poe alllocally to ensure this change passes linter check and testsExpected Behavior
cz_customizewithchangelog_pattern+change_type_order, nocommit_parserkeycz changelog --dry-runrenders### feat,### fix,### choreheadingscz_customizewith an explicitcustomize.commit_parsercz_*(e.g.cz_conventional_commits)BaseCommitizen.commit_parseris unchangedcz_customizewith commits that don't match the new default (e.g.ticket-123 do stuff)change_type = None— same as before;changelog_patterncontrols what's includedSteps to Test This Pull Request