merge: test(scripts): lock self_healing safe CLI behavior (#469)
Some checks failed
Architecture Lint / Linter Tests (push) Successful in 11s
Architecture Lint / Lint Repository (push) Has been cancelled
Smoke Test / smoke (push) Failing after 10s
Validate Config / YAML Lint (push) Has been cancelled
Validate Config / JSON Validate (push) Has been cancelled
Validate Config / Python Syntax & Import Check (push) Has been cancelled
Validate Config / Shell Script Lint (push) Has been cancelled
Validate Config / Cron Syntax Check (push) Has been cancelled
Validate Config / Deploy Script Dry Run (push) Has been cancelled
Validate Config / Playbook Schema Validation (push) Has been cancelled
Some checks failed
Architecture Lint / Linter Tests (push) Successful in 11s
Architecture Lint / Lint Repository (push) Has been cancelled
Smoke Test / smoke (push) Failing after 10s
Validate Config / YAML Lint (push) Has been cancelled
Validate Config / JSON Validate (push) Has been cancelled
Validate Config / Python Syntax & Import Check (push) Has been cancelled
Validate Config / Shell Script Lint (push) Has been cancelled
Validate Config / Cron Syntax Check (push) Has been cancelled
Validate Config / Deploy Script Dry Run (push) Has been cancelled
Validate Config / Playbook Schema Validation (push) Has been cancelled
Auto-merged by PR triage bot
This commit was merged in pull request #469.
This commit is contained in:
@@ -14,6 +14,7 @@ import subprocess
|
||||
import argparse
|
||||
import requests
|
||||
import datetime
|
||||
from typing import Sequence
|
||||
|
||||
# --- CONFIGURATION ---
|
||||
FLEET = {
|
||||
@@ -192,10 +193,10 @@ EXAMPLES:
|
||||
"""
|
||||
print(help_text)
|
||||
|
||||
def main():
|
||||
def build_parser() -> argparse.ArgumentParser:
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Self-healing infrastructure script (safe-by-default).",
|
||||
add_help=False # We'll handle --help ourselves
|
||||
add_help=False,
|
||||
)
|
||||
parser.add_argument("--dry-run", action="store_true", default=False,
|
||||
help="Run in dry-run mode (default behavior).")
|
||||
@@ -209,25 +210,28 @@ def main():
|
||||
help="Show detailed help about safety features.")
|
||||
parser.add_argument("--help", "-h", action="store_true", default=False,
|
||||
help="Show standard help.")
|
||||
return parser
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
def main(argv: Sequence[str] | None = None):
|
||||
parser = build_parser()
|
||||
args = parser.parse_args(list(argv) if argv is not None else None)
|
||||
|
||||
if args.help_safe:
|
||||
print_help_safe()
|
||||
sys.exit(0)
|
||||
raise SystemExit(0)
|
||||
|
||||
if args.help:
|
||||
parser.print_help()
|
||||
sys.exit(0)
|
||||
raise SystemExit(0)
|
||||
|
||||
# Determine mode: if --execute is given, disable dry-run
|
||||
dry_run = not args.execute
|
||||
# If --dry-run is explicitly given, ensure dry-run (redundant but clear)
|
||||
if args.dry_run:
|
||||
dry_run = True
|
||||
|
||||
healer = SelfHealer(dry_run=dry_run, confirm_kill=args.confirm_kill, yes=args.yes)
|
||||
healer.run()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
62
tests/test_self_healing.py
Normal file
62
tests/test_self_healing.py
Normal file
@@ -0,0 +1,62 @@
|
||||
"""Tests for scripts/self_healing.py safe CLI behavior."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import importlib.util
|
||||
from pathlib import Path
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
import pytest
|
||||
|
||||
REPO_ROOT = Path(__file__).parent.parent
|
||||
spec = importlib.util.spec_from_file_location("self_healing", REPO_ROOT / "scripts" / "self_healing.py")
|
||||
sh = importlib.util.module_from_spec(spec)
|
||||
spec.loader.exec_module(sh)
|
||||
|
||||
|
||||
class TestMainCli:
|
||||
def test_help_exits_without_running_healer(self, monkeypatch, capsys):
|
||||
healer_cls = MagicMock()
|
||||
monkeypatch.setattr(sh, "SelfHealer", healer_cls)
|
||||
|
||||
with pytest.raises(SystemExit) as excinfo:
|
||||
sh.main(["--help"])
|
||||
|
||||
assert excinfo.value.code == 0
|
||||
healer_cls.assert_not_called()
|
||||
out = capsys.readouterr().out
|
||||
assert "--execute" in out
|
||||
assert "--help-safe" in out
|
||||
|
||||
def test_help_safe_exits_without_running_healer(self, monkeypatch, capsys):
|
||||
healer_cls = MagicMock()
|
||||
monkeypatch.setattr(sh, "SelfHealer", healer_cls)
|
||||
|
||||
with pytest.raises(SystemExit) as excinfo:
|
||||
sh.main(["--help-safe"])
|
||||
|
||||
assert excinfo.value.code == 0
|
||||
healer_cls.assert_not_called()
|
||||
out = capsys.readouterr().out
|
||||
assert "DRY-RUN" in out
|
||||
assert "--confirm-kill" in out
|
||||
|
||||
def test_default_invocation_runs_in_dry_run_mode(self, monkeypatch):
|
||||
healer = MagicMock()
|
||||
healer_cls = MagicMock(return_value=healer)
|
||||
monkeypatch.setattr(sh, "SelfHealer", healer_cls)
|
||||
|
||||
sh.main([])
|
||||
|
||||
healer_cls.assert_called_once_with(dry_run=True, confirm_kill=False, yes=False)
|
||||
healer.run.assert_called_once_with()
|
||||
|
||||
def test_execute_flag_disables_dry_run(self, monkeypatch):
|
||||
healer = MagicMock()
|
||||
healer_cls = MagicMock(return_value=healer)
|
||||
monkeypatch.setattr(sh, "SelfHealer", healer_cls)
|
||||
|
||||
sh.main(["--execute", "--yes", "--confirm-kill"])
|
||||
|
||||
healer_cls.assert_called_once_with(dry_run=False, confirm_kill=True, yes=True)
|
||||
healer.run.assert_called_once_with()
|
||||
Reference in New Issue
Block a user