Skip to content

Commit f429a68

Browse files
committed
feat: add --no-raise to avoid raising error codes
Closes #485
1 parent 605b125 commit f429a68

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",
@@ -274,13 +286,20 @@
274286
original_excepthook = sys.excepthook
275287

276288

277-
def commitizen_excepthook(type, value, tracekback, debug=False):
289+
def commitizen_excepthook(
290+
type, value, tracekback, debug=False, no_raise: List[int] = None
291+
):
292+
if not no_raise:
293+
no_raise = []
278294
if isinstance(value, CommitizenException):
279295
if value.message:
280296
value.output_method(value.message)
281297
if debug:
282298
original_excepthook(type, value, tracekback)
283-
sys.exit(value.exit_code)
299+
exit_code = value.exit_code
300+
if exit_code in no_raise:
301+
exit_code = 0
302+
sys.exit(exit_code)
284303
else:
285304
original_excepthook(type, value, tracekback)
286305

@@ -290,6 +309,27 @@ def commitizen_excepthook(type, value, tracekback, debug=False):
290309
sys.excepthook = commitizen_excepthook
291310

292311

312+
def parse_no_raise(comma_separated_no_raise: str) -> List[int]:
313+
"""
314+
Convert the given string with exit code digits or exit
315+
codes name to its integer representation
316+
"""
317+
no_raise_items = comma_separated_no_raise.split(",")
318+
no_raise_codes = []
319+
for item in no_raise_items:
320+
if item.isdecimal():
321+
no_raise_codes.append(int(item))
322+
continue
323+
try:
324+
exit_code = ExitCode[item]
325+
except KeyError:
326+
out.warn(f"WARN: no_raise key {item} does not exist. Skipping.")
327+
continue
328+
else:
329+
no_raise_codes.append(exit_code.value)
330+
return no_raise_codes
331+
332+
293333
def main():
294334
conf = config.read_cfg()
295335
parser = cli(data)
@@ -319,6 +359,12 @@ def main():
319359
if args.debug:
320360
logging.getLogger("commitizen").setLevel(logging.DEBUG)
321361
sys.excepthook = commitizen_debug_excepthook
362+
elif args.no_raise:
363+
no_raise_exit_codes = parse_no_raise(args.no_raise)
364+
no_raise_debug_excepthook = partial(
365+
commitizen_excepthook, no_raise=no_raise_exit_codes
366+
)
367+
sys.excepthook = no_raise_debug_excepthook
322368

323369
args.func(conf, vars(args))()
324370

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)