Skip to content

Commit b6997fa

Browse files
committed
add wont fix feature
Signed-off-by: Jefferson <jefferson.rios.caro@gmail.com>
1 parent 7613c0e commit b6997fa

1 file changed

Lines changed: 44 additions & 3 deletions

File tree

dep_checker/reconcile_issues.py

Lines changed: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@
1414
listed by the per-stream LABEL, which is index-independent and immediately consistent, so
1515
near-simultaneous runs cannot create duplicates.
1616
17-
Closed issues are never touched: a reappearing vulnerability always gets a fresh issue.
17+
Closed issues are never re-opened. A vulnerability whose key matches a closed
18+
issue carrying a "won't fix" label (any case, ``_`` or space) is suppressed and
19+
not re-created. Other reappearing vulnerabilities get a fresh issue.
1820
"""
1921

2022
from __future__ import annotations
@@ -36,6 +38,15 @@
3638
# Severity labels are mutually exclusive, so they are reset (not just added) on update.
3739
SEVERITY_LABELS = {"CRITICAL", "HIGH", "MODERATE", "MEDIUM", "LOW"}
3840

41+
# Labels marking a closed issue as "won't fix"; matched case-insensitively, with
42+
# ``_`` and space treated as equivalent. A vuln whose key matches a closed issue
43+
# carrying any of these labels is not re-opened on subsequent scans.
44+
WONT_FIX_LABEL = "WONT FIX" # normalized form (uppercase, underscore -> space)
45+
46+
47+
def _is_wont_fix_label(label_name: str) -> bool:
48+
return label_name.upper().replace("_", " ").strip() == WONT_FIX_LABEL
49+
3950

4051
def eprint(*args: Any) -> None:
4152
print(*args, file=sys.stderr)
@@ -205,6 +216,20 @@ def list_open_issues(self, stream: str, limit: int = 1000) -> List[Dict[str, Any
205216
eprint(f"WARNING: open-issue list hit the limit of {limit}; results may be truncated")
206217
return issues
207218

219+
def list_closed_issues(self, stream: str, limit: int = 1000) -> List[Dict[str, Any]]:
220+
"""Closed issues for the stream, used to detect won't-fix suppressions."""
221+
out = self._run([
222+
"issue", "list",
223+
"--state", "closed",
224+
"--label", stream,
225+
"--limit", str(limit),
226+
"--json", "number,title,body,labels",
227+
])
228+
issues = json.loads(out) if out.strip() else []
229+
if len(issues) >= limit:
230+
eprint(f"WARNING: closed-issue list hit the limit of {limit}; results may be truncated")
231+
return issues
232+
208233
def create_issue(self, title: str, body: str) -> Optional[int]:
209234
out = self._run(
210235
["issue", "create", "--title", title, "--body-file", "-"],
@@ -288,7 +313,20 @@ def reconcile(scan: Dict[str, Any], stream: str, action_url: str, gh: Gh) -> int
288313
recognizable.add(issue["number"])
289314

290315
matched: set = set()
291-
created = updated = closed = 0
316+
created = updated = closed = skipped = 0
317+
318+
# Build the set of suppressed keys from closed issues marked won't fix.
319+
suppressed: set = set()
320+
for issue in gh.list_closed_issues(stream):
321+
if not any(_is_wont_fix_label(lbl.get("name", "")) for lbl in issue.get("labels", [])):
322+
continue
323+
mk = extract_key(issue.get("body"))
324+
if mk:
325+
suppressed.add(mk)
326+
continue
327+
lk = legacy_key_from_title(issue.get("title", ""))
328+
if lk:
329+
suppressed.add(lk)
292330

293331
# Create / update.
294332
for pkey, vuln in desired.items():
@@ -300,6 +338,9 @@ def reconcile(scan: Dict[str, Any], stream: str, action_url: str, gh: Gh) -> int
300338
matched.add(issue["number"])
301339
updated += 1
302340
eprint(f"Updated #{issue['number']}: {render_title(stream, vuln)}")
341+
elif pkey in suppressed or legacy_key_for_vuln(stream, vuln) in suppressed:
342+
skipped += 1
343+
eprint(f"Skipped (won't fix): {render_title(stream, vuln)}")
303344
else:
304345
number = gh.create_issue(render_title(stream, vuln), body)
305346
if number is not None:
@@ -324,7 +365,7 @@ def reconcile(scan: Dict[str, Any], stream: str, action_url: str, gh: Gh) -> int
324365
else:
325366
eprint("Scan incomplete (scan_complete=false): skipping close phase to avoid false closes")
326367

327-
eprint(f"Reconcile summary for {stream}: created={created} updated={updated} closed={closed}")
368+
eprint(f"Reconcile summary for {stream}: created={created} updated={updated} closed={closed} skipped={skipped}")
328369
return 0
329370

330371

0 commit comments

Comments
 (0)