diff --git a/ghost/ui/cli.py b/ghost/ui/cli.py index e9721e7..c28e45e 100644 --- a/ghost/ui/cli.py +++ b/ghost/ui/cli.py @@ -17,7 +17,7 @@ from ghost.core.investigator import GhostInvestigator from ghost.core.config import config -from ghost.core.doctor import run_doctor_checks, summarize_doctor_checks +from ghost.core.doctor import has_error, run_doctor_checks, summarize_doctor_checks from ghost.backend.db import ( delete_investigation, get_graph_data, @@ -129,6 +129,8 @@ def doctor(as_json): if as_json: click.echo(json.dumps(summarize_doctor_checks(checks), indent=2)) + if has_error(checks): + raise click.exceptions.Exit(1) return print_banner() @@ -145,6 +147,8 @@ def add(name: str, ok: bool, detail: str, severity: str = "warn"): for check in checks: add(check.name, check.ok, check.detail, check.severity) console.print(table) + if has_error(checks): + raise click.exceptions.Exit(1) @cli.command(name="list") diff --git a/tests/test_investigator.py b/tests/test_investigator.py index 1191c30..6da7471 100644 --- a/tests/test_investigator.py +++ b/tests/test_investigator.py @@ -252,6 +252,38 @@ def test_doctor_cli_json_output(self): assert "checks" in payload assert "Ghost Doctor" not in result.output + def test_doctor_cli_json_exits_nonzero_on_hard_error(self, monkeypatch): + from click.testing import CliRunner + from ghost.core.doctor import DoctorCheck + from ghost.ui import cli as cli_module + + monkeypatch.setattr( + cli_module, + "run_doctor_checks", + lambda: [DoctorCheck("database", False, "unavailable", "error")], + ) + + result = CliRunner().invoke(cli_module.cli, ["doctor", "--json"]) + + assert result.exit_code == 1 + assert json.loads(result.output)["ok"] is False + + def test_doctor_cli_human_output_exits_nonzero_on_hard_error(self, monkeypatch): + from click.testing import CliRunner + from ghost.core.doctor import DoctorCheck + from ghost.ui import cli as cli_module + + monkeypatch.setattr( + cli_module, + "run_doctor_checks", + lambda: [DoctorCheck("database", False, "unavailable", "error")], + ) + + result = CliRunner().invoke(cli_module.cli, ["doctor"]) + + assert result.exit_code == 1 + assert "FAIL" in result.output + def test_doctor_reports_unsupported_database_override(self): from ghost.core.config import Config from ghost.core.doctor import has_error, run_doctor_checks, summarize_doctor_checks