Skip to content

Commit c100021

Browse files
committed
CM-53929 - apply .cycodeignore when it is allowed by API
1 parent c4c7fe4 commit c100021

File tree

10 files changed

+108
-38
lines changed

10 files changed

+108
-38
lines changed

cycode/cli/apps/report/sbom/path/path_command.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
from cycode.cli.files_collector.zip_documents import zip_documents
1313
from cycode.cli.utils.get_api_client import get_report_cycode_client
1414
from cycode.cli.utils.progress_bar import SbomReportProgressBarSection
15+
from cycode.cli.utils.scan_utils import is_cycodeignore_allowed_by_scan_config
1516
from cycode.cli.utils.sentry import add_breadcrumb
1617

1718

@@ -36,8 +37,9 @@ def path_command(
3637
report_execution_id = -1
3738

3839
try:
40+
is_cycodeignore_allowed = is_cycodeignore_allowed_by_scan_config(ctx)
3941
documents = get_relevant_documents(
40-
progress_bar, SbomReportProgressBarSection.PREPARE_LOCAL_FILES, consts.SCA_SCAN_TYPE, (str(path),)
42+
progress_bar, SbomReportProgressBarSection.PREPARE_LOCAL_FILES, consts.SCA_SCAN_TYPE, (str(path),), is_cycodeignore_allowed=is_cycodeignore_allowed
4143
)
4244
# TODO(MarshalX): combine perform_pre_scan_documents_actions with get_relevant_document.
4345
# unhardcode usage of context in perform_pre_scan_documents_actions

cycode/cli/apps/scan/code_scanner.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
from cycode.cli.models import CliError, Document, LocalScanResult
2424
from cycode.cli.utils.progress_bar import ScanProgressBarSection
2525
from cycode.cli.utils.scan_batch import run_parallel_batched_scan
26-
from cycode.cli.utils.scan_utils import generate_unique_scan_id, set_issue_detected_by_scan_results
26+
from cycode.cli.utils.scan_utils import generate_unique_scan_id, is_cycodeignore_allowed_by_scan_config, set_issue_detected_by_scan_results
2727
from cycode.cyclient.models import ZippedFileScanResult
2828
from cycode.logger import get_logger
2929

@@ -42,7 +42,8 @@ def scan_disk_files(ctx: typer.Context, paths: tuple[str, ...]) -> None:
4242
progress_bar = ctx.obj['progress_bar']
4343

4444
try:
45-
documents = get_relevant_documents(progress_bar, ScanProgressBarSection.PREPARE_LOCAL_FILES, scan_type, paths)
45+
is_cycodeignore_allowed = is_cycodeignore_allowed_by_scan_config(ctx)
46+
documents = get_relevant_documents(progress_bar, ScanProgressBarSection.PREPARE_LOCAL_FILES, scan_type, paths, is_cycodeignore_allowed=is_cycodeignore_allowed)
4647
add_sca_dependencies_tree_documents_if_needed(ctx, scan_type, documents)
4748
scan_documents(ctx, documents, get_scan_parameters(ctx, paths))
4849
except Exception as e:

cycode/cli/apps/scan/commit_range_scanner.py

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141
from cycode.cli.utils.git_proxy import git_proxy
4242
from cycode.cli.utils.path_utils import get_path_by_os
4343
from cycode.cli.utils.progress_bar import ScanProgressBarSection
44-
from cycode.cli.utils.scan_utils import generate_unique_scan_id, set_issue_detected_by_scan_results
44+
from cycode.cli.utils.scan_utils import generate_unique_scan_id, is_cycodeignore_allowed_by_scan_config, set_issue_detected_by_scan_results
4545
from cycode.cyclient.models import ZippedFileScanResult
4646
from cycode.logger import get_logger
4747

@@ -190,8 +190,9 @@ def _scan_sca_commit_range(ctx: typer.Context, repo_path: str, commit_range: str
190190
from_commit_documents = excluder.exclude_irrelevant_documents_to_scan(consts.SCA_SCAN_TYPE, from_commit_documents)
191191
to_commit_documents = excluder.exclude_irrelevant_documents_to_scan(consts.SCA_SCAN_TYPE, to_commit_documents)
192192

193-
from_commit_documents = filter_documents_with_cycodeignore(from_commit_documents, repo_path)
194-
to_commit_documents = filter_documents_with_cycodeignore(to_commit_documents, repo_path)
193+
is_cycodeignore_allowed = is_cycodeignore_allowed_by_scan_config(ctx)
194+
from_commit_documents = filter_documents_with_cycodeignore(from_commit_documents, repo_path, is_cycodeignore_allowed)
195+
to_commit_documents = filter_documents_with_cycodeignore(to_commit_documents, repo_path, is_cycodeignore_allowed)
195196

196197
perform_sca_pre_commit_range_scan_actions(
197198
repo_path, from_commit_documents, from_commit_rev, to_commit_documents, to_commit_rev
@@ -208,7 +209,8 @@ def _scan_secret_commit_range(
208209
consts.SECRET_SCAN_TYPE, commit_diff_documents_to_scan
209210
)
210211

211-
diff_documents_to_scan = filter_documents_with_cycodeignore(diff_documents_to_scan, repo_path)
212+
is_cycodeignore_allowed = is_cycodeignore_allowed_by_scan_config(ctx)
213+
diff_documents_to_scan = filter_documents_with_cycodeignore(diff_documents_to_scan, repo_path, is_cycodeignore_allowed)
212214

213215
scan_documents(
214216
ctx, diff_documents_to_scan, get_scan_parameters(ctx, (repo_path,)), is_git_diff=True, is_commit_range=True
@@ -231,8 +233,9 @@ def _scan_sast_commit_range(ctx: typer.Context, repo_path: str, commit_range: st
231233
commit_documents = excluder.exclude_irrelevant_documents_to_scan(consts.SAST_SCAN_TYPE, commit_documents)
232234
diff_documents = excluder.exclude_irrelevant_documents_to_scan(consts.SAST_SCAN_TYPE, diff_documents)
233235

234-
commit_documents = filter_documents_with_cycodeignore(commit_documents, repo_path)
235-
diff_documents = filter_documents_with_cycodeignore(diff_documents, repo_path)
236+
is_cycodeignore_allowed = is_cycodeignore_allowed_by_scan_config(ctx)
237+
commit_documents = filter_documents_with_cycodeignore(commit_documents, repo_path, is_cycodeignore_allowed)
238+
diff_documents = filter_documents_with_cycodeignore(diff_documents, repo_path, is_cycodeignore_allowed)
236239

237240
_scan_commit_range_documents(ctx, commit_documents, diff_documents, scan_parameters=scan_parameters)
238241

@@ -270,8 +273,9 @@ def _scan_sca_pre_commit(ctx: typer.Context, repo_path: str) -> None:
270273
consts.SCA_SCAN_TYPE, pre_committed_documents
271274
)
272275

273-
git_head_documents = filter_documents_with_cycodeignore(git_head_documents, repo_path)
274-
pre_committed_documents = filter_documents_with_cycodeignore(pre_committed_documents, repo_path)
276+
is_cycodeignore_allowed = is_cycodeignore_allowed_by_scan_config(ctx)
277+
git_head_documents = filter_documents_with_cycodeignore(git_head_documents, repo_path, is_cycodeignore_allowed)
278+
pre_committed_documents = filter_documents_with_cycodeignore(pre_committed_documents, repo_path, is_cycodeignore_allowed)
275279

276280
perform_sca_pre_hook_range_scan_actions(repo_path, git_head_documents, pre_committed_documents)
277281

@@ -305,7 +309,8 @@ def _scan_secret_pre_commit(ctx: typer.Context, repo_path: str) -> None:
305309

306310
documents_to_scan = excluder.exclude_irrelevant_documents_to_scan(consts.SECRET_SCAN_TYPE, documents_to_scan)
307311

308-
documents_to_scan = filter_documents_with_cycodeignore(documents_to_scan, repo_path)
312+
is_cycodeignore_allowed = is_cycodeignore_allowed_by_scan_config(ctx)
313+
documents_to_scan = filter_documents_with_cycodeignore(documents_to_scan, repo_path, is_cycodeignore_allowed)
309314

310315
scan_documents(ctx, documents_to_scan, get_scan_parameters(ctx), is_git_diff=True)
311316

@@ -324,8 +329,9 @@ def _scan_sast_pre_commit(ctx: typer.Context, repo_path: str, **_) -> None:
324329
)
325330
diff_documents = excluder.exclude_irrelevant_documents_to_scan(consts.SAST_SCAN_TYPE, diff_documents)
326331

327-
pre_committed_documents = filter_documents_with_cycodeignore(pre_committed_documents, repo_path)
328-
diff_documents = filter_documents_with_cycodeignore(diff_documents, repo_path)
332+
is_cycodeignore_allowed = is_cycodeignore_allowed_by_scan_config(ctx)
333+
pre_committed_documents = filter_documents_with_cycodeignore(pre_committed_documents, repo_path, is_cycodeignore_allowed)
334+
diff_documents = filter_documents_with_cycodeignore(diff_documents, repo_path, is_cycodeignore_allowed)
329335

330336
_scan_commit_range_documents(ctx, pre_committed_documents, diff_documents, scan_parameters=scan_parameters)
331337

cycode/cli/apps/scan/repository/repository_command.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
from cycode.cli.models import Document
1717
from cycode.cli.utils.path_utils import get_path_by_os
1818
from cycode.cli.utils.progress_bar import ScanProgressBarSection
19+
from cycode.cli.utils.scan_utils import is_cycodeignore_allowed_by_scan_config
1920
from cycode.cli.utils.sentry import add_breadcrumb
2021

2122

@@ -61,7 +62,8 @@ def repository_command(
6162

6263
documents_to_scan = excluder.exclude_irrelevant_documents_to_scan(scan_type, documents_to_scan)
6364

64-
documents_to_scan = filter_documents_with_cycodeignore(documents_to_scan, str(path))
65+
is_cycodeignore_allowed = is_cycodeignore_allowed_by_scan_config(ctx)
66+
documents_to_scan = filter_documents_with_cycodeignore(documents_to_scan, str(path), is_cycodeignore_allowed)
6567

6668
add_sca_dependencies_tree_documents_if_needed(ctx, scan_type, documents_to_scan)
6769

cycode/cli/apps/scan/scan_command.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,8 @@ def scan_command(
169169
remote_scan_config = scan_client.get_scan_configuration_safe(scan_type, remote_url)
170170
if remote_scan_config:
171171
excluder.apply_scan_config(str(scan_type), remote_scan_config)
172+
173+
ctx.obj['scan_config'] = remote_scan_config
172174

173175
if export_type and export_file:
174176
console_printer = ctx.obj['console_printer']

cycode/cli/files_collector/documents_walk_ignore.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,13 +86,16 @@ def _filter_documents_by_allowed_paths(
8686
logger.debug('Filtered out document due to .cycodeignore: %s', relative_path)
8787
except Exception as e:
8888
logger.debug('Error processing document %s: %s', document.path, e)
89-
# Include document if we can't determine if it should be ignored
9089
filtered_documents.append(document)
9190

9291
return filtered_documents
9392

9493

95-
def filter_documents_with_cycodeignore(documents: list['Document'], repo_path: str) -> list['Document']:
94+
def filter_documents_with_cycodeignore(
95+
documents: list['Document'],
96+
repo_path: str,
97+
is_cycodeignore_allowed: bool = True
98+
) -> list['Document']:
9699
"""Filter documents based on .cycodeignore patterns.
97100
98101
This function uses .cycodeignore file in the repository root to filter out
@@ -101,10 +104,15 @@ def filter_documents_with_cycodeignore(documents: list['Document'], repo_path: s
101104
Args:
102105
documents: List of Document objects to filter
103106
repo_path: Path to the repository root
107+
is_cycodeignore_allowed: Whether .cycodeignore filtering is allowed by scan configuration
104108
105109
Returns:
106110
List of Document objects that don't match any .cycodeignore patterns
107111
"""
112+
if not is_cycodeignore_allowed:
113+
logger.debug('.cycodeignore filtering is not allowed by scan configuration')
114+
return documents
115+
108116
cycodeignore_path = _get_cycodeignore_path(repo_path)
109117

110118
if not os.path.exists(cycodeignore_path):

cycode/cli/files_collector/path_documents.py

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,18 +17,27 @@
1717
from cycode.cli.utils.progress_bar import BaseProgressBar, ProgressBarSection
1818

1919

20-
def _get_all_existing_files_in_directory(path: str, *, walk_with_ignore_patterns: bool = True) -> list[str]:
20+
def _get_all_existing_files_in_directory(
21+
path: str,
22+
*,
23+
walk_with_ignore_patterns: bool = True,
24+
is_cycodeignore_allowed: bool = True
25+
) -> list[str]:
2126
files: list[str] = []
2227

23-
walk_func = walk_ignore if walk_with_ignore_patterns else os.walk
28+
if walk_with_ignore_patterns:
29+
walk_func = lambda p: walk_ignore(p, is_cycodeignore_allowed=is_cycodeignore_allowed)
30+
else:
31+
walk_func = os.walk
32+
2433
for root, _, filenames in walk_func(path):
2534
for filename in filenames:
2635
files.append(os.path.join(root, filename))
2736

2837
return files
2938

3039

31-
def _get_relevant_files_in_path(path: str) -> list[str]:
40+
def _get_relevant_files_in_path(path: str, *, is_cycodeignore_allowed: bool = True) -> list[str]:
3241
absolute_path = get_absolute_path(path)
3342

3443
if not os.path.isfile(absolute_path) and not os.path.isdir(absolute_path):
@@ -37,16 +46,21 @@ def _get_relevant_files_in_path(path: str) -> list[str]:
3746
if os.path.isfile(absolute_path):
3847
return [absolute_path]
3948

40-
file_paths = _get_all_existing_files_in_directory(absolute_path)
49+
file_paths = _get_all_existing_files_in_directory(absolute_path, is_cycodeignore_allowed=is_cycodeignore_allowed)
4150
return [file_path for file_path in file_paths if os.path.isfile(file_path)]
4251

4352

4453
def _get_relevant_files(
45-
progress_bar: 'BaseProgressBar', progress_bar_section: 'ProgressBarSection', scan_type: str, paths: tuple[str, ...]
54+
progress_bar: 'BaseProgressBar',
55+
progress_bar_section: 'ProgressBarSection',
56+
scan_type: str,
57+
paths: tuple[str, ...],
58+
*,
59+
is_cycodeignore_allowed: bool = True
4660
) -> list[str]:
4761
all_files_to_scan = []
4862
for path in paths:
49-
all_files_to_scan.extend(_get_relevant_files_in_path(path))
63+
all_files_to_scan.extend(_get_relevant_files_in_path(path, is_cycodeignore_allowed=is_cycodeignore_allowed))
5064

5165
# we are double the progress bar section length because we are going to process the files twice
5266
# first time to get the file list with respect of excluded patterns (excluding takes seconds to execute)
@@ -94,8 +108,9 @@ def get_relevant_documents(
94108
paths: tuple[str, ...],
95109
*,
96110
is_git_diff: bool = False,
111+
is_cycodeignore_allowed: bool = True,
97112
) -> list[Document]:
98-
relevant_files = _get_relevant_files(progress_bar, progress_bar_section, scan_type, paths)
113+
relevant_files = _get_relevant_files(progress_bar, progress_bar_section, scan_type, paths, is_cycodeignore_allowed=is_cycodeignore_allowed)
99114

100115
documents: list[Document] = []
101116
for file in relevant_files:

cycode/cli/files_collector/walk_ignore.py

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010

1111
_SUPPORTED_IGNORE_PATTERN_FILES = {
1212
'.gitignore',
13-
consts.CYCODEIGNORE_FILENAME,
1413
}
1514
_DEFAULT_GLOBAL_IGNORE_PATTERNS = [
1615
'.git',
@@ -27,22 +26,29 @@ def _walk_to_top(path: str) -> Iterable[str]:
2726
yield path # Include the top-level directory
2827

2928

30-
def _collect_top_level_ignore_files(path: str) -> list[str]:
29+
def _collect_top_level_ignore_files(path: str, *, is_cycodeignore_allowed: bool = True) -> list[str]:
3130
ignore_files = []
3231
top_paths = reversed(list(_walk_to_top(path))) # we must reverse it to make top levels more prioritized
32+
33+
supported_files = {_SUPPORTED_IGNORE_PATTERN_FILES}
34+
if is_cycodeignore_allowed:
35+
supported_files.add(consts.CYCODEIGNORE_FILENAME)
36+
logger.debug('.cycodeignore files included due to scan configuration')
37+
3338
for dir_path in top_paths:
34-
for ignore_file in _SUPPORTED_IGNORE_PATTERN_FILES:
39+
for ignore_file in supported_files:
3540
ignore_file_path = os.path.join(dir_path, ignore_file)
3641
if os.path.exists(ignore_file_path):
3742
logger.debug('Reading top level ignore file: %s', ignore_file_path)
3843
ignore_files.append(ignore_file_path)
3944
return ignore_files
4045

4146

42-
def walk_ignore(path: str) -> Generator[tuple[str, list[str], list[str]], None, None]:
47+
def walk_ignore(path: str, *, is_cycodeignore_allowed: bool = True) -> Generator[tuple[str, list[str], list[str]], None, None]:
48+
ignore_file_paths = _collect_top_level_ignore_files(path, is_cycodeignore_allowed=is_cycodeignore_allowed)
4349
ignore_filter_manager = IgnoreFilterManager.build(
4450
path=path,
45-
global_ignore_file_paths=_collect_top_level_ignore_files(path),
51+
global_ignore_file_paths=ignore_file_paths,
4652
global_patterns=_DEFAULT_GLOBAL_IGNORE_PATTERNS,
4753
)
4854
for dirpath, dirnames, filenames, ignored_dirnames, ignored_filenames in ignore_filter_manager.walk_with_ignored():

cycode/cli/utils/scan_utils.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
import os
2-
from typing import TYPE_CHECKING
2+
from typing import TYPE_CHECKING, Optional
33
from uuid import UUID, uuid4
44

55
import typer
66

77
if TYPE_CHECKING:
88
from cycode.cli.models import LocalScanResult
9+
from cycode.cyclient.models import ScanConfiguration
910

1011

1112
def set_issue_detected(ctx: typer.Context, issue_detected: bool) -> None:
@@ -22,6 +23,11 @@ def is_scan_failed(ctx: typer.Context) -> bool:
2223
return did_fail or issue_detected
2324

2425

26+
def is_cycodeignore_allowed_by_scan_config(ctx: typer.Context) -> bool:
27+
scan_config: Optional['ScanConfiguration'] = ctx.obj.get('scan_config')
28+
return scan_config.is_repository_ignore_configuration_allowed if scan_config else True
29+
30+
2531
def generate_unique_scan_id() -> UUID:
2632
if 'PYTEST_TEST_UNIQUE_ID' in os.environ:
2733
return UUID(os.environ['PYTEST_TEST_UNIQUE_ID'])

0 commit comments

Comments
 (0)