-
Notifications
You must be signed in to change notification settings - Fork 25
Expand file tree
/
Copy pathfilter-sarif.py
More file actions
64 lines (55 loc) · 2.41 KB
/
Copy pathfilter-sarif.py
File metadata and controls
64 lines (55 loc) · 2.41 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#!/usr/bin/python
# GitHub Code Scanning does not allow more than 20 runs per SARIF file.
# We split runs into chunks of at most 20 and write each to a separate
# file (out_0.sarif, out_1.sarif, ...). Each file should be uploaded
# separately with a distinct category to stay within GitHub's limit.
#
# The workflow supports at most 2 chunks (40 runs). If Snyk produces
# more, this script will error so we know to add more upload steps.
import glob
import json
import os
import sys
MAX_RUNS = 20
MAX_CHUNKS = 2
if not os.path.exists("snyk.sarif"):
print("snyk.sarif not found — Snyk scan likely failed. Writing empty SARIF.")
empty = {
"$schema": "https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json",
"version": "2.1.0",
"runs": [{"tool": {"driver": {"name": "SnykContainer", "rules": []}}, "results": []}],
}
with open("out_0.sarif", "w") as out:
json.dump(empty, out, indent=2)
sys.exit(0)
with open("snyk.sarif") as f:
sarif = json.load(f)
# Remove runs with no results to stay well within the chunk limit.
runs = [run for run in sarif["runs"] if len(run["results"]) > 0]
if len(runs) == 0:
# Keep at least one run so the upload is valid.
runs = [sarif["runs"][0]]
num_chunks = (len(runs) + MAX_RUNS - 1) // MAX_RUNS
if num_chunks > MAX_CHUNKS:
print(
f"error: {len(runs)} runs would require {num_chunks} chunks, "
f"but the workflow only supports {MAX_CHUNKS} "
f"(max {MAX_CHUNKS * MAX_RUNS} runs)",
file=sys.stderr,
)
sys.exit(1)
# GitHub expects each tool to only create 1 run, but Snyk splits the results
# across multiple runs. As a workaround, we rename the tools for each run to
# ensure they are unique within the file.
# https://github.blog/changelog/2025-07-21-code-scanning-will-stop-combining-multiple-sarif-runs-uploaded-in-the-same-sarif-file/
for i, run in enumerate(runs):
run["tool"]["driver"]["name"] += f"_{i}"
# Clean any prior output so sequential runs in the same job don't mix results.
for old in glob.glob("out_*.sarif"):
os.remove(old)
# Split runs into chunks of at most MAX_RUNS and write each to a separate file.
for chunk_idx in range(0, len(runs), MAX_RUNS):
chunk = runs[chunk_idx:chunk_idx + MAX_RUNS]
chunk_sarif = {**sarif, "runs": chunk}
with open(f"out_{chunk_idx // MAX_RUNS}.sarif", "w") as out:
json.dump(chunk_sarif, out, indent=2)