8000 feat(template): add `changelog --export-template` command · sacha-c/commitizen@3adc171 · GitHub
[go: up one dir, main page]

Skip to content

Commit 3adc171

Browse files
noirbizarreLee-W
authored andcommitted
feat(template): add changelog --export-template command
1 parent 7306fa9 commit 3adc171

File tree

4 files changed

+79
-6
lines changed

4 files changed

+79
-6
lines changed

commitizen/changelog.py

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
Environment,
3939
FileSystemLoader,
4040
PackageLoader,
41+
Template,
4142
)
4243

4344
from commitizen import out
@@ -195,17 +196,26 @@ def order_changelog_tree(tree: Iterable, change_type_order: list[str]) -> Iterab
195196
return sorted_tree
196197

197198

199+
def get_changelog_template(
200+
loader: BaseLoader | None = None, template: str | None = None
201+
) -> Template:
202+
loader = ChoiceLoader(
203+
[
204+
FileSystemLoader("."),
205+
loader or PackageLoader("commitizen", "templates"),
206+
]
207+
)
208+
env = Environment(loader=loader, trim_blocks=True)
209+
return env.get_template(template or DEFAULT_TEMPLATE)
210+
211+
198212
def render_changelog(
199213
tree: Iterable,
200214
loader: BaseLoader | None = None,
201215
template: str | None = None,
202216
**kwargs,
203217
) -> str:
204-
loader = ChoiceLoader(
205-
[FileSystemLoader("."), loader or PackageLoader("commitizen", "templates")]
206-
)
207-
env = Environment(loader=loader, trim_blocks=True)
208-
jinja_template = env.get_template(template or DEFAULT_TEMPLATE)
218+
jinja_template = get_changelog_template(loader, template or DEFAULT_TEMPLATE)
209219
changelog: str = jinja_template.render(tree=tree, **kwargs)
210220
return changelog
211221

commitizen/cli.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,11 @@ def __call__(self, parser, namespace, kwarg, option_string=None):
346346
"default": None,
347347
"choices": version_schemes.KNOWN_SCHEMES,
348348
},
349+
{
350+
"name": "--export-template",
351+
"default": None,
352+
"help": "Export the changelog template into this file instead of rendering it",
353+
},
349354
*deepcopy(tpl_arguments),
350355
],
351356
},

commitizen/commands/changelog.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,11 @@
33
import os.path
44
from difflib import SequenceMatcher
55
from operator import itemgetter
6+
from pathlib import Path
67
from typing import Callable
78

89
from commitizen import bump, changelog, defaults, factory, git, out
10+
911
from commitizen.config import BaseConfig
1012
from commitizen.exceptions import (
1113
DryRunExit,
@@ -65,8 +67,13 @@ def __init__(self, config: BaseConfig, args):
6567
"merge_prerelease"
6668
) or self.config.settings.get("changelog_merge_prerelease")
6769

68-
self.template = args.get("template") or self.config.settings.get("template")
70+
self.template = (
71+
args.get("template")
72+
or self.config.settings.get("template")
73+
or self.cz.template
74+
)
6975
self.extras = args.get("extras") or {}
76+
self.export_template_to = args.get("export_template")
7077

7178
def _find_incremental_rev(self, latest_version: str, tags: list[GitTag]) -> str:
7279
"""Try to find the 'start_rev'.
@@ -118,6 +125,11 @@ def write_changelog(
118125
changelog_out = changelog_hook(changelog_out, partial_changelog)
119126
changelog_file.write(changelog_out)
120127

128+
def export_template(self):
129+
tpl = changelog.get_changelog_template(self.cz.template_loader, self.template)
130+
src = Path(tpl.filename)
131+
Path(self.export_template_to).write_text(src.read_text())
132+
121133
def __call__(self):
122134
commit_parser = self.cz.commit_parser
123135
changelog_pattern = self.cz.changelog_pattern
@@ -130,6 +142,9 @@ def __call__(self):
130142
) = self.cz.changelog_message_builder_hook
131143
merge_prerelease = self.merge_prerelease
132144

145+
if self.export_template_to:
146+
return self.export_template()
147+
133148
if not changelog_pattern or not commit_parser:
134149
raise NoPatternMapError(
135150
f"'{self.config.settings['name']}' rule does not support changelog"

tests/commands/test_changelog_command.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,10 @@
66

77
import pytest
88
from dateutil import relativedelta
9+
from jinja2 import FileSystemLoader
910
from pytest_mock import MockFixture
1011

12+
from commitizen import __file__ as commitizen_init
1113
from commitizen import cli, git
1214
from commitizen.changelog import DEFAULT_TEMPLATE
1315
from commitizen.commands.changelog import Changelog
@@ -1478,3 +1480,44 @@ def test_changelog_template_extra_quotes(
14781480

14791481
changelog = project_root / "CHANGELOG.md"
14801482
assert changelog.read_text() == "no-quote - single quotes - double quotes"
1483+
1484+
1485+
def test_export_changelog_template_from_default(
1486+
mocker: MockFixture,
1487+
tmp_commitizen_project: Path,
1488+
):
1489+
project_root = Path(tmp_commitizen_project)
1490+
target = project_root / "changelog.jinja"
1491+
src = Path(commitizen_init).parent / "templates" / DEFAULT_TEMPLATE
1492+
1493+
args = ["cz", "changelog", "--export-template", str(target)]
1494+
1495+
mocker.patch.object(sys, "argv", args)
1496+
cli.main()
1497+
1498+
assert target.exists()
1499+
assert target.read_text() == src.read_text()
1500+
1501+
1502+
def test_export_changelog_template_from_plugin(
1503+
mocker: MockFixture,
1504+
tmp_commitizen_project: Path,
1505+
mock_plugin: BaseCommitizen,
1506+
tmp_path: Path,
1507+
):
1508+
project_root = Path(tmp_commitizen_project)
1509+
target = project_root / "changelog.jinja"
1510+
filename = "template.jinja"
1511+
src = tmp_path / filename
1512+
tpl = "I am a custom template"
1513+
src.write_text(tpl)
1514+
mock_plugin.template_loader = FileSystemLoader(tmp_path)
1515+
mock_plugin.template = filename
1516+
1517+
args = ["cz", "changelog", "--export-template", str(target)]
1518+
1519+
mocker.patch.object(sys, "argv", args)
1520+
cli.main()
1521+
1522+
assert target.exists()
1523+
assert target.read_text() == tpl

0 commit comments

Comments
 (0)
0