Skip to content

Commit 3c687cf

Browse files
authored
Merge pull request #187 from commitizen-tools/feature/change-type-map
feature: maps and hooks
2 parents 47cc712 + df0042c commit 3c687cf

12 files changed

+209
-60
lines changed

commitizen/changelog.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
import re
3030
from collections import defaultdict
3131
from datetime import date
32-
from typing import Dict, Iterable, List, Optional
32+
from typing import Callable, Dict, Iterable, List, Optional
3333

3434
import pkg_resources
3535
from jinja2 import Template
@@ -72,6 +72,8 @@ def generate_tree_from_commits(
7272
commit_parser: str,
7373
changelog_pattern: str = defaults.bump_pattern,
7474
unreleased_version: Optional[str] = None,
75+
change_type_map: Optional[Dict[str, str]] = None,
76+
changelog_message_builder_hook: Optional[Callable] = None,
7577
) -> Iterable[Dict]:
7678
pat = re.compile(changelog_pattern)
7779
map_pat = re.compile(commit_parser)
@@ -112,10 +114,14 @@ def generate_tree_from_commits(
112114
message = map_pat.match(commit.message)
113115
message_body = map_pat.match(commit.body)
114116
if message:
115-
# TODO: add a post hook coming from a rule (CzBase)
116117
parsed_message: Dict = message.groupdict()
117118
# change_type becomes optional by providing None
118119
change_type = parsed_message.pop("change_type", None)
120+
121+
if change_type_map:
122+
change_type = change_type_map.get(change_type, change_type)
123+
if changelog_message_builder_hook:
124+
parsed_message = changelog_message_builder_hook(parsed_message, commit)
119125
changes[change_type].append(parsed_message)
120126
if message_body:
121127
parsed_message_body: Dict = message_body.groupdict()

commitizen/commands/changelog.py

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import os.path
22
from difflib import SequenceMatcher
33
from operator import itemgetter
4-
from typing import Dict, List
4+
from typing import Callable, Dict, List, Optional
55

66
from commitizen import changelog, factory, git, out
77
from commitizen.config import BaseConfig
@@ -27,6 +27,9 @@ def __init__(self, config: BaseConfig, args):
2727
self.incremental = args["incremental"]
2828
self.dry_run = args["dry_run"]
2929
self.unreleased_version = args["unreleased_version"]
30+
self.change_type_map = (
31+
self.config.settings.get("change_type_map") or self.cz.change_type_map
32+
)
3033

3134
def _find_incremental_rev(self, latest_version: str, tags: List[GitTag]) -> str:
3235
"""Try to find the 'start_rev'.
@@ -60,6 +63,11 @@ def __call__(self):
6063
start_rev = self.start_rev
6164
unreleased_version = self.unreleased_version
6265
changelog_meta: Dict = {}
66+
change_type_map: Optional[Dict] = self.change_type_map
67+
changelog_message_builder_hook: Optional[
68+
Callable
69+
] = self.cz.changelog_message_builder_hook
70+
changelog_hook: Optional[Callable] = self.cz.changelog_hook
6371

6472
if not changelog_pattern or not commit_parser:
6573
out.error(
@@ -83,7 +91,13 @@ def __call__(self):
8391
raise SystemExit(NO_COMMITS_FOUND)
8492

8593
tree = changelog.generate_tree_from_commits(
86-
commits, tags, commit_parser, changelog_pattern, unreleased_version
94+
commits,
95+
tags,
96+
commit_parser,
97+
changelog_pattern,
98+
unreleased_version,
99+
change_type_map=change_type_map,
100+
changelog_message_builder_hook=changelog_message_builder_hook,
87101
)
88102
changelog_out = changelog.render_changelog(tree)
89103

@@ -97,10 +111,14 @@ def __call__(self):
97111
lines = changelog_file.readlines()
98112

99113
with open(self.file_name, "w") as changelog_file:
114+
partial_changelog: Optional[str] = None
100115
if self.incremental:
101116
new_lines = changelog.incremental_build(
102117
changelog_out, lines, changelog_meta
103118
)
104-
changelog_file.writelines(new_lines)
105-
else:
106-
changelog_file.write(changelog_out)
119+
changelog_out = "".join(new_lines)
120+
partial_changelog = changelog_out
121+
122+
if changelog_hook:
123+
changelog_out = changelog_hook(changelog_out, partial_changelog)
124+
changelog_file.write(changelog_out)

commitizen/commands/version.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,14 @@ def __call__(self):
1616
if version:
1717
out.write(f"{version}")
1818
else:
19-
out.error(f"No project information in this project.")
19+
out.error("No project information in this project.")
2020
elif self.parameter.get("verbose"):
2121
out.write(f"Installed Commitizen Version: {__version__}")
2222
version = self.config.settings["version"]
2323
if version:
2424
out.write(f"Project Version: {version}")
2525
else:
26-
out.error(f"No project information in this project.")
26+
out.error("No project information in this project.")
2727
else:
2828
# if no argument is given, show installed commitizen version
2929
out.write(f"{__version__}")

commitizen/cz/base.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
from abc import ABCMeta, abstractmethod
2-
from typing import List, Optional, Tuple
2+
from typing import Callable, Dict, List, Optional, Tuple
33

44
from prompt_toolkit.styles import Style, merge_styles
55

6+
from commitizen import git
67
from commitizen.config.base_config import BaseConfig
78

89

@@ -27,7 +28,15 @@ class BaseCommitizen(metaclass=ABCMeta):
2728
# It can be modified per rule
2829
commit_parser: Optional[str] = r"(?P<message>.*)"
2930
changelog_pattern: Optional[str] = r".*"
30-
changelog_map: Optional[dict] = None # TODO: Use it
31+
change_type_map: Optional[Dict[str, str]] = None
32+
33+
# Executed per message parsed by the commitizen
34+
changelog_message_builder_hook: Optional[
35+
Callable[[Dict, git.GitCommit], Dict]
36+
] = None
37+
38+
# Executed only at the end of the changelog generation
39+
changelog_hook: Optional[Callable[[str, Optional[str]], str]] = None
3140

3241
def __init__(self, config: BaseConfig):
3342
self.config = config

commitizen/cz/conventional_commits/conventional_commits.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,12 @@ class ConventionalCommitsCz(BaseCommitizen):
3232
bump_map = defaults.bump_map
3333
commit_parser = defaults.commit_parser
3434
changelog_pattern = defaults.bump_pattern
35+
change_type_map = {
36+
"feat": "Feat",
37+
"fix": "Fix",
38+
"refactor": "Refactor",
39+
"perf": "Perf",
40+
}
3541

3642
def questions(self) -> List[Dict[str, Any]]:
3743
questions: List[Dict[str, Any]] = [

commitizen/templates/keep_a_changelog_template.j2

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
{% for change_key, changes in entry.changes.items() %}
66

77
{% if change_key %}
8-
### {{ change_key|title }}
8+
### {{ change_key }}
99
{% endif %}
1010

1111
{% for change in changes %}

docs/changelog.md

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -124,10 +124,15 @@ Benefits:
124124
cz changelog --incremental
125125
```
126126
127-
## TODO
127+
## Hooks
128128
129-
- [ ] support for hooks: this would allow introduction of custom information in the commiter, like a github or jira url. Eventually we could build a `CzConventionalGithub`, which would add links to commits
130-
- [ ] support for map: allow the usage of a `change_type` mapper, to convert from feat to feature for example.
129+
Supported hook methods:
130+
131+
- per parsed message: useful to add links
132+
- end of changelog generation: useful to send slack or chat message, or notify another department
133+
134+
Read more about hooks in the [customization page][customization]
131135
132136
[keepachangelog]: https://keepachangelog.com/
133137
[semver]: https://semver.org/
138+
[customization]: ./customization.md

0 commit comments

Comments
 (0)