Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 11 additions & 6 deletions cycode/cli/printers/tables/sca_table_printer.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from collections import defaultdict
from typing import TYPE_CHECKING, Dict, List
from typing import TYPE_CHECKING, Dict, List, Set, Tuple

import typer

Expand Down Expand Up @@ -37,9 +37,12 @@ def _print_results(self, local_scan_results: List['LocalScanResult']) -> None:
for policy_id, detections in detections_per_policy_id.items():
table = self._get_table(policy_id)

for detection in self._sort_and_group_detections(detections):
resulting_detections, group_separator_indexes = self._sort_and_group_detections(detections)
for detection in resulting_detections:
self._enrich_table_with_values(policy_id, table, detection)

table.set_group_separator_indexes(group_separator_indexes)

self._print_summary_issues(len(detections), self._get_title(policy_id))
self._print_table(table)

Expand Down Expand Up @@ -76,7 +79,7 @@ def __package_sort_key(detection: Detection) -> int:
def _sort_detections_by_package(self, detections: List[Detection]) -> List[Detection]:
return sorted(detections, key=self.__package_sort_key)

def _sort_and_group_detections(self, detections: List[Detection]) -> List[Detection]:
def _sort_and_group_detections(self, detections: List[Detection]) -> Tuple[List[Detection], Set[int]]:
"""Sort detections by severity and group by repository, code project and package name.

Note:
Expand All @@ -85,7 +88,8 @@ def _sort_and_group_detections(self, detections: List[Detection]) -> List[Detect
Grouping by code projects also groups by ecosystem.
Because manifest files are unique per ecosystem.
"""
result = []
resulting_detections = []
group_separator_indexes = set()

# we sort detections by package name to make persist output order
sorted_detections = self._sort_detections_by_package(detections)
Expand All @@ -96,9 +100,10 @@ def _sort_and_group_detections(self, detections: List[Detection]) -> List[Detect
for code_project_group in grouped_by_code_project.values():
grouped_by_package = self.__group_by(code_project_group, 'package_name')
for package_group in grouped_by_package.values():
result.extend(self._sort_detections_by_severity(package_group))
group_separator_indexes.add(len(resulting_detections) - 1) # indexing starts from 0
resulting_detections.extend(self._sort_detections_by_severity(package_group))

return result
return resulting_detections, group_separator_indexes

def _get_table(self, policy_id: str) -> Table:
table = Table()
Expand Down
11 changes: 8 additions & 3 deletions cycode/cli/printers/tables/table.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import urllib.parse
from typing import TYPE_CHECKING, Dict, List, Optional
from typing import TYPE_CHECKING, Dict, List, Optional, Set

from rich.markup import escape
from rich.table import Table as RichTable
Expand All @@ -12,6 +12,8 @@ class Table:
"""Helper class to manage columns and their values in the right order and only if the column should be presented."""

def __init__(self, column_infos: Optional[List['ColumnInfo']] = None) -> None:
self._group_separator_indexes: Set[int] = set()

self._columns: Dict['ColumnInfo', List[str]] = {}
if column_infos:
self._columns = {columns: [] for columns in column_infos}
Expand All @@ -35,6 +37,9 @@ def add_file_path_cell(self, column: 'ColumnInfo', path: str) -> None:
escaped_path = escape(encoded_path)
self._add_cell_no_error(column, f'[link file://{escaped_path}]{path}')

def set_group_separator_indexes(self, group_separator_indexes: Set[int]) -> None:
self._group_separator_indexes = group_separator_indexes

def _get_ordered_columns(self) -> List['ColumnInfo']:
# we are sorting columns by index to make sure that columns will be printed in the right order
return sorted(self._columns, key=lambda column_info: column_info.index)
Expand All @@ -53,7 +58,7 @@ def get_table(self) -> 'RichTable':
extra_args = column.column_opts if column.column_opts else {}
table.add_column(header=column.name, overflow='fold', **extra_args)

for raw in self.get_rows():
table.add_row(*raw)
for index, raw in enumerate(self.get_rows()):
table.add_row(*raw, end_section=index in self._group_separator_indexes)

return table
25 changes: 15 additions & 10 deletions cycode/cli/printers/tables/table_printer.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from collections import defaultdict
from typing import TYPE_CHECKING, List, Tuple
from typing import TYPE_CHECKING, List, Set, Tuple

from cycode.cli.cli_types import SeverityOption
from cycode.cli.consts import SECRET_SCAN_TYPE
Expand All @@ -18,12 +18,12 @@
SEVERITY_COLUMN = column_builder.build(name='Severity')
ISSUE_TYPE_COLUMN = column_builder.build(name='Issue Type')
FILE_PATH_COLUMN = column_builder.build(name='File Path', highlight=False)
LINE_NUMBER_COLUMN = column_builder.build(name='Line')
COLUMN_NUMBER_COLUMN = column_builder.build(name='Column')
VIOLATION_COLUMN = column_builder.build(name='Violation', highlight=False)
VIOLATION_LENGTH_COLUMN = column_builder.build(name='Length')
SECRET_SHA_COLUMN = column_builder.build(name='Secret SHA')
COMMIT_SHA_COLUMN = column_builder.build(name='Commit SHA')
LINE_NUMBER_COLUMN = column_builder.build(name='Line Number')
COLUMN_NUMBER_COLUMN = column_builder.build(name='Column Number')
VIOLATION_LENGTH_COLUMN = column_builder.build(name='Violation Length')
VIOLATION_COLUMN = column_builder.build(name='Violation', highlight=False)


class TablePrinter(TablePrinterBase):
Expand All @@ -37,9 +37,12 @@ def _print_results(self, local_scan_results: List['LocalScanResult']) -> None:
[(detection, document_detections.document) for detection in document_detections.detections]
)

for detection, document in self._sort_and_group_detections(detections_with_documents):
detections, group_separator_indexes = self._sort_and_group_detections(detections_with_documents)
for detection, document in detections:
self._enrich_table_with_values(table, detection, document)

table.set_group_separator_indexes(group_separator_indexes)

self._print_table(table)
self._print_report_urls(local_scan_results, self.ctx.obj.get('aggregation_report_url'))

Expand All @@ -66,9 +69,10 @@ def _sort_detections_by_file_path(

def _sort_and_group_detections(
self, detections_with_documents: List[Tuple[Detection, Document]]
) -> List[Tuple[Detection, Document]]:
) -> Tuple[List[Tuple[Detection, Document]], Set[int]]:
"""Sort detections by severity and group by file name."""
result = []
detections = []
group_separator_indexes = set()

# we sort detections by file path to make persist output order
sorted_detections = self._sort_detections_by_file_path(detections_with_documents)
Expand All @@ -78,9 +82,10 @@ def _sort_and_group_detections(
grouped_by_file_path[document.path].append((detection, document))

for file_path_group in grouped_by_file_path.values():
result.extend(self._sort_detections_by_severity(file_path_group))
group_separator_indexes.add(len(detections) - 1) # indexing starts from 0
detections.extend(self._sort_detections_by_severity(file_path_group))

return result
return detections, group_separator_indexes

def _get_table(self) -> Table:
table = Table()
Expand Down