Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 1ca2a45

Browse files
feat(template): allow to override the template from cli, configuration and plugins
Fixes commitizen-tools#132 Fixes commitizen-tools#384 Fixes commitizen-tools#433 Closes commitizen-tools#376 Closes commitizen-tools#640
1 parent 4060cc2 commit 1ca2a45

File tree

15 files changed

+615
-12
lines changed

15 files changed

+615
-12
lines changed

‎commitizen/changelog.py‎

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,13 @@
3333
from datetime import date
3434
from typing import Callable, Dict, Iterable, List, Optional, Tuple, Type
3535

36-
from jinja2 import Environment, PackageLoader
36+
from jinja2 import (
37+
BaseLoader,
38+
ChoiceLoader,
39+
Environment,
40+
FileSystemLoader,
41+
PackageLoader,
42+
)
3743
from packaging.version import InvalidVersion, Version
3844

3945
from commitizen import defaults
@@ -47,6 +53,8 @@
4753
# workaround mypy issue for 3.7 python
4854
VersionProtocol = typing.Any
4955

56+
DEFAULT_TEMPLATE = "keep_a_changelog_template.j2"
57+
5058

5159
def get_commit_tag(commit: GitCommit, tags: List[GitTag]) -> Optional[GitTag]:
5260
return next((tag for tag in tags if tag.rev == commit.rev), None)
@@ -176,11 +184,18 @@ def order_changelog_tree(tree: Iterable, change_type_order: List[str]) -> Iterab
176184
return sorted_tree
177185

178186

179-
def render_changelog(tree: Iterable) -> str:
180-
loader = PackageLoader("commitizen", "templates")
187+
def render_changelog(
188+
tree: Iterable,
189+
loader: Optional[BaseLoader] = None,
190+
template: Optional[str] = None,
191+
**kwargs,
192+
) -> str:
193+
loader = ChoiceLoader(
194+
[FileSystemLoader("."), loader or PackageLoader("commitizen", "templates")]
195+
)
181196
env = Environment(loader=loader, trim_blocks=True)
182-
jinja_template = env.get_template("keep_a_changelog_template.j2")
183-
changelog: str = jinja_template.render(tree=tree)
197+
jinja_template = env.get_template(templateorDEFAULT_TEMPLATE)
198+
changelog: str = jinja_template.render(tree=tree, **kwargs)
184199
return changelog
185200

186201

‎commitizen/cli.py‎

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import argparse
22
import logging
33
import sys
4-
from pathlib import Path
4+
from copy import deepcopy
55
from functools import partial
6+
from pathlib import Path
67
from types import TracebackType
78
from typing import List
89

@@ -18,6 +19,51 @@
1819
)
1920

2021
logger = logging.getLogger(__name__)
22+
23+
24+
class ParseKwargs(argparse.Action):
25+
"""
26+
Parse arguments in the for `key=value`.
27+
28+
Quoted strings are automatically unquoted.
29+
Can be submitted multiple times:
30+
31+
ex:
32+
-k key=value -k double-quotes="value" -k single-quotes='value'
33+
34+
will result in
35+
36+
namespace["opt"] == {
37+
"key": "value",
38+
"double-quotes": "value",
39+
"single-quotes": "value",
40+
}
41+
"""
42+
43+
def __call__(self, parser, namespace, kwarg, option_string=None):
44+
kwargs = getattr(namespace, self.dest, None) or {}
45+
key, value = kwarg.split("=", 1)
46+
kwargs[key] = value.strip("'\"")
47+
setattr(namespace, self.dest, kwargs)
48+
49+
50+
tpl_arguments = (
51+
{
52+
"name": ["--template", "-t"],
53+
"help": (
54+
"changelog template file name "
55+
"(relative to the current working directory)"
56+
),
57+
},
58+
{
59+
"name": ["--extra", "-e"],
60+
"action": ParseKwargs,
61+
"dest": "extras",
62+
"metavar": "EXTRA",
63+
"help": "a changelog extra variable (in the form 'key=value')",
64+
},
65+
)
66+
2167
data = {
2268
"prog": "cz",
2369
"description": (
@@ -197,6 +243,7 @@
197243
"default": None,
198244
"help": "keep major version at zero, even for breaking changes",
199245
},
246+
*deepcopy(tpl_arguments),
200247
{
201248
"name": ["--prerelease-offset"],
202249
"type": int,
@@ -274,6 +321,7 @@
274321
"If not set, it will include prereleases in the changelog"
275322
),
276323
},
324+
*deepcopy(tpl_arguments),
277325
],
278326
},
279327
{

‎commitizen/commands/bump.py‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ def __init__(self, config: BaseConfig, arguments: dict):
4848
"annotated_tag",
4949
"major_version_zero",
5050
"prerelease_offset",
51+
"template",
5152
]
5253
if arguments[key] is not None
5354
},
@@ -66,6 +67,8 @@ def __init__(self, config: BaseConfig, arguments: dict):
6667
"version_type"
6768
)
6869
self.version_type = version_type and version_types.VERSION_TYPES[version_type]
70+
self.template = arguments["template"] or self.config.settings.get("template")
71+
self.extras = arguments["extras"]
6972

7073
def is_initial_tag(self, current_tag_version: str, is_yes: bool = False) -> bool:
7174
"""Check if reading the whole git tree up to HEAD is needed."""
@@ -271,6 +274,8 @@ def __call__(self): # noqa: C901
271274
"unreleased_version": new_tag_version,
272275
"incremental": True,
273276
"dry_run": dry_run,
277+
"template": self.template,
278+
"extras": self.extras,
274279
},
275280
)
276281
changelog_cmd()

‎commitizen/commands/changelog.py‎

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ def __init__(self, config: BaseConfig, args):
6464

6565
version_type = self.config.settings.get("version_type")
6666
self.version_type = version_type and version_types.VERSION_TYPES[version_type]
67+
self.template = args.get("template") or self.config.settings.get("template")
68+
self.extras = args.get("extras") or {}
6769

6870
def _find_incremental_rev(self, latest_version: str, tags: List[GitTag]) -> str:
6971
"""Try to find the 'start_rev'.
@@ -182,7 +184,13 @@ def __call__(self):
182184
)
183185
if self.change_type_order:
184186
tree = changelog.order_changelog_tree(tree, self.change_type_order)
185-
changelog_out = changelog.render_changelog(tree)
187+
188+
extras = self.cz.template_extras.copy()
189+
extras.update(self.config.settings["extras"])
190+
extras.update(self.extras)
191+
changelog_out = changelog.render_changelog(
192+
tree, loader=self.cz.template_loader, template=self.template, **extras
193+
)
186194
changelog_out = changelog_out.lstrip("\n")
187195

188196
if self.dry_run:

‎commitizen/cz/base.py‎

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
1+
from __future__ import annotations
2+
13
from abc import ABCMeta, abstractmethod
2-
from typing import Callable, Dict, List, Optional, Tuple
4+
from typing import Any, Callable, Dict, List, Optional, Tuple
35

6+
from jinja2 import BaseLoader
47
from prompt_toolkit.styles import Style, merge_styles
58

69
from commitizen import git
10+
from commitizen.changelog import DEFAULT_TEMPLATE
711
from commitizen.config.base_config import BaseConfig
812
from commitizen.defaults import Questions
913

@@ -41,6 +45,10 @@ class BaseCommitizen(metaclass=ABCMeta):
4145
# Executed only at the end of the changelog generation
4246
changelog_hook: Optional[Callable[[str, Optional[str]], str]] = None
4347

48+
template: str = DEFAULT_TEMPLATE
49+
template_loader: Optional[BaseLoader] = None
50+
template_extras: dict[str, Any] = {}
51+
4452
def __init__(self, config: BaseConfig):
4553
self.config = config
4654
if not self.config.settings.get("style"):

‎commitizen/defaults.py‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
from __future__ import annotations
2+
13
import pathlib
24
import sys
35
from collections import OrderedDict
@@ -51,6 +53,8 @@ class Settings(TypedDict, total=False):
5153
post_bump_hooks: Optional[List[str]]
5254
prerelease_offset: int
5355
version_type: Optional[str]
56+
template: Optional[str]
57+
extras: dict[str, Any]
5458

5559

5660
name: str = "cz_conventional_commits"
@@ -82,6 +86,8 @@ class Settings(TypedDict, total=False):
8286
"post_bump_hooks": [],
8387
"prerelease_offset": 0,
8488
"version_type": None,
89+
"template": None,
90+
"extras": {},
8591
}
8692

8793
MAJOR = "MAJOR"

‎docs/bump.md‎

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ usage: cz bump [-h] [--dry-run] [--files-only] [--local-version] [--changelog]
5858
[--devrelease DEVRELEASE] [--increment {MAJOR,MINOR,PATCH}]
5959
[--check-consistency] [--annotated-tag] [--gpg-sign]
6060
[--changelog-to-stdout] [--retry] [--major-version-zero]
61+
[--template TEMPLATE] [--extra EXTRA]
6162
[MANUAL_VERSION]
6263

6364
positional arguments:
@@ -97,6 +98,10 @@ options:
9798
--version-type {pep440,semver}
9899
choose version type
99100

101+
--template TEMPLATE, -t TEMPLATE
102+
changelog template file name (relative to the current working directory)
103+
--extra EXTRA, -e EXTRA
104+
a changelog extra variable (in the form 'key=value')
100105
```
101106
102107
### `--files-only`
@@ -241,6 +246,21 @@ Can I transition from one to the other?
241246
242247
Yes, you shouldn't have any issues.
243248
249+
### `--template`
250+
251+
Provides your own changelog jinja template.
252+
See [the template customization section](customization.md#customizing-the-changelog-template)
253+
254+
### `--extra`
255+
256+
Provides your own changelog extra variables by using the `extras` settings or the `--extra/-e` parameter.
257+
258+
```bash
259+
cz bump --changelog --extra key=value -e short="quoted value"
260+
```
261+
262+
See [the template customization section](customization.md#customizing-the-changelog-template).
263+
244264
## Avoid raising errors
245265
246266
Some situations from commitizen raise an exit code different than 0.

‎docs/changelog.md‎

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ update_changelog_on_bump = true
1414
```bash
1515
$ cz changelog --help
1616
usage: cz changelog [-h] [--dry-run] [--file-name FILE_NAME] [--unreleased-version UNRELEASED_VERSION] [--incremental] [--start-rev START_REV]
17+
[--template TEMPLATE] [--extra EXTRA]
1718
[rev_range]
1819

1920
positional arguments:
@@ -28,9 +29,19 @@ optional arguments:
2829
set the value for the new version (use the tag value), instead of using unreleased
2930
--incremental generates changelog from last created version, useful if the changelog has been manually modified
3031
--start-rev START_REV
32+
<<<<<<< HEAD
3133
start rev of the changelog. If not set, it will generate changelog from the start
3234
--merge-prerelease
3335
collect all changes from prereleases into next non-prerelease. If not set, it will include prereleases in the changelog
36+
||||||| parent of a3c1026 (feat(template): allow to override the template from cli, configuration and plugins)
37+
start rev of the changelog.If not set, it will generate changelog from the start
38+
=======
39+
start rev of the changelog.If not set, it will generate changelog from the start
40+
--template TEMPLATE, -t TEMPLATE
41+
changelog template file name (relative to the current working directory)
42+
--extra EXTRA, -e EXTRA
43+
a changelog extra variable (in the form 'key=value')
44+
>>>>>>> a3c1026 (feat(template): allow to override the template from cli, configuration and plugins)
3445
```
3546
3647
### Examples
@@ -186,6 +197,21 @@ cz changelog --merge-prerelease
186197
changelog_merge_prerelease = true
187198
```
188199
200+
### `template`
201+
202+
Provides your own changelog jinja template by using the `template` settings or the `--template` parameter.
203+
See [the template customization section](customization.md#customizing-the-changelog-template)
204+
205+
### `extras`
206+
207+
Provides your own changelog extra variables by using the `extras` settings or the `--extra/-e` parameter.
208+
209+
```bash
210+
cz changelog --extra key=value -e short="quoted value"
211+
```
212+
213+
See [the template customization section](customization.md#customizing-the-changelog-template)
214+
189215
## Hooks
190216
191217
Supported hook methods:

‎docs/config.md‎

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,22 @@ Default: `[]`
178178

179179
Calls the hook scripts **after** bumping the version. [Read more][post_bump_hooks]
180180

181+
### `template`
182+
183+
Type: `str`
184+
185+
Default: `None` (provided by plugin)
186+
187+
Provide custom changelog jinja template path relative to the current working directory. [Read more][template-customization]
188+
189+
### `extras`
190+
191+
Type: `dict[str, Any]`
192+
193+
Default: `{}`
194+
195+
Provide extra variables to the changelog template. [Read more][template-customization] |
196+
181197
## Configuration file
182198

183199
### pyproject.toml or .cz.toml
@@ -349,4 +365,5 @@ setup(
349365
[additional-features]: https://github.com/tmbo/questionary#additional-features
350366
[customization]: customization.md
351367
[shortcuts]: customization.md#shortcut-keys
368+
[template-customization]: customization.md#customizing-the-changelog-template
352369
[annotated-tags-vs-lightweight]: https://stackoverflow.com/a/11514139/2047185

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /