Skip to content

Commit b14a252

Browse files
dwozDaniel A. Wozniak
authored andcommitted
Fix sbom verification test
1 parent 90bff8e commit b14a252

7 files changed

Lines changed: 83 additions & 234 deletions

File tree

relenv/build/common/__init__.py

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -9,25 +9,6 @@
99

1010
from __future__ import annotations
1111

12-
<<<<<<< HEAD
13-
=======
14-
from .builders import (
15-
build_openssl,
16-
build_openssl_fips,
17-
build_sqlite,
18-
)
19-
20-
from .install import (
21-
update_ensurepip,
22-
install_runtime,
23-
finalize,
24-
create_archive,
25-
patch_file,
26-
update_sbom_checksums,
27-
generate_relenv_sbom,
28-
)
29-
30-
>>>>>>> 63cae3d (Initial sbom support)
3112
from .builder import (
3213
Dirs,
3314
builds,
@@ -39,7 +20,6 @@
3920
build_sqlite,
4021
)
4122
from .install import (
42-
copy_sbom_files,
4323
create_archive,
4424
finalize,
4525
generate_relenv_sbom,
@@ -56,7 +36,6 @@
5636
# Dependency version management
5737
"get_dependency_version",
5838
# Install functions
59-
"copy_sbom_files",
6039
"finalize",
6140
"install_runtime",
6241
"create_archive",

relenv/build/common/install.py

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
import sys
2020
import tarfile
2121
import time
22-
from typing import IO, TYPE_CHECKING, Any, Dict, List, Optional, Union
22+
from typing import IO, TYPE_CHECKING, Any
2323

2424
import relenv.relocate
2525
from relenv.common import (
@@ -425,9 +425,10 @@ def generate_relenv_sbom(env: MutableMapping[str, str], dirs: Dirs) -> None:
425425
:param dirs: The working directories
426426
:type dirs: ``relenv.build.common.Dirs``
427427
"""
428-
from .builder import get_dependency_version
429428
import relenv
430429

430+
from .builder import get_dependency_version
431+
431432
python_version = dirs.version
432433

433434
platform_map = {
@@ -438,10 +439,10 @@ def generate_relenv_sbom(env: MutableMapping[str, str], dirs: Dirs) -> None:
438439
platform = platform_map.get(sys.platform, sys.platform)
439440

440441
# Build dependency list - get versions from python-versions.json
441-
packages: List[Dict[str, Any]] = []
442+
packages: list[dict[str, Any]] = []
442443

443444
# Add Python itself as the primary package
444-
python_package: Dict[str, Any] = {
445+
python_package: dict[str, Any] = {
445446
"SPDXID": "SPDXRef-PACKAGE-Python",
446447
"name": "Python",
447448
"versionInfo": python_version,
@@ -503,8 +504,7 @@ def generate_relenv_sbom(env: MutableMapping[str, str], dirs: Dirs) -> None:
503504
[
504505
(
505506
"tirpc",
506-
"https://downloads.sourceforge.net/project/libtirpc/"
507-
"libtirpc/{version}/libtirpc-{version}.tar.bz2",
507+
"https://downloads.sourceforge.net/project/libtirpc/libtirpc/{version}/libtirpc-{version}.tar.bz2",
508508
),
509509
(
510510
"krb5",
@@ -526,7 +526,7 @@ def generate_relenv_sbom(env: MutableMapping[str, str], dirs: Dirs) -> None:
526526
)
527527
checksum = dep_info.get("sha256", "")
528528

529-
package: Dict[str, Any] = {
529+
package: dict[str, Any] = {
530530
"SPDXID": f"SPDXRef-PACKAGE-{dep_name}",
531531
"name": dep_name,
532532
"versionInfo": version,
@@ -557,7 +557,7 @@ def generate_relenv_sbom(env: MutableMapping[str, str], dirs: Dirs) -> None:
557557
parts = dist_name.rsplit("-", 1)
558558
if len(parts) == 2:
559559
pkg_name, pkg_version = parts
560-
package2: Dict[str, Any] = {
560+
package2: dict[str, Any] = {
561561
"SPDXID": f"SPDXRef-PACKAGE-python-{pkg_name}",
562562
"name": pkg_name,
563563
"versionInfo": pkg_version,
@@ -575,11 +575,12 @@ def generate_relenv_sbom(env: MutableMapping[str, str], dirs: Dirs) -> None:
575575
bundled_deps = []
576576

577577
# Try to read Python's SBOM to get accurate versions of bundled components
578-
python_sbom_path = pathlib.Path(str(dirs.source)) / "Misc" / "sbom.spdx.json"
579-
python_bundled_versions: Dict[str, Dict[str, Any]] = {}
578+
python_source_dir = dirs.sources / f"Python-{dirs.version}"
579+
python_sbom_path = python_source_dir / "Misc" / "sbom.spdx.json"
580+
python_bundled_versions: dict[str, dict[str, Any]] = {}
580581
if python_sbom_path.exists():
581582
try:
582-
with io.open(python_sbom_path, "r") as fp:
583+
with open(python_sbom_path) as fp:
583584
python_sbom = json.load(fp)
584585
for pkg in python_sbom.get("packages", []):
585586
pkg_name = pkg.get("name")
@@ -602,7 +603,7 @@ def generate_relenv_sbom(env: MutableMapping[str, str], dirs: Dirs) -> None:
602603
for comp_name, comp_desc in bundled_components.items():
603604
if comp_name in python_bundled_versions:
604605
src_pkg = python_bundled_versions[comp_name]
605-
bundled_pkg: Dict[str, Any] = {
606+
bundled_pkg: dict[str, Any] = {
606607
"SPDXID": f"SPDXRef-PACKAGE-{comp_name}",
607608
"name": comp_name,
608609
"versionInfo": src_pkg.get("versionInfo", "NOASSERTION"),
@@ -627,6 +628,16 @@ def generate_relenv_sbom(env: MutableMapping[str, str], dirs: Dirs) -> None:
627628
timestamp = time.strftime("%Y%m%d%H%M%S", time.gmtime())
628629
doc_name = f"relenv-{env.get('RELENV_PY_VERSION', 'unknown')}-{env.get('RELENV_HOST', 'unknown')}"
629630

631+
# Create relationships - SPDX requires DESCRIBES relationship
632+
# The document DESCRIBES the Python package (the primary component)
633+
relationships = [
634+
{
635+
"spdxElementId": "SPDXRef-DOCUMENT",
636+
"relatedSpdxElement": "SPDXRef-PACKAGE-Python",
637+
"relationshipType": "DESCRIBES",
638+
}
639+
]
640+
630641
sbom = {
631642
"SPDXID": "SPDXRef-DOCUMENT",
632643
"spdxVersion": "SPDX-2.3",
@@ -643,11 +654,12 @@ def generate_relenv_sbom(env: MutableMapping[str, str], dirs: Dirs) -> None:
643654
"vulnerability scanning and compliance.",
644655
},
645656
"packages": packages,
657+
"relationships": relationships,
646658
}
647659

648660
# Write the SBOM file
649661
sbom_path = pathlib.Path(dirs.prefix) / "relenv-sbom.spdx.json"
650-
with io.open(sbom_path, "w") as fp:
662+
with open(sbom_path, "w") as fp:
651663
json.dump(sbom, fp, indent=2)
652664
log.info(
653665
"Generated relenv-sbom.spdx.json with %d packages (Python %s + dependencies + pip packages)",

relenv/build/windows.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
import tarfile
1919
import time
2020
from collections.abc import MutableMapping
21-
from typing import IO, Union
21+
from typing import IO
2222

2323
from ..common import (
2424
MODULE_DIR,
@@ -36,7 +36,6 @@
3636
install_runtime,
3737
patch_file,
3838
update_ensurepip,
39-
update_sbom_checksums,
4039
)
4140

4241
log = logging.getLogger(__name__)
@@ -1012,6 +1011,10 @@ def runpip(pkg: str | os.PathLike[str]) -> None:
10121011
else:
10131012
runpip("relenv")
10141013

1014+
from relenv.build.common.install import generate_relenv_sbom
1015+
1016+
generate_relenv_sbom(env, dirs)
1017+
10151018
for root, _, files in os.walk(dirs.prefix):
10161019
for file in files:
10171020
if file.endswith(".pyc"):
@@ -1024,6 +1027,7 @@ def runpip(pkg: str | os.PathLike[str]) -> None:
10241027
"*.dll",
10251028
"*.lib",
10261029
"*.whl",
1030+
"*.spdx.json",
10271031
"/Include/*",
10281032
"/Lib/site-packages/*",
10291033
]

relenv/sbom.py

Lines changed: 14 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,22 @@
1-
# Copyright 2022-2025 Broadcom.
1+
# Copyright 2022-2026 Broadcom.
22
# SPDX-License-Identifier: Apache-2.0
33
"""
44
SBOM (Software Bill of Materials) management for relenv.
55
"""
6+
67
from __future__ import annotations
78

8-
import argparse
99
import json
1010
import pathlib
1111
import sys
1212
import time
13-
from typing import Any, Dict, List, Optional, Tuple
13+
from typing import TYPE_CHECKING, Any
14+
15+
if TYPE_CHECKING:
16+
import argparse
1417

1518

16-
def get_python_version(relenv_root: pathlib.Path) -> Optional[Tuple[int, int, int]]:
19+
def get_python_version(relenv_root: pathlib.Path) -> tuple[int, int, int] | None:
1720
"""
1821
Get the Python version of a relenv environment.
1922
@@ -73,20 +76,17 @@ def find_relenv_root(start_path: pathlib.Path) -> pathlib.Path:
7376
return path.parent
7477

7578
# Not a relenv environment
76-
raise FileNotFoundError(
77-
f"Not a relenv environment: {start_path}\n"
78-
f"Expected to find bin/python3 or bin/python3.exe"
79-
)
79+
raise FileNotFoundError(f"Not a relenv environment: {start_path}\nExpected to find bin/python3 or bin/python3.exe")
8080

8181

82-
def scan_installed_packages(relenv_root: pathlib.Path) -> List[Dict[str, Any]]:
82+
def scan_installed_packages(relenv_root: pathlib.Path) -> list[dict[str, Any]]:
8383
"""
8484
Scan for installed Python packages in a relenv environment.
8585
8686
:param relenv_root: Path to relenv environment root
8787
:return: List of package dicts with SPDX metadata
8888
"""
89-
packages: List[Dict[str, Any]] = []
89+
packages: list[dict[str, Any]] = []
9090

9191
# Find the Python site-packages directory
9292
lib_dir = relenv_root / "lib"
@@ -102,7 +102,7 @@ def scan_installed_packages(relenv_root: pathlib.Path) -> List[Dict[str, Any]]:
102102
parts = dist_name.rsplit("-", 1)
103103
if len(parts) == 2:
104104
pkg_name, pkg_version = parts
105-
package: Dict[str, Any] = {
105+
package: dict[str, Any] = {
106106
"SPDXID": f"SPDXRef-PACKAGE-python-{pkg_name}",
107107
"name": pkg_name,
108108
"versionInfo": pkg_version,
@@ -138,15 +138,14 @@ def update_sbom(relenv_root: pathlib.Path) -> None:
138138
major, minor, micro = py_version
139139
if major < 3 or (major == 3 and minor < 12):
140140
raise RuntimeError(
141-
f"SBOM generation is only supported for Python 3.12+. "
142-
f"This environment is Python {major}.{minor}.{micro}"
141+
f"SBOM generation is only supported for Python 3.12+. This environment is Python {major}.{minor}.{micro}"
143142
)
144143

145144
sbom_path = relenv_root / "relenv-sbom.spdx.json"
146145

147146
# Load existing SBOM if it exists
148147
if sbom_path.exists():
149-
with open(sbom_path, "r") as f:
148+
with open(sbom_path) as f:
150149
sbom = json.load(f)
151150
else:
152151
# Create new SBOM if it doesn't exist
@@ -164,9 +163,7 @@ def update_sbom(relenv_root: pathlib.Path) -> None:
164163

165164
# Separate build dependencies from Python packages
166165
build_deps = [
167-
pkg
168-
for pkg in sbom.get("packages", [])
169-
if not pkg.get("SPDXID", "").startswith("SPDXRef-PACKAGE-python-")
166+
pkg for pkg in sbom.get("packages", []) if not pkg.get("SPDXID", "").startswith("SPDXRef-PACKAGE-python-")
170167
]
171168

172169
# Scan for currently installed packages

0 commit comments

Comments
 (0)