Initial curated ITWorx_MCP_Hub source from 368fba691ea8d23403b4d56b53b5ec670d7c5020
This commit is contained in:
commit
cb5be898ea
663 files changed
+82674
No files matched your search
@@ -0,0 +1,116 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Generate a dependency and image SBOM from locked manifests and Compose."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import shutil
|
||||
import subprocess
|
||||
import tomllib
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
import yaml # type: ignore[import-untyped]
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
|
||||
|
||||
def _purl(kind: str, name: str, version: str) -> str:
|
||||
return f"pkg:{kind}/{name}@{version}"
|
||||
|
||||
|
||||
def _python_components(repo_root: Path = ROOT) -> list[dict[str, str]]:
|
||||
document = tomllib.loads((repo_root / "pyproject.toml").read_text(encoding="utf-8"))
|
||||
values = [*document["project"]["dependencies"], *document["dependency-groups"]["dev"]]
|
||||
components = []
|
||||
for value in values:
|
||||
name, version = value.split("==", 1)
|
||||
normalized = name.split("[", 1)[0]
|
||||
components.append(
|
||||
{
|
||||
"type": "library",
|
||||
"name": normalized,
|
||||
"version": version,
|
||||
"purl": _purl("pypi", normalized, version),
|
||||
}
|
||||
)
|
||||
return components
|
||||
|
||||
|
||||
def _node_components(repo_root: Path = ROOT) -> list[dict[str, str]]:
|
||||
components: list[dict[str, str]] = []
|
||||
for path in sorted(repo_root.glob("**/package.json")):
|
||||
if set(path.parts) & {"node_modules", "dist"}:
|
||||
continue
|
||||
document = json.loads(path.read_text(encoding="utf-8"))
|
||||
for section in ("dependencies", "devDependencies"):
|
||||
for name, version in sorted(document.get(section, {}).items()):
|
||||
components.append(
|
||||
{
|
||||
"type": "library",
|
||||
"name": name,
|
||||
"version": version,
|
||||
"purl": _purl("npm", name, version),
|
||||
}
|
||||
)
|
||||
return components
|
||||
|
||||
|
||||
def _image_components(repo_root: Path = ROOT) -> list[dict[str, str]]:
|
||||
compose_path = repo_root / "infrastructure/compose/docker-compose.yml"
|
||||
if not compose_path.is_file():
|
||||
return []
|
||||
document = yaml.safe_load(compose_path.read_text(encoding="utf-8"))
|
||||
return [
|
||||
{"type": "container", "name": name, "version": str(service["image"])}
|
||||
for name, service in sorted(document["services"].items())
|
||||
if service.get("image")
|
||||
]
|
||||
|
||||
|
||||
def generate(repo_root: Path = ROOT) -> dict[str, Any]:
|
||||
git_executable = shutil.which("git")
|
||||
if git_executable is None:
|
||||
raise RuntimeError("git is required to generate the SBOM")
|
||||
commit = subprocess.run( # noqa: S603
|
||||
[git_executable, "rev-parse", "HEAD"],
|
||||
cwd=repo_root,
|
||||
check=True,
|
||||
capture_output=True,
|
||||
text=True,
|
||||
).stdout.strip()
|
||||
return {
|
||||
"bomFormat": "CycloneDX",
|
||||
"specVersion": "1.5",
|
||||
"version": 1,
|
||||
"metadata": {
|
||||
"component": {"type": "application", "name": "itworx-mcp-hub", "version": "0.1.0"},
|
||||
"sourceCommit": commit,
|
||||
},
|
||||
"components": [
|
||||
*_python_components(repo_root),
|
||||
*_node_components(repo_root),
|
||||
*_image_components(repo_root),
|
||||
],
|
||||
"scanScope": {
|
||||
"lockfiles": ["uv.lock", "pnpm-lock.yaml"],
|
||||
"images": "declared Compose images; local release digests require built artifacts",
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
def main() -> int:
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("--output", type=Path, required=True)
|
||||
args = parser.parse_args()
|
||||
args.output.parent.mkdir(parents=True, exist_ok=True)
|
||||
args.output.write_text(
|
||||
json.dumps(generate(), indent=2, sort_keys=True) + "\n", encoding="utf-8"
|
||||
)
|
||||
print(f"wrote SBOM: {args.output}")
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
Reference in new issue
Block a user