Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit ed13b7d

Browse files
committed
feat(changelog): add merge_prereleases flag
1 parent 378a428 commit ed13b7d

15 files changed

+505
-5
lines changed

commitizen/changelog.py

+30-3
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
from typing import Callable, Dict, Iterable, List, Optional, Tuple
3333

3434
from jinja2 import Environment, PackageLoader
35+
from packaging.version import InvalidVersion, Version
3536

3637
from commitizen import defaults
3738
from commitizen.bump import normalize_tag
@@ -43,6 +44,31 @@ def get_commit_tag(commit: GitCommit, tags: List[GitTag]) -> Optional[GitTag]:
4344
return next((tag for tag in tags if tag.rev == commit.rev), None)
4445

4546

47+
def get_version(tag: GitTag) -> Optional[Version]:
48+
version = None
49+
try:
50+
version = Version(tag.name)
51+
except InvalidVersion:
52+
pass
53+
return version
54+
55+
56+
def tag_included_in_changelog(
57+
tag: GitTag, used_tags: List, merge_prerelease: bool
58+
) -> bool:
59+
if tag in used_tags:
60+
return False
61+
62+
version = get_version(tag)
63+
if version is None:
64+
return False
65+
66+
if merge_prerelease and version.is_prerelease:
67+
return False
68+
69+
return True
70+
71+
4672
def generate_tree_from_commits(
4773
commits: List[GitCommit],
4874
tags: List[GitTag],
@@ -51,6 +77,7 @@ def generate_tree_from_commits(
5177
unreleased_version: Optional[str] = None,
5278
change_type_map: Optional[Dict[str, str]] = None,
5379
changelog_message_builder_hook: Optional[Callable] = None,
80+
merge_prerelease: bool = False,
5481
) -> Iterable[Dict]:
5582
pat = re.compile(changelog_pattern)
5683
map_pat = re.compile(commit_parser, re.MULTILINE)
@@ -73,15 +100,15 @@ def generate_tree_from_commits(
73100
for commit in commits:
74101
commit_tag = get_commit_tag(commit, tags)
75102

76-
if commit_tag is not None and commit_tag not in used_tags:
103+
if commit_tag is not None and tag_included_in_changelog(
104+
commit_tag, used_tags, merge_prerelease
105+
):
77106
used_tags.append(commit_tag)
78107
yield {
79108
"version": current_tag_name,
80109
"date": current_tag_date,
81110
"changes": changes,
82111
}
83-
# TODO: Check if tag matches the version pattern, otherwise skip it.
84-
# This in order to prevent tags that are not versions.
85112
current_tag_name = commit_tag.name
86113
current_tag_date = commit_tag.date
87114
changes = defaultdict(list)

commitizen/cli.py

+10-1
Original file line numberDiff line numberDiff line change
@@ -247,10 +247,19 @@
247247
"name": "--start-rev",
248248
"default": None,
249249
"help": (
250-
"start rev of the changelog."
250+
"start rev of the changelog. "
251251
"If not set, it will generate changelog from the start"
252252
),
253253
},
254+
{
255+
"name": "--merge-prerelease",
256+
"action": "store_true",
257+
"default": False,
258+
"help": (
259+
"collect all changes from prereleases into next non-prerelease. "
260+
"If not set, it will include prereleases in the changelog"
261+
),
262+
},
254263
],
255264
},
256265
{

commitizen/commands/changelog.py

+5
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,9 @@ def __init__(self, config: BaseConfig, args):
4949
self.tag_format = args.get("tag_format") or self.config.settings.get(
5050
"tag_format"
5151
)
52+
self.merge_prerelease = args.get(
53+
"merge_prerelease"
54+
) or self.config.settings.get("changelog_merge_prerelease")
5255

5356
def _find_incremental_rev(self, latest_version: str, tags: List[GitTag]) -> str:
5457
"""Try to find the 'start_rev'.
@@ -110,6 +113,7 @@ def __call__(self):
110113
changelog_message_builder_hook: Optional[
111114
Callable
112115
] = self.cz.changelog_message_builder_hook
116+
merge_prerelease = self.merge_prerelease
113117

114118
if not changelog_pattern or not commit_parser:
115119
raise NoPatternMapError(
@@ -158,6 +162,7 @@ def __call__(self):
158162
unreleased_version,
159163
change_type_map=change_type_map,
160164
changelog_message_builder_hook=changelog_message_builder_hook,
165+
merge_prerelease=merge_prerelease,
161166
)
162167
if self.change_type_order:
163168
tree = changelog.order_changelog_tree(tree, self.change_type_order)

commitizen/defaults.py

+2
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ class Settings(TypedDict, total=False):
3939
changelog_file: str
4040
changelog_incremental: bool
4141
changelog_start_rev: Optional[str]
42+
changelog_merge_prerelease: bool
4243
update_changelog_on_bump: bool
4344
use_shortcuts: bool
4445
style: Optional[List[Tuple[str, str]]]
@@ -69,6 +70,7 @@ class Settings(TypedDict, total=False):
6970
"changelog_file": "CHANGELOG.md",
7071
"changelog_incremental": False,
7172
"changelog_start_rev": None,
73+
"changelog_merge_prerelease": False,
7274
"update_changelog_on_bump": False,
7375
"use_shortcuts": False,
7476
"major_version_zero": False,

docs/changelog.md

+19-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@ optional arguments:
2121
set the value for the new version (use the tag value), instead of using unreleased
2222
--incremental generates changelog from last created version, useful if the changelog has been manually modified
2323
--start-rev START_REV
24-
start rev of the changelog.If not set, it will generate changelog from the start
24+
start rev of the changelog. If not set, it will generate changelog from the start
25+
--merge-prerelease
26+
collect all changes from prereleases into next non-prerelease. If not set, it will include prereleases in the changelog
2527
```
2628
2729
### Examples
@@ -161,6 +163,22 @@ cz changelog --start-rev="v0.2.0"
161163
changelog_start_rev = "v0.2.0"
162164
```
163165
166+
### merge-prerelease
167+
168+
This flag can be set in the `toml` file with the key `changelog_merge_prerelease` under `tools.commitizen`
169+
170+
Collects changes from prereleases into the next non-prerelease. This means that if you have a prerelease version, and then a normal release, the changelog will show the prerelease changes as part of the changes of the normal release. If not set, it will include prereleases in the changelog.
171+
172+
```bash
173+
cz changelog --merge-prerelease
174+
```
175+
176+
```toml
177+
[tools.commitizen]
178+
# ...
179+
changelog_merge_prerelease = true
180+
```
181+
164182
## Hooks
165183
166184
Supported hook methods:

docs/config.md

+1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
| `changelog_file` | `str` | `CHANGELOG.md` | filename of exported changelog |
1717
| `changelog_incremental` | `bool` | `false` | Update changelog with the missing versions. This is good if you don't want to replace previous versions in the file. Note: when doing `cz bump --changelog` this is automatically set to `true` |
1818
| `changelog_start_rev` | `str` | `None` | Start from a given git rev to generate the changelog |
19+
| `changelog_merge_prerelease` | `bool` | `false` | Collect all changes of prerelease versions into the next non-prerelease version when creating the changelog. |
1920
| `style` | `list` | see above | Style for the prompts (It will merge this value with default style.) [See More (Styling your prompts with your favorite colors)][additional-features] |
2021
| `customize` | `dict` | `None` | **This is only supported when config through `toml`.** Custom rules for committing and bumping. [See more][customization] |
2122
| `use_shortcuts` | `bool` | `false` | If enabled, commitizen will show keyboard shortcuts when selecting from a list. Define a `key` for each of your choices to set the key. [See more][shortcuts] |

tests/commands/test_changelog_command.py

+68
Original file line numberDiff line numberDiff line change
@@ -461,6 +461,40 @@ def test_changelog_config_flag_increment(
461461
file_regression.check(out, extension=".md")
462462

463463

464+
@pytest.mark.parametrize("test_input", ["rc", "alpha", "beta"])
465+
@pytest.mark.usefixtures("tmp_commitizen_project")
466+
def test_changelog_config_flag_merge_prerelease(
467+
mocker: MockFixture, changelog_path, config_path, file_regression, test_input
468+
):
469+
with open(config_path, "a") as f:
470+
f.write("changelog_merge_prerelease = true\n")
471+
472+
create_file_and_commit("irrelevant commit")
473+
mocker.patch("commitizen.git.GitTag.date", "1970-01-01")
474+
git.tag("1.0.0")
475+
476+
create_file_and_commit("feat: add new output")
477+
create_file_and_commit("fix: output glitch")
478+
479+
testargs = ["cz", "bump", "--prerelease", test_input, "--yes"]
480+
mocker.patch.object(sys, "argv", testargs)
481+
cli.main()
482+
483+
create_file_and_commit("fix: mama gotta work")
484+
create_file_and_commit("feat: add more stuff")
485+
create_file_and_commit("Merge into master")
486+
487+
testargs = ["cz", "changelog"]
488+
489+
mocker.patch.object(sys, "argv", testargs)
490+
cli.main()
491+
492+
with open(changelog_path, "r") as f:
493+
out = f.read()
494+
495+
file_regression.check(out, extension=".md")
496+
497+
464498
@pytest.mark.usefixtures("tmp_commitizen_project")
465499
def test_changelog_config_start_rev_option(
466500
mocker: MockFixture, capsys, config_path, file_regression
@@ -549,6 +583,40 @@ def test_changelog_incremental_with_release_candidate_version(
549583
file_regression.check(out, extension=".md")
550584

551585

586+
@pytest.mark.parametrize("test_input", ["rc", "alpha", "beta"])
587+
@pytest.mark.usefixtures("tmp_commitizen_project")
588+
def test_changelog_release_candidate_version_with_merge_prerelease(
589+
mocker: MockFixture, changelog_path, file_regression, test_input
590+
):
591+
"""Fix #357"""
592+
with open(changelog_path, "w") as f:
593+
f.write(KEEP_A_CHANGELOG)
594+
create_file_and_commit("irrelevant commit")
595+
mocker.patch("commitizen.git.GitTag.date", "1970-01-01")
596+
git.tag("1.0.0")
597+
598+
create_file_and_commit("feat: add new output")
599+
create_file_and_commit("fix: output glitch")
600+
601+
testargs = ["cz", "bump", "--prerelease", test_input, "--yes"]
602+
mocker.patch.object(sys, "argv", testargs)
603+
cli.main()
604+
605+
create_file_and_commit("fix: mama gotta work")
606+
create_file_and_commit("feat: add more stuff")
607+
create_file_and_commit("Merge into master")
608+
609+
testargs = ["cz", "changelog", "--merge-prerelease"]
610+
611+
mocker.patch.object(sys, "argv", testargs)
612+
cli.main()
613+
614+
with open(changelog_path, "r") as f:
615+
out = f.read()
616+
617+
file_regression.check(out, extension=".md")
618+
619+
552620
@pytest.mark.usefixtures("tmp_commitizen_project")
553621
def test_changelog_with_filename_as_empty_string(
554622
mocker: MockFixture, changelog_path, config_path
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
## Unreleased
2+
3+
### Feat
4+
5+
- add more stuff
6+
- add new output
7+
8+
### Fix
9+
10+
- mama gotta work
11+
- output glitch
12+
13+
## 1.0.0 (1970-01-01)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
## Unreleased
2+
3+
### Feat
4+
5+
- add more stuff
6+
- add new output
7+
8+
### Fix
9+
10+
- mama gotta work
11+
- output glitch
12+
13+
## 1.0.0 (1970-01-01)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
## Unreleased
2+
3+
### Feat
4+
5+
- add more stuff
6+
- add new output
7+
8+
### Fix
9+
10+
- mama gotta work
11+
- output glitch
12+
13+
## 1.0.0 (1970-01-01)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
## Unreleased
2+
3+
### Feat
4+
5+
- add more stuff
6+
- add new output
7+
8+
### Fix
9+
10+
- mama gotta work
11+
- output glitch
12+
13+
## 1.0.0 (1970-01-01)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
## Unreleased
2+
3+
### Feat
4+
5+
- add more stuff
6+
- add new output
7+
8+
### Fix
9+
10+
- mama gotta work
11+
- output glitch
12+
13+
## 1.0.0 (1970-01-01)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
## Unreleased
2+
3+
### Feat
4+
5+
- add more stuff
6+
- add new output
7+
8+
### Fix
9+
10+
- mama gotta work
11+
- output glitch
12+
13+
## 1.0.0 (1970-01-01)

0 commit comments

Comments
 (0)