cycode 1.9.5.dev5__tar.gz → 1.9.6.dev3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (110) hide show
  1. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/PKG-INFO +6 -3
  2. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/README.md +5 -2
  3. cycode-1.9.6.dev3/cycode/__init__.py +1 -0
  4. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/cycode/cli/commands/auth/auth_manager.py +11 -11
  5. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/cycode/cli/commands/report/sbom/common.py +1 -1
  6. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/cycode/cli/commands/scan/code_scanner.py +67 -35
  7. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/cycode/cli/commands/scan/pre_receive/pre_receive_command.py +5 -4
  8. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/cycode/cli/files_collector/excluder.py +38 -11
  9. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/cycode/cli/files_collector/path_documents.py +1 -1
  10. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/cycode/cli/files_collector/sca/maven/base_restore_maven_dependencies.py +1 -1
  11. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/cycode/cli/files_collector/sca/sca_code_scanner.py +6 -6
  12. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/cycode/cli/files_collector/zip_documents.py +7 -6
  13. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/cycode/cli/printers/console_printer.py +4 -2
  14. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/cycode/cli/printers/json_printer.py +4 -2
  15. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/cycode/cli/printers/tables/sca_table_printer.py +2 -3
  16. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/cycode/cli/printers/tables/table_printer.py +1 -1
  17. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/cycode/cli/printers/tables/table_printer_base.py +8 -2
  18. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/cycode/cli/printers/text_printer.py +19 -13
  19. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/cycode/cli/utils/progress_bar.py +11 -6
  20. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/cycode/cli/utils/shell_executor.py +2 -2
  21. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/cycode/cyclient/config.py +18 -9
  22. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/cycode/cyclient/cycode_client_base.py +8 -2
  23. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/cycode/cyclient/headers.py +1 -1
  24. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/cycode/cyclient/scan_client.py +13 -1
  25. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/pyproject.toml +2 -1
  26. cycode-1.9.5.dev5/cycode/__init__.py +0 -1
  27. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/cycode/cli/__init__.py +0 -0
  28. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/cycode/cli/commands/__init__.py +0 -0
  29. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/cycode/cli/commands/auth/__init__.py +0 -0
  30. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/cycode/cli/commands/auth/auth_command.py +0 -0
  31. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/cycode/cli/commands/configure/__init__.py +0 -0
  32. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/cycode/cli/commands/configure/configure_command.py +0 -0
  33. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/cycode/cli/commands/ignore/__init__.py +0 -0
  34. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/cycode/cli/commands/ignore/ignore_command.py +0 -0
  35. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/cycode/cli/commands/main_cli.py +0 -0
  36. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/cycode/cli/commands/report/__init__.py +0 -0
  37. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/cycode/cli/commands/report/report_command.py +0 -0
  38. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/cycode/cli/commands/report/sbom/__init__.py +0 -0
  39. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/cycode/cli/commands/report/sbom/path/__init__.py +0 -0
  40. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/cycode/cli/commands/report/sbom/path/path_command.py +0 -0
  41. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/cycode/cli/commands/report/sbom/repository_url/__init__.py +0 -0
  42. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/cycode/cli/commands/report/sbom/repository_url/repository_url_command.py +0 -0
  43. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/cycode/cli/commands/report/sbom/sbom_command.py +0 -0
  44. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/cycode/cli/commands/report/sbom/sbom_report_file.py +0 -0
  45. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/cycode/cli/commands/scan/__init__.py +0 -0
  46. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/cycode/cli/commands/scan/commit_history/__init__.py +0 -0
  47. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/cycode/cli/commands/scan/commit_history/commit_history_command.py +0 -0
  48. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/cycode/cli/commands/scan/path/__init__.py +0 -0
  49. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/cycode/cli/commands/scan/path/path_command.py +0 -0
  50. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/cycode/cli/commands/scan/pre_commit/__init__.py +0 -0
  51. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/cycode/cli/commands/scan/pre_commit/pre_commit_command.py +0 -0
  52. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/cycode/cli/commands/scan/pre_receive/__init__.py +0 -0
  53. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/cycode/cli/commands/scan/repository/__init__.py +0 -0
  54. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/cycode/cli/commands/scan/repository/repository_command.py +0 -0
  55. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/cycode/cli/commands/scan/scan_ci/__init__.py +0 -0
  56. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/cycode/cli/commands/scan/scan_ci/ci_integrations.py +0 -0
  57. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/cycode/cli/commands/scan/scan_ci/scan_ci_command.py +0 -0
  58. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/cycode/cli/commands/scan/scan_command.py +0 -0
  59. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/cycode/cli/commands/version/__init__.py +0 -0
  60. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/cycode/cli/commands/version/version_command.py +0 -0
  61. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/cycode/cli/config.py +0 -0
  62. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/cycode/cli/config.yaml +0 -0
  63. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/cycode/cli/consts.py +0 -0
  64. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/cycode/cli/exceptions/__init__.py +0 -0
  65. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/cycode/cli/exceptions/custom_exceptions.py +0 -0
  66. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/cycode/cli/exceptions/handle_report_sbom_errors.py +0 -0
  67. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/cycode/cli/exceptions/handle_scan_errors.py +0 -0
  68. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/cycode/cli/files_collector/__init__.py +0 -0
  69. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/cycode/cli/files_collector/iac/__init__.py +0 -0
  70. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/cycode/cli/files_collector/iac/tf_content_generator.py +0 -0
  71. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/cycode/cli/files_collector/models/__init__.py +0 -0
  72. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/cycode/cli/files_collector/models/in_memory_zip.py +0 -0
  73. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/cycode/cli/files_collector/repository_documents.py +0 -0
  74. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/cycode/cli/files_collector/sca/__init__.py +0 -0
  75. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/cycode/cli/files_collector/sca/maven/__init__.py +0 -0
  76. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/cycode/cli/files_collector/sca/maven/restore_gradle_dependencies.py +0 -0
  77. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/cycode/cli/files_collector/sca/maven/restore_maven_dependencies.py +0 -0
  78. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/cycode/cli/main.py +0 -0
  79. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/cycode/cli/models.py +0 -0
  80. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/cycode/cli/printers/__init__.py +0 -0
  81. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/cycode/cli/printers/printer_base.py +0 -0
  82. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/cycode/cli/printers/tables/__init__.py +0 -0
  83. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/cycode/cli/printers/tables/table.py +0 -0
  84. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/cycode/cli/printers/tables/table_models.py +0 -0
  85. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/cycode/cli/user_settings/__init__.py +0 -0
  86. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/cycode/cli/user_settings/base_file_manager.py +0 -0
  87. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/cycode/cli/user_settings/config_file_manager.py +0 -0
  88. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/cycode/cli/user_settings/configuration_manager.py +0 -0
  89. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/cycode/cli/user_settings/credentials_manager.py +0 -0
  90. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/cycode/cli/user_settings/jwt_creator.py +0 -0
  91. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/cycode/cli/utils/__init__.py +0 -0
  92. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/cycode/cli/utils/enum_utils.py +0 -0
  93. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/cycode/cli/utils/get_api_client.py +0 -0
  94. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/cycode/cli/utils/path_utils.py +0 -0
  95. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/cycode/cli/utils/scan_batch.py +0 -0
  96. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/cycode/cli/utils/scan_utils.py +0 -0
  97. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/cycode/cli/utils/string_utils.py +0 -0
  98. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/cycode/cli/utils/task_timer.py +0 -0
  99. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/cycode/cli/utils/yaml_utils.py +0 -0
  100. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/cycode/cyclient/__init__.py +0 -0
  101. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/cycode/cyclient/auth_client.py +0 -0
  102. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/cycode/cyclient/client_creator.py +0 -0
  103. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/cycode/cyclient/config.yaml +0 -0
  104. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/cycode/cyclient/config_dev.py +0 -0
  105. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/cycode/cyclient/cycode_client.py +0 -0
  106. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/cycode/cyclient/cycode_dev_based_client.py +0 -0
  107. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/cycode/cyclient/cycode_token_based_client.py +0 -0
  108. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/cycode/cyclient/models.py +0 -0
  109. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/cycode/cyclient/report_client.py +0 -0
  110. {cycode-1.9.5.dev5 → cycode-1.9.6.dev3}/cycode/cyclient/scan_config_base.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: cycode
3
- Version: 1.9.5.dev5
3
+ Version: 1.9.6.dev3
4
4
  Summary: Boost security in your dev lifecycle via SAST, SCA, Secrets & IaC scanning.
5
5
  Home-page: https://github.com/cycodehq/cycode-cli
6
6
  License: MIT
@@ -557,9 +557,12 @@ Secret SHA: a44081db3296c84b82d12a35c446a3cba19411dddfa0380134c75f7b3973bff0
557
557
 
558
558
  ### Soft Fail
559
559
 
560
- Utilizing the soft fail feature will not fail the CI/CD step within the pipeline if the Cycode scan finds an issue. Additionally, in case an issue occurs from Cycode’s side, a soft fail will automatically execute to avoid interference.
560
+ Using the soft fail feature will not fail the CI/CD step within the pipeline if the Cycode scan detects an issue.
561
+ If an issue occurs during the Cycode scan, using a soft fail feature will automatically execute with success (`0`) to avoid interference.
561
562
 
562
- Add the `--soft-fail` argument to any type of scan to configure this feature, then assign a value of `1` if you want found issues to result in a failure within the CI/CD tool or `0` for scan results to have no impact (result in a `success` result).
563
+ To configure this feature, add the `--soft-fail` option to any type of scan. This will force the scan results to succeed (exit code `0`).
564
+
565
+ Scan results are assigned with a value of exit code `1` when issues are found in the scan results; this will result in a failure within the CI/CD tool. Use the option `--soft-fail` to force the results with the exit code `0` to have no impact (i.e., to have a successful result).
563
566
 
564
567
  ### Example Scan Results
565
568
 
@@ -519,9 +519,12 @@ Secret SHA: a44081db3296c84b82d12a35c446a3cba19411dddfa0380134c75f7b3973bff0
519
519
 
520
520
  ### Soft Fail
521
521
 
522
- Utilizing the soft fail feature will not fail the CI/CD step within the pipeline if the Cycode scan finds an issue. Additionally, in case an issue occurs from Cycode’s side, a soft fail will automatically execute to avoid interference.
522
+ Using the soft fail feature will not fail the CI/CD step within the pipeline if the Cycode scan detects an issue.
523
+ If an issue occurs during the Cycode scan, using a soft fail feature will automatically execute with success (`0`) to avoid interference.
523
524
 
524
- Add the `--soft-fail` argument to any type of scan to configure this feature, then assign a value of `1` if you want found issues to result in a failure within the CI/CD tool or `0` for scan results to have no impact (result in a `success` result).
525
+ To configure this feature, add the `--soft-fail` option to any type of scan. This will force the scan results to succeed (exit code `0`).
526
+
527
+ Scan results are assigned with a value of exit code `1` when issues are found in the scan results; this will result in a failure within the CI/CD tool. Use the option `--soft-fail` to force the results with the exit code `0` to have no impact (i.e., to have a successful result).
525
528
 
526
529
  ### Example Scan Results
527
530
 
@@ -0,0 +1 @@
1
+ __version__ = '1.9.6.dev3' # DON'T TOUCH. Placeholder. Will be filled automatically on poetry build from Git Tag
@@ -29,20 +29,20 @@ class AuthManager:
29
29
  self.auth_client = AuthClient()
30
30
 
31
31
  def authenticate(self) -> None:
32
- logger.debug('generating pkce code pair')
32
+ logger.debug('Generating PKCE code pair')
33
33
  code_challenge, code_verifier = self._generate_pkce_code_pair()
34
34
 
35
- logger.debug('starting authentication session')
35
+ logger.debug('Starting authentication session')
36
36
  session_id = self.start_session(code_challenge)
37
- logger.debug('authentication session created, %s', {'session_id': session_id})
37
+ logger.debug('Authentication session created, %s', {'session_id': session_id})
38
38
 
39
- logger.debug('opening browser and redirecting to cycode login page')
39
+ logger.debug('Opening browser and redirecting to Cycode login page')
40
40
  self.redirect_to_login_page(code_challenge, session_id)
41
41
 
42
- logger.debug('starting get api token process')
42
+ logger.debug('Getting API token')
43
43
  api_token = self.get_api_token(session_id, code_verifier)
44
44
 
45
- logger.debug('saving get api token')
45
+ logger.debug('Saving API token')
46
46
  self.save_api_token(api_token)
47
47
 
48
48
  def start_session(self, code_challenge: str) -> str:
@@ -56,20 +56,20 @@ class AuthManager:
56
56
  def get_api_token(self, session_id: str, code_verifier: str) -> 'ApiToken':
57
57
  api_token = self.get_api_token_polling(session_id, code_verifier)
58
58
  if api_token is None:
59
- raise AuthProcessError('getting api token is completed, but the token is missing')
59
+ raise AuthProcessError('API token pulling is completed, but the token is missing')
60
60
  return api_token
61
61
 
62
62
  def get_api_token_polling(self, session_id: str, code_verifier: str) -> 'ApiToken':
63
63
  end_polling_time = time.time() + self.POLLING_TIMEOUT_IN_SECONDS
64
64
  while time.time() < end_polling_time:
65
- logger.debug('trying to get api token...')
65
+ logger.debug('Trying to get API token...')
66
66
  api_token_polling_response = self.auth_client.get_api_token(session_id, code_verifier)
67
67
  if self._is_api_token_process_completed(api_token_polling_response):
68
- logger.debug('get api token process completed')
68
+ logger.debug('Got API token process completion response')
69
69
  return api_token_polling_response.api_token
70
70
  if self._is_api_token_process_failed(api_token_polling_response):
71
- logger.debug('get api token process failed')
72
- raise AuthProcessError('error during getting api token')
71
+ logger.debug('Got API token process failure response')
72
+ raise AuthProcessError('Error while obtaining API token')
73
73
  time.sleep(self.POLLING_WAIT_INTERVAL_IN_SECONDS)
74
74
 
75
75
  raise AuthProcessError('session expired')
@@ -70,7 +70,7 @@ def send_report_feedback(
70
70
 
71
71
  client.report_status(report_execution_id, scan_status)
72
72
  except Exception as e:
73
- logger.debug(f'Failed to send report feedback: {e}')
73
+ logger.debug('Failed to send report feedback', exc_info=e)
74
74
 
75
75
 
76
76
  def create_sbom_report(
@@ -148,14 +148,14 @@ def _enrich_scan_result_with_data_from_detection_rules(
148
148
 
149
149
  def _get_scan_documents_thread_func(
150
150
  context: click.Context, is_git_diff: bool, is_commit_range: bool, scan_parameters: dict
151
- ) -> Callable[[List[Document]], Tuple[str, CliError, LocalScanResult]]:
151
+ ) -> Tuple[Callable[[List[Document]], Tuple[str, CliError, LocalScanResult]], str]:
152
152
  cycode_client = context.obj['client']
153
153
  scan_type = context.obj['scan_type']
154
154
  severity_threshold = context.obj['severity_threshold']
155
155
  sync_option = context.obj['sync']
156
156
  command_scan_type = context.info_name
157
-
158
- scan_parameters['aggregation_id'] = str(_generate_unique_id())
157
+ aggregation_id = str(_generate_unique_id())
158
+ scan_parameters['aggregation_id'] = aggregation_id
159
159
 
160
160
  def _scan_batch_thread_func(batch: List[Document]) -> Tuple[str, CliError, LocalScanResult]:
161
161
  local_scan_result = error = error_message = None
@@ -200,7 +200,7 @@ def _get_scan_documents_thread_func(
200
200
  scan_id = local_scan_result.scan_id
201
201
 
202
202
  logger.debug(
203
- 'Finished scan process, %s',
203
+ 'Processing scan results, %s',
204
204
  {
205
205
  'all_violations_count': detections_count,
206
206
  'relevant_violations_count': relevant_detections_count,
@@ -224,7 +224,7 @@ def _get_scan_documents_thread_func(
224
224
 
225
225
  return scan_id, error, local_scan_result
226
226
 
227
- return _scan_batch_thread_func
227
+ return _scan_batch_thread_func, aggregation_id
228
228
 
229
229
 
230
230
  def scan_commit_range(
@@ -246,14 +246,14 @@ def scan_commit_range(
246
246
 
247
247
  repo = Repo(path)
248
248
  total_commits_count = int(repo.git.rev_list('--count', commit_range))
249
- logger.debug(f'Calculating diffs for {total_commits_count} commits in the commit range {commit_range}')
249
+ logger.debug('Calculating diffs for %s commits in the commit range %s', total_commits_count, commit_range)
250
250
 
251
251
  progress_bar.set_section_length(ScanProgressBarSection.PREPARE_LOCAL_FILES, total_commits_count)
252
252
 
253
253
  scanned_commits_count = 0
254
254
  for commit in repo.iter_commits(rev=commit_range):
255
255
  if _does_reach_to_max_commits_to_scan_limit(commit_ids_to_scan, max_commits_count):
256
- logger.debug(f'Reached to max commits to scan count. Going to scan only {max_commits_count} last commits')
256
+ logger.debug('Reached to max commits to scan count. Going to scan only %s last commits', max_commits_count)
257
257
  progress_bar.update(ScanProgressBarSection.PREPARE_LOCAL_FILES, total_commits_count - scanned_commits_count)
258
258
  break
259
259
 
@@ -284,7 +284,7 @@ def scan_commit_range(
284
284
  scanned_commits_count += 1
285
285
 
286
286
  logger.debug('List of commit ids to scan, %s', {'commit_ids': commit_ids_to_scan})
287
- logger.debug('Starting to scan commit range (It may take a few minutes)')
287
+ logger.debug('Starting to scan commit range (it may take a few minutes)')
288
288
 
289
289
  scan_documents(context, documents_to_scan, is_git_diff=True, is_commit_range=True)
290
290
  return None
@@ -307,16 +307,22 @@ def scan_documents(
307
307
  ConsolePrinter(context).print_error(
308
308
  CliError(
309
309
  code='no_relevant_files',
310
- message='Error: The scan could not be completed - relevant files to scan are not found.',
310
+ message='Error: The scan could not be completed - relevant files to scan are not found. '
311
+ 'Enable verbose mode to see more details.',
311
312
  )
312
313
  )
313
314
  return
314
315
 
315
- scan_batch_thread_func = _get_scan_documents_thread_func(context, is_git_diff, is_commit_range, scan_parameters)
316
+ scan_batch_thread_func, aggregation_id = _get_scan_documents_thread_func(
317
+ context, is_git_diff, is_commit_range, scan_parameters
318
+ )
316
319
  errors, local_scan_results = run_parallel_batched_scan(
317
320
  scan_batch_thread_func, documents_to_scan, progress_bar=progress_bar
318
321
  )
319
-
322
+ aggregation_report_url = _try_get_aggregation_report_url_if_needed(
323
+ scan_parameters, context.obj['client'], context.obj['scan_type']
324
+ )
325
+ set_aggregation_report_url(context, aggregation_report_url)
320
326
  progress_bar.set_section_length(ScanProgressBarSection.GENERATE_REPORT, 1)
321
327
  progress_bar.update(ScanProgressBarSection.GENERATE_REPORT)
322
328
  progress_bar.stop()
@@ -325,6 +331,25 @@ def scan_documents(
325
331
  print_results(context, local_scan_results, errors)
326
332
 
327
333
 
334
+ def set_aggregation_report_url(context: click.Context, aggregation_report_url: Optional[str] = None) -> None:
335
+ context.obj['aggregation_report_url'] = aggregation_report_url
336
+
337
+
338
+ def _try_get_aggregation_report_url_if_needed(
339
+ scan_parameters: dict, cycode_client: 'ScanClient', scan_type: str
340
+ ) -> Optional[str]:
341
+ aggregation_id = scan_parameters.get('aggregation_id')
342
+ if not scan_parameters.get('report'):
343
+ return None
344
+ if aggregation_id is None:
345
+ return None
346
+ try:
347
+ report_url_response = cycode_client.get_scan_aggregation_report_url(aggregation_id, scan_type)
348
+ return report_url_response.report_url
349
+ except Exception as e:
350
+ logger.debug('Failed to get aggregation report url: %s', str(e))
351
+
352
+
328
353
  def scan_commit_range_documents(
329
354
  context: click.Context,
330
355
  from_documents_to_scan: List[Document],
@@ -392,7 +417,7 @@ def scan_commit_range_documents(
392
417
  scan_id = local_scan_result.scan_id
393
418
 
394
419
  logger.debug(
395
- 'Finished scan process, %s',
420
+ 'Processing commit range scan results, %s',
396
421
  {
397
422
  'all_violations_count': detections_count,
398
423
  'relevant_violations_count': relevant_detections_count,
@@ -475,7 +500,7 @@ def perform_scan_async(
475
500
  scan_parameters: dict,
476
501
  ) -> ZippedFileScanResult:
477
502
  scan_async_result = cycode_client.zipped_file_scan_async(zipped_documents, scan_type, scan_parameters)
478
- logger.debug('scan request has been triggered successfully, scan id: %s', scan_async_result.scan_id)
503
+ logger.debug('Async scan request has been triggered successfully, %s', {'scan_id': scan_async_result.scan_id})
479
504
 
480
505
  return poll_scan_results(
481
506
  cycode_client,
@@ -492,7 +517,7 @@ def perform_scan_sync(
492
517
  scan_parameters: dict,
493
518
  ) -> ZippedFileScanResult:
494
519
  scan_results = cycode_client.zipped_file_scan_sync(zipped_documents, scan_type, scan_parameters)
495
- logger.debug('scan request has been triggered successfully, scan id: %s', scan_results.id)
520
+ logger.debug('Sync scan request has been triggered successfully, %s', {'scan_id': scan_results.id})
496
521
  return ZippedFileScanResult(
497
522
  did_detect=True,
498
523
  detections_per_file=_map_detections_per_file(scan_results.detection_messages),
@@ -512,7 +537,9 @@ def perform_commit_range_scan_async(
512
537
  from_commit_zipped_documents, to_commit_zipped_documents, scan_type, scan_parameters
513
538
  )
514
539
 
515
- logger.debug('scan request has been triggered successfully, scan id: %s', scan_async_result.scan_id)
540
+ logger.debug(
541
+ 'Async commit range scan request has been triggered successfully, %s', {'scan_id': scan_async_result.scan_id}
542
+ )
516
543
  return poll_scan_results(
517
544
  cycode_client, scan_async_result.scan_id, scan_type, scan_parameters.get('report'), timeout
518
545
  )
@@ -552,11 +579,12 @@ def poll_scan_results(
552
579
 
553
580
 
554
581
  def print_debug_scan_details(scan_details_response: 'ScanDetailsResponse') -> None:
555
- logger.debug(f'Scan update: (scan_id: {scan_details_response.id})')
556
- logger.debug(f'Scan status: {scan_details_response.scan_status}')
582
+ logger.debug(
583
+ 'Scan update, %s', {'scan_id': scan_details_response.id, 'scan_status': scan_details_response.scan_status}
584
+ )
557
585
 
558
586
  if scan_details_response.message:
559
- logger.debug(f'Scan message: {scan_details_response.message}')
587
+ logger.debug('Scan message: %s', scan_details_response.message)
560
588
 
561
589
 
562
590
  def print_results(
@@ -569,14 +597,16 @@ def print_results(
569
597
  def get_document_detections(
570
598
  scan_result: ZippedFileScanResult, documents_to_scan: List[Document]
571
599
  ) -> List[DocumentDetections]:
572
- logger.debug('Get document detections')
600
+ logger.debug('Getting document detections')
573
601
 
574
602
  document_detections = []
575
603
  for detections_per_file in scan_result.detections_per_file:
576
604
  file_name = get_path_by_os(detections_per_file.file_name)
577
605
  commit_id = detections_per_file.commit_id
578
606
 
579
- logger.debug('Going to find document of violated file, %s', {'file_name': file_name, 'commit_id': commit_id})
607
+ logger.debug(
608
+ 'Going to find the document of the violated file., %s', {'file_name': file_name, 'commit_id': commit_id}
609
+ )
580
610
 
581
611
  document = _get_document_by_file_name(documents_to_scan, file_name, commit_id)
582
612
  document_detections.append(DocumentDetections(document=document, detections=detections_per_file.detections))
@@ -659,10 +689,10 @@ def get_scan_parameters(context: click.Context, paths: Tuple[str]) -> dict:
659
689
  def try_get_git_remote_url(path: str) -> Optional[str]:
660
690
  try:
661
691
  remote_url = Repo(path).remotes[0].config_reader.get('url')
662
- logger.debug(f'Found Git remote URL "{remote_url}" in path "{path}"')
692
+ logger.debug('Found Git remote URL, %s', {'remote_url': remote_url, 'path': path})
663
693
  return remote_url
664
694
  except Exception as e:
665
- logger.debug('Failed to get git remote URL. %s', {'exception_message': str(e)})
695
+ logger.debug('Failed to get Git remote URL', exc_info=e)
666
696
  return None
667
697
 
668
698
 
@@ -719,15 +749,15 @@ def _should_exclude_detection(detection: Detection, exclusions: Dict) -> bool:
719
749
  exclusions_by_value = exclusions.get(consts.EXCLUSIONS_BY_VALUE_SECTION_NAME, [])
720
750
  if _is_detection_sha_configured_in_exclusions(detection, exclusions_by_value):
721
751
  logger.debug(
722
- 'Going to ignore violations because is in the values to ignore list, %s',
723
- {'sha': detection.detection_details.get('sha512', '')},
752
+ 'Going to ignore violations because they are on the values-to-ignore list, %s',
753
+ {'value_sha': detection.detection_details.get('sha512', '')},
724
754
  )
725
755
  return True
726
756
 
727
757
  exclusions_by_sha = exclusions.get(consts.EXCLUSIONS_BY_SHA_SECTION_NAME, [])
728
758
  if _is_detection_sha_configured_in_exclusions(detection, exclusions_by_sha):
729
759
  logger.debug(
730
- 'Going to ignore violations because is in the shas to ignore list, %s',
760
+ 'Going to ignore violations because they are on the SHA ignore list, %s',
731
761
  {'sha': detection.detection_details.get('sha512', '')},
732
762
  )
733
763
  return True
@@ -737,7 +767,7 @@ def _should_exclude_detection(detection: Detection, exclusions: Dict) -> bool:
737
767
  detection_rule = detection.detection_rule_id
738
768
  if detection_rule in exclusions_by_rule:
739
769
  logger.debug(
740
- 'Going to ignore violations because is in the shas to ignore list, %s',
770
+ 'Going to ignore violations because they are on the Rule ID ignore list, %s',
741
771
  {'detection_rule': detection_rule},
742
772
  )
743
773
  return True
@@ -747,7 +777,7 @@ def _should_exclude_detection(detection: Detection, exclusions: Dict) -> bool:
747
777
  package = _get_package_name(detection)
748
778
  if package in exclusions_by_package:
749
779
  logger.debug(
750
- 'Going to ignore violations because is in the packages to ignore list, %s', {'package': package}
780
+ 'Going to ignore violations because they are on the packages-to-ignore list, %s', {'package': package}
751
781
  )
752
782
  return True
753
783
 
@@ -810,7 +840,7 @@ def _report_scan_status(
810
840
 
811
841
  cycode_client.report_scan_status(scan_type, scan_id, scan_status, should_use_scan_service)
812
842
  except Exception as e:
813
- logger.debug('Failed to report scan status, %s', {'exception_message': str(e)})
843
+ logger.debug('Failed to report scan status', exc_info=e)
814
844
 
815
845
 
816
846
  def _generate_unique_id() -> UUID:
@@ -868,7 +898,7 @@ def _try_get_report_url_if_needed(
868
898
  report_url_response = cycode_client.get_scan_report_url(scan_id, scan_type)
869
899
  return report_url_response.report_url
870
900
  except Exception as e:
871
- logger.debug('Failed to get report url: %s', str(e))
901
+ logger.debug('Failed to get report URL', exc_info=e)
872
902
 
873
903
 
874
904
  def wait_for_detections_creation(
@@ -883,16 +913,18 @@ def wait_for_detections_creation(
883
913
  while time.time() < end_polling_time:
884
914
  scan_persisted_detections_count = cycode_client.get_scan_detections_count(scan_type, scan_id)
885
915
  logger.debug(
886
- f'Excepted {expected_detections_count} detections, got {scan_persisted_detections_count} detections '
887
- f'({expected_detections_count - scan_persisted_detections_count} more; '
888
- f'{round(end_polling_time - time.time())} seconds left)'
916
+ 'Excepting %s detections, got %s detections (%s more; %s seconds left)',
917
+ expected_detections_count,
918
+ scan_persisted_detections_count,
919
+ expected_detections_count - scan_persisted_detections_count,
920
+ round(end_polling_time - time.time()),
889
921
  )
890
922
  if scan_persisted_detections_count == expected_detections_count:
891
923
  return
892
924
 
893
925
  time.sleep(consts.DETECTIONS_COUNT_VERIFICATION_WAIT_INTERVAL_IN_SECONDS)
894
926
 
895
- logger.debug(f'{scan_persisted_detections_count} detections has been created')
927
+ logger.debug('%s detections has been created', scan_persisted_detections_count)
896
928
  raise custom_exceptions.ScanAsyncError(
897
929
  f'Failed to wait for detections to be created after {polling_timeout} seconds'
898
930
  )
@@ -905,14 +937,14 @@ def _map_detections_per_file(detections: List[dict]) -> List[DetectionsPerFile]:
905
937
  detection['message'] = detection['correlation_message']
906
938
  file_name = _get_file_name_from_detection(detection)
907
939
  if file_name is None:
908
- logger.debug('file name is missing from detection with id %s', detection.get('id'))
940
+ logger.debug('File name is missing from detection with ID %s', detection.get('id'))
909
941
  continue
910
942
  if detections_per_files.get(file_name) is None:
911
943
  detections_per_files[file_name] = [DetectionSchema().load(detection)]
912
944
  else:
913
945
  detections_per_files[file_name].append(DetectionSchema().load(detection))
914
946
  except Exception as e:
915
- logger.debug('Failed to parse detection: %s', str(e))
947
+ logger.debug('Failed to parse detection', exc_info=e)
916
948
  continue
917
949
 
918
950
  return [
@@ -32,14 +32,14 @@ def pre_receive_command(context: click.Context, ignored_args: List[str]) -> None
32
32
 
33
33
  if should_skip_pre_receive_scan():
34
34
  logger.info(
35
- 'A scan has been skipped as per your request.'
36
- ' Please note that this may leave your system vulnerable to secrets that have not been detected'
35
+ 'A scan has been skipped as per your request. '
36
+ 'Please note that this may leave your system vulnerable to secrets that have not been detected.'
37
37
  )
38
38
  return
39
39
 
40
40
  if is_verbose_mode_requested_in_pre_receive_scan():
41
41
  enable_verbose_mode(context)
42
- logger.debug('Verbose mode enabled, all log levels will be displayed')
42
+ logger.debug('Verbose mode enabled: all log levels will be displayed.')
43
43
 
44
44
  command_scan_type = context.info_name
45
45
  timeout = configuration_manager.get_pre_receive_command_timeout(command_scan_type)
@@ -51,7 +51,8 @@ def pre_receive_command(context: click.Context, ignored_args: List[str]) -> None
51
51
  commit_range = calculate_pre_receive_commit_range(branch_update_details)
52
52
  if not commit_range:
53
53
  logger.info(
54
- 'No new commits found for pushed branch, %s', {'branch_update_details': branch_update_details}
54
+ 'No new commits found for pushed branch, %s',
55
+ {'branch_update_details': branch_update_details},
55
56
  )
56
57
  return
57
58
 
@@ -62,23 +62,36 @@ def _does_document_exceed_max_size_limit(content: str) -> bool:
62
62
 
63
63
  def _is_relevant_file_to_scan(scan_type: str, filename: str) -> bool:
64
64
  if _is_subpath_of_cycode_configuration_folder(filename):
65
- logger.debug('file is irrelevant because it is in cycode configuration directory, %s', {'filename': filename})
65
+ logger.debug(
66
+ 'The file is irrelevant because it is in the Cycode configuration directory, %s',
67
+ {'filename': filename, 'configuration_directory': consts.CYCODE_CONFIGURATION_DIRECTORY},
68
+ )
66
69
  return False
67
70
 
68
71
  if _is_path_configured_in_exclusions(scan_type, filename):
69
- logger.debug('file is irrelevant because the file path is in the ignore paths list, %s', {'filename': filename})
72
+ logger.debug('The file is irrelevant because its path is in the ignore paths list, %s', {'filename': filename})
70
73
  return False
71
74
 
72
75
  if not _is_file_extension_supported(scan_type, filename):
73
- logger.debug('file is irrelevant because the file extension is not supported, %s', {'filename': filename})
76
+ logger.debug(
77
+ 'The file is irrelevant because its extension is not supported, %s',
78
+ {'scan_type': scan_type, 'filename': filename},
79
+ )
74
80
  return False
75
81
 
76
82
  if is_binary_file(filename):
77
- logger.debug('file is irrelevant because it is binary file, %s', {'filename': filename})
83
+ logger.debug('The file is irrelevant because it is a binary file, %s', {'filename': filename})
78
84
  return False
79
85
 
80
86
  if scan_type != consts.SCA_SCAN_TYPE and _does_file_exceed_max_size_limit(filename):
81
- logger.debug('file is irrelevant because its exceeded max size limit, %s', {'filename': filename})
87
+ logger.debug(
88
+ 'The file is irrelevant because it has exceeded the maximum size limit, %s',
89
+ {
90
+ 'max_file_size': consts.FILE_MAX_SIZE_LIMIT_IN_BYTES,
91
+ 'file_size': get_file_size(filename),
92
+ 'filename': filename,
93
+ },
94
+ )
82
95
  return False
83
96
 
84
97
  if scan_type == consts.SCA_SCAN_TYPE and not _is_file_relevant_for_sca_scan(filename):
@@ -89,7 +102,9 @@ def _is_relevant_file_to_scan(scan_type: str, filename: str) -> bool:
89
102
 
90
103
  def _is_file_relevant_for_sca_scan(filename: str) -> bool:
91
104
  if any(sca_excluded_path in filename for sca_excluded_path in consts.SCA_EXCLUDED_PATHS):
92
- logger.debug("file is irrelevant because it is from node_modules's inner path, %s", {'filename': filename})
105
+ logger.debug(
106
+ 'The file is irrelevant because it is from the inner path of node_modules, %s', {'filename': filename}
107
+ )
93
108
  return False
94
109
 
95
110
  return True
@@ -98,27 +113,39 @@ def _is_file_relevant_for_sca_scan(filename: str) -> bool:
98
113
  def _is_relevant_document_to_scan(scan_type: str, filename: str, content: str) -> bool:
99
114
  if _is_subpath_of_cycode_configuration_folder(filename):
100
115
  logger.debug(
101
- 'document is irrelevant because it is in cycode configuration directory, %s', {'filename': filename}
116
+ 'The document is irrelevant because it is in the Cycode configuration directory, %s',
117
+ {'filename': filename, 'configuration_directory': consts.CYCODE_CONFIGURATION_DIRECTORY},
102
118
  )
103
119
  return False
104
120
 
105
121
  if _is_path_configured_in_exclusions(scan_type, filename):
106
122
  logger.debug(
107
- 'document is irrelevant because the document path is in the ignore paths list, %s', {'filename': filename}
123
+ 'The document is irrelevant because its path is in the ignore paths list, %s', {'filename': filename}
108
124
  )
109
125
  return False
110
126
 
111
127
  if not _is_file_extension_supported(scan_type, filename):
112
- logger.debug('document is irrelevant because the file extension is not supported, %s', {'filename': filename})
128
+ logger.debug(
129
+ 'The document is irrelevant because its extension is not supported, %s',
130
+ {'scan_type': scan_type, 'filename': filename},
131
+ )
113
132
  return False
114
133
 
115
134
  if is_binary_content(content):
116
- logger.debug('document is irrelevant because it is binary, %s', {'filename': filename})
135
+ logger.debug('The document is irrelevant because it is a binary file, %s', {'filename': filename})
117
136
  return False
118
137
 
119
138
  if scan_type != consts.SCA_SCAN_TYPE and _does_document_exceed_max_size_limit(content):
120
- logger.debug('document is irrelevant because its exceeded max size limit, %s', {'filename': filename})
139
+ logger.debug(
140
+ 'The document is irrelevant because it has exceeded the maximum size limit, %s',
141
+ {
142
+ 'max_document_size': consts.FILE_MAX_SIZE_LIMIT_IN_BYTES,
143
+ 'document_size': get_content_size(content),
144
+ 'filename': filename,
145
+ },
146
+ )
121
147
  return False
148
+
122
149
  return True
123
150
 
124
151
 
@@ -74,7 +74,7 @@ def _get_relevant_files(
74
74
  progress_bar.set_section_length(progress_bar_section, progress_bar_section_len)
75
75
 
76
76
  logger.debug(
77
- 'Found all relevant files for scanning %s', {'paths': paths, 'file_to_scan_count': len(relevant_files_to_scan)}
77
+ 'Found all relevant files for scanning, %s', {'paths': paths, 'file_to_scan_count': len(relevant_files_to_scan)}
78
78
  )
79
79
 
80
80
  return relevant_files_to_scan
@@ -17,7 +17,7 @@ def execute_command(command: List[str], file_name: str, command_timeout: int) ->
17
17
  try:
18
18
  dependencies = shell(command, command_timeout)
19
19
  except Exception as e:
20
- logger.debug('Failed to restore dependencies shell comment. %s', {'filename': file_name, 'exception': str(e)})
20
+ logger.debug('Failed to restore dependencies via shell command, %s', {'filename': file_name}, exc_info=e)
21
21
  return None
22
22
 
23
23
  return dependencies
@@ -47,7 +47,7 @@ def add_ecosystem_related_files_if_exists(
47
47
  for doc in documents:
48
48
  ecosystem = get_project_file_ecosystem(doc)
49
49
  if ecosystem is None:
50
- logger.debug('failed to resolve project file ecosystem: %s', doc.path)
50
+ logger.debug('Failed to resolve project file ecosystem: %s', doc.path)
51
51
  continue
52
52
 
53
53
  documents_to_add.extend(get_doc_ecosystem_related_project_files(doc, documents, ecosystem, commit_rev, repo))
@@ -94,20 +94,20 @@ def try_restore_dependencies(
94
94
  if restore_dependencies.is_project(document):
95
95
  restore_dependencies_document = restore_dependencies.restore(document)
96
96
  if restore_dependencies_document is None:
97
- logger.warning('Error occurred while trying to generate dependencies tree. %s', {'filename': document.path})
97
+ logger.warning('Error occurred while trying to generate dependencies tree, %s', {'filename': document.path})
98
98
  return
99
99
 
100
100
  if restore_dependencies_document.content is None:
101
- logger.warning('Error occurred while trying to generate dependencies tree. %s', {'filename': document.path})
101
+ logger.warning('Error occurred while trying to generate dependencies tree, %s', {'filename': document.path})
102
102
  restore_dependencies_document.content = ''
103
103
  else:
104
104
  is_monitor_action = context.obj.get('monitor')
105
105
  project_path = context.params.get('path')
106
106
  manifest_file_path = get_manifest_file_path(document, is_monitor_action, project_path)
107
- logger.debug(f'Succeeded to generate dependencies tree on path: {manifest_file_path}')
107
+ logger.debug('Succeeded to generate dependencies tree on path: %s', manifest_file_path)
108
108
 
109
109
  if restore_dependencies_document.path in documents_to_add:
110
- logger.debug(f'Duplicate document on restore for path: {restore_dependencies_document.path}')
110
+ logger.debug('Duplicate document on restore for path: %s', restore_dependencies_document.path)
111
111
  else:
112
112
  documents_to_add[restore_dependencies_document.path] = restore_dependencies_document
113
113
 
@@ -147,5 +147,5 @@ def perform_pre_scan_documents_actions(
147
147
  context: click.Context, scan_type: str, documents_to_scan: List[Document], is_git_diff: bool = False
148
148
  ) -> None:
149
149
  if scan_type == consts.SCA_SCAN_TYPE and not context.obj.get(consts.SCA_SKIP_RESTORE_DEPENDENCIES_FLAG):
150
- logger.debug('Perform pre scan document add_dependencies_tree_document action')
150
+ logger.debug('Perform pre-scan document add_dependencies_tree_document action')
151
151
  add_dependencies_tree_document(context, documents_to_scan, is_git_diff)
@@ -1,4 +1,4 @@
1
- import time
1
+ import timeit
2
2
  from pathlib import Path
3
3
  from typing import List, Optional
4
4
 
@@ -22,25 +22,26 @@ def zip_documents(scan_type: str, documents: List[Document], zip_file: Optional[
22
22
  if zip_file is None:
23
23
  zip_file = InMemoryZip()
24
24
 
25
- start_zip_creation_time = time.time()
25
+ start_zip_creation_time = timeit.default_timer()
26
26
 
27
27
  for index, document in enumerate(documents):
28
28
  _validate_zip_file_size(scan_type, zip_file.size)
29
29
 
30
30
  logger.debug(
31
- 'adding file to zip, %s', {'index': index, 'filename': document.path, 'unique_id': document.unique_id}
31
+ 'Adding file to ZIP, %s',
32
+ {'index': index, 'filename': document.path, 'unique_id': document.unique_id},
32
33
  )
33
34
  zip_file.append(document.path, document.unique_id, document.content)
34
35
 
35
36
  zip_file.close()
36
37
 
37
- end_zip_creation_time = time.time()
38
+ end_zip_creation_time = timeit.default_timer()
38
39
  zip_creation_time = int(end_zip_creation_time - start_zip_creation_time)
39
- logger.debug('finished to create zip file, %s', {'zip_creation_time': zip_creation_time})
40
+ logger.debug('Finished to create ZIP file, %s', {'zip_creation_time': zip_creation_time})
40
41
 
41
42
  if zip_file.configuration_manager.get_debug_flag():
42
43
  zip_file_path = Path.joinpath(Path.cwd(), f'{scan_type}_scan_{end_zip_creation_time}.zip')
43
- logger.debug('writing zip file to disk, %s', {'zip_file_path': zip_file_path})
44
+ logger.debug('Writing ZIP file to disk, %s', {'zip_file_path': zip_file_path})
44
45
  zip_file.write_on_disk(zip_file_path)
45
46
 
46
47
  return zip_file
@@ -28,13 +28,15 @@ class ConsolePrinter:
28
28
  self.context = context
29
29
  self.scan_type = self.context.obj.get('scan_type')
30
30
  self.output_type = self.context.obj.get('output')
31
-
31
+ self.aggregation_report_url = self.context.obj.get('aggregation_report_url')
32
32
  self._printer_class = self._AVAILABLE_PRINTERS.get(self.output_type)
33
33
  if self._printer_class is None:
34
34
  raise CycodeError(f'"{self.output_type}" output type is not supported.')
35
35
 
36
36
  def print_scan_results(
37
- self, local_scan_results: List['LocalScanResult'], errors: Optional[Dict[str, 'CliError']] = None
37
+ self,
38
+ local_scan_results: List['LocalScanResult'],
39
+ errors: Optional[Dict[str, 'CliError']] = None,
38
40
  ) -> None:
39
41
  printer = self._get_scan_printer()
40
42
  printer.print_scan_results(local_scan_results, errors)