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

feat(changelog): add merge-prerelease flag #703

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Apr 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/pythonpackage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ jobs:
shell: bash
- name: Upload coverage to Codecov
if: runner.os == 'Linux'
uses: codecov/codecov-action@v1.0.3
uses: codecov/codecov-action@v3
with:
token: ${{secrets.CODECOV_TOKEN}}
file: ./coverage.xml
Expand Down
33 changes: 30 additions & 3 deletions commitizen/changelog.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
from typing import Callable, Dict, Iterable, List, Optional, Tuple

from jinja2 import Environment, PackageLoader
from packaging.version import InvalidVersion, Version

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


def get_version(tag: GitTag) -> Optional[Version]:
version = None
try:
version = Version(tag.name)
except InvalidVersion:
pass
return version


def tag_included_in_changelog(
tag: GitTag, used_tags: List, merge_prerelease: bool
) -> bool:
if tag in used_tags:
return False

version = get_version(tag)
if version is None:
return False

if merge_prerelease and version.is_prerelease:
return False

return True


def generate_tree_from_commits(
commits: List[GitCommit],
tags: List[GitTag],
Expand All @@ -51,6 +77,7 @@ def generate_tree_from_commits(
unreleased_version: Optional[str] = None,
change_type_map: Optional[Dict[str, str]] = None,
changelog_message_builder_hook: Optional[Callable] = None,
merge_prerelease: bool = False,
) -> Iterable[Dict]:
pat = re.compile(changelog_pattern)
map_pat = re.compile(commit_parser, re.MULTILINE)
Expand All @@ -73,15 +100,15 @@ def generate_tree_from_commits(
for commit in commits:
commit_tag = get_commit_tag(commit, tags)

if commit_tag is not None and commit_tag not in used_tags:
if commit_tag is not None and tag_included_in_changelog(
commit_tag, used_tags, merge_prerelease
):
used_tags.append(commit_tag)
yield {
"version": current_tag_name,
"date": current_tag_date,
"changes": changes,
}
# TODO: Check if tag matches the version pattern, otherwise skip it.
# This in order to prevent tags that are not versions.
current_tag_name = commit_tag.name
current_tag_date = commit_tag.date
changes = defaultdict(list)
Expand Down
11 changes: 10 additions & 1 deletion commitizen/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -248,10 +248,19 @@
"name": "--start-rev",
"default": None,
"help": (
"start rev of the changelog."
"start rev of the changelog. "
"If not set, it will generate changelog from the start"
),
},
{
"name": "--merge-prerelease",
"action": "store_true",
"default": False,
"help": (
"collect all changes from prereleases into next non-prerelease. "
"If not set, it will include prereleases in the changelog"
),
},
],
},
{
Expand Down
5 changes: 5 additions & 0 deletions commitizen/commands/changelog.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ def __init__(self, config: BaseConfig, args):
self.tag_format = args.get("tag_format") or self.config.settings.get(
"tag_format"
)
self.merge_prerelease = args.get(
"merge_prerelease"
) or self.config.settings.get("changelog_merge_prerelease")

def _find_incremental_rev(self, latest_version: str, tags: List[GitTag]) -> str:
"""Try to find the 'start_rev'.
Expand Down Expand Up @@ -110,6 +113,7 @@ def __call__(self):
changelog_message_builder_hook: Optional[
Callable
] = self.cz.changelog_message_builder_hook
merge_prerelease = self.merge_prerelease

if not changelog_pattern or not commit_parser:
raise NoPatternMapError(
Expand Down Expand Up @@ -156,6 +160,7 @@ def __call__(self):
unreleased_version,
change_type_map=change_type_map,
changelog_message_builder_hook=changelog_message_builder_hook,
merge_prerelease=merge_prerelease,
)
if self.change_type_order:
tree = changelog.order_changelog_tree(tree, self.change_type_order)
Expand Down
2 changes: 2 additions & 0 deletions commitizen/defaults.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ class Settings(TypedDict, total=False):
changelog_file: str
changelog_incremental: bool
changelog_start_rev: Optional[str]
changelog_merge_prerelease: bool
update_changelog_on_bump: bool
use_shortcuts: bool
style: Optional[List[Tuple[str, str]]]
Expand Down Expand Up @@ -67,6 +68,7 @@ class Settings(TypedDict, total=False):
"changelog_file": "CHANGELOG.md",
"changelog_incremental": False,
"changelog_start_rev": None,
"changelog_merge_prerelease": False,
"update_changelog_on_bump": False,
"use_shortcuts": False,
"major_version_zero": False,
Expand Down
20 changes: 19 additions & 1 deletion docs/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@ optional arguments:
set the value for the new version (use the tag value), instead of using unreleased
--incremental generates changelog from last created version, useful if the changelog has been manually modified
--start-rev START_REV
start rev of the changelog.If not set, it will generate changelog from the start
start rev of the changelog. If not set, it will generate changelog from the start
--merge-prerelease
collect all changes from prereleases into next non-prerelease. If not set, it will include prereleases in the changelog
```

### Examples
Expand Down Expand Up @@ -161,6 +163,22 @@ cz changelog --start-rev="v0.2.0"
changelog_start_rev = "v0.2.0"
```

### merge-prerelease

This flag can be set in the `toml` file with the key `changelog_merge_prerelease` under `tools.commitizen`

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.

```bash
cz changelog --merge-prerelease
```

```toml
[tools.commitizen]
# ...
changelog_merge_prerelease = true
```

## Hooks

Supported hook methods:
Expand Down
1 change: 1 addition & 0 deletions docs/config.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
| `changelog_file` | `str` | `CHANGELOG.md` | filename of exported changelog |
| `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` |
| `changelog_start_rev` | `str` | `None` | Start from a given git rev to generate the changelog |
| `changelog_merge_prerelease` | `bool` | `false` | Collect all changes of prerelease versions into the next non-prerelease version when creating the changelog. |
| `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] |
| `customize` | `dict` | `None` | **This is only supported when config through `toml`.** Custom rules for committing and bumping. [See more][customization] |
| `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] |
Expand Down
20 changes: 2 additions & 18 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,6 @@ ipython = "^7.2"
pytest = "^7.2.0"
pytest-cov = "^4.0"
pytest-mock = "^3.10"
codecov = "^2.0"
pytest-regressions = "^2.4.0"
pytest-freezer = "^0.4.6"
# code formatter
Expand Down
2 changes: 1 addition & 1 deletion scripts/test
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ set -e
export PREFIX='poetry run python -m '
export REGEX='^(?![.]|venv).*'

${PREFIX}pytest -n 3 --cov-report term-missing --cov-report=xml:coverage.xml --cov=commitizen tests/
${PREFIX}pytest -n 3 --dist=loadfile --cov-report term-missing --cov-report=xml:coverage.xml --cov=commitizen tests/
${PREFIX}black commitizen tests --check
${PREFIX}isort --check-only commitizen tests
${PREFIX}flake8 commitizen/ tests/
Expand Down
107 changes: 107 additions & 0 deletions tests/commands/test_changelog_command.py
Original file line number Diff line number Diff line change
Expand Up @@ -538,6 +538,40 @@ def test_changelog_config_flag_increment(
file_regression.check(out, extension=".md")


@pytest.mark.parametrize("test_input", ["rc", "alpha", "beta"])
@pytest.mark.usefixtures("tmp_commitizen_project")
def test_changelog_config_flag_merge_prerelease(
mocker: MockFixture, changelog_path, config_path, file_regression, test_input
):
with open(config_path, "a") as f:
f.write("changelog_merge_prerelease = true\n")

create_file_and_commit("irrelevant commit")
mocker.patch("commitizen.git.GitTag.date", "1970-01-01")
git.tag("1.0.0")

create_file_and_commit("feat: add new output")
create_file_and_commit("fix: output glitch")

testargs = ["cz", "bump", "--prerelease", test_input, "--yes"]
mocker.patch.object(sys, "argv", testargs)
cli.main()

create_file_and_commit("fix: mama gotta work")
create_file_and_commit("feat: add more stuff")
create_file_and_commit("Merge into master")

testargs = ["cz", "changelog"]

mocker.patch.object(sys, "argv", testargs)
cli.main()

with open(changelog_path, "r") as f:
out = f.read()

file_regression.check(out, extension=".md")


@pytest.mark.usefixtures("tmp_commitizen_project")
def test_changelog_config_start_rev_option(
mocker: MockFixture, capsys, config_path, file_regression
Expand Down Expand Up @@ -626,6 +660,79 @@ def test_changelog_incremental_with_release_candidate_version(
file_regression.check(out, extension=".md")


@pytest.mark.parametrize("test_input", ["rc", "alpha", "beta"])
@pytest.mark.usefixtures("tmp_commitizen_project")
def test_changelog_release_candidate_version_with_merge_prerelease(
mocker: MockFixture, changelog_path, file_regression, test_input
):
"""Fix #357"""
with open(changelog_path, "w") as f:
f.write(KEEP_A_CHANGELOG)
create_file_and_commit("irrelevant commit")
mocker.patch("commitizen.git.GitTag.date", "1970-01-01")
git.tag("1.0.0")

create_file_and_commit("feat: add new output")
create_file_and_commit("fix: output glitch")

testargs = ["cz", "bump", "--prerelease", test_input, "--yes"]
mocker.patch.object(sys, "argv", testargs)
cli.main()

create_file_and_commit("fix: mama gotta work")
create_file_and_commit("feat: add more stuff")
create_file_and_commit("Merge into master")

testargs = ["cz", "changelog", "--merge-prerelease"]

mocker.patch.object(sys, "argv", testargs)
cli.main()

with open(changelog_path, "r") as f:
out = f.read()

file_regression.check(out, extension=".md")


@pytest.mark.parametrize("test_input", ["rc", "alpha", "beta"])
@pytest.mark.usefixtures("tmp_commitizen_project")
def test_changelog_incremental_with_merge_prerelease(
mocker: MockFixture, changelog_path, file_regression, test_input
):
"""Fix #357"""
with open(changelog_path, "w") as f:
f.write(KEEP_A_CHANGELOG)
create_file_and_commit("irrelevant commit")
mocker.patch("commitizen.git.GitTag.date", "1970-01-01")
git.tag("1.0.0")

create_file_and_commit("feat: add new output")

testargs = ["cz", "bump", "--prerelease", test_input, "--yes", "--changelog"]
mocker.patch.object(sys, "argv", testargs)
cli.main()

create_file_and_commit("fix: output glitch")

testargs = ["cz", "bump", "--prerelease", test_input, "--yes"]
mocker.patch.object(sys, "argv", testargs)
cli.main()

create_file_and_commit("fix: mama gotta work")
create_file_and_commit("feat: add more stuff")
create_file_and_commit("Merge into master")

testargs = ["cz", "changelog", "--merge-prerelease", "--incremental"]

mocker.patch.object(sys, "argv", testargs)
cli.main()

with open(changelog_path, "r") as f:
out = f.read()

file_regression.check(out, extension=".md")


@pytest.mark.usefixtures("tmp_commitizen_project")
def test_changelog_with_filename_as_empty_string(
mocker: MockFixture, changelog_path, config_path
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
## Unreleased

### Feat

- add more stuff
- add new output

### Fix

- mama gotta work
- output glitch

## 1.0.0 (1970-01-01)
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
## Unreleased

### Feat

- add more stuff
- add new output

### Fix

- mama gotta work
- output glitch

## 1.0.0 (1970-01-01)
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
## Unreleased

### Feat

- add more stuff
- add new output

### Fix

- mama gotta work
- output glitch

## 1.0.0 (1970-01-01)
Loading