Skip to content

Commit 79a72cd

Browse files
committed
feat(conventional_commits): allow exclamation in title on BC
Add a configuration (disable by default) to allow exclamation in commit title to ease identify BC simple git log parsing. Signed-off-by: Sebastien Fusilier <[email protected]>
1 parent b8f9bf6 commit 79a72cd

File tree

5 files changed

+75
-0
lines changed

5 files changed

+75
-0
lines changed

commitizen/cz/conventional_commits/conventional_commits.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,12 +153,22 @@ def message(self, answers: ConventionalCommitsAnswers) -> str: # type: ignore[o
153153
body = answers["body"]
154154
footer = answers["footer"]
155155
is_breaking_change = answers["is_breaking_change"]
156+
157+
# Check if breaking change exclamation in title is enabled
158+
breaking_change_exclamation_in_title = self.config.settings.get(
159+
"breaking_change_exclamation_in_title", False
160+
)
156161

157162
if scope:
158163
scope = f"({scope})"
159164
if body:
160165
body = f"\n\n{body}"
161166
if is_breaking_change:
167+
if breaking_change_exclamation_in_title:
168+
if scope:
169+
scope = f"{scope}!"
170+
else:
171+
prefix = f"{prefix}!"
162172
footer = f"BREAKING CHANGE: {footer}"
163173
if footer:
164174
footer = f"\n\n{footer}"

commitizen/defaults.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ class Settings(TypedDict, total=False):
6161
version_scheme: str | None
6262
version_type: str | None
6363
version: str | None
64+
breaking_change_exclamation_in_title: bool
6465

6566

6667
CONFIG_FILES: list[str] = [
@@ -108,6 +109,7 @@ class Settings(TypedDict, total=False):
108109
"always_signoff": False,
109110
"template": None, # default provided by plugin
110111
"extras": {},
112+
"breaking_change_exclamation_in_title": False,
111113
}
112114

113115
MAJOR = "MAJOR"

docs/config.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,15 @@ Default: `None`
103103

104104
Create custom commit message, useful to skip CI. [Read more][bump_message]
105105

106+
### `breaking_change_exclamation_in_title`
107+
108+
Type: `bool`
109+
110+
Default: `false`
111+
112+
When true, breaking changes will be indicated by an exclamation mark in the commit title (e.g., `feat!: breaking change`).
113+
When false, breaking changes will be indicated by `BREAKING CHANGE:` in the footer. [Read more][breaking-change-exclamation]
114+
106115
### `retry_after_failure`
107116

108117
Type: `bool`

docs/tutorials/writing_commits.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ add to your commit body the following `BREAKING CHANGE`.
1313
Using these three keywords will allow the proper identification of the semantic version.
1414
Of course, there are other keywords, but I'll leave it to the reader to explore them.
1515

16+
Note: You can also indicate breaking changes by adding an exclamation mark in the commit title
17+
(e.g., `feat!: breaking change`) by setting the `breaking_change_exclamation_in_title`
18+
configuration option to `true`. [Read more][breaking-change-config]
19+
1620
## Writing commits
1721

1822
Now to the important part: when writing commits, it's important to think about:
@@ -44,3 +48,4 @@ Emojis may be added as well (e.g., see [cz-emoji][cz_emoji]), which requires the
4448
[conventional_commits]: https://www.conventionalcommits.org
4549
[cz_emoji]: https://commitizen-tools.github.io/commitizen/third-party-commitizen/#cz-emoji
4650
[configuration]: ../config.md#encoding
51+
[breaking-change-config]: ../config.md#breaking_change_exclamation_in_title

tests/test_cz_conventional_commits.py

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,55 @@ def test_breaking_change_in_footer(config):
105105
)
106106

107107

108+
@pytest.mark.parametrize(
109+
"scope,breaking_change_exclamation_in_title,expected_message",
110+
[
111+
# Test with scope and breaking_change_exclamation_in_title enabled
112+
(
113+
"users",
114+
True,
115+
"feat(users)!: email pattern corrected\n\ncomplete content\n\nBREAKING CHANGE: migrate by renaming user to users",
116+
),
117+
# Test without scope and breaking_change_exclamation_in_title enabled
118+
(
119+
"",
120+
True,
121+
"feat!: email pattern corrected\n\ncomplete content\n\nBREAKING CHANGE: migrate by renaming user to users",
122+
),
123+
# Test with scope and breaking_change_exclamation_in_title disabled
124+
(
125+
"users",
126+
False,
127+
"feat(users): email pattern corrected\n\ncomplete content\n\nBREAKING CHANGE: migrate by renaming user to users",
128+
),
129+
# Test without scope and breaking_change_exclamation_in_title disabled
130+
(
131+
"",
132+
False,
133+
"feat: email pattern corrected\n\ncomplete content\n\nBREAKING CHANGE: migrate by renaming user to users",
134+
),
135+
],
136+
)
137+
def test_breaking_change_message_formats(
138+
config, scope, breaking_change_exclamation_in_title, expected_message
139+
):
140+
# Set the breaking_change_exclamation_in_title setting
141+
config.settings["breaking_change_exclamation_in_title"] = (
142+
breaking_change_exclamation_in_title
143+
)
144+
conventional_commits = ConventionalCommitsCz(config)
145+
answers = {
146+
"prefix": "feat",
147+
"scope": scope,
148+
"subject": "email pattern corrected",
149+
"is_breaking_change": True,
150+
"body": "complete content",
151+
"footer": "migrate by renaming user to users",
152+
}
153+
message = conventional_commits.message(answers)
154+
assert message == expected_message
155+
156+
108157
def test_example(config):
109158
"""just testing a string is returned. not the content"""
110159
conventional_commits = ConventionalCommitsCz(config)

0 commit comments

Comments
 (0)