From 18cfc8f37a98ea1b24552611f0dbd7f39c12b32d Mon Sep 17 00:00:00 2001 From: Ilia Shkolyar Date: Thu, 12 Feb 2026 12:39:49 +0200 Subject: [PATCH 1/2] CM-59469 switch SCA/IAC from file_name to file_path in detection_details Co-Authored-By: Claude Opus 4.6 --- cycode/cli/apps/scan/scan_result.py | 2 +- .../cli/printers/tables/sca_table_printer.py | 2 +- cycode/cli/printers/utils/detection_data.py | 2 +- .../utils/detection_ordering/sca_ordering.py | 2 +- tests/cli/commands/scan/test_scan_result.py | 45 +++++++++++++++++++ .../cli/printers/utils/test_detection_data.py | 41 +++++++++++++++++ 6 files changed, 90 insertions(+), 4 deletions(-) create mode 100644 tests/cli/commands/scan/test_scan_result.py create mode 100644 tests/cli/printers/utils/test_detection_data.py diff --git a/cycode/cli/apps/scan/scan_result.py b/cycode/cli/apps/scan/scan_result.py index 31a36368..13fb8576 100644 --- a/cycode/cli/apps/scan/scan_result.py +++ b/cycode/cli/apps/scan/scan_result.py @@ -88,7 +88,7 @@ def _get_file_name_from_detection(scan_type: str, raw_detection: dict) -> str: if scan_type == consts.SECRET_SCAN_TYPE: return _get_secret_file_name_from_detection(raw_detection) - return raw_detection['detection_details']['file_name'] + return raw_detection['detection_details']['file_path'] def _get_secret_file_name_from_detection(raw_detection: dict) -> str: diff --git a/cycode/cli/printers/tables/sca_table_printer.py b/cycode/cli/printers/tables/sca_table_printer.py index c0bedcc7..064d21d1 100644 --- a/cycode/cli/printers/tables/sca_table_printer.py +++ b/cycode/cli/printers/tables/sca_table_printer.py @@ -86,7 +86,7 @@ def _enrich_table_with_values(table: Table, detection: Detection) -> None: table.add_cell(SEVERITY_COLUMN, 'N/A') table.add_cell(REPOSITORY_COLUMN, detection_details.get('repository_name')) - table.add_file_path_cell(CODE_PROJECT_COLUMN, detection_details.get('file_name')) + table.add_file_path_cell(CODE_PROJECT_COLUMN, detection_details.get('file_path')) table.add_cell(ECOSYSTEM_COLUMN, detection_details.get('ecosystem')) table.add_cell(PACKAGE_COLUMN, detection_details.get('package_name')) diff --git a/cycode/cli/printers/utils/detection_data.py b/cycode/cli/printers/utils/detection_data.py index 37bee310..679429a3 100644 --- a/cycode/cli/printers/utils/detection_data.py +++ b/cycode/cli/printers/utils/detection_data.py @@ -105,4 +105,4 @@ def get_detection_file_path(scan_type: str, detection: 'Detection') -> Path: return Path(file_path) - return Path(detection.detection_details.get('file_name', '')) + return Path(detection.detection_details.get('file_path', '')) diff --git a/cycode/cli/printers/utils/detection_ordering/sca_ordering.py b/cycode/cli/printers/utils/detection_ordering/sca_ordering.py index a8be3430..9e1f8022 100644 --- a/cycode/cli/printers/utils/detection_ordering/sca_ordering.py +++ b/cycode/cli/printers/utils/detection_ordering/sca_ordering.py @@ -49,7 +49,7 @@ def sort_and_group_detections(detections: list['Detection']) -> tuple[list['Dete grouped_by_repository = __group_by(sorted_detections, 'repository_name') for repository_group in grouped_by_repository.values(): - grouped_by_code_project = __group_by(repository_group, 'file_name') + grouped_by_code_project = __group_by(repository_group, 'file_path') for code_project_group in grouped_by_code_project.values(): grouped_by_package = __group_by(code_project_group, 'package_name') for package_group in grouped_by_package.values(): diff --git a/tests/cli/commands/scan/test_scan_result.py b/tests/cli/commands/scan/test_scan_result.py new file mode 100644 index 00000000..c2c561b3 --- /dev/null +++ b/tests/cli/commands/scan/test_scan_result.py @@ -0,0 +1,45 @@ +from cycode.cli.apps.scan.scan_result import _get_file_name_from_detection +from cycode.cli.consts import IAC_SCAN_TYPE, SAST_SCAN_TYPE, SCA_SCAN_TYPE, SECRET_SCAN_TYPE + + +def test_get_file_name_from_detection_sca_uses_file_path() -> None: + raw_detection = { + 'detection_details': { + 'file_name': 'package.json', + 'file_path': '/repo/path/package.json', + }, + } + result = _get_file_name_from_detection(SCA_SCAN_TYPE, raw_detection) + assert result == '/repo/path/package.json' + + +def test_get_file_name_from_detection_iac_uses_file_path() -> None: + raw_detection = { + 'detection_details': { + 'file_name': 'main.tf', + 'file_path': '/repo/infra/main.tf', + }, + } + result = _get_file_name_from_detection(IAC_SCAN_TYPE, raw_detection) + assert result == '/repo/infra/main.tf' + + +def test_get_file_name_from_detection_sast_uses_file_path() -> None: + raw_detection = { + 'detection_details': { + 'file_path': '/repo/src/app.py', + }, + } + result = _get_file_name_from_detection(SAST_SCAN_TYPE, raw_detection) + assert result == '/repo/src/app.py' + + +def test_get_file_name_from_detection_secret_uses_file_path_and_file_name() -> None: + raw_detection = { + 'detection_details': { + 'file_path': '/repo/src', + 'file_name': '.env', + }, + } + result = _get_file_name_from_detection(SECRET_SCAN_TYPE, raw_detection) + assert result == '/repo/src/.env' diff --git a/tests/cli/printers/utils/test_detection_data.py b/tests/cli/printers/utils/test_detection_data.py new file mode 100644 index 00000000..603c25db --- /dev/null +++ b/tests/cli/printers/utils/test_detection_data.py @@ -0,0 +1,41 @@ +from pathlib import Path +from unittest.mock import MagicMock + +from cycode.cli.consts import IAC_SCAN_TYPE, SAST_SCAN_TYPE, SCA_SCAN_TYPE, SECRET_SCAN_TYPE +from cycode.cli.printers.utils.detection_data import get_detection_file_path + + +def _make_detection(**details: str) -> MagicMock: + detection = MagicMock() + detection.detection_details = dict(details) + return detection + + +def test_get_detection_file_path_sca_uses_file_path() -> None: + detection = _make_detection(file_name='package.json', file_path='/repo/path/package.json') + result = get_detection_file_path(SCA_SCAN_TYPE, detection) + assert result == Path('/repo/path/package.json') + + +def test_get_detection_file_path_iac_uses_file_path() -> None: + detection = _make_detection(file_name='main.tf', file_path='/repo/infra/main.tf') + result = get_detection_file_path(IAC_SCAN_TYPE, detection) + assert result == Path('/repo/infra/main.tf') + + +def test_get_detection_file_path_sca_fallback_empty() -> None: + detection = _make_detection() + result = get_detection_file_path(SCA_SCAN_TYPE, detection) + assert result == Path('') + + +def test_get_detection_file_path_secret() -> None: + detection = _make_detection(file_path='/repo/src', file_name='.env') + result = get_detection_file_path(SECRET_SCAN_TYPE, detection) + assert result == Path('/repo/src/.env') + + +def test_get_detection_file_path_sast() -> None: + detection = _make_detection(file_path='repo/src/app.py') + result = get_detection_file_path(SAST_SCAN_TYPE, detection) + assert result == Path('/repo/src/app.py') From 5c679082d0fc9e1e04aa2fa85148ab18ab9f0487 Mon Sep 17 00:00:00 2001 From: Ilia Shkolyar Date: Thu, 12 Feb 2026 12:47:36 +0200 Subject: [PATCH 2/2] CM-59469 fix Windows path separator in secret scan test Co-Authored-By: Claude Opus 4.6 --- tests/cli/commands/scan/test_scan_result.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/cli/commands/scan/test_scan_result.py b/tests/cli/commands/scan/test_scan_result.py index c2c561b3..e85ca116 100644 --- a/tests/cli/commands/scan/test_scan_result.py +++ b/tests/cli/commands/scan/test_scan_result.py @@ -1,3 +1,5 @@ +import os + from cycode.cli.apps.scan.scan_result import _get_file_name_from_detection from cycode.cli.consts import IAC_SCAN_TYPE, SAST_SCAN_TYPE, SCA_SCAN_TYPE, SECRET_SCAN_TYPE @@ -42,4 +44,4 @@ def test_get_file_name_from_detection_secret_uses_file_path_and_file_name() -> N }, } result = _get_file_name_from_detection(SECRET_SCAN_TYPE, raw_detection) - assert result == '/repo/src/.env' + assert result == os.path.join('/repo/src', '.env')