Skip to content

Commit 843f916

Browse files
vmeurissecjames23
andauthored
add support for sbom file from build data (#2109)
Initial implementation of PEP 770 (8695db4) documented it but implemented only sbom-files from configuration. ref #2047 Co-authored-by: Cary Hawkins <hawkinscary23@gmail.com>
1 parent e6b01c8 commit 843f916

File tree

2 files changed

+72
-2
lines changed

2 files changed

+72
-2
lines changed

backend/src/hatchling/builders/wheel.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -684,8 +684,9 @@ def add_shared_scripts(self, archive: WheelArchive, records: RecordFile, build_d
684684
record = archive.write_shared_script(shared_script, content.getvalue())
685685
records.write(record)
686686

687-
def add_sboms(self, archive: WheelArchive, records: RecordFile) -> None:
687+
def add_sboms(self, archive: WheelArchive, records: RecordFile, build_data: dict[str, Any]) -> None:
688688
sbom_files = self.config.sbom_files
689+
sbom_files.extend(build_data["sbom_files"])
689690
if not sbom_files:
690691
return
691692

@@ -724,7 +725,7 @@ def write_metadata(
724725
self.add_licenses(archive, records)
725726

726727
# sboms/
727-
self.add_sboms(archive, records)
728+
self.add_sboms(archive, records, build_data)
728729

729730
# extra_metadata/ - write last
730731
self.add_extra_metadata(archive, records, build_data)
@@ -849,6 +850,7 @@ def get_default_build_data(self) -> dict[str, Any]: # noqa: PLR6301
849850
"extra_metadata": {},
850851
"shared_data": {},
851852
"shared_scripts": {},
853+
"sbom_files": [],
852854
}
853855

854856
def get_forced_inclusion_map(self, build_data: dict[str, Any]) -> dict[str, str]:

tests/backend/builders/test_wheel.py

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3922,3 +3922,71 @@ def test_sbom_file_invalid_item(self, isolation):
39223922
TypeError, match="SBOM file #1 in field `tool.hatch.build.targets.wheel.sbom-files` must be a string"
39233923
):
39243924
_ = builder.config.sbom_files
3925+
3926+
def test_sbom_from_build_data(self, hatch, helpers, temp_dir, config_file):
3927+
config_file.model.template.plugins["default"]["tests"] = False
3928+
config_file.save()
3929+
3930+
with temp_dir.as_cwd():
3931+
result = hatch("new", "My.App")
3932+
3933+
assert result.exit_code == 0, result.output
3934+
3935+
project_path = temp_dir / "my-app"
3936+
(project_path / "sbom1.cyclonedx.json").write_text('{"bomFormat": "CycloneDX"}')
3937+
(project_path / "sbom2.spdx.json").write_text('{"spdxVersion": "SPDX-2.3"}')
3938+
3939+
build_script = project_path / DEFAULT_BUILD_SCRIPT
3940+
build_script.write_text(
3941+
helpers.dedent(
3942+
"""
3943+
import pathlib
3944+
3945+
from hatchling.builders.hooks.plugin.interface import BuildHookInterface
3946+
3947+
class CustomHook(BuildHookInterface):
3948+
def initialize(self, version, build_data):
3949+
build_data["sbom_files"].append("sbom2.spdx.json")
3950+
"""
3951+
)
3952+
)
3953+
3954+
config = {
3955+
"project": {"name": "My.App", "dynamic": ["version"]},
3956+
"tool": {
3957+
"hatch": {
3958+
"version": {"path": "src/my_app/__about__.py"},
3959+
"build": {
3960+
"targets": {"wheel": {"sbom-files": ["sbom1.cyclonedx.json"]}},
3961+
"hooks": {"custom": {"path": DEFAULT_BUILD_SCRIPT}},
3962+
},
3963+
}
3964+
},
3965+
}
3966+
builder = WheelBuilder(str(project_path), config=config)
3967+
3968+
build_path = project_path / "dist"
3969+
build_path.mkdir()
3970+
3971+
with project_path.as_cwd():
3972+
artifacts = list(builder.build(directory=str(build_path)))
3973+
3974+
assert len(artifacts) == 1
3975+
3976+
extraction_directory = temp_dir / "_archive"
3977+
extraction_directory.mkdir()
3978+
3979+
with zipfile.ZipFile(str(artifacts[0]), "r") as zip_archive:
3980+
zip_archive.extractall(str(extraction_directory))
3981+
3982+
metadata_directory = f"{builder.project_id}.dist-info"
3983+
expected_files = helpers.get_template_files(
3984+
"wheel.standard_default_sbom",
3985+
"My.App",
3986+
metadata_directory=metadata_directory,
3987+
sbom_files=[
3988+
("sbom1.cyclonedx.json", '{"bomFormat": "CycloneDX"}'),
3989+
("sbom2.spdx.json", '{"spdxVersion": "SPDX-2.3"}'),
3990+
],
3991+
)
3992+
helpers.assert_files(extraction_directory, expected_files)

0 commit comments

Comments
 (0)