Skip to content
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

feat: pre-release seperated changelog #454

Closed
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
51 changes: 31 additions & 20 deletions commitizen/changelog.py
Original file line number Diff line number Diff line change
@@ -66,13 +66,13 @@ def get_commit_tag(commit: GitCommit, tags: List[GitTag]) -> Optional[GitTag]:


def generate_tree_from_commits(
commits: List[GitCommit],
tags: List[GitTag],
commit_parser: str,
changelog_pattern: str = defaults.bump_pattern,
unreleased_version: Optional[str] = None,
change_type_map: Optional[Dict[str, str]] = None,
changelog_message_builder_hook: Optional[Callable] = None,
commits: List[GitCommit],
tags: List[GitTag],
commit_parser: str,
changelog_pattern: str = defaults.bump_pattern,
unreleased_version: Optional[str] = None,
change_type_map: Optional[Dict[str, str]] = None,
changelog_message_builder_hook: Optional[Callable] = None,
) -> Iterable[Dict]:
pat = re.compile(changelog_pattern)
map_pat = re.compile(commit_parser, re.MULTILINE)
@@ -169,13 +169,25 @@ def render_changelog(tree: Iterable) -> str:
return changelog


def parse_version_from_markdown(value: str) -> Optional[str]:
def parse_version_from_markdown(value: str, pr_filter: str) -> Optional[str]:
"""
:param pr_filter: pass to only find a certain type of version, or None for any
version type. Example: when there is 1.0.0 and 2.0.0b1 and you pass "" 1.0.0 will be returned
as it is the last release.
"""
if not value.startswith("#"):
return None
if not value.__contains__(pr_filter):
return None
m = re.search(defaults.version_parser, value)
if not m:
return None
return m.groupdict().get("version")
version = m.groupdict().get("version")
# when pr_filter is provided but empty
is_stable = re.match(defaults.stable_parser, version)
if not is_stable and pr_filter == "":
return None # because the version is a pre-release but a "full" release is expected
return version


def parse_title_type_of_line(value: str) -> Optional[str]:
@@ -186,7 +198,7 @@ def parse_title_type_of_line(value: str) -> Optional[str]:
return m.groupdict().get("title")


def get_metadata(filepath: str) -> Dict:
def get_metadata(filepath: str, pr_filter: str) -> Dict:
unreleased_start: Optional[int] = None
unreleased_end: Optional[int] = None
unreleased_title: Optional[str] = None
@@ -213,13 +225,13 @@ def get_metadata(filepath: str) -> Dict:
unreleased_title = unreleased
continue
elif (
isinstance(unreleased_title, str)
and parse_title_type_of_line(line) == unreleased_title
isinstance(unreleased_title, str)
and parse_title_type_of_line(line) == unreleased_title
):
unreleased_end = index

# Try to find the latest release done
version = parse_version_from_markdown(line)
version = parse_version_from_markdown(line, pr_filter)
if version:
latest_version = version
latest_version_position = index
@@ -259,21 +271,20 @@ def incremental_build(new_content: str, lines: List, metadata: Dict) -> List:
elif index == unreleased_end:
skip = False
if (
latest_version_position is None
or isinstance(latest_version_position, int)
and isinstance(unreleased_end, int)
and latest_version_position > unreleased_end
latest_version_position is None
or isinstance(latest_version_position, int)
and isinstance(unreleased_end, int)
and latest_version_position > unreleased_end
):
continue

if skip:
continue

if (
isinstance(latest_version_position, int)
and index == latest_version_position
isinstance(latest_version_position, int)
and index == latest_version_position
):

output_lines.append(new_content)
output_lines.append("\n")

15 changes: 14 additions & 1 deletion commitizen/cli.py
Original file line number Diff line number Diff line change
@@ -109,6 +109,19 @@
"action": "store_true",
"help": "accept automatically questions done",
},
{
"name": "--separate-pre-changelog",
"action": "store_true",
"default": False,
"help": "use a separate changelog for each type of prerelease"
},
{
"name": "--separate-pre-releases",
"action": "store_true",
"default": False,
"help": "changes in the changelog will always relate to the latest "
"release of the same pre-release"
},
{
"name": "--tag-format",
"help": (
@@ -260,7 +273,7 @@
"exclusive_group": "group1",
},
],
},
}
],
},
}
13 changes: 11 additions & 2 deletions commitizen/commands/changelog.py
Original file line number Diff line number Diff line change
@@ -22,7 +22,7 @@ def similar(a, b):
class Changelog:
"""Generate a changelog based on the commit history."""

def __init__(self, config: BaseConfig, args):
def __init__(self, config: BaseConfig, args: dict):
if not git.is_git_project():
raise NotAGitProjectError()

@@ -40,6 +40,12 @@ def __init__(self, config: BaseConfig, args):
)
self.dry_run = args["dry_run"]
self.unreleased_version = args["unreleased_version"]
self.separate_pre_releases = args["separate_pre_releases"]
self.separate_pre_changelog = args["separate_pre_changelog"]
self.pre_release = args["prerelease"]
if self.separate_pre_changelog:
self.separate_pre_releases = True
self.file_name = f"{self.file_name}-${self.pre_release}"
self.change_type_map = (
self.config.settings.get("change_type_map") or self.cz.change_type_map
)
@@ -94,7 +100,10 @@ def __call__(self):
tags = []

if self.incremental:
changelog_meta = changelog.get_metadata(self.file_name)
pr_filter = None
if self.separate_pre_releases:
pr_filter = self.pre_release
changelog_meta = changelog.get_metadata(self.file_name, pr_filter)
latest_version = changelog_meta.get("latest_version")
if latest_version:
start_rev = self._find_incremental_rev(latest_version, tags)
1 change: 1 addition & 0 deletions commitizen/defaults.py
Original file line number Diff line number Diff line change
@@ -45,3 +45,4 @@

commit_parser = r"^(?P<change_type>feat|fix|refactor|perf|BREAKING CHANGE)(?:\((?P<scope>[^()\r\n]*)\)|\()?(?P<breaking>!)?:\s(?P<message>.*)?" # noqa
version_parser = r"(?P<version>([0-9]+)\.([0-9]+)\.([0-9]+)(?:-([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?(?:\+[0-9A-Za-z-]+)?(\w+)?)"
stable_parser = r"^([0-9]|[1-9][0-9]*)\.([0-9]|[1-9][0-9]*)\.([0-9]|[1-9][0-9]*)$"