diff --git a/great_ai/__main__.py b/great_ai/__main__.py index 8e79328..b8416c7 100644 --- a/great_ai/__main__.py +++ b/great_ai/__main__.py @@ -212,6 +212,7 @@ def main() -> None: exit() except Exception as e: logger.error(e) + raise SystemExit(1) from e if __name__ == "__main__": diff --git a/great_ai/large_file/__main__.py b/great_ai/large_file/__main__.py index 2e804a6..41692a9 100644 --- a/great_ai/large_file/__main__.py +++ b/great_ai/large_file/__main__.py @@ -69,6 +69,7 @@ def main() -> None: exit() except Exception as e: logger.exception(e) + raise SystemExit(1) from e if __name__ == "__main__": diff --git a/tests/test_cli_regressions.py b/tests/test_cli_regressions.py index 4be66ea..11c3bb0 100644 --- a/tests/test_cli_regressions.py +++ b/tests/test_cli_regressions.py @@ -1,5 +1,8 @@ +import importlib from threading import Event +from unittest.mock import patch +import pytest from watchdog.events import FileClosedEvent, FileModifiedEvent, FileMovedEvent from great_ai.deploy.reload_event_handler import ReloadEventHandler @@ -25,3 +28,18 @@ def test_reload_debounces_edit_and_replacement_events() -> None: handler.close() handler.dispatch(FileModifiedEvent("service.py")) assert calls == ["restart"] + + +@pytest.mark.parametrize( + "module_name, operation", + [ + ("great_ai.__main__", "serve"), + ("great_ai.large_file.__main__", "handle_command"), + ], +) +def test_cli_operational_errors_exit_nonzero(module_name: str, operation: str) -> None: + module = importlib.import_module(module_name) + with patch.object(module, operation, side_effect=ValueError("failed")): + with pytest.raises(SystemExit) as error: + module.main() + assert error.value.code == 1