fix(sbom-ci): summary shows only scanned severities (drop always-zero MED/LOW)
SEVERITY 로 스캔한 심각도만 요약표 컬럼으로 동적 출력. 기본(HIGH,CRITICAL)에서 항상 0이던 MED/LOW 컬럼 제거. SEVERITY 에 MEDIUM/LOW 추가 시에만 해당 컬럼 표시. TSV 는 CRITICAL 을 첫 카운트 열로 유지(게이트 호환). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
+17
-11
@@ -139,6 +139,10 @@ python3 - "$RESULTS" "$CHARTMAP" "$SEVERITY" "$TOTAL" "$(ts)" "$SUMMARY_TSV" <<'
|
|||||||
import sys
|
import sys
|
||||||
results, chartmap, sev, total, tstamp, tsv_out = sys.argv[1:7]
|
results, chartmap, sev, total, tstamp, tsv_out = sys.argv[1:7]
|
||||||
total=int(total)
|
total=int(total)
|
||||||
|
# 표시 심각도 = 실제 스캔한 SEVERITY 만 (순위 내림차순). MED/LOW 는 스캔 안 하면 항상 0이므로 제외.
|
||||||
|
RANK=["CRITICAL","HIGH","MEDIUM","LOW"]; IDX={"CRITICAL":1,"HIGH":2,"MEDIUM":3,"LOW":4}
|
||||||
|
scanned=[s.strip().upper() for s in sev.split(",") if s.strip()]
|
||||||
|
shown=[s for s in RANK if s in scanned] or ["CRITICAL","HIGH"]
|
||||||
cm={}
|
cm={}
|
||||||
try:
|
try:
|
||||||
for l in open(chartmap):
|
for l in open(chartmap):
|
||||||
@@ -152,29 +156,31 @@ for l in open(results):
|
|||||||
img=p[0]
|
img=p[0]
|
||||||
if p[5]=="OK" or img not in best or best[img][5]!="OK": best[img]=p
|
if p[5]=="OK" or img not in best or best[img][5]!="OK": best[img]=p
|
||||||
rows=list(best.values())
|
rows=list(best.values())
|
||||||
def key(r):
|
def cnt(r,s):
|
||||||
try: return (-int(r[1]),-int(r[2]))
|
try: return int(r[IDX[s]])
|
||||||
except: return (1,0)
|
except: return 0
|
||||||
rows.sort(key=key)
|
rows.sort(key=lambda r: tuple(-cnt(r,s) for s in shown))
|
||||||
ok=[r for r in rows if r[5]=="OK"]; err=[r for r in rows if r[5]!="OK"]
|
ok=[r for r in rows if r[5]=="OK"]; err=[r for r in rows if r[5]!="OK"]
|
||||||
tc=sum(int(r[1]) for r in ok); th=sum(int(r[2]) for r in ok)
|
totals={s:sum(cnt(r,s) for r in ok) for s in shown}
|
||||||
secs=[int(r[6]) for r in rows if len(r)>=7 and r[6].isdigit()]
|
secs=[int(r[6]) for r in rows if len(r)>=7 and r[6].isdigit()]
|
||||||
|
# TSV: chart, image, <shown counts...>, status, sec (CRITICAL 은 첫 카운트 열 = col3)
|
||||||
with open(tsv_out,"w") as f:
|
with open(tsv_out,"w") as f:
|
||||||
for r in rows:
|
for r in rows:
|
||||||
f.write(f"{cm.get(r[0],'')}\t{r[0]}\t{r[1]}\t{r[2]}\t{r[3]}\t{r[4]}\t{r[5]}\t{r[6] if len(r)>=7 else ''}\n")
|
cols=[cm.get(r[0],""), r[0]] + [str(cnt(r,s)) for s in shown] + [r[5], r[6] if len(r)>=7 else ""]
|
||||||
|
f.write("\t".join(cols)+"\n")
|
||||||
print("# Trivy SBOM 취약점 요약\n")
|
print("# Trivy SBOM 취약점 요약\n")
|
||||||
print(f"- 생성: {tstamp}")
|
print(f"- 생성: {tstamp}")
|
||||||
print(f"- 총 소요: **{total//60}분 {total%60}초** (SBOM {len(rows)}개)")
|
print(f"- 총 소요: **{total//60}분 {total%60}초** (SBOM {len(rows)}개)")
|
||||||
print(f"- 성공/실패: **{len(ok)} / {len(err)}**")
|
print(f"- 성공/실패: **{len(ok)} / {len(err)}**")
|
||||||
print(f"- 집계 심각도: `{sev}`")
|
print(f"- 집계 심각도: `{sev}`")
|
||||||
print(f"- 취약점 합계: **CRITICAL {tc}**, **HIGH {th}**")
|
print("- 취약점 합계: " + ", ".join(f"**{s} {totals[s]}**" for s in shown))
|
||||||
if secs: print(f"- SBOM당 스캔시간: 최소 {min(secs)}s / 최대 {max(secs)}s / 평균 {sum(secs)//len(secs)}s")
|
if secs: print(f"- SBOM당 스캔시간: 최소 {min(secs)}s / 최대 {max(secs)}s / 평균 {sum(secs)//len(secs)}s")
|
||||||
print()
|
print()
|
||||||
print("| Chart | Image | CRIT | HIGH | MED | LOW | Status | Sec |")
|
print("| Chart | Image | " + " | ".join(shown) + " | Status | Sec |")
|
||||||
print("|---|---|---:|---:|---:|---:|---|---:|")
|
print("|---|---|" + "---:|"*len(shown) + "---|---:|")
|
||||||
for r in rows:
|
for r in rows:
|
||||||
sec=r[6] if len(r)>=7 else "-"
|
cells=" | ".join(str(cnt(r,s)) for s in shown)
|
||||||
print(f"| {cm.get(r[0],'')} | `{r[0]}` | {r[1]} | {r[2]} | {r[3]} | {r[4]} | {r[5]} | {sec} |")
|
print(f"| {cm.get(r[0],'')} | `{r[0]}` | {cells} | {r[5]} | {r[6] if len(r)>=7 else '-'} |")
|
||||||
PY
|
PY
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user