chore(release): move tooling tests to meta repository
This commit is contained in:
@@ -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()
|
|
||||||
@@ -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()
|
|
||||||
Reference in New Issue
Block a user