Skip to content

Commit c2235be

Browse files
committed
feat: add --no-raise to avoid raising error codes
Closes #485
1 parent 6efad39 commit c2235be

File tree

3 files changed

+98
-4
lines changed

3 files changed

+98
-4
lines changed

commitizen/cli.py

+50-4
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,18 @@
22
import logging
33
import sys
44
from functools import partial
5+
from typing import List
56

67
import argcomplete
78
from decli import cli
89

9-
from commitizen import commands, config
10-
from commitizen.exceptions import CommitizenException, ExpectedExit, NoCommandFoundError
10+
from commitizen import commands, config, out
11+
from commitizen.exceptions import (
12+
CommitizenException,
13+
ExitCode,
14+
ExpectedExit,
15+
NoCommandFoundError,
16+
)
1117

1218
logger = logging.getLogger(__name__)
1319
data = {
@@ -24,6 +30,12 @@
2430
"name": ["-n", "--name"],
2531
"help": "use the given commitizen (default: cz_conventional_commits)",
2632
},
33+
{
34+
"name": ["-nr", "--no-raise"],
35+
"type": str,
36+
"required": False,
37+
"help": "comma separated error codes that won't rise error, e.g: cz -nr 1,2,3 bump. See codes at https://commitizen-tools.github.io/commitizen/exit_codes/",
38+
},
2739
],
2840
"subcommands": {
2941
"title": "commands",
@@ -268,13 +280,20 @@
268280
original_excepthook = sys.excepthook
269281

270282

271-
def commitizen_excepthook(type, value, tracekback, debug=False):
283+
def commitizen_excepthook(
284+
type, value, tracekback, debug=False, no_raise: List[int] = None
285+
):
286+
if not no_raise:
287+
no_raise = []
272288
if isinstance(value, CommitizenException):
273289
if value.message:
274290
value.output_method(value.message)
275291
if debug:
276292
original_excepthook(type, value, tracekback)
277-
sys.exit(value.exit_code)
293+
exit_code = value.exit_code
294+
if exit_code in no_raise:
295+
exit_code = 0
296+
sys.exit(exit_code)
278297
else:
279298
original_excepthook(type, value, tracekback)
280299

@@ -284,6 +303,27 @@ def commitizen_excepthook(type, value, tracekback, debug=False):
284303
sys.excepthook = commitizen_excepthook
285304

286305

306+
def parse_no_raise(comma_separated_no_raise: str) -> List[int]:
307+
"""
308+
Convert the given string with exit code digits or exit
309+
codes name to its integer representation
310+
"""
311+
no_raise_items = comma_separated_no_raise.split(",")
312+
no_raise_codes = []
313+
for item in no_raise_items:
314+
if item.isdecimal():
315+
no_raise_codes.append(int(item))
316+
continue
317+
try:
318+
exit_code = ExitCode[item]
319+
except KeyError:
320+
out.warn(f"WARN: no_raise key {item} does not exist. Skipping.")
321+
continue
322+
else:
323+
no_raise_codes.append(exit_code.value)
324+
return no_raise_codes
325+
326+
287327
def main():
288328
conf = config.read_cfg()
289329
parser = cli(data)
@@ -313,6 +353,12 @@ def main():
313353
if args.debug:
314354
logging.getLogger("commitizen").setLevel(logging.DEBUG)
315355
sys.excepthook = commitizen_debug_excepthook
356+
elif args.no_raise:
357+
no_raise_exit_codes = parse_no_raise(args.no_raise)
358+
no_raise_debug_excepthook = partial(
359+
commitizen_excepthook, no_raise=no_raise_exit_codes
360+
)
361+
sys.excepthook = no_raise_debug_excepthook
316362

317363
args.func(conf, vars(args))()
318364

commitizen/out.py

+5
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,8 @@ def info(value: str) -> None:
3030

3131
def diagnostic(value: str):
3232
line(value, file=sys.stderr)
33+
34+
35+
def warn(value: str) -> None:
36+
message = colored(value, "magenta")
37+
line(message)

tests/test_cli.py

+43
Original file line numberDiff line numberDiff line change
@@ -95,3 +95,46 @@ def test_argcomplete_activation():
9595
output = subprocess.run(["register-python-argcomplete", "cz"])
9696

9797
assert output.returncode == 0
98+
99+
100+
def test_commitizen_excepthook_no_raises(capsys):
101+
with pytest.raises(SystemExit) as excinfo:
102+
cli.commitizen_excepthook(
103+
NotAGitProjectError,
104+
NotAGitProjectError(),
105+
"",
106+
no_raise=[NotAGitProjectError.exit_code],
107+
)
108+
109+
assert excinfo.type == SystemExit
110+
assert excinfo.value.code == 0
111+
112+
113+
def test_parse_no_raise_single_integer():
114+
input_str = "1"
115+
result = cli.parse_no_raise(input_str)
116+
assert result == [1]
117+
118+
119+
def test_parse_no_raise_integers():
120+
input_str = "1,2,3"
121+
result = cli.parse_no_raise(input_str)
122+
assert result == [1, 2, 3]
123+
124+
125+
def test_parse_no_raise_error_code():
126+
input_str = "NO_COMMITIZEN_FOUND,NO_COMMITS_FOUND,NO_PATTERN_MAP"
127+
result = cli.parse_no_raise(input_str)
128+
assert result == [1, 3, 5]
129+
130+
131+
def test_parse_no_raise_mix_integer_error_code():
132+
input_str = "NO_COMMITIZEN_FOUND,2,NO_COMMITS_FOUND,4"
133+
result = cli.parse_no_raise(input_str)
134+
assert result == [1, 2, 3, 4]
135+
136+
137+
def test_parse_no_raise_mix_invalid_arg_is_skipped():
138+
input_str = "NO_COMMITIZEN_FOUND,2,nothing,4"
139+
result = cli.parse_no_raise(input_str)
140+
assert result == [1, 2, 4]

0 commit comments

Comments
 (0)