feat(v2): complete v2 reimplementation
This commit is contained in:
@@ -0,0 +1,55 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Generate a deterministic, dependency-only CycloneDX SBOM for the M14 OCI images."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import re
|
||||
import tomllib
|
||||
from pathlib import Path
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
OUTPUT = ROOT / "docs" / "release" / "m14-sbom.json"
|
||||
|
||||
|
||||
def component(name: str, version: str, ecosystem: str) -> dict[str, str]:
|
||||
return {
|
||||
"name": name,
|
||||
"type": "library",
|
||||
"version": version,
|
||||
"purl": f"pkg:{ecosystem}/{name}@{version}",
|
||||
}
|
||||
|
||||
|
||||
def main() -> None:
|
||||
try:
|
||||
project = tomllib.loads((ROOT / "backend" / "pyproject.toml").read_text())
|
||||
package_lock = json.loads((ROOT / "frontend" / "package-lock.json").read_text())
|
||||
except (OSError, json.JSONDecodeError, tomllib.TOMLDecodeError) as error:
|
||||
raise RuntimeError("could not load pinned dependency metadata") from error
|
||||
components: list[dict[str, str]] = []
|
||||
for dependency in project["project"]["dependencies"]:
|
||||
match = re.fullmatch(
|
||||
r"([A-Za-z0-9_.-]+)(?:\[[A-Za-z0-9_,-]+\])?==([A-Za-z0-9_.+-]+)", dependency
|
||||
)
|
||||
if match is None:
|
||||
raise ValueError(f"un-pinned Python dependency: {dependency}")
|
||||
components.append(component(match.group(1), match.group(2), "pypi"))
|
||||
for path, item in package_lock.get("packages", {}).items():
|
||||
if not path.startswith("node_modules/") or "version" not in item:
|
||||
continue
|
||||
components.append(component(path.removeprefix("node_modules/"), item["version"], "npm"))
|
||||
payload = {
|
||||
"bomFormat": "CycloneDX",
|
||||
"components": sorted(components, key=lambda item: (item["purl"], item["version"])),
|
||||
"metadata": {
|
||||
"component": component("backup-tool", project["project"]["version"], "generic")
|
||||
},
|
||||
"specVersion": "1.5",
|
||||
"version": 1,
|
||||
}
|
||||
OUTPUT.write_text(json.dumps(payload, indent=2, sort_keys=True) + "\n")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user