Skip to content

Commit 6262176

Browse files
committed
All packages now show and not just vulnerable packages, with accurate status including "Security scan not supported" and "No issues found" to match the UI.
1 parent 9318618 commit 6262176

1 file changed

Lines changed: 67 additions & 40 deletions

File tree

cloudsmith_cli/cli/commands/vulnerabilities.py

Lines changed: 67 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,10 @@ def get_packages_in_repo(opts, owner, repo):
6363
f"The repository may be empty, or the owner/repo names may be incorrect."
6464
)
6565

66-
return [pkg["slug_perm"] for pkg in all_packages]
66+
return [
67+
(pkg["slug_perm"], pkg.get("name", pkg["slug_perm"]), pkg.get("version", ""))
68+
for pkg in all_packages
69+
]
6770

6871

6972
def _has_scan_results(data):
@@ -189,18 +192,28 @@ def _print_repo_summary_table(package_rows, severity_filter=None):
189192
table.add_column("Total", justify="center", header_style="bold white")
190193

191194
grand_total = 0
195+
num_sev_cols = len(severity_keys)
192196

193-
for label, counts in package_rows:
194-
row_total = 0
197+
for label, counts, status in package_rows:
195198
cells = [label]
196-
for _display, sev_key in severity_keys.items():
197-
count = counts.get(sev_key, 0)
198-
cells.append(_colorize_count(count, sev_key))
199-
row_total += count
200-
total_style = "[bold red]" if row_total > 0 else "[dim]"
201-
cells.append(f"{total_style}{row_total}[/]")
199+
if status == "no_scan":
200+
cells.append("[dim italic]Security scan not supported[/dim italic]")
201+
cells.extend([""] * (num_sev_cols - 1))
202+
cells.append("")
203+
elif status == "no_issues_found":
204+
cells.append("[bold green]No issues found[/bold green]")
205+
cells.extend([""] * (num_sev_cols - 1))
206+
cells.append("")
207+
else:
208+
row_total = 0
209+
for _display, sev_key in severity_keys.items():
210+
count = counts.get(sev_key, 0)
211+
cells.append(_colorize_count(count, sev_key))
212+
row_total += count
213+
total_style = "[bold red]" if row_total > 0 else "[dim]"
214+
cells.append(f"{total_style}{row_total}[/]")
215+
grand_total += row_total
202216
table.add_row(*cells)
203-
grand_total += row_total
204217

205218
console.print()
206219
console.print(table)
@@ -210,7 +223,9 @@ def _print_repo_summary_table(package_rows, severity_filter=None):
210223
def _collect_repo_scan_data(opts, owner, repo, slugs, severity_filter, fixable):
211224
"""Silently collect scan data for all packages with a progress bar.
212225
213-
Returns list of (slug, label, counts) tuples sorted by total desc.
226+
Returns list of (slug, label, counts, status) tuples where status is one of
227+
"vulnerable", "safe", or "no_scan". Sorted: vulnerable (by count desc),
228+
then safe, then no_scan.
214229
"""
215230
rows = []
216231
console = Console(stderr=True)
@@ -226,8 +241,13 @@ def _collect_repo_scan_data(opts, owner, repo, slugs, severity_filter, fixable):
226241
) as progress:
227242
task = progress.add_task("Scanning packages...", total=len(slugs))
228243

229-
for slug in slugs:
244+
for slug, pkg_name_fallback, pkg_version_fallback in slugs:
230245
progress.update(task, description=f"Processing {slug}...")
246+
fallback_label = (
247+
f"{pkg_name_fallback}:{pkg_version_fallback}"
248+
if pkg_version_fallback
249+
else pkg_name_fallback
250+
)
231251

232252
try:
233253
data = get_package_scan_result(
@@ -240,35 +260,49 @@ def _collect_repo_scan_data(opts, owner, repo, slugs, severity_filter, fixable):
240260
fixable=fixable,
241261
)
242262
except Exception: # pylint: disable=broad-exception-caught
263+
rows.append((slug, fallback_label, {}, "no_scan"))
243264
progress.advance(task)
244265
continue
245266

267+
# Build label from scan response metadata, fall back to list_packages data
268+
pkg_data = getattr(data, "package", None) if data else None
269+
pkg_name = (
270+
getattr(pkg_data, "name", pkg_name_fallback)
271+
if pkg_data
272+
else pkg_name_fallback
273+
)
274+
pkg_version = (
275+
getattr(pkg_data, "version", pkg_version_fallback)
276+
if pkg_data
277+
else pkg_version_fallback
278+
)
279+
label = f"{pkg_name}:{pkg_version}" if pkg_version else pkg_name
280+
246281
if not data or not _has_scan_results(data):
282+
rows.append((slug, label, {}, "no_scan"))
247283
progress.advance(task)
248284
continue
249285

250286
# Apply filters if active
251287
if severity_filter or fixable is not None:
252288
_apply_filters(data, severity_filter, fixable)
253289

254-
# Build label from package metadata
255-
pkg_data = getattr(data, "package", None)
256-
pkg_name = getattr(pkg_data, "name", slug)
257-
pkg_version = getattr(pkg_data, "version", "")
258-
label = f"{pkg_name}:{pkg_version}" if pkg_version else pkg_name
259-
260290
counts = _aggregate_severity_counts(data, severity_filter)
261291

262-
# Skip packages where filters removed all vulnerabilities
263292
if sum(counts.values()) > 0:
264-
rows.append((slug, label, counts))
293+
rows.append((slug, label, counts, "vulnerable"))
294+
else:
295+
rows.append((slug, label, counts, "no_issues_found"))
265296

266297
progress.advance(task)
267298

268-
# Sort by total vulnerability count descending
269-
rows.sort(key=lambda row: sum(row[2].values()), reverse=True)
299+
# Sort: vulnerable first (by total desc), then safe, then no_scan
300+
vulnerable = [r for r in rows if r[3] == "vulnerable"]
301+
vulnerable.sort(key=lambda r: sum(r[2].values()), reverse=True)
302+
safe = [r for r in rows if r[3] == "no_issues_found"]
303+
no_scan = [r for r in rows if r[3] == "no_scan"]
270304

271-
return rows
305+
return vulnerable + safe + no_scan
272306

273307

274308
@main.command()
@@ -363,20 +397,12 @@ def vulnerabilities(
363397
)
364398

365399
if not repo_summary_rows:
366-
if severity_filter or fixable is not None:
367-
click.secho(
368-
f"No vulnerabilities matched the applied filters "
369-
f"for any packages in '{owner}/{repo}'.",
370-
fg="yellow",
371-
err=use_stderr,
372-
)
373-
else:
374-
click.secho(
375-
f"No vulnerability scan results found for any packages "
376-
f"in '{owner}/{repo}'.",
377-
fg="yellow",
378-
err=use_stderr,
379-
)
400+
click.secho(
401+
f"No scan data could be retrieved for any packages "
402+
f"in '{owner}/{repo}'.",
403+
fg="yellow",
404+
err=use_stderr,
405+
)
380406
return
381407

382408
json_output = {
@@ -386,18 +412,19 @@ def vulnerabilities(
386412
{
387413
"slug_perm": slug_perm,
388414
"package": label,
415+
"status": status,
389416
"vulnerabilities": counts,
390417
}
391-
for slug_perm, label, counts in repo_summary_rows
418+
for slug_perm, label, counts, status in repo_summary_rows
392419
],
393420
}
394421

395422
if utils.maybe_print_as_json(opts, json_output):
396423
return
397424

398-
# Table only needs label and counts
425+
# Table only needs label, counts, and status
399426
_print_repo_summary_table(
400-
[(label, counts) for _, label, counts in repo_summary_rows],
427+
[(label, counts, status) for _, label, counts, status in repo_summary_rows],
401428
severity_filter,
402429
)
403430
return

0 commit comments

Comments
 (0)