Skip to content

Commit afa0063

Browse files
committed
refactor(bump_rule): add old school bump rule for backward compatibility
1 parent 57205e4 commit afa0063

File tree

2 files changed

+231
-2
lines changed

2 files changed

+231
-2
lines changed

commitizen/bump_rule.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from functools import cached_property
66
from typing import Callable, Protocol
77

8+
from commitizen.exceptions import NoPatternMapError
89
from commitizen.version_schemes import Increment
910

1011
_VERSION_ORDERING = dict(zip((None, "PATCH", "MINOR", "MAJOR"), range(4)))
@@ -86,4 +87,39 @@ def _head_pattern(self) -> re.Pattern:
8687
return re.compile(f"^{re_change_type}{re_scope}{re_bang}:")
8788

8889

90+
class OldSchoolBumpRule(BumpRule):
91+
"""TODO: rename?"""
92+
93+
def __init__(
94+
self,
95+
bump_pattern: str,
96+
bump_map: dict[str, Increment],
97+
bump_map_major_version_zero: dict[str, Increment],
98+
):
99+
if not bump_map or not bump_pattern:
100+
raise NoPatternMapError(
101+
f"Invalid bump rule: {bump_pattern=} and {bump_map=}"
102+
)
103+
104+
self.bump_pattern = re.compile(bump_pattern)
105+
self.bump_map = bump_map
106+
self.bump_map_major_version_zero = bump_map_major_version_zero
107+
108+
def get_increment(
109+
self, commit_message: str, major_version_zero: bool
110+
) -> Increment | None:
111+
if not (m := self.bump_pattern.search(commit_message)):
112+
return None
113+
114+
bump_map = (
115+
self.bump_map_major_version_zero if major_version_zero else self.bump_map
116+
)
117+
118+
found_keyword = m.group(1)
119+
for match_pattern, increment in bump_map.items():
120+
if re.match(match_pattern, found_keyword):
121+
return increment
122+
return None
123+
124+
89125
# TODO: Implement CustomBumpRule

tests/test_bump_rule.py

Lines changed: 195 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,19 @@
11
import pytest
22

3-
from commitizen.bump_rule import ConventionalCommitBumpRule, find_increment_by_callable
4-
from commitizen.defaults import MAJOR, MINOR, PATCH
3+
from commitizen.bump_rule import (
4+
ConventionalCommitBumpRule,
5+
OldSchoolBumpRule,
6+
find_increment_by_callable,
7+
)
8+
from commitizen.defaults import (
9+
BUMP_MAP,
10+
BUMP_MAP_MAJOR_VERSION_ZERO,
11+
BUMP_PATTERN,
12+
MAJOR,
13+
MINOR,
14+
PATCH,
15+
)
16+
from commitizen.exceptions import NoPatternMapError
517

618

719
@pytest.fixture
@@ -165,3 +177,184 @@ def test_commit_with_scope(self, get_increment):
165177
"fix(ui): fix button alignment",
166178
]
167179
assert find_increment_by_callable(commit_messages, get_increment) == MINOR
180+
181+
182+
class TestOldSchoolBumpRule:
183+
@pytest.fixture
184+
def bump_pattern(self):
185+
return r"^.*?\[(.*?)\].*$"
186+
187+
@pytest.fixture
188+
def bump_map(self):
189+
return {
190+
"MAJOR": MAJOR,
191+
"MINOR": MINOR,
192+
"PATCH": PATCH,
193+
}
194+
195+
@pytest.fixture
196+
def bump_map_major_version_zero(self):
197+
return {
198+
"MAJOR": MINOR, # MAJOR becomes MINOR in version zero
199+
"MINOR": MINOR,
200+
"PATCH": PATCH,
201+
}
202+
203+
@pytest.fixture
204+
def old_school_rule(self, bump_pattern, bump_map, bump_map_major_version_zero):
205+
return OldSchoolBumpRule(bump_pattern, bump_map, bump_map_major_version_zero)
206+
207+
def test_major_version(self, old_school_rule):
208+
assert (
209+
old_school_rule.get_increment("feat: add new feature [MAJOR]", False)
210+
== MAJOR
211+
)
212+
assert old_school_rule.get_increment("fix: bug fix [MAJOR]", False) == MAJOR
213+
214+
def test_minor_version(self, old_school_rule):
215+
assert (
216+
old_school_rule.get_increment("feat: add new feature [MINOR]", False)
217+
== MINOR
218+
)
219+
assert old_school_rule.get_increment("fix: bug fix [MINOR]", False) == MINOR
220+
221+
def test_patch_version(self, old_school_rule):
222+
assert (
223+
old_school_rule.get_increment("feat: add new feature [PATCH]", False)
224+
== PATCH
225+
)
226+
assert old_school_rule.get_increment("fix: bug fix [PATCH]", False) == PATCH
227+
228+
def test_major_version_zero(self, old_school_rule):
229+
assert (
230+
old_school_rule.get_increment("feat: add new feature [MAJOR]", True)
231+
== MINOR
232+
)
233+
assert old_school_rule.get_increment("fix: bug fix [MAJOR]", True) == MINOR
234+
235+
def test_no_match(self, old_school_rule):
236+
assert old_school_rule.get_increment("feat: add new feature", False) is None
237+
assert old_school_rule.get_increment("fix: bug fix", False) is None
238+
239+
def test_invalid_pattern(self, bump_map, bump_map_major_version_zero):
240+
with pytest.raises(NoPatternMapError):
241+
OldSchoolBumpRule("", bump_map, bump_map_major_version_zero)
242+
243+
def test_invalid_bump_map(self, bump_pattern):
244+
with pytest.raises(NoPatternMapError):
245+
OldSchoolBumpRule(bump_pattern, {}, {})
246+
247+
def test_complex_pattern(self):
248+
pattern = r"^.*?\[(.*?)\].*?\[(.*?)\].*$"
249+
bump_map = {
250+
"MAJOR": MAJOR,
251+
"MINOR": MINOR,
252+
"PATCH": PATCH,
253+
}
254+
rule = OldSchoolBumpRule(pattern, bump_map, bump_map)
255+
256+
assert (
257+
rule.get_increment("feat: add new feature [MAJOR] [MINOR]", False) == MAJOR
258+
)
259+
assert rule.get_increment("fix: bug fix [MINOR] [PATCH]", False) == MINOR
260+
261+
def test_with_find_increment_by_callable(self, old_school_rule):
262+
commit_messages = [
263+
"feat: add new feature [MAJOR]",
264+
"fix: bug fix [PATCH]",
265+
"docs: update readme [MINOR]",
266+
]
267+
assert (
268+
find_increment_by_callable(
269+
commit_messages, lambda x: old_school_rule.get_increment(x, False)
270+
)
271+
== MAJOR
272+
)
273+
274+
275+
class TestOldSchoolBumpRuleWithDefault:
276+
@pytest.fixture
277+
def old_school_rule(self):
278+
return OldSchoolBumpRule(BUMP_PATTERN, BUMP_MAP, BUMP_MAP_MAJOR_VERSION_ZERO)
279+
280+
def test_breaking_change_with_bang(self, old_school_rule):
281+
assert old_school_rule.get_increment("feat!: breaking change", False) == MAJOR
282+
assert old_school_rule.get_increment("fix!: breaking change", False) == MAJOR
283+
assert old_school_rule.get_increment("feat!: breaking change", True) == MINOR
284+
assert old_school_rule.get_increment("fix!: breaking change", True) == MINOR
285+
286+
def test_breaking_change_type(self, old_school_rule):
287+
assert (
288+
old_school_rule.get_increment("BREAKING CHANGE: major change", False)
289+
== MAJOR
290+
)
291+
assert (
292+
old_school_rule.get_increment("BREAKING-CHANGE: major change", False)
293+
== MAJOR
294+
)
295+
assert (
296+
old_school_rule.get_increment("BREAKING CHANGE: major change", True)
297+
== MINOR
298+
)
299+
assert (
300+
old_school_rule.get_increment("BREAKING-CHANGE: major change", True)
301+
== MINOR
302+
)
303+
304+
def test_feat_commit(self, old_school_rule):
305+
assert old_school_rule.get_increment("feat: add new feature", False) == MINOR
306+
assert old_school_rule.get_increment("feat: add new feature", True) == MINOR
307+
308+
def test_fix_commit(self, old_school_rule):
309+
assert old_school_rule.get_increment("fix: fix bug", False) == PATCH
310+
assert old_school_rule.get_increment("fix: fix bug", True) == PATCH
311+
312+
def test_refactor_commit(self, old_school_rule):
313+
assert (
314+
old_school_rule.get_increment("refactor: restructure code", False) == PATCH
315+
)
316+
assert (
317+
old_school_rule.get_increment("refactor: restructure code", True) == PATCH
318+
)
319+
320+
def test_perf_commit(self, old_school_rule):
321+
assert (
322+
old_school_rule.get_increment("perf: improve performance", False) == PATCH
323+
)
324+
assert old_school_rule.get_increment("perf: improve performance", True) == PATCH
325+
326+
def test_commit_with_scope(self, old_school_rule):
327+
assert (
328+
old_school_rule.get_increment("feat(api): add new endpoint", False) == MINOR
329+
)
330+
assert (
331+
old_school_rule.get_increment("fix(ui): fix button alignment", False)
332+
== PATCH
333+
)
334+
assert (
335+
old_school_rule.get_increment("refactor(core): restructure", False) == PATCH
336+
)
337+
338+
def test_no_match(self, old_school_rule):
339+
assert (
340+
old_school_rule.get_increment("docs: update documentation", False) is None
341+
)
342+
assert old_school_rule.get_increment("style: format code", False) is None
343+
assert old_school_rule.get_increment("test: add unit tests", False) is None
344+
assert (
345+
old_school_rule.get_increment("build: update build config", False) is None
346+
)
347+
assert old_school_rule.get_increment("ci: update CI pipeline", False) is None
348+
349+
def test_with_find_increment_by_callable(self, old_school_rule):
350+
commit_messages = [
351+
"feat!: breaking change",
352+
"fix: bug fix",
353+
"perf: improve performance",
354+
]
355+
assert (
356+
find_increment_by_callable(
357+
commit_messages, lambda x: old_school_rule.get_increment(x, False)
358+
)
359+
== MAJOR
360+
)

0 commit comments

Comments
 (0)