fix(config): one bounded backups/config/ dir replaces four config.yaml.bak schemes
Four writers each dropped their own uniquely-named copy of config.yaml next to the real file and none of them ever deleted anything: hermes setup (config.yaml.bak.YYYYMMDD_HHMMSS, one per run even with no change), the corrupt-YAML snapshot (config.yaml.corrupt.<ts>.bak), hermes migrate xai (config.yaml.bak-pre-migrate-xai-<ts>) and the Docker boot migration (config.yaml.bak-<ts>, .env.bak-<ts>). A home dir accumulated a dozen variants with no way to tell which mattered. hermes_cli/config_backups.py::backup_config is now the single writer: backups/config/config.yaml.<reason>.<YYYYMMDD-HHMMSS>, skipped when the newest copy for that reason is byte-identical, rotated to the newest five per reason. backups/ is already excluded from full backups so nothing nests. Legacy siblings written by the old schemes are moved into the dir on first use; hand-named copies (config.yaml.bak-my-note) are left alone. Live: three `hermes setup --non-interactive` runs against an unchanged config went from three .bak files in HERMES_HOME to one pre-setup copy under backups/config/; repeated loads of broken YAML produce one corrupt copy instead of one per process (deduped by content).
This commit is contained in:
+2
-15
@@ -580,20 +580,6 @@ def run_setup_wizard(args):
|
||||
return None
|
||||
|
||||
|
||||
def _backup_config_file(config_path: Path) -> Path | None:
|
||||
"""Back up config.yaml before setup modifies it; None when absent or copy fails."""
|
||||
if not config_path.exists():
|
||||
return None
|
||||
import shutil
|
||||
from datetime import datetime
|
||||
backup_path = config_path.with_suffix(f".yaml.bak.{datetime.now().strftime('%Y%m%d_%H%M%S')}")
|
||||
try:
|
||||
shutil.copy2(config_path, backup_path)
|
||||
return backup_path
|
||||
except Exception:
|
||||
return None
|
||||
|
||||
|
||||
def _run_setup_section(config: dict, section: str) -> None:
|
||||
"""``hermes setup <section>``: run one SETUP_SECTIONS entry under the banner."""
|
||||
entry = next(((label, func) for key, label, func in SETUP_SECTIONS if key == section), None)
|
||||
@@ -672,7 +658,8 @@ def _run_setup_wizard_impl(args):
|
||||
hermes_home = get_hermes_home()
|
||||
# Back up existing config before setup modifies it (#3522)
|
||||
config_path = get_config_path()
|
||||
_backup_path = _backup_config_file(config_path)
|
||||
from hermes_cli.config_backups import backup_config
|
||||
_backup_path = backup_config(config_path, "pre-setup")
|
||||
|
||||
# Non-interactive environments (headless SSH, Docker, CI/CD)
|
||||
if getattr(args, 'non_interactive', False) or not is_interactive_stdin():
|
||||
|
||||
Reference in New Issue
Block a user