from __future__ import annotations import json from pathlib import Path import sys import tempfile import unittest from unittest.mock import patch META_ROOT = Path(__file__).resolve().parents[1] RELEASE_TOOLS_ROOT = META_ROOT / "tools" / "release" if str(RELEASE_TOOLS_ROOT) not in sys.path: sys.path.insert(0, str(RELEASE_TOOLS_ROOT)) from govoplan_release.publisher import publish_catalog_candidate # noqa: E402 class ReleaseCatalogPublicationTests(unittest.TestCase): def test_publication_requires_an_existing_trust_anchor(self) -> None: with tempfile.TemporaryDirectory() as tmp: root = Path(tmp) candidate = self._candidate(root, key="candidate-key") web_root = root / "website" web_root.mkdir() with patch( "govoplan_release.publisher.validate_module_package_catalog", return_value={"valid": True, "warnings": [], "error": None}, ): result = publish_catalog_candidate( candidate_dir=candidate, web_root=web_root, workspace_root=root, ) self.assertEqual("blocked", result.status) self.assertIn("publication trust anchor is missing", " ".join(result.notes)) def test_publication_rejects_rebinding_an_existing_key_id(self) -> None: with tempfile.TemporaryDirectory() as tmp: root = Path(tmp) candidate = self._candidate(root, key="replacement-key") web_root = root / "website" target_keyring = web_root / "public" / "catalogs" / "v1" / "keyring.json" target_keyring.parent.mkdir(parents=True) target_keyring.write_text(json.dumps(self._keyring("trusted-key"))) with patch( "govoplan_release.publisher.validate_module_package_catalog", return_value={"valid": True, "warnings": [], "error": None}, ): result = publish_catalog_candidate( candidate_dir=candidate, web_root=web_root, workspace_root=root, ) self.assertEqual("blocked", result.status) self.assertIn("changes the public key", " ".join(result.notes)) @staticmethod def _candidate(root: Path, *, key: str) -> Path: candidate = root / "candidate" channel = candidate / "channels" channel.mkdir(parents=True) channel.joinpath("stable.json").write_text( json.dumps( { "channel": "stable", "core_release": { "version": "1.2.3", "python_ref": ( "govoplan-core @ git+ssh://git@example.test/acme/" "govoplan-core.git@v1.2.3" ), }, "modules": [], } ) ) candidate.joinpath("keyring.json").write_text(json.dumps(ReleaseCatalogPublicationTests._keyring(key))) return candidate @staticmethod def _keyring(key: str) -> dict[str, object]: return { "keys": [ { "key_id": "release-key", "status": "active", "public_key": key, } ] } if __name__ == "__main__": unittest.main()