Files
redmine/tests/test_post_import_refresh.py
2026-05-04 09:49:47 -04:00

113 lines
5.3 KiB
Python

import json
import tempfile
import unittest
from pathlib import Path
from post_import_refresh import AutomationConfig, StepResult, build_steps, write_status
class PostImportRefreshPlanTest(unittest.TestCase):
def test_dry_run_is_the_default_and_never_enables_index_writes(self):
config = AutomationConfig()
steps = build_steps(config)
commands = "\n".join(command for step in steps for command in step.commands)
self.assertFalse(config.apply)
self.assertIn("validate semantic index dry-run", [step.name for step in steps])
self.assertIn("semantic_index/refresh.sh", commands)
self.assertNotIn("semantic_index/refresh.sh --apply", commands)
self.assertNotIn("--force-rebuild", commands)
self.assertNotIn("systemctl enable --now semantic-index-refresh.timer", commands)
def test_plugin_reapply_happens_before_migrations_and_helpdesk_reset(self):
names = [step.name for step in build_steps(AutomationConfig())]
self.assertLess(names.index("reapply tracked plugins"), names.index("run plugin migrations"))
self.assertLess(names.index("run plugin migrations"), names.index("reset Helpdesk mail settings"))
def test_expected_plugins_are_reapplied_to_remote_redmine_tree(self):
steps = build_steps(AutomationConfig())
plugin_step = next(step for step in steps if step.name == "reapply tracked plugins")
commands = "\n".join(plugin_step.commands)
self.assertIn("plugins/redmine_event_outbox", commands)
self.assertIn("plugins/redmine_contacts", commands)
self.assertIn("plugins/redmine_contacts_helpdesk", commands)
self.assertNotIn("plugins/redmine_event_outbox/", commands)
self.assertIn("reddev@192.168.50.170:/usr/share/redmine/plugins/", commands)
def test_apply_mode_runs_mutating_validation_sequence(self):
steps = build_steps(AutomationConfig(apply=True))
commands = "\n".join(command for step in steps for command in step.commands)
self.assertIn("bundle exec rake redmine:plugins:migrate", commands)
self.assertIn("./reset_helpdesk_mail_settings.py", commands)
self.assertIn("touch tmp/restart.txt", commands)
self.assertIn("./validate_test_instance.py", commands)
def test_remote_write_steps_use_sudo_by_default(self):
commands = "\n".join(command for step in build_steps(AutomationConfig()) for command in step.commands)
self.assertIn("--rsync-path 'sudo rsync'", commands)
self.assertIn("sudo mkdir -p", commands)
self.assertIn("sudo chmod -R g+rwX", commands)
def test_local_mode_emits_local_commands_without_ssh(self):
config = AutomationConfig(local=True)
commands = "\n".join(command for step in build_steps(config) for command in step.commands)
self.assertNotIn("ssh -i", commands)
self.assertNotIn("rsync-path", commands)
self.assertIn("reset_helpdesk_mail_settings.py --local", commands)
self.assertIn("validate_test_instance.py --local", commands)
self.assertNotIn("--composer-bin", commands)
self.assertIn("redmine_outbox_worker.py --local --status", commands)
self.assertIn("/opt/lanscratch/redmine-post-import/repo/plugins/redmine_event_outbox", commands)
self.assertIn("/usr/share/redmine/plugins/", commands)
self.assertIn("cd /usr/share/redmine && RAILS_ENV=production bundle exec rake redmine:plugins:migrate", commands)
def test_local_semantic_check_is_non_blocking_without_staged_venv(self):
config = AutomationConfig(local=True)
semantic_step = next(step for step in build_steps(config) if step.name == "validate semantic index dry-run")
command = semantic_step.commands[0]
self.assertIn("test -x /opt/lanscratch/redmine-post-import/repo/.venv/bin/python", command)
self.assertIn("semantic index runtime missing; skipping dry-run", command)
self.assertIn("else", command)
def test_status_paths_default_to_lanscratch(self):
config = AutomationConfig()
self.assertEqual(Path("/opt/lanscratch/redmine-post-import/status"), config.status_dir)
def test_write_status_updates_latest_and_success_only_on_success(self):
with tempfile.TemporaryDirectory() as tmp:
config = AutomationConfig(status_dir=Path(tmp))
failed = write_status(
config,
run_id="20260428T010000Z",
status="failed",
results=[StepResult("preflight", "test -d missing", 1)],
failed_step="preflight",
)
self.assertTrue((Path(tmp) / "latest.json").exists())
self.assertTrue((Path(tmp) / "runs" / "20260428T010000Z.json").exists())
self.assertFalse((Path(tmp) / "latest-success.json").exists())
self.assertEqual("failed", failed["status"])
successful = write_status(
config,
run_id="20260428T010100Z",
status="success",
results=[StepResult("preflight", "test -d plugins", 0)],
)
latest_success = json.loads((Path(tmp) / "latest-success.json").read_text())
self.assertEqual(successful["run_id"], latest_success["run_id"])
self.assertEqual("success", latest_success["status"])
if __name__ == "__main__":
unittest.main()