Skip to content

Commit 7a8c2d8

Browse files
authored
Merge pull request #703 from MoritzBoehme/merge-prerelease
feat(changelog): add merge-prerelease flag
2 parents 642f2c8 + e34de55 commit 7a8c2d8

22 files changed

+656
-30
lines changed

.github/workflows/pythonpackage.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ jobs:
3030
shell: bash
3131
- name: Upload coverage to Codecov
3232
if: runner.os == 'Linux'
33-
uses: codecov/codecov-action@v1.0.3
33+
uses: codecov/codecov-action@v3
3434
with:
3535
token: ${{secrets.CODECOV_TOKEN}}
3636
file: ./coverage.xml

commitizen/changelog.py

Lines changed: 30 additions & 3 deletions
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

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -248,10 +248,19 @@
248248
"name": "--start-rev",
249249
"default": None,
250250
"help": (
251-
"start rev of the changelog."
251+
"start rev of the changelog. "
252252
"If not set, it will generate changelog from the start"
253253
),
254254
},
255+
{
256+
"name": "--merge-prerelease",
257+
"action": "store_true",
258+
"default": False,
259+
"help": (
260+
"collect all changes from prereleases into next non-prerelease. "
261+
"If not set, it will include prereleases in the changelog"
262+
),
263+
},
255264
],
256265
},
257266
{

commitizen/commands/changelog.py

Lines changed: 5 additions & 0 deletions
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(
@@ -156,6 +160,7 @@ def __call__(self):
156160
unreleased_version,
157161
change_type_map=change_type_map,
158162
changelog_message_builder_hook=changelog_message_builder_hook,
163+
merge_prerelease=merge_prerelease,
159164
)
160165
if self.change_type_order:
161166
tree = changelog.order_changelog_tree(tree, self.change_type_order)

commitizen/defaults.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ class Settings(TypedDict, total=False):
3636
changelog_file: str
3737
changelog_incremental: bool
3838
changelog_start_rev: Optional[str]
39+
changelog_merge_prerelease: bool
3940
update_changelog_on_bump: bool
4041
use_shortcuts: bool
4142
style: Optional[List[Tuple[str, str]]]
@@ -67,6 +68,7 @@ class Settings(TypedDict, total=False):
6768
"changelog_file": "CHANGELOG.md",
6869
"changelog_incremental": False,
6970
"changelog_start_rev": None,
71+
"changelog_merge_prerelease": False,
7072
"update_changelog_on_bump": False,
7173
"use_shortcuts": False,
7274
"major_version_zero": False,

docs/changelog.md

Lines changed: 19 additions & 1 deletion
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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
| `changelog_file` | `str` | `CHANGELOG.md` | filename of exported changelog |
1818
| `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` |
1919
| `changelog_start_rev` | `str` | `None` | Start from a given git rev to generate the changelog |
20+
| `changelog_merge_prerelease` | `bool` | `false` | Collect all changes of prerelease versions into the next non-prerelease version when creating the changelog. |
2021
| `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] |
2122
| `customize` | `dict` | `None` | **This is only supported when config through `toml`.** Custom rules for committing and bumping. [See more][customization] |
2223
| `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] |

poetry.lock

Lines changed: 2 additions & 18 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,6 @@ ipython = "^7.2"
7777
pytest = "^7.2.0"
7878
pytest-cov = "^4.0"
7979
pytest-mock = "^3.10"
80-
codecov = "^2.0"
8180
pytest-regressions = "^2.4.0"
8281
pytest-freezer = "^0.4.6"
8382
# code formatter

scripts/test

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ set -e
44
export PREFIX='poetry run python -m '
55
export REGEX='^(?![.]|venv).*'
66

7-
${PREFIX}pytest -n 3 --cov-report term-missing --cov-report=xml:coverage.xml --cov=commitizen tests/
7+
${PREFIX}pytest -n 3 --dist=loadfile --cov-report term-missing --cov-report=xml:coverage.xml --cov=commitizen tests/
88
${PREFIX}black commitizen tests --check
99
${PREFIX}isort --check-only commitizen tests
1010
${PREFIX}flake8 commitizen/ tests/

tests/commands/test_changelog_command.py

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -538,6 +538,40 @@ def test_changelog_config_flag_increment(
538538
file_regression.check(out, extension=".md")
539539

540540

541+
@pytest.mark.parametrize("test_input", ["rc", "alpha", "beta"])
542+
@pytest.mark.usefixtures("tmp_commitizen_project")
543+
def test_changelog_config_flag_merge_prerelease(
544+
mocker: MockFixture, changelog_path, config_path, file_regression, test_input
545+
):
546+
with open(config_path, "a") as f:
547+
f.write("changelog_merge_prerelease = true\n")
548+
549+
create_file_and_commit("irrelevant commit")
550+
mocker.patch("commitizen.git.GitTag.date", "1970-01-01")
551+
git.tag("1.0.0")
552+
553+
create_file_and_commit("feat: add new output")
554+
create_file_and_commit("fix: output glitch")
555+
556+
testargs = ["cz", "bump", "--prerelease", test_input, "--yes"]
557+
mocker.patch.object(sys, "argv", testargs)
558+
cli.main()
559+
560+
create_file_and_commit("fix: mama gotta work")
561+
create_file_and_commit("feat: add more stuff")
562+
create_file_and_commit("Merge into master")
563+
564+
testargs = ["cz", "changelog"]
565+
566+
mocker.patch.object(sys, "argv", testargs)
567+
cli.main()
568+
569+
with open(changelog_path, "r") as f:
570+
out = f.read()
571+
572+
file_regression.check(out, extension=".md")
573+
574+
541575
@pytest.mark.usefixtures("tmp_commitizen_project")
542576
def test_changelog_config_start_rev_option(
543577
mocker: MockFixture, capsys, config_path, file_regression
@@ -626,6 +660,79 @@ def test_changelog_incremental_with_release_candidate_version(
626660
file_regression.check(out, extension=".md")
627661

628662

663+
@pytest.mark.parametrize("test_input", ["rc", "alpha", "beta"])
664+
@pytest.mark.usefixtures("tmp_commitizen_project")
665+
def test_changelog_release_candidate_version_with_merge_prerelease(
666+
mocker: MockFixture, changelog_path, file_regression, test_input
667+
):
668+
"""Fix #357"""
669+
with open(changelog_path, "w") as f:
670+
f.write(KEEP_A_CHANGELOG)
671+
create_file_and_commit("irrelevant commit")
672+
mocker.patch("commitizen.git.GitTag.date", "1970-01-01")
673+
git.tag("1.0.0")
674+
675+
create_file_and_commit("feat: add new output")
676+
create_file_and_commit("fix: output glitch")
677+
678+
testargs = ["cz", "bump", "--prerelease", test_input, "--yes"]
679+
mocker.patch.object(sys, "argv", testargs)
680+
cli.main()
681+
682+
create_file_and_commit("fix: mama gotta work")
683+
create_file_and_commit("feat: add more stuff")
684+
create_file_and_commit("Merge into master")
685+
686+
testargs = ["cz", "changelog", "--merge-prerelease"]
687+
688+
mocker.patch.object(sys, "argv", testargs)
689+
cli.main()
690+
691+
with open(changelog_path, "r") as f:
692+
out = f.read()
693+
694+
file_regression.check(out, extension=".md")
695+
696+
697+
@pytest.mark.parametrize("test_input", ["rc", "alpha", "beta"])
698+
@pytest.mark.usefixtures("tmp_commitizen_project")
699+
def test_changelog_incremental_with_merge_prerelease(
700+
mocker: MockFixture, changelog_path, file_regression, test_input
701+
):
702+
"""Fix #357"""
703+
with open(changelog_path, "w") as f:
704+
f.write(KEEP_A_CHANGELOG)
705+
create_file_and_commit("irrelevant commit")
706+
mocker.patch("commitizen.git.GitTag.date", "1970-01-01")
707+
git.tag("1.0.0")
708+
709+
create_file_and_commit("feat: add new output")
710+
711+
testargs = ["cz", "bump", "--prerelease", test_input, "--yes", "--changelog"]
712+
mocker.patch.object(sys, "argv", testargs)
713+
cli.main()
714+
715+
create_file_and_commit("fix: output glitch")
716+
717+
testargs = ["cz", "bump", "--prerelease", test_input, "--yes"]
718+
mocker.patch.object(sys, "argv", testargs)
719+
cli.main()
720+
721+
create_file_and_commit("fix: mama gotta work")
722+
create_file_and_commit("feat: add more stuff")
723+
create_file_and_commit("Merge into master")
724+
725+
testargs = ["cz", "changelog", "--merge-prerelease", "--incremental"]
726+
727+
mocker.patch.object(sys, "argv", testargs)
728+
cli.main()
729+
730+
with open(changelog_path, "r") as f:
731+
out = f.read()
732+
733+
file_regression.check(out, extension=".md")
734+
735+
629736
@pytest.mark.usefixtures("tmp_commitizen_project")
630737
def test_changelog_with_filename_as_empty_string(
631738
mocker: MockFixture, changelog_path, config_path
Lines changed: 13 additions & 0 deletions
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)
Lines changed: 13 additions & 0 deletions
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)
Lines changed: 13 additions & 0 deletions
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)