Skip to content

Commit b8eff6f

Browse files
committed
scripts: Add syft-license-summary
Takes a Syft JSON file as a the first argument and outputs a human-readable summary of source packages and their licenses. Signed-off-by: Loïc Minier <[email protected]>
1 parent 3b5ebed commit b8eff6f

File tree

1 file changed

+76
-0
lines changed

1 file changed

+76
-0
lines changed

scripts/syft-license-summary.py

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
#!/usr/bin/env python3
2+
# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
3+
# SPDX-License-Identifier: BSD-3-Clause
4+
5+
# input is a syft JSON file as the first argument; output is a summary of
6+
# source packages and their licenses
7+
8+
import json
9+
import os
10+
import sys
11+
import hashlib
12+
from collections import defaultdict
13+
from pathlib import Path
14+
15+
def load_syft_json(file_path):
16+
with open(file_path, 'r') as f:
17+
return json.load(f)
18+
19+
def sha256_of_file(path):
20+
try:
21+
with open(path, 'rb') as f:
22+
return hashlib.sha256(f.read()).hexdigest()
23+
except Exception:
24+
return "unreadable"
25+
26+
def group_by_source_package(data):
27+
grouped = defaultdict(lambda: {
28+
"binaries": set(),
29+
"licenses": set(),
30+
"copyrights": {},
31+
"source_version": None
32+
})
33+
34+
for artifact in data.get("artifacts", []):
35+
metadata = artifact.get("metadata", {})
36+
binary = metadata.get("package", "unknown")
37+
source = metadata.get("source") or binary
38+
source_version = metadata.get("sourceVersion") or metadata.get("version", "")
39+
grouped[source]["binaries"].add(binary)
40+
grouped[source]["source_version"] = source_version
41+
42+
for lic in artifact.get("licenses", []):
43+
grouped[source]["licenses"].add(lic.get("value", "unknown"))
44+
45+
for loc in artifact.get("locations", []):
46+
path = loc.get("path", "")
47+
if "copyright" in path:
48+
grouped[source]["copyrights"][binary] = path
49+
50+
return grouped
51+
52+
def print_table(grouped):
53+
print("source,version,binaries,licenses,copyright_sha256")
54+
for source, data in grouped.items():
55+
binaries = " ".join(sorted(data["binaries"]))
56+
licenses = " ".join(sorted(data["licenses"]))
57+
version = data["source_version"] or "unknown"
58+
59+
# Compute SHA256 hashes
60+
hashes = set()
61+
for path in data["copyrights"].values():
62+
hashes.add(sha256_of_file(path.lstrip('/')))
63+
hash_summary = " ".join(sorted(hashes))
64+
65+
print(f"{source},{version},{binaries},{licenses},{hash_summary}")
66+
67+
if __name__ == "__main__":
68+
if len(sys.argv) != 2:
69+
print("Usage: syft-license-summary.py <syft-json-file>")
70+
sys.exit(1)
71+
72+
syft_file = sys.argv[1]
73+
data = load_syft_json(syft_file)
74+
grouped = group_by_source_package(data)
75+
print_table(grouped)
76+

0 commit comments

Comments
 (0)