diff --git a/src/fromager/sbom.py b/src/fromager/sbom.py index 9ec4372f..1ce7a409 100644 --- a/src/fromager/sbom.py +++ b/src/fromager/sbom.py @@ -67,9 +67,9 @@ def _build_upstream_purl( """Build the upstream source package URL. If ``upstream`` is set in the per-package ``PurlConfig``, it is - used as-is. Otherwise, the upstream purl is derived from the same - base as the downstream purl but without the ``repository_url`` - qualifier. + used as-is. Otherwise, the upstream purl uses the resolved source + version rather than a downstream wheel version override, and excludes + the ``repository_url`` qualifier. """ pc = pbi.purl_config if pc and pc.upstream: @@ -78,12 +78,11 @@ def _build_upstream_purl( purl_type = pc.type if pc else None purl_namespace = pc.namespace if pc else None purl_name = pc.name if pc else None - purl_version = pc.version if pc else None return PackageURL( type=purl_type or sbom_settings.purl_type, namespace=purl_namespace, name=purl_name or name, - version=purl_version or str(version), + version=str(version), ) diff --git a/tests/test_sbom.py b/tests/test_sbom.py index 50e38e07..b228c3fb 100644 --- a/tests/test_sbom.py +++ b/tests/test_sbom.py @@ -147,6 +147,33 @@ def test_generate_sbom_document_identity_follows_purl_version_override( _validate_spdx(doc) +def test_generate_sbom_upstream_uses_source_version_without_upstream_override( + tmp_path: pathlib.Path, +) -> None: + """Keep the source release distinct from a locally versioned wheel.""" + ctx = make_sbom_ctx( + tmp_path, + sbom_settings=SbomSettings(), + package_overrides={"purl": {"version": "0.5.5+local.1"}}, + ) + doc = sbom.generate_sbom( + ctx=ctx, + req=Requirement("test-pkg==0.5.5"), + version=Version("0.5.5"), + ) + + wheel, upstream = doc["packages"] + assert wheel["versionInfo"] == "0.5.5+local.1" + assert wheel["externalRefs"][0]["referenceLocator"] == ( + "pkg:pypi/test-pkg@0.5.5%2Blocal.1" + ) + assert upstream["versionInfo"] == "0.5.5" + assert upstream["externalRefs"][0]["referenceLocator"] == ( + "pkg:pypi/test-pkg@0.5.5" + ) + _validate_spdx(doc) + + def test_generate_sbom_namespace_is_unique_per_document( tmp_path: pathlib.Path, ) -> None: