from __future__ import annotations import base64 from datetime import UTC, datetime import hashlib from pathlib import Path import sys import unittest 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.sbom import build_release_sbom, render_sbom, sbom_sha256, validate_sbom # noqa: E402 class ReleaseSbomTests(unittest.TestCase): @staticmethod def _build_at(timestamp: datetime) -> dict: return build_release_sbom( product_version="1.2.3", pip_inspect={ "version": "1", "installed": [{"metadata": {"name": "FastAPI", "version": "0.100.0"}}], }, npm_lock={"packages": {"": {"name": "govoplan", "version": "1.2.3"}}}, timestamp=timestamp, ) def test_builds_valid_deduplicated_python_and_npm_components(self) -> None: integrity = base64.b64encode(b"example digest").decode("ascii") payload = build_release_sbom( product_version="1.2.3", pip_inspect={ "version": "1", "installed": [ {"metadata": {"name": "FastAPI", "version": "0.100.0"}}, {"metadata": {"name": "FastAPI", "version": "0.100.0"}}, ], }, npm_lock={ "packages": { "": {"name": "govoplan", "version": "1.2.3"}, "node_modules/@scope/example": { "name": "@scope/example", "version": "4.5.6", "integrity": f"sha512-{integrity}", }, } }, ) validate_sbom(payload) self.assertEqual(2, len(payload["components"])) npm = next(item for item in payload["components"] if item["name"] == "@scope/example") self.assertEqual("SHA-512", npm["hashes"][0]["alg"]) self.assertIn("pkg:npm/%40scope/example@4.5.6", npm["purl"]) self.assertEqual( hashlib.sha256(render_sbom(payload).encode("utf-8")).hexdigest(), sbom_sha256(payload), ) def test_rejects_empty_component_inventory(self) -> None: payload = build_release_sbom( product_version="1.2.3", pip_inspect={"version": "1", "installed": []}, npm_lock={"packages": {"": {"version": "1.2.3"}}}, ) with self.assertRaisesRegex(ValueError, "no dependency components"): validate_sbom(payload) def test_fixed_timestamp_produces_identical_bytes_and_digest(self) -> None: timestamp = datetime(2026, 7, 21, 8, 30, tzinfo=UTC) first = self._build_at(timestamp) second = self._build_at(timestamp) self.assertEqual(render_sbom(first), render_sbom(second)) self.assertEqual(sbom_sha256(first), sbom_sha256(second)) def test_timestamp_changes_serial_and_digest(self) -> None: first = self._build_at(datetime(2026, 7, 21, 8, 30, tzinfo=UTC)) second = self._build_at(datetime(2026, 7, 21, 8, 31, tzinfo=UTC)) self.assertNotEqual(first["serialNumber"], second["serialNumber"]) self.assertNotEqual(sbom_sha256(first), sbom_sha256(second)) def test_local_and_credential_bearing_distribution_urls_are_omitted(self) -> None: payload = build_release_sbom( product_version="1.2.3", pip_inspect={ "version": "1", "installed": [ { "metadata": {"name": "LocalPackage", "version": "1.0.0"}, "direct_url": {"url": "file:///private/build/govoplan-core"}, }, { "metadata": {"name": "PrivatePackage", "version": "1.0.0"}, "direct_url": {"url": "https://user:secret@example.test/private.whl"}, }, { "metadata": {"name": "PublicPackage", "version": "1.0.0"}, "direct_url": {"url": "https://example.test/public.whl"}, }, ], }, npm_lock={"packages": {"": {"name": "govoplan", "version": "1.2.3"}}}, timestamp=datetime(2026, 7, 21, 8, 30, tzinfo=UTC), ) by_name = {component["name"]: component for component in payload["components"]} self.assertNotIn("externalReferences", by_name["LocalPackage"]) self.assertNotIn("externalReferences", by_name["PrivatePackage"]) self.assertEqual( [{"type": "distribution", "url": "https://example.test/public.whl"}], by_name["PublicPackage"]["externalReferences"], ) if __name__ == "__main__": unittest.main()