diff --git a/tests/test_release_doctor.py b/tests/test_release_doctor.py deleted file mode 100644 index 4ea2957..0000000 --- a/tests/test_release_doctor.py +++ /dev/null @@ -1,187 +0,0 @@ -from __future__ import annotations - -import importlib.util -from pathlib import Path -import sys -import unittest - - -ROOT = Path(__file__).resolve().parents[1] -SCRIPT = ROOT / "scripts" / "release-doctor.py" - - -def load_doctor_module(): - spec = importlib.util.spec_from_file_location("release_doctor", SCRIPT) - if spec is None or spec.loader is None: - raise RuntimeError(f"Could not load {SCRIPT}") - module = importlib.util.module_from_spec(spec) - sys.modules[spec.name] = module - spec.loader.exec_module(module) - return module - - -class ReleaseDoctorTests(unittest.TestCase): - def test_release_repo_names_include_catalog_and_migration_baseline_owners(self) -> None: - doctor = load_doctor_module() - - names = set(doctor.release_repo_names(ROOT.parent)) - - self.assertIn("govoplan-core", names) - self.assertIn("govoplan-files", names) - self.assertIn("govoplan-idm", names) - - def test_repo_findings_detect_dirty_repositories(self) -> None: - doctor = load_doctor_module() - repo = doctor.RepoState( - name="govoplan-files", - path="/tmp/govoplan-files", - exists=True, - dirty_entries=(" M pyproject.toml",), - pyproject_version="0.1.7", - local_tag_exists=True, - ) - - findings = doctor.repo_findings((repo,), target_version="0.1.7", target_tag="v0.1.7") - - self.assertEqual("blocker", findings[0].severity) - self.assertEqual("repo-dirty", findings[0].check_id) - self.assertIn("git status --short", [item.command for item in findings[0].commands]) - - def test_dubious_ownership_errors_suggest_safe_directory_command(self) -> None: - doctor = load_doctor_module() - repo = doctor.RepoState( - name="govoplan-files", - path="/tmp/govoplan-files", - exists=True, - safe_directory_required=True, - safe_directory_command="git config --global --add safe.directory /tmp/govoplan-files", - errors=("fatal: detected dubious ownership in repository",), - ) - - findings = doctor.repo_findings((repo,), target_version="0.1.7", target_tag="v0.1.7") - - self.assertEqual("repo-safe-directory", findings[0].check_id) - self.assertEqual("blocker", findings[0].severity) - self.assertTrue(findings[0].commands[0].mutating) - self.assertIn("safe.directory", findings[0].commands[0].command) - - def test_dubious_ownership_detection_matches_git_error(self) -> None: - doctor = load_doctor_module() - - self.assertTrue( - doctor.is_dubious_ownership_error( - "fatal: detected dubious ownership in repository at '/workspace/repo'\n" - "git config --global --add safe.directory /workspace/repo" - ) - ) - - def test_release_migration_strict_errors_suggest_recording_baseline(self) -> None: - doctor = load_doctor_module() - - findings = doctor.migration_findings( - { - "release": { - "ok": True, - "graph_errors": [], - "strict_errors": ["current migration heads are not recorded"], - }, - "dev": {"ok": True, "graph_errors": [], "strict_errors": []}, - }, - target_version="0.2.0", - ) - - self.assertEqual("migration-release-baseline", findings[0].check_id) - self.assertEqual("blocker", findings[0].severity) - commands = [item.command for item in findings[0].commands] - self.assertTrue(any("--record-release 0.2.0" in item for item in commands)) - - def test_catalog_findings_detect_missing_signatures(self) -> None: - doctor = load_doctor_module() - - findings = doctor.catalog_findings( - { - "catalog_exists": True, - "catalog_path": "/tmp/stable.json", - "core_release_version": "0.1.7", - "signature_count": 0, - "keyring_exists": True, - "key_count": 1, - }, - target_version="0.1.7", - online=False, - ) - - self.assertEqual("catalog-signatures", findings[0].check_id) - self.assertEqual("blocker", findings[0].severity) - - def test_suggested_commands_are_deduplicated(self) -> None: - doctor = load_doctor_module() - suggested = doctor.SuggestedCommand(title="Status", command="git status --short", cwd="/tmp/repo") - report = doctor.DoctorReport( - generated_at="2026-07-11T00:00:00Z", - workspace_root="/tmp", - target_version="0.1.7", - target_tag="v0.1.7", - online=False, - overall_status="blocked", - repos=(), - findings=( - doctor.Finding("a", "blocker", "A", "", (suggested,)), - doctor.Finding("b", "warning", "B", "", (suggested,)), - ), - ) - - self.assertEqual((suggested,), doctor.collect_suggested_commands(report)) - - def test_default_report_is_concise_and_keeps_details_out(self) -> None: - doctor = load_doctor_module() - repo = doctor.RepoState( - name="govoplan-files", - path="/tmp/govoplan-files", - exists=True, - dirty_entries=(" M pyproject.toml",), - ) - report = doctor.DoctorReport( - generated_at="2026-07-11T00:00:00Z", - workspace_root="/tmp", - target_version="0.1.7", - target_tag="v0.1.7", - online=False, - overall_status="blocked", - repos=(repo,), - findings=(doctor.Finding("repo-dirty", "blocker", "govoplan-files has uncommitted changes", "M pyproject.toml"),), - ) - - concise = doctor.render_text_report(report, detailed=False, include_commands=False) - detailed = doctor.render_text_report(report, detailed=True, include_commands=False) - - self.assertIn("dirty=1", concise) - self.assertNotIn("M pyproject.toml", concise) - self.assertIn("M pyproject.toml", detailed) - - def test_interactive_actions_offer_dirty_bulk_commit_push(self) -> None: - doctor = load_doctor_module() - repo = doctor.RepoState( - name="govoplan-files", - path="/tmp/govoplan-files", - exists=True, - dirty_entries=(" M pyproject.toml",), - ) - report = doctor.DoctorReport( - generated_at="2026-07-11T00:00:00Z", - workspace_root="/tmp", - target_version="0.1.7", - target_tag="v0.1.7", - online=False, - overall_status="blocked", - repos=(repo,), - findings=(), - ) - - actions = dict(doctor.interactive_actions(report)) - - self.assertIn("commit-push-dirty", actions) - - -if __name__ == "__main__": - unittest.main() diff --git a/tests/test_release_migration_audit.py b/tests/test_release_migration_audit.py deleted file mode 100644 index 838140a..0000000 --- a/tests/test_release_migration_audit.py +++ /dev/null @@ -1,190 +0,0 @@ -from __future__ import annotations - -import importlib.util -from pathlib import Path -import sys -import tempfile -import unittest - - -ROOT = Path(__file__).resolve().parents[1] -SCRIPT = ROOT / "scripts" / "release-migration-audit.py" - - -def load_audit_module(): - spec = importlib.util.spec_from_file_location("release_migration_audit", SCRIPT) - if spec is None or spec.loader is None: - raise RuntimeError(f"Could not load {SCRIPT}") - module = importlib.util.module_from_spec(spec) - sys.modules[spec.name] = module - spec.loader.exec_module(module) - return module - - -class ReleaseMigrationAuditTests(unittest.TestCase): - def test_typed_alembic_variables_are_parsed(self) -> None: - audit = load_audit_module() - with tempfile.TemporaryDirectory(prefix="migration-audit-test-") as directory: - path = Path(directory) / "1234_example.py" - path.write_text( - """ -from __future__ import annotations -from typing import Sequence, Union - -revision: str = "1234" -down_revision: Union[str, None] = "base" -depends_on: Union[str, None] = "core" -branch_labels: Union[str, Sequence[str], None] = None -""", - encoding="utf-8", - ) - - migration = audit.parse_migration_file("govoplan-core", path) - - self.assertIsNotNone(migration) - self.assertEqual(migration.revision, "1234") - self.assertEqual(migration.down_revisions, ("base",)) - self.assertEqual(migration.depends_on, ("core",)) - self.assertEqual(migration.branch_labels, ()) - - def test_release_baseline_matches_current_heads_in_strict_report(self) -> None: - audit = load_audit_module() - migrations = [ - audit.Migration("govoplan-core", Path("base.py"), "base", (), (), ()), - audit.Migration("govoplan-core", Path("head.py"), "head", ("base",), (), ()), - ] - report = audit.build_report( - migrations, - baseline={ - "version": 1, - "releases": [ - { - "release": "0.1.0", - "heads": [{"owner": "govoplan-core", "revision": "head"}], - } - ], - }, - baseline_file=Path("docs/migration-release-baselines.json"), - workspace_root=Path("/workspace"), - ) - - self.assertEqual(report["current_heads"], ["head"]) - self.assertEqual(report["graph_errors"], []) - self.assertEqual(report["strict_errors"], []) - - def test_owner_heads_are_accepted_for_subset_installs(self) -> None: - audit = load_audit_module() - migrations = [ - audit.Migration("govoplan-core", Path("base.py"), "base", (), (), ()), - audit.Migration("govoplan-core", Path("core_head.py"), "core-head", ("base",), (), ()), - ] - report = audit.build_report( - migrations, - baseline={ - "version": 1, - "releases": [ - { - "release": "0.1.0", - "heads": [{"owner": "govoplan-files", "revision": "files-head"}], - "owner_heads": [{"owner": "govoplan-core", "revisions": ["core-head"]}], - } - ], - }, - baseline_file=Path("docs/migration-release-baselines.json"), - workspace_root=Path("/workspace"), - ) - - self.assertEqual(report["current_heads"], ["core-head"]) - self.assertEqual(report["strict_errors"], []) - - def test_records_current_release_baseline(self) -> None: - audit = load_audit_module() - migrations = [ - audit.Migration("govoplan-core", Path("base.py"), "base", (), (), ()), - audit.Migration("govoplan-core", Path("core_head.py"), "core-head", ("base",), (), ()), - audit.Migration("govoplan-files", Path("files_head.py"), "files-head", ("core-head",), (), ()), - ] - report = audit.build_report( - migrations, - baseline={"version": 1, "releases": []}, - baseline_file=Path("docs/migration-release-baselines.json"), - workspace_root=Path("/workspace"), - ) - - baseline = audit.record_release_baseline( - {"version": 1, "releases": []}, - report, - release="0.2.0", - replace=False, - ) - - release = baseline["releases"][0] - self.assertEqual(release["release"], "0.2.0") - self.assertEqual(release["squash_policy"], "reviewed-manual") - self.assertEqual(release["heads"], [{"owner": "govoplan-files", "revision": "files-head"}]) - self.assertIn({"owner": "govoplan-core", "revisions": ["core-head"]}, release["owner_heads"]) - - def test_missing_down_revision_is_a_graph_error(self) -> None: - audit = load_audit_module() - migrations = [ - audit.Migration("govoplan-core", Path("head.py"), "head", ("missing",), (), ()), - ] - report = audit.build_report( - migrations, - baseline={"version": 1, "releases": []}, - baseline_file=Path("docs/migration-release-baselines.json"), - workspace_root=Path("/workspace"), - ) - - self.assertIn("references missing down_revision", report["graph_errors"][0]) - - def test_depends_on_participates_in_graph_validation_and_heads(self) -> None: - audit = load_audit_module() - migrations = [ - audit.Migration("govoplan-core", Path("core.py"), "core", (), (), ()), - audit.Migration("govoplan-files", Path("files.py"), "files", (), ("core",), ()), - ] - report = audit.build_report( - migrations, - baseline={"version": 1, "releases": []}, - baseline_file=Path("docs/migration-release-baselines.json"), - workspace_root=Path("/workspace"), - ) - - self.assertEqual(report["graph_errors"], []) - self.assertEqual(report["current_heads"], ["files"]) - - def test_missing_depends_on_is_a_graph_error(self) -> None: - audit = load_audit_module() - migrations = [ - audit.Migration("govoplan-files", Path("files.py"), "files", (), ("missing",), ()), - ] - report = audit.build_report( - migrations, - baseline={"version": 1, "releases": []}, - baseline_file=Path("docs/migration-release-baselines.json"), - workspace_root=Path("/workspace"), - ) - - self.assertIn("references missing depends_on", report["graph_errors"][0]) - - def test_dev_track_does_not_emit_release_baseline_warnings(self) -> None: - audit = load_audit_module() - migrations = [ - audit.Migration("govoplan-core", Path("base.py"), "base", (), (), ()), - audit.Migration("govoplan-core", Path("head.py"), "head", ("base",), (), ()), - ] - report = audit.build_report( - migrations, - baseline={"version": 1, "releases": []}, - baseline_file=Path("docs/migration-release-baselines.json"), - workspace_root=Path("/workspace"), - track="dev", - ) - - self.assertEqual(report["track"], "dev") - self.assertEqual(report["strict_errors"], []) - - -if __name__ == "__main__": - unittest.main()