from __future__ import annotations import sys import unittest from pathlib import Path from govoplan_core.core.modules import ModuleManifest from govoplan_core.core.provider_governance import ( ExternalProviderDeclaration, ModuleArchitectureDeclaration, ModuleMaturityEvidence, ProviderBehaviorDeclaration, ProviderObjectDeclaration, ) META_ROOT = Path(__file__).resolve().parents[1] RELEASE_ROOT = META_ROOT / "tools" / "release" if str(RELEASE_ROOT) not in sys.path: sys.path.insert(0, str(RELEASE_ROOT)) from govoplan_release.catalog_entry_synthesis import ( # noqa: E402 manifest_catalog_entry, validate_initial_entry_closure, ) from govoplan_release.selective_catalog import apply_repo_updates # noqa: E402 class ReleaseCatalogEntrySynthesisTests(unittest.TestCase): def test_catalog_entry_preserves_architecture_and_provider_declarations( self, ) -> None: provider = ExternalProviderDeclaration( id="example.records", module_id="example", label="Example records", maturity="read", operations=("read",), objects=( ProviderObjectDeclaration( object_type="record", field_groups=("identity", "content"), authority_modes=("external_mirror",), default_authority_mode="external_mirror", ), ), behavior=ProviderBehaviorDeclaration( freshness="Reports the acquisition timestamp.", health="Reports source and parser health.", max_read_items=100, classifications=("internal",), purposes=("release contract test",), retention="The owning package retention policy applies.", ), ) architecture = ModuleArchitectureDeclaration( layer="data_reporting_integration", kind="integration", maturity="vertical_slice", evidence=( ModuleMaturityEvidence( kind="test", reference="tests/test_release_catalog_entry_synthesis.py", summary="Proves catalog metadata preservation.", ), ModuleMaturityEvidence( kind="documentation", reference="docs/INSTITUTIONAL_GOVERNANCE_TARGET_ARCHITECTURE.md", summary="Defines the provider declaration contract.", ), ), known_limits=("Test-only provider.",), supported_authority_modes=("external_mirror",), owned_concepts=("example transport",), target_tested_providers=(provider.id,), ) entry = manifest_catalog_entry( manifest=ModuleManifest( id="example", name="Example", version="1.2.3", architecture=architecture, external_providers=(provider,), ), repo="govoplan-example", package="govoplan-example", version="1.2.3", description=None, root=META_ROOT, repository_base="git+ssh://git@git.add-ideas.de/GovOPlaN", ) self.assertEqual("vertical_slice", entry["architecture"]["maturity"]) self.assertEqual( "external_mirror", entry["external_providers"][0]["objects"][0][ "default_authority_mode" ], ) def test_selective_update_synthesizes_initial_entries_from_package_manifests(self) -> None: payload: dict[str, object] = { "core_release": {}, "release": {}, "modules": [ { "module_id": "access", "version": "0.1.11", "python_package": "govoplan-access", "python_ref": "govoplan-access @ git+ssh://git@git.add-ideas.de/GovOPlaN/govoplan-access.git@v0.1.11", } ], } changes = apply_repo_updates( payload, repo_versions={ "govoplan-addresses": "0.1.9", "govoplan-poll": "0.1.11", "govoplan-scheduling": "0.1.11", }, repo_contracts={}, repository_base="git+ssh://git@git.add-ideas.de/GovOPlaN", workspace=META_ROOT.parent, ) modules = { item["module_id"]: item for item in payload["modules"] # type: ignore[index] } self.assertEqual({"access", "addresses", "poll", "scheduling"}, set(modules)) self.assertEqual("@govoplan/addresses-webui", modules["addresses"]["webui_package"]) self.assertIn( {"name": "addresses.people_search", "version": "0.1.0"}, modules["addresses"]["provides_interfaces"], ) self.assertEqual("govoplan-poll", modules["poll"]["python_package"]) self.assertEqual(["poll"], modules["scheduling"]["dependencies"]) self.assertEqual("@govoplan/scheduling-webui", modules["scheduling"]["webui_package"]) self.assertEqual("requires_review", modules["scheduling"]["migration_safety"]) self.assertTrue( any( item["name"] == "poll.governed_participation" and item["optional"] is False for item in modules["scheduling"]["requires_interfaces"] ) ) self.assertEqual( {"govoplan-addresses", "govoplan-poll", "govoplan-scheduling"}, {change.repo for change in changes}, ) self.assertEqual({"catalog_entry"}, {change.field for change in changes}) def test_initial_required_dependency_must_be_represented(self) -> None: with self.assertRaisesRegex(ValueError, "requires catalog module 'poll'"): validate_initial_entry_closure( catalog_modules=[ { "module_id": "scheduling", "dependencies": ["poll"], } ], initial_module_ids={"scheduling"}, ) if __name__ == "__main__": unittest.main()