33
44from __future__ import annotations
55
6+ import json
67import re
78import subprocess
89import sys
@@ -56,6 +57,17 @@ def count_detectors_and_languages() -> tuple[int, int]:
5657 return int (parts [0 ]), int (parts [1 ])
5758
5859
60+ def count_vulnerabilities () -> int :
61+ """Count open Dependabot alerts via gh CLI (requires repo access)."""
62+ try :
63+ out = _run (["gh" , "api" , "repos/RandomCodeSpace/code-iq/dependabot/alerts?state=open&per_page=100" ])
64+ alerts = json .loads (out )
65+ return len (alerts ) if isinstance (alerts , list ) else 0
66+ except Exception :
67+ # Fallback: try GITHUB_TOKEN env var or return -1 to skip update
68+ return - 1
69+
70+
5971def fmt (n : int ) -> str :
6072 """Format number with commas for display, URL-encoded."""
6173 return f"{ n :,} "
@@ -64,8 +76,11 @@ def fmt(n: int) -> str:
6476def badge (label : str , value : str , color : str , logo : str ) -> str :
6577 """Generate a shields.io badge HTML snippet."""
6678 val_encoded = quote (value , safe = "" )
79+ link = "https://github.com/RandomCodeSpace/code-iq"
80+ if label == "vulnerabilities" :
81+ link += "/security/dependabot"
6782 return (
68- f'<a href="https://github.com/RandomCodeSpace/code-iq ">'
83+ f'<a href="{ link } ">'
6984 f'<img src="https://img.shields.io/badge/{ label } -{ val_encoded } -{ color } '
7085 f'?style=flat-square&logo={ logo } &logoColor=white" alt="{ value } { label .capitalize ()} ">'
7186 f"</a>"
@@ -86,12 +101,14 @@ def main() -> None:
86101 loc = count_loc ()
87102 tests = count_tests ()
88103 detectors , languages = count_detectors_and_languages ()
104+ vulns = count_vulnerabilities ()
89105
90106 print (f" Files: { files } " )
91107 print (f" LOC: { loc :,} " )
92108 print (f" Tests: { tests } " )
93109 print (f" Detectors: { detectors } " )
94110 print (f" Languages: { languages } " )
111+ print (f" Vulnerabilities: { vulns if vulns >= 0 else 'skipped (no access)' } " )
95112
96113 content = README .read_text ()
97114 original = content
@@ -116,6 +133,13 @@ def main() -> None:
116133 content , "loc" ,
117134 badge ("LOC" , fmt (loc ), "informational" , "codacy" ),
118135 )
136+ if vulns >= 0 :
137+ vuln_color = "brightgreen" if vulns == 0 else "yellow" if vulns <= 3 else "red"
138+ vuln_label = "0 - clean" if vulns == 0 else str (vulns )
139+ content = update_badge (
140+ content , "vulnerabilities" ,
141+ badge ("vulnerabilities" , vuln_label , vuln_color , "hackthebox" ),
142+ )
119143
120144 if content != original :
121145 README .write_text (content )
0 commit comments