Skip to content

Commit 71a594d

Browse files
noirbizarrewoile
authored andcommitted
feat(changelog): changelog_message_build_hook can remove message by returning a falsy value
1 parent fc54b51 commit 71a594d

File tree

6 files changed

+53
-14
lines changed

6 files changed

+53
-14
lines changed

commitizen/changelog.py

+8-2
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,8 @@ def generate_tree_from_commits(
166166
change_type = change_type_map.get(change_type, change_type)
167167
if changelog_message_builder_hook:
168168
parsed_message = changelog_message_builder_hook(parsed_message, commit)
169-
changes[change_type].append(parsed_message)
169+
if parsed_message:
170+
changes[change_type].append(parsed_message)
170171

171172
# Process body from commit message
172173
body_parts = commit.body.split("\n\n")
@@ -179,7 +180,12 @@ def generate_tree_from_commits(
179180
change_type = parsed_message_body.pop("change_type", None)
180181
if change_type_map:
181182
change_type = change_type_map.get(change_type, change_type)
182-
changes[change_type].append(parsed_message_body)
183+
if changelog_message_builder_hook:
184+
parsed_message_body = changelog_message_builder_hook(
185+
parsed_message_body, commit
186+
)
187+
if parsed_message_body:
188+
changes[change_type].append(parsed_message_body)
183189

184190
yield {"version": current_tag_name, "date": current_tag_date, "changes": changes}
185191

commitizen/commands/changelog.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
from commitizen import bump, changelog, defaults, factory, git, out
1010

1111
from commitizen.config import BaseConfig
12+
from commitizen.cz.base import MessageBuilderHook
1213
from commitizen.exceptions import (
1314
DryRunExit,
1415
NoCommitsFoundError,
@@ -145,7 +146,7 @@ def __call__(self):
145146
unreleased_version = self.unreleased_version
146147
changelog_meta = changelog.Metadata()
147148
change_type_map: dict | None = self.change_type_map
148-
changelog_message_builder_hook: Callable | None = (
149+
changelog_message_builder_hook: MessageBuilderHook | None = (
149150
self.cz.changelog_message_builder_hook
150151
)
151152
merge_prerelease = self.merge_prerelease

commitizen/cz/base.py

+8-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from __future__ import annotations
22

33
from abc import ABCMeta, abstractmethod
4-
from typing import Any, Callable
4+
from typing import Any, Callable, Protocol
55

66
from jinja2 import BaseLoader, PackageLoader
77
from prompt_toolkit.styles import Style, merge_styles
@@ -11,6 +11,12 @@
1111
from commitizen.defaults import Questions
1212

1313

14+
class MessageBuilderHook(Protocol):
15+
def __call__(
16+
self, message: dict[str, Any], commit: git.GitCommit
17+
) -> dict[str, Any] | None: ...
18+
19+
1420
class BaseCommitizen(metaclass=ABCMeta):
1521
bump_pattern: str | None = None
1622
bump_map: dict[str, str] | None = None
@@ -37,9 +43,7 @@ class BaseCommitizen(metaclass=ABCMeta):
3743
change_type_order: list[str] | None = None
3844

3945
# Executed per message parsed by the commitizen
40-
changelog_message_builder_hook: None | (Callable[[dict, git.GitCommit], dict]) = (
41-
None
42-
)
46+
changelog_message_builder_hook: MessageBuilderHook | None = None
4347

4448
# Executed only at the end of the changelog generation
4549
changelog_hook: Callable[[str, str | None], str] | None = None

docs/bump.md

+5-5
Original file line numberDiff line numberDiff line change
@@ -147,13 +147,13 @@ by their precedence and showcase how a release might flow through a development
147147
148148
### `--increment-mode`
149149
150-
By default, `--increment-mode` is set to `linear`, which ensures taht bumping pre-releases _maintains linearity_:
151-
bumping of a pre-release with lower precedence than the current pre-release phase maintains the current phase of
152-
higher precedence. For example, if the current version is `1.0.0b1` then bumping with `--prerelease alpha` will
150+
By default, `--increment-mode` is set to `linear`, which ensures that bumping pre-releases _maintains linearity_:
151+
bumping of a pre-release with lower precedence than the current pre-release phase maintains the current phase of
152+
higher precedence. For example, if the current version is `1.0.0b1` then bumping with `--prerelease alpha` will
153153
continue to bump the “beta” phase.
154154
155-
Setting `--increment-mode` to `exact` instructs `cz bump` to instead apply the
156-
exact changes that have been specified with `--increment` or determined from the commit log. For example,
155+
Setting `--increment-mode` to `exact` instructs `cz bump` to instead apply the
156+
exact changes that have been specified with `--increment` or determined from the commit log. For example,
157157
`--prerelease beta` will always result in a `b` tag, and `--increment PATCH` will always increase the patch component.
158158
159159
Below are some examples that illustrate the difference in behavior:

docs/customization.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,7 @@ You can customize it of course, and this are the variables you need to add to yo
318318
| `commit_parser` | `str` | NO | Regex which should provide the variables explained in the [changelog description][changelog-des] |
319319
| `changelog_pattern` | `str` | NO | Regex to validate the commits, this is useful to skip commits that don't meet your ruling standards like a Merge. Usually the same as bump_pattern |
320320
| `change_type_map` | `dict` | NO | Convert the title of the change type that will appear in the changelog, if a value is not found, the original will be provided |
321-
| `changelog_message_builder_hook` | `method: (dict, git.GitCommit) -> dict` | NO | Customize with extra information your message output, like adding links, this function is executed per parsed commit. Each GitCommit contains the following attrs: `rev`, `title`, `body`, `author`, `author_email` |
321+
| `changelog_message_builder_hook` | `method: (dict, git.GitCommit) -> dict | None` | NO | Customize with extra information your message output, like adding links, this function is executed per parsed commit. Each GitCommit contains the following attrs: `rev`, `title`, `body`, `author`, `author_email`. Returning a falsy value ignore the commit. |
322322
| `changelog_hook` | `method: (full_changelog: str, partial_changelog: Optional[str]) -> str` | NO | Receives the whole and partial (if used incremental) changelog. Useful to send slack messages or notify a compliance department. Must return the full_changelog |
323323

324324
```python
@@ -339,7 +339,7 @@ class StrangeCommitizen(BaseCommitizen):
339339
340340
def changelog_message_builder_hook(
341341
self, parsed_message: dict, commit: git.GitCommit
342-
) -> dict:
342+
) -> dict | None:
343343
rev = commit.rev
344344
m = parsed_message["message"]
345345
parsed_message[

tests/test_changelog.py

+28
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import re
2+
13
from pathlib import Path
24

35
import pytest
@@ -1319,6 +1321,32 @@ def changelog_message_builder_hook(message: dict, commit: git.GitCommit) -> dict
13191321
assert "[link](github.com/232323232) Commitizen [email protected]" in result
13201322

13211323

1324+
def test_changelog_message_builder_hook_can_remove_commits(
1325+
gitcommits, tags, any_changelog_format: ChangelogFormat
1326+
):
1327+
def changelog_message_builder_hook(message: dict, commit: git.GitCommit):
1328+
return None
1329+
1330+
parser = ConventionalCommitsCz.commit_parser
1331+
changelog_pattern = ConventionalCommitsCz.changelog_pattern
1332+
loader = ConventionalCommitsCz.template_loader
1333+
template = any_changelog_format.template
1334+
tree = changelog.generate_tree_from_commits(
1335+
gitcommits,
1336+
tags,
1337+
parser,
1338+
changelog_pattern,
1339+
changelog_message_builder_hook=changelog_message_builder_hook,
1340+
)
1341+
result = changelog.render_changelog(tree, loader, template)
1342+
1343+
RE_HEADER = re.compile(r"^## v?\d+\.\d+\.\d+(\w)* \(\d{4}-\d{2}-\d{2}\)$")
1344+
# Rendered changelog should be empty, only containing version headers
1345+
for no, line in enumerate(result.splitlines()):
1346+
if line := line.strip():
1347+
assert RE_HEADER.match(line), f"Line {no} should not be there: {line}"
1348+
1349+
13221350
def test_get_smart_tag_range_returns_an_extra_for_a_range(tags):
13231351
start, end = (
13241352
tags[0],

0 commit comments

Comments
 (0)