This is an automated email from the ASF dual-hosted git repository.
sbp pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tooling-trusted-releases.git
The following commit(s) were added to refs/heads/main by this push:
new 4f32711 Adjust SBOM tool interface names to suit the revised structure
4f32711 is described below
commit 4f32711539286f9838d155f48cfec756d48b3ac2
Author: Sean B. Palmer <[email protected]>
AuthorDate: Thu Oct 16 19:59:17 2025 +0100
Adjust SBOM tool interface names to suit the revised structure
---
atr/routes/sbom.py | 10 +++----
atr/sbom/__init__.py | 64 ++++++++-------------------------------------
atr/sbom/cli.py | 26 +++++++++---------
atr/sbom/conformance.py | 12 ++++-----
atr/sbom/constants/maven.py | 2 +-
atr/sbom/constants/spdx.py | 2 +-
atr/sbom/cyclonedx.py | 4 +--
atr/sbom/licenses.py | 20 +++++++-------
atr/sbom/maven.py | 22 ++++++++--------
atr/sbom/models/licenses.py | 6 ++---
atr/sbom/models/sbomqs.py | 6 ++---
atr/sbom/sbomqs.py | 4 +--
atr/sbom/spdx.py | 8 +++---
atr/sbom/utilities.py | 6 ++---
atr/tasks/sbom.py | 14 +++++-----
15 files changed, 82 insertions(+), 124 deletions(-)
diff --git a/atr/routes/sbom.py b/atr/routes/sbom.py
index 246d804..13c654c 100644
--- a/atr/routes/sbom.py
+++ b/atr/routes/sbom.py
@@ -117,8 +117,8 @@ async def report(session: route.CommitterSession, project:
str, version: str, fi
task_result = tasks[0].result
if not isinstance(task_result, results.SBOMToolScore):
raise base.ASFQuartException("Invalid SBOM score result",
errorcode=500)
- warnings = [sbom.MissingAdapter.validate_python(json.loads(w)) for w in
task_result.warnings]
- errors = [sbom.MissingAdapter.validate_python(json.loads(e)) for e in
task_result.errors]
+ warnings =
[sbom.models.conformance.MissingAdapter.validate_python(json.loads(w)) for w in
task_result.warnings]
+ errors =
[sbom.models.conformance.MissingAdapter.validate_python(json.loads(e)) for e in
task_result.errors]
block.p[
"""This is a report by the sbomtool, for debugging and
@@ -159,7 +159,7 @@ async def report(session: route.CommitterSession, project:
str, version: str, fi
outdated = None
if task_result.outdated:
- outdated =
sbom.OutdatedAdapter.validate_python(json.loads(task_result.outdated))
+ outdated =
sbom.models.maven.OutdatedAdapter.validate_python(json.loads(task_result.outdated))
block.h2["Outdated tool"]
if outdated:
if outdated.kind == "tool":
@@ -186,7 +186,7 @@ async def report(session: route.CommitterSession, project:
str, version: str, fi
return await template.blank("SBOM report", content=block.collect())
-def _missing_table(block: htm.Block, items: list[sbom.Missing]) -> None:
+def _missing_table(block: htm.Block, items:
list[sbom.models.conformance.Missing]) -> None:
warning_rows = [
htpy.tr[
htpy.td[kind.upper()],
@@ -201,7 +201,7 @@ def _missing_table(block: htm.Block, items:
list[sbom.Missing]) -> None:
]
-def _missing_tally(items: list[sbom.Missing]) -> list[tuple[str, str, int]]:
+def _missing_tally(items: list[sbom.models.conformance.Missing]) ->
list[tuple[str, str, int]]:
counts: dict[tuple[str, str], int] = {}
for item in items:
key = (getattr(item, "kind", ""), getattr(getattr(item, "property",
None), "name", ""))
diff --git a/atr/sbom/__init__.py b/atr/sbom/__init__.py
index af5eadc..c59f817 100644
--- a/atr/sbom/__init__.py
+++ b/atr/sbom/__init__.py
@@ -17,59 +17,17 @@
from __future__ import annotations
-from typing import Final
-
-from . import constants, models
-from .conformance import ntia_2021_conformance_issues,
ntia_2021_conformance_patch
-from .cyclonedx import validate_cyclonedx_cli, validate_cyclonedx_py
-from .licenses import check_licenses
-from .maven import maven_plugin_outdated_version
-from .sbomqs import sbomqs_total_score
-from .spdx import spdx_license_expression_atoms
-from .utilities import bundle_to_patch, patch_to_data, path_to_bundle
-
-VERSION: Final[str] = constants.version.VERSION
-
-Bom = models.bom.Bom
-Bundle = models.bundle.Bundle
-Component = models.bom.Component
-LicenseCategory = models.licenses.LicenseCategory
-LicenseIssue = models.licenses.LicenseIssue
-Metadata = models.bom.Metadata
-Missing = models.conformance.Missing
-MissingAdapter = models.conformance.MissingAdapter
-MissingComponentProperty = models.conformance.MissingComponentProperty
-MissingProperty = models.conformance.MissingProperty
-Outdated = models.maven.Outdated
-OutdatedAdapter = models.maven.OutdatedAdapter
-OutdatedTool = models.maven.OutdatedTool
-Supplier = models.bom.Supplier
+from . import cli, conformance, constants, cyclonedx, licenses, maven, models,
sbomqs, spdx, utilities
__all__ = [
- "VERSION",
- "Bom",
- "Bundle",
- "Component",
- "LicenseCategory",
- "LicenseIssue",
- "Metadata",
- "Missing",
- "MissingAdapter",
- "MissingComponentProperty",
- "MissingProperty",
- "Outdated",
- "OutdatedAdapter",
- "OutdatedTool",
- "Supplier",
- "bundle_to_patch",
- "check_licenses",
- "maven_plugin_outdated_version",
- "ntia_2021_conformance_issues",
- "ntia_2021_conformance_patch",
- "patch_to_data",
- "path_to_bundle",
- "sbomqs_total_score",
- "spdx_license_expression_atoms",
- "validate_cyclonedx_cli",
- "validate_cyclonedx_py",
+ "cli",
+ "conformance",
+ "constants",
+ "cyclonedx",
+ "licenses",
+ "maven",
+ "models",
+ "sbomqs",
+ "spdx",
+ "utilities",
]
diff --git a/atr/sbom/cli.py b/atr/sbom/cli.py
index 53b70d0..7ca74e0 100644
--- a/atr/sbom/cli.py
+++ b/atr/sbom/cli.py
@@ -23,11 +23,11 @@ import sys
import yyjson
from . import models
-from .conformance import ntia_2021_conformance_issues
-from .cyclonedx import validate_cyclonedx_cli, validate_cyclonedx_py
-from .licenses import check_licenses
-from .maven import maven_plugin_outdated_version
-from .sbomqs import sbomqs_total_score
+from .conformance import ntia_2021_issues
+from .cyclonedx import validate_cli, validate_py
+from .licenses import check
+from .maven import plugin_outdated_version
+from .sbomqs import total_score
from .utilities import bundle_to_patch, patch_to_data, path_to_bundle
@@ -44,13 +44,13 @@ def main() -> None:
else:
print(bundle.doc.dumps())
case "missing":
- _warnings, errors = ntia_2021_conformance_issues(bundle.bom)
+ _warnings, errors = ntia_2021_issues(bundle.bom)
for error in errors:
print(error)
# for warning in warnings:
# print(warning)
case "outdated":
- outdated = maven_plugin_outdated_version(bundle.bom)
+ outdated = plugin_outdated_version(bundle.bom)
if outdated:
print(outdated)
else:
@@ -67,11 +67,11 @@ def main() -> None:
if patch_ops:
patch_data = patch_to_data(patch_ops)
merged = bundle.doc.patch(yyjson.Document(patch_data))
- print(sbomqs_total_score(bundle.doc), "->",
sbomqs_total_score(merged))
+ print(total_score(bundle.doc), "->", total_score(merged))
else:
- print(sbomqs_total_score(bundle.doc))
+ print(total_score(bundle.doc))
case "validate-cli":
- errors = validate_cyclonedx_cli(bundle)
+ errors = validate_cli(bundle)
if not errors:
print("valid")
else:
@@ -81,7 +81,7 @@ def main() -> None:
print("...")
break
case "validate-py":
- errors = validate_cyclonedx_py(bundle)
+ errors = validate_py(bundle)
if not errors:
print("valid")
else:
@@ -91,7 +91,7 @@ def main() -> None:
print("...")
break
case "where":
- _warnings, errors = ntia_2021_conformance_issues(bundle.bom)
+ _warnings, errors = ntia_2021_issues(bundle.bom)
for error in errors:
match error:
case models.conformance.MissingProperty():
@@ -107,7 +107,7 @@ def main() -> None:
print(primary_component.model_dump_json(indent=2))
print()
case "license":
- warnings, errors = check_licenses(bundle.bom)
+ warnings, errors = check(bundle.bom)
if warnings:
print("WARNINGS (Category B):")
for warning in warnings:
diff --git a/atr/sbom/conformance.py b/atr/sbom/conformance.py
index 1c3432a..52f0afc 100644
--- a/atr/sbom/conformance.py
+++ b/atr/sbom/conformance.py
@@ -25,7 +25,7 @@ import urllib.request
import yyjson
from . import constants, models
-from .maven import maven_cache_read, maven_cache_write
+from .maven import cache_read, cache_write
from .utilities import get_pointer
@@ -112,7 +112,7 @@ def assemble_component_supplier(doc: yyjson.Document,
patch_ops: models.patch.Pa
url += "/"
return make_supplier_op(url, url)
- cache = maven_cache_read()
+ cache = cache_read()
if key in cache:
cached = cache[key]
@@ -128,7 +128,7 @@ def assemble_component_supplier(doc: yyjson.Document,
patch_ops: models.patch.Pa
data = yyjson.Document(response.read())
except urllib.error.HTTPError:
cache[key] = None
- maven_cache_write(cache)
+ cache_write(cache)
return
links = get_pointer(data, "/links") or []
homepage = None
@@ -141,7 +141,7 @@ def assemble_component_supplier(doc: yyjson.Document,
patch_ops: models.patch.Pa
cache[key] = homepage
else:
cache[key] = None
- maven_cache_write(cache)
+ cache_write(cache)
return
@@ -226,7 +226,7 @@ def assemble_metadata_timestamp(doc: yyjson.Document,
patch_ops: models.patch.Pa
)
-def ntia_2021_conformance_issues(
+def ntia_2021_issues(
bom_value: models.bom.Bom,
) -> tuple[list[models.conformance.Missing], list[models.conformance.Missing]]:
# 1. Supplier
@@ -341,7 +341,7 @@ def ntia_2021_conformance_issues(
return warnings, errors
-def ntia_2021_conformance_patch(doc: yyjson.Document, errors:
list[models.conformance.Missing]) -> models.patch.Patch:
+def ntia_2021_patch(doc: yyjson.Document, errors:
list[models.conformance.Missing]) -> models.patch.Patch:
patch_ops: models.patch.Patch = []
# TODO: Add tool metadata
for error in errors:
diff --git a/atr/sbom/constants/maven.py b/atr/sbom/constants/maven.py
index 90d4d57..5fd780f 100644
--- a/atr/sbom/constants/maven.py
+++ b/atr/sbom/constants/maven.py
@@ -22,7 +22,7 @@ from typing import Final
CACHE_PATH: Final[pathlib.Path] = pathlib.Path("/tmp/sbomtool-cache.json")
-MAVEN_PLUGIN_VERSIONS: Final[dict[str, str]] = {
+PLUGIN_VERSIONS: Final[dict[str, str]] = {
"2024-11-28T21:29:12Z": "2.9.1",
"2024-10-08T04:31:11Z": "2.9.0",
"2024-09-25T20:08:34Z": "2.8.2",
diff --git a/atr/sbom/constants/spdx.py b/atr/sbom/constants/spdx.py
index a6efd36..3cfef2e 100644
--- a/atr/sbom/constants/spdx.py
+++ b/atr/sbom/constants/spdx.py
@@ -20,7 +20,7 @@ from __future__ import annotations
import re
from typing import Final
-SPDX_TOKEN: Final[re.Pattern[str]] = re.compile(
+TOKEN: Final[re.Pattern[str]] = re.compile(
r"""
(?P<WS>\s+)
| (?P<LPAREN>\()
diff --git a/atr/sbom/cyclonedx.py b/atr/sbom/cyclonedx.py
index aa5a452..320cb1e 100644
--- a/atr/sbom/cyclonedx.py
+++ b/atr/sbom/cyclonedx.py
@@ -32,7 +32,7 @@ if TYPE_CHECKING:
from . import models
-def validate_cyclonedx_cli(bundle_value: models.bundle.Bundle) -> list[str] |
None:
+def validate_cli(bundle_value: models.bundle.Bundle) -> list[str] | None:
args = [
"cyclonedx",
"validate",
@@ -53,7 +53,7 @@ def validate_cyclonedx_cli(bundle_value:
models.bundle.Bundle) -> list[str] | No
return None
-def validate_cyclonedx_py(
+def validate_py(
bundle_value: models.bundle.Bundle,
) -> Iterable[cyclonedx.validation.json.JsonValidationError] | None:
json_sv = get_pointer(bundle_value.doc, "/specVersion")
diff --git a/atr/sbom/licenses.py b/atr/sbom/licenses.py
index 3556471..0d1d7ae 100644
--- a/atr/sbom/licenses.py
+++ b/atr/sbom/licenses.py
@@ -18,14 +18,14 @@
from __future__ import annotations
from . import constants, models
-from .spdx import spdx_license_expression_atoms
+from .spdx import license_expression_atoms
-def check_licenses(
+def check(
bom_value: models.bom.Bom,
-) -> tuple[list[models.licenses.LicenseIssue],
list[models.licenses.LicenseIssue]]:
- warnings: list[models.licenses.LicenseIssue] = []
- errors: list[models.licenses.LicenseIssue] = []
+) -> tuple[list[models.licenses.Issue], list[models.licenses.Issue]]:
+ warnings: list[models.licenses.Issue] = []
+ errors: list[models.licenses.Issue] = []
components = bom_value.components or []
if bom_value.metadata and bom_value.metadata.component:
@@ -53,7 +53,7 @@ def check_licenses(
parse_failed = False
if license_choice.expression:
try:
- atoms = spdx_license_expression_atoms(license_expr)
+ atoms = license_expression_atoms(license_expr)
except ValueError:
parse_failed = True
atoms = {license_expr}
@@ -76,22 +76,22 @@ def check_licenses(
any_unknown = True
if got_error:
errors.append(
- models.licenses.LicenseIssue(
+ models.licenses.Issue(
component_name=name,
component_version=version,
license_expression=license_expr,
- category=models.licenses.LicenseCategory.X,
+ category=models.licenses.Category.X,
any_unknown=any_unknown,
scope=scope,
)
)
elif got_warning:
warnings.append(
- models.licenses.LicenseIssue(
+ models.licenses.Issue(
component_name=name,
component_version=version,
license_expression=license_expr,
- category=models.licenses.LicenseCategory.B,
+ category=models.licenses.Category.B,
any_unknown=False,
scope=scope,
)
diff --git a/atr/sbom/maven.py b/atr/sbom/maven.py
index 9ad9a7e..14c2f43 100644
--- a/atr/sbom/maven.py
+++ b/atr/sbom/maven.py
@@ -25,7 +25,7 @@ import yyjson
from . import constants, models
-def maven_cache_read() -> dict[str, Any]:
+def cache_read() -> dict[str, Any]:
try:
with open(constants.maven.CACHE_PATH) as file:
return yyjson.load(file)
@@ -33,7 +33,7 @@ def maven_cache_read() -> dict[str, Any]:
return {}
-def maven_cache_write(cache: dict[str, Any]) -> None:
+def cache_write(cache: dict[str, Any]) -> None:
try:
with open(constants.maven.CACHE_PATH, "w") as file:
yyjson.dump(cache, file)
@@ -41,7 +41,7 @@ def maven_cache_write(cache: dict[str, Any]) -> None:
pass
-def maven_plugin_outdated_version(bom_value: models.bom.Bom) ->
models.maven.Outdated | None:
+def plugin_outdated_version(bom_value: models.bom.Bom) ->
models.maven.Outdated | None:
if bom_value.metadata is None:
return models.maven.OutdatedMissingMetadata()
timestamp = bom_value.metadata.timestamp
@@ -66,7 +66,7 @@ def maven_plugin_outdated_version(bom_value: models.bom.Bom)
-> models.maven.Out
continue
if tool.version is None:
return
models.maven.OutdatedMissingVersion(name=name_or_description)
- available_version = maven_plugin_outdated_version_core(timestamp,
tool.version)
+ available_version = plugin_outdated_version_core(timestamp,
tool.version)
if available_version is not None:
return models.maven.OutdatedTool(
name=name_or_description,
@@ -76,14 +76,14 @@ def maven_plugin_outdated_version(bom_value:
models.bom.Bom) -> models.maven.Out
return None
-def maven_plugin_outdated_version_core(isotime: str, version: str) -> str |
None:
- expected_version = maven_version_as_of(isotime)
+def plugin_outdated_version_core(isotime: str, version: str) -> str | None:
+ expected_version = version_as_of(isotime)
if expected_version is None:
return None
if version == expected_version:
return None
- expected_version_comparable = maven_version_parse(expected_version)
- version_comparable = maven_version_parse(version)
+ expected_version_comparable = version_parse(expected_version)
+ version_comparable = version_parse(version)
# If the version used is less than the version available
if version_comparable < expected_version_comparable:
# Then note the version available
@@ -92,7 +92,7 @@ def maven_plugin_outdated_version_core(isotime: str, version:
str) -> str | None
return None
-def maven_version_as_of(isotime: str) -> str | None:
+def version_as_of(isotime: str) -> str | None:
# Given these mappings:
# {
# t3: v3
@@ -103,12 +103,12 @@ def maven_version_as_of(isotime: str) -> str | None:
# If the input is between t2 and t1, then the output is v2
# If the input is between t1 and t2, then the output is v1
# If the input is before t1, then the output is None
- for date, version in sorted(constants.maven.MAVEN_PLUGIN_VERSIONS.items(),
reverse=True):
+ for date, version in sorted(constants.maven.PLUGIN_VERSIONS.items(),
reverse=True):
if isotime >= date:
return version
return None
-def maven_version_parse(version: str) -> tuple[int, int, int]:
+def version_parse(version: str) -> tuple[int, int, int]:
parts = version.split(".")
return int(parts[0]), int(parts[1]), int(parts[2])
diff --git a/atr/sbom/models/licenses.py b/atr/sbom/models/licenses.py
index 9a3083b..3ddb0bc 100644
--- a/atr/sbom/models/licenses.py
+++ b/atr/sbom/models/licenses.py
@@ -22,16 +22,16 @@ import enum
from .base import Strict
-class LicenseCategory(enum.Enum):
+class Category(enum.Enum):
A = enum.auto()
B = enum.auto()
X = enum.auto()
-class LicenseIssue(Strict):
+class Issue(Strict):
component_name: str
component_version: str | None
license_expression: str
- category: LicenseCategory
+ category: Category
any_unknown: bool = False
scope: str | None = None
diff --git a/atr/sbom/models/sbomqs.py b/atr/sbom/models/sbomqs.py
index 8ae5b9b..96d9f72 100644
--- a/atr/sbom/models/sbomqs.py
+++ b/atr/sbom/models/sbomqs.py
@@ -20,9 +20,9 @@ from __future__ import annotations
from .base import Lax
-class SBOMQSSummary(Lax):
+class Summary(Lax):
total_score: float
-class SBOMQSReport(Lax):
- summary: SBOMQSSummary
+class Report(Lax):
+ summary: Summary
diff --git a/atr/sbom/sbomqs.py b/atr/sbom/sbomqs.py
index 56d451a..3c0e89b 100644
--- a/atr/sbom/sbomqs.py
+++ b/atr/sbom/sbomqs.py
@@ -26,7 +26,7 @@ import yyjson
from . import models
-def sbomqs_total_score(value: pathlib.Path | str | yyjson.Document) -> float:
+def total_score(value: pathlib.Path | str | yyjson.Document) -> float:
args = ["sbomqs", "compliance", "--ntia", "--json"]
with tempfile.NamedTemporaryFile("w", encoding="utf-8", suffix=".json") as
tf:
match value:
@@ -47,5 +47,5 @@ def sbomqs_total_score(value: pathlib.Path | str |
yyjson.Document) -> float:
if proc.returncode != 0:
err = proc.stderr.strip() or "sbomqs failed"
raise RuntimeError(err)
- report = models.sbomqs.SBOMQSReport.model_validate_json(proc.stdout)
+ report = models.sbomqs.Report.model_validate_json(proc.stdout)
return report.summary.total_score
diff --git a/atr/sbom/spdx.py b/atr/sbom/spdx.py
index 4ac132a..7f15eef 100644
--- a/atr/sbom/spdx.py
+++ b/atr/sbom/spdx.py
@@ -20,7 +20,7 @@ from __future__ import annotations
from . import constants
-class SPDXLicenseExpressionParser:
+class LicenseExpressionParser:
def __init__(self, items: list[tuple[str, str]], text: str) -> None:
self.items = items
self.text = text
@@ -86,10 +86,10 @@ class SPDXLicenseExpressionParser:
return (self.position < len(self.items)) and
(self.items[self.position][0] == kind)
-def spdx_license_expression_atoms(expr: str) -> set[str]:
+def license_expression_atoms(expr: str) -> set[str]:
pos = 0
tokens: list[tuple[str, str]] = []
- for match in constants.spdx.SPDX_TOKEN.finditer(expr):
+ for match in constants.spdx.TOKEN.finditer(expr):
if match.start() != pos:
raise ValueError(expr)
pos = match.end()
@@ -99,4 +99,4 @@ def spdx_license_expression_atoms(expr: str) -> set[str]:
if pos != len(expr):
raise ValueError(expr)
- return SPDXLicenseExpressionParser(tokens, expr).parse()
+ return LicenseExpressionParser(tokens, expr).parse()
diff --git a/atr/sbom/utilities.py b/atr/sbom/utilities.py
index 2d90a9d..543c135 100644
--- a/atr/sbom/utilities.py
+++ b/atr/sbom/utilities.py
@@ -28,10 +28,10 @@ from . import models
def bundle_to_patch(bundle_value: models.bundle.Bundle) -> models.patch.Patch:
- from .conformance import ntia_2021_conformance_issues,
ntia_2021_conformance_patch
+ from .conformance import ntia_2021_issues, ntia_2021_patch
- _warnings, errors = ntia_2021_conformance_issues(bundle_value.bom)
- patch_ops = ntia_2021_conformance_patch(bundle_value.doc, errors)
+ _warnings, errors = ntia_2021_issues(bundle_value.bom)
+ patch_ops = ntia_2021_patch(bundle_value.doc, errors)
return patch_ops
diff --git a/atr/tasks/sbom.py b/atr/tasks/sbom.py
index c1bd51c..e091505 100644
--- a/atr/tasks/sbom.py
+++ b/atr/tasks/sbom.py
@@ -79,11 +79,11 @@ async def augment(args: FileArgs) -> results.Results | None:
if not (full_path.endswith(".cdx.json") and os.path.isfile(full_path)):
raise SBOMScoringError("SBOM file does not exist", {"file_path":
args.file_path})
# Read from the old revision
- bundle = sbom.path_to_bundle(pathlib.Path(full_path))
- patch_ops = sbom.bundle_to_patch(bundle)
+ bundle = sbom.utilities.path_to_bundle(pathlib.Path(full_path))
+ patch_ops = sbom.utilities.bundle_to_patch(bundle)
new_full_path: str | None = None
if patch_ops:
- patch_data = sbom.patch_to_data(patch_ops)
+ patch_data = sbom.utilities.patch_to_data(patch_ops)
merged = bundle.doc.patch(yyjson.Document(patch_data))
description = "SBOM augmentation through web interface"
async with storage.write(args.asf_uid) as write:
@@ -168,10 +168,10 @@ async def score_tool(args: FileArgs) -> results.Results |
None:
full_path = os.path.join(base_dir, args.file_path)
if not (full_path.endswith(".cdx.json") and os.path.isfile(full_path)):
raise SBOMScoringError("SBOM file does not exist", {"file_path":
args.file_path})
- bundle = sbom.path_to_bundle(pathlib.Path(full_path))
- warnings, errors = sbom.ntia_2021_conformance_issues(bundle.bom)
- outdated = sbom.maven_plugin_outdated_version(bundle.bom)
- cli_errors = sbom.validate_cyclonedx_cli(bundle)
+ bundle = sbom.utilities.path_to_bundle(pathlib.Path(full_path))
+ warnings, errors = sbom.conformance.ntia_2021_issues(bundle.bom)
+ outdated = sbom.maven.plugin_outdated_version(bundle.bom)
+ cli_errors = sbom.cyclonedx.validate_cli(bundle)
return results.SBOMToolScore(
kind="sbom_tool_score",
project_name=args.project_name,
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]