cycode 1.9.5.dev5__tar.gz → 1.9.6.dev2__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.dev2}/PKG-INFO +6 -3
  2. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/README.md +5 -2
  3. cycode-1.9.6.dev2/cycode/__init__.py +1 -0
  4. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/commands/auth/auth_manager.py +11 -11
  5. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/commands/report/sbom/common.py +1 -1
  6. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/commands/scan/code_scanner.py +37 -29
  7. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/commands/scan/pre_receive/pre_receive_command.py +5 -4
  8. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/files_collector/excluder.py +38 -11
  9. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/files_collector/path_documents.py +1 -1
  10. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/files_collector/sca/maven/base_restore_maven_dependencies.py +1 -1
  11. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/files_collector/sca/sca_code_scanner.py +6 -6
  12. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/files_collector/zip_documents.py +7 -6
  13. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/utils/progress_bar.py +11 -6
  14. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/utils/shell_executor.py +2 -2
  15. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cyclient/config.py +18 -9
  16. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cyclient/cycode_client_base.py +8 -2
  17. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cyclient/headers.py +1 -1
  18. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/pyproject.toml +2 -1
  19. cycode-1.9.5.dev5/cycode/__init__.py +0 -1
  20. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/__init__.py +0 -0
  21. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/commands/__init__.py +0 -0
  22. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/commands/auth/__init__.py +0 -0
  23. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/commands/auth/auth_command.py +0 -0
  24. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/commands/configure/__init__.py +0 -0
  25. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/commands/configure/configure_command.py +0 -0
  26. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/commands/ignore/__init__.py +0 -0
  27. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/commands/ignore/ignore_command.py +0 -0
  28. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/commands/main_cli.py +0 -0
  29. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/commands/report/__init__.py +0 -0
  30. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/commands/report/report_command.py +0 -0
  31. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/commands/report/sbom/__init__.py +0 -0
  32. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/commands/report/sbom/path/__init__.py +0 -0
  33. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/commands/report/sbom/path/path_command.py +0 -0
  34. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/commands/report/sbom/repository_url/__init__.py +0 -0
  35. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/commands/report/sbom/repository_url/repository_url_command.py +0 -0
  36. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/commands/report/sbom/sbom_command.py +0 -0
  37. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/commands/report/sbom/sbom_report_file.py +0 -0
  38. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/commands/scan/__init__.py +0 -0
  39. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/commands/scan/commit_history/__init__.py +0 -0
  40. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/commands/scan/commit_history/commit_history_command.py +0 -0
  41. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/commands/scan/path/__init__.py +0 -0
  42. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/commands/scan/path/path_command.py +0 -0
  43. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/commands/scan/pre_commit/__init__.py +0 -0
  44. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/commands/scan/pre_commit/pre_commit_command.py +0 -0
  45. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/commands/scan/pre_receive/__init__.py +0 -0
  46. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/commands/scan/repository/__init__.py +0 -0
  47. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/commands/scan/repository/repository_command.py +0 -0
  48. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/commands/scan/scan_ci/__init__.py +0 -0
  49. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/commands/scan/scan_ci/ci_integrations.py +0 -0
  50. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/commands/scan/scan_ci/scan_ci_command.py +0 -0
  51. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/commands/scan/scan_command.py +0 -0
  52. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/commands/version/__init__.py +0 -0
  53. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/commands/version/version_command.py +0 -0
  54. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/config.py +0 -0
  55. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/config.yaml +0 -0
  56. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/consts.py +0 -0
  57. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/exceptions/__init__.py +0 -0
  58. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/exceptions/custom_exceptions.py +0 -0
  59. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/exceptions/handle_report_sbom_errors.py +0 -0
  60. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/exceptions/handle_scan_errors.py +0 -0
  61. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/files_collector/__init__.py +0 -0
  62. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/files_collector/iac/__init__.py +0 -0
  63. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/files_collector/iac/tf_content_generator.py +0 -0
  64. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/files_collector/models/__init__.py +0 -0
  65. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/files_collector/models/in_memory_zip.py +0 -0
  66. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/files_collector/repository_documents.py +0 -0
  67. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/files_collector/sca/__init__.py +0 -0
  68. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/files_collector/sca/maven/__init__.py +0 -0
  69. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/files_collector/sca/maven/restore_gradle_dependencies.py +0 -0
  70. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/files_collector/sca/maven/restore_maven_dependencies.py +0 -0
  71. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/main.py +0 -0
  72. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/models.py +0 -0
  73. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/printers/__init__.py +0 -0
  74. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/printers/console_printer.py +0 -0
  75. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/printers/json_printer.py +0 -0
  76. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/printers/printer_base.py +0 -0
  77. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/printers/tables/__init__.py +0 -0
  78. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/printers/tables/sca_table_printer.py +0 -0
  79. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/printers/tables/table.py +0 -0
  80. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/printers/tables/table_models.py +0 -0
  81. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/printers/tables/table_printer.py +0 -0
  82. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/printers/tables/table_printer_base.py +0 -0
  83. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/printers/text_printer.py +0 -0
  84. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/user_settings/__init__.py +0 -0
  85. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/user_settings/base_file_manager.py +0 -0
  86. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/user_settings/config_file_manager.py +0 -0
  87. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/user_settings/configuration_manager.py +0 -0
  88. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/user_settings/credentials_manager.py +0 -0
  89. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/user_settings/jwt_creator.py +0 -0
  90. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/utils/__init__.py +0 -0
  91. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/utils/enum_utils.py +0 -0
  92. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/utils/get_api_client.py +0 -0
  93. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/utils/path_utils.py +0 -0
  94. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/utils/scan_batch.py +0 -0
  95. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/utils/scan_utils.py +0 -0
  96. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/utils/string_utils.py +0 -0
  97. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/utils/task_timer.py +0 -0
  98. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/utils/yaml_utils.py +0 -0
  99. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cyclient/__init__.py +0 -0
  100. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cyclient/auth_client.py +0 -0
  101. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cyclient/client_creator.py +0 -0
  102. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cyclient/config.yaml +0 -0
  103. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cyclient/config_dev.py +0 -0
  104. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cyclient/cycode_client.py +0 -0
  105. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cyclient/cycode_dev_based_client.py +0 -0
  106. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cyclient/cycode_token_based_client.py +0 -0
  107. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cyclient/models.py +0 -0
  108. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cyclient/report_client.py +0 -0
  109. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cyclient/scan_client.py +0 -0
  110. {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/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.dev2
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.dev2' # 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(
@@ -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,
@@ -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,7 +307,8 @@ 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
@@ -392,7 +393,7 @@ def scan_commit_range_documents(
392
393
  scan_id = local_scan_result.scan_id
393
394
 
394
395
  logger.debug(
395
- 'Finished scan process, %s',
396
+ 'Processing commit range scan results, %s',
396
397
  {
397
398
  'all_violations_count': detections_count,
398
399
  'relevant_violations_count': relevant_detections_count,
@@ -475,7 +476,7 @@ def perform_scan_async(
475
476
  scan_parameters: dict,
476
477
  ) -> ZippedFileScanResult:
477
478
  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)
479
+ logger.debug('Async scan request has been triggered successfully, %s', {'scan_id': scan_async_result.scan_id})
479
480
 
480
481
  return poll_scan_results(
481
482
  cycode_client,
@@ -492,7 +493,7 @@ def perform_scan_sync(
492
493
  scan_parameters: dict,
493
494
  ) -> ZippedFileScanResult:
494
495
  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)
496
+ logger.debug('Sync scan request has been triggered successfully, %s', {'scan_id': scan_results.id})
496
497
  return ZippedFileScanResult(
497
498
  did_detect=True,
498
499
  detections_per_file=_map_detections_per_file(scan_results.detection_messages),
@@ -512,7 +513,9 @@ def perform_commit_range_scan_async(
512
513
  from_commit_zipped_documents, to_commit_zipped_documents, scan_type, scan_parameters
513
514
  )
514
515
 
515
- logger.debug('scan request has been triggered successfully, scan id: %s', scan_async_result.scan_id)
516
+ logger.debug(
517
+ 'Async commit range scan request has been triggered successfully, %s', {'scan_id': scan_async_result.scan_id}
518
+ )
516
519
  return poll_scan_results(
517
520
  cycode_client, scan_async_result.scan_id, scan_type, scan_parameters.get('report'), timeout
518
521
  )
@@ -552,11 +555,12 @@ def poll_scan_results(
552
555
 
553
556
 
554
557
  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}')
558
+ logger.debug(
559
+ 'Scan update, %s', {'scan_id': scan_details_response.id, 'scan_status': scan_details_response.scan_status}
560
+ )
557
561
 
558
562
  if scan_details_response.message:
559
- logger.debug(f'Scan message: {scan_details_response.message}')
563
+ logger.debug('Scan message: %s', scan_details_response.message)
560
564
 
561
565
 
562
566
  def print_results(
@@ -569,14 +573,16 @@ def print_results(
569
573
  def get_document_detections(
570
574
  scan_result: ZippedFileScanResult, documents_to_scan: List[Document]
571
575
  ) -> List[DocumentDetections]:
572
- logger.debug('Get document detections')
576
+ logger.debug('Getting document detections')
573
577
 
574
578
  document_detections = []
575
579
  for detections_per_file in scan_result.detections_per_file:
576
580
  file_name = get_path_by_os(detections_per_file.file_name)
577
581
  commit_id = detections_per_file.commit_id
578
582
 
579
- logger.debug('Going to find document of violated file, %s', {'file_name': file_name, 'commit_id': commit_id})
583
+ logger.debug(
584
+ 'Going to find the document of the violated file., %s', {'file_name': file_name, 'commit_id': commit_id}
585
+ )
580
586
 
581
587
  document = _get_document_by_file_name(documents_to_scan, file_name, commit_id)
582
588
  document_detections.append(DocumentDetections(document=document, detections=detections_per_file.detections))
@@ -659,10 +665,10 @@ def get_scan_parameters(context: click.Context, paths: Tuple[str]) -> dict:
659
665
  def try_get_git_remote_url(path: str) -> Optional[str]:
660
666
  try:
661
667
  remote_url = Repo(path).remotes[0].config_reader.get('url')
662
- logger.debug(f'Found Git remote URL "{remote_url}" in path "{path}"')
668
+ logger.debug('Found Git remote URL, %s', {'remote_url': remote_url, 'path': path})
663
669
  return remote_url
664
670
  except Exception as e:
665
- logger.debug('Failed to get git remote URL. %s', {'exception_message': str(e)})
671
+ logger.debug('Failed to get Git remote URL', exc_info=e)
666
672
  return None
667
673
 
668
674
 
@@ -719,15 +725,15 @@ def _should_exclude_detection(detection: Detection, exclusions: Dict) -> bool:
719
725
  exclusions_by_value = exclusions.get(consts.EXCLUSIONS_BY_VALUE_SECTION_NAME, [])
720
726
  if _is_detection_sha_configured_in_exclusions(detection, exclusions_by_value):
721
727
  logger.debug(
722
- 'Going to ignore violations because is in the values to ignore list, %s',
723
- {'sha': detection.detection_details.get('sha512', '')},
728
+ 'Going to ignore violations because they are on the values-to-ignore list, %s',
729
+ {'value_sha': detection.detection_details.get('sha512', '')},
724
730
  )
725
731
  return True
726
732
 
727
733
  exclusions_by_sha = exclusions.get(consts.EXCLUSIONS_BY_SHA_SECTION_NAME, [])
728
734
  if _is_detection_sha_configured_in_exclusions(detection, exclusions_by_sha):
729
735
  logger.debug(
730
- 'Going to ignore violations because is in the shas to ignore list, %s',
736
+ 'Going to ignore violations because they are on the SHA ignore list, %s',
731
737
  {'sha': detection.detection_details.get('sha512', '')},
732
738
  )
733
739
  return True
@@ -737,7 +743,7 @@ def _should_exclude_detection(detection: Detection, exclusions: Dict) -> bool:
737
743
  detection_rule = detection.detection_rule_id
738
744
  if detection_rule in exclusions_by_rule:
739
745
  logger.debug(
740
- 'Going to ignore violations because is in the shas to ignore list, %s',
746
+ 'Going to ignore violations because they are on the Rule ID ignore list, %s',
741
747
  {'detection_rule': detection_rule},
742
748
  )
743
749
  return True
@@ -747,7 +753,7 @@ def _should_exclude_detection(detection: Detection, exclusions: Dict) -> bool:
747
753
  package = _get_package_name(detection)
748
754
  if package in exclusions_by_package:
749
755
  logger.debug(
750
- 'Going to ignore violations because is in the packages to ignore list, %s', {'package': package}
756
+ 'Going to ignore violations because they are on the packages-to-ignore list, %s', {'package': package}
751
757
  )
752
758
  return True
753
759
 
@@ -810,7 +816,7 @@ def _report_scan_status(
810
816
 
811
817
  cycode_client.report_scan_status(scan_type, scan_id, scan_status, should_use_scan_service)
812
818
  except Exception as e:
813
- logger.debug('Failed to report scan status, %s', {'exception_message': str(e)})
819
+ logger.debug('Failed to report scan status', exc_info=e)
814
820
 
815
821
 
816
822
  def _generate_unique_id() -> UUID:
@@ -868,7 +874,7 @@ def _try_get_report_url_if_needed(
868
874
  report_url_response = cycode_client.get_scan_report_url(scan_id, scan_type)
869
875
  return report_url_response.report_url
870
876
  except Exception as e:
871
- logger.debug('Failed to get report url: %s', str(e))
877
+ logger.debug('Failed to get report URL', exc_info=e)
872
878
 
873
879
 
874
880
  def wait_for_detections_creation(
@@ -883,16 +889,18 @@ def wait_for_detections_creation(
883
889
  while time.time() < end_polling_time:
884
890
  scan_persisted_detections_count = cycode_client.get_scan_detections_count(scan_type, scan_id)
885
891
  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)'
892
+ 'Excepting %s detections, got %s detections (%s more; %s seconds left)',
893
+ expected_detections_count,
894
+ scan_persisted_detections_count,
895
+ expected_detections_count - scan_persisted_detections_count,
896
+ round(end_polling_time - time.time()),
889
897
  )
890
898
  if scan_persisted_detections_count == expected_detections_count:
891
899
  return
892
900
 
893
901
  time.sleep(consts.DETECTIONS_COUNT_VERIFICATION_WAIT_INTERVAL_IN_SECONDS)
894
902
 
895
- logger.debug(f'{scan_persisted_detections_count} detections has been created')
903
+ logger.debug('%s detections has been created', scan_persisted_detections_count)
896
904
  raise custom_exceptions.ScanAsyncError(
897
905
  f'Failed to wait for detections to be created after {polling_timeout} seconds'
898
906
  )
@@ -905,14 +913,14 @@ def _map_detections_per_file(detections: List[dict]) -> List[DetectionsPerFile]:
905
913
  detection['message'] = detection['correlation_message']
906
914
  file_name = _get_file_name_from_detection(detection)
907
915
  if file_name is None:
908
- logger.debug('file name is missing from detection with id %s', detection.get('id'))
916
+ logger.debug('File name is missing from detection with ID %s', detection.get('id'))
909
917
  continue
910
918
  if detections_per_files.get(file_name) is None:
911
919
  detections_per_files[file_name] = [DetectionSchema().load(detection)]
912
920
  else:
913
921
  detections_per_files[file_name].append(DetectionSchema().load(detection))
914
922
  except Exception as e:
915
- logger.debug('Failed to parse detection: %s', str(e))
923
+ logger.debug('Failed to parse detection', exc_info=e)
916
924
  continue
917
925
 
918
926
  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
@@ -11,8 +11,8 @@ if TYPE_CHECKING:
11
11
  from click._termui_impl import ProgressBar
12
12
  from click.termui import V as ProgressBarValue
13
13
 
14
-
15
- logger = get_logger('progress bar')
14
+ # use LOGGING_LEVEL=DEBUG env var to see debug logs of this module
15
+ logger = get_logger('progress bar', control_level_in_runtime=False)
16
16
 
17
17
 
18
18
  class ProgressBarSection(AutoCountEnum):
@@ -184,7 +184,7 @@ class CompositeProgressBar(BaseProgressBar):
184
184
  self.__exit__(None, None, None)
185
185
 
186
186
  def set_section_length(self, section: 'ProgressBarSection', length: int = 0) -> None:
187
- logger.debug(f'set_section_length: {section} {length}')
187
+ logger.debug('Calling set_section_length, %s', {'section': str(section), 'length': length})
188
188
  self._section_lengths[section] = length
189
189
 
190
190
  if length == 0:
@@ -203,8 +203,11 @@ class CompositeProgressBar(BaseProgressBar):
203
203
  def _increment_section_value(self, section: 'ProgressBarSection', value: int) -> None:
204
204
  self._section_values[section] = self._section_values.get(section, 0) + value
205
205
  logger.debug(
206
- f'_increment_section_value: {section} +{value}. '
207
- f'{self._section_values[section]}/{self._section_lengths[section]}'
206
+ 'Calling _increment_section_value: %s +%s. %s/%s',
207
+ section,
208
+ value,
209
+ self._section_values[section],
210
+ self._section_lengths[section],
208
211
  )
209
212
 
210
213
  def _rerender_progress_bar(self) -> None:
@@ -225,7 +228,9 @@ class CompositeProgressBar(BaseProgressBar):
225
228
  cur_val = self._section_values.get(self._current_section.section, 0)
226
229
  if cur_val >= max_val:
227
230
  next_section = self._progress_bar_sections[self._current_section.section.next()]
228
- logger.debug(f'_update_current_section: {self._current_section.section} -> {next_section.section}')
231
+ logger.debug(
232
+ 'Calling _update_current_section: %s -> %s', self._current_section.section, next_section.section
233
+ )
229
234
 
230
235
  self._current_section = next_section
231
236
  self._current_section_value = 0
@@ -11,7 +11,7 @@ _SUBPROCESS_DEFAULT_TIMEOUT_SEC = 60
11
11
  def shell(
12
12
  command: Union[str, List[str]], timeout: int = _SUBPROCESS_DEFAULT_TIMEOUT_SEC, execute_in_shell: bool = False
13
13
  ) -> Optional[str]:
14
- logger.debug(f'Executing shell command: {command}')
14
+ logger.debug('Executing shell command: %s', command)
15
15
 
16
16
  try:
17
17
  result = subprocess.run(
@@ -24,7 +24,7 @@ def shell(
24
24
 
25
25
  return result.stdout.decode('UTF-8').strip()
26
26
  except subprocess.CalledProcessError as e:
27
- logger.debug(f'Error occurred while running shell command. Exception: {e.stderr}')
27
+ logger.debug('Error occurred while running shell command', exc_info=e)
28
28
  except subprocess.TimeoutExpired as e:
29
29
  raise click.Abort(f'Command "{command}" timed out') from e
30
30
  except Exception as e:
@@ -1,7 +1,7 @@
1
1
  import logging
2
2
  import os
3
3
  import sys
4
- from typing import Optional, Union
4
+ from typing import NamedTuple, Optional, Set, Union
5
5
  from urllib.parse import urlparse
6
6
 
7
7
  from cycode.cli import consts
@@ -42,7 +42,13 @@ DEFAULT_CONFIGURATION = {
42
42
 
43
43
  configuration = dict(DEFAULT_CONFIGURATION, **os.environ)
44
44
 
45
- _CREATED_LOGGERS = set()
45
+
46
+ class CreatedLogger(NamedTuple):
47
+ logger: logging.Logger
48
+ control_level_in_runtime: bool
49
+
50
+
51
+ _CREATED_LOGGERS: Set[CreatedLogger] = set()
46
52
 
47
53
 
48
54
  def get_logger_level() -> Optional[Union[int, str]]:
@@ -50,18 +56,19 @@ def get_logger_level() -> Optional[Union[int, str]]:
50
56
  return logging.getLevelName(config_level)
51
57
 
52
58
 
53
- def get_logger(logger_name: Optional[str] = None) -> logging.Logger:
59
+ def get_logger(logger_name: Optional[str] = None, control_level_in_runtime: bool = True) -> logging.Logger:
54
60
  new_logger = logging.getLogger(logger_name)
55
61
  new_logger.setLevel(get_logger_level())
56
62
 
57
- _CREATED_LOGGERS.add(new_logger)
63
+ _CREATED_LOGGERS.add(CreatedLogger(logger=new_logger, control_level_in_runtime=control_level_in_runtime))
58
64
 
59
65
  return new_logger
60
66
 
61
67
 
62
68
  def set_logging_level(level: int) -> None:
63
69
  for created_logger in _CREATED_LOGGERS:
64
- created_logger.setLevel(level)
70
+ if created_logger.control_level_in_runtime:
71
+ created_logger.logger.setLevel(level)
65
72
 
66
73
 
67
74
  def get_val_as_string(key: str) -> str:
@@ -83,10 +90,9 @@ def get_val_as_int(key: str) -> Optional[int]:
83
90
 
84
91
  def is_valid_url(url: str) -> bool:
85
92
  try:
86
- urlparse(url)
87
- return True
88
- except ValueError as e:
89
- logger.warning(f'Invalid cycode api url: {url}, using default value', e)
93
+ parsed_url = urlparse(url)
94
+ return all([parsed_url.scheme, parsed_url.netloc])
95
+ except ValueError:
90
96
  return False
91
97
 
92
98
 
@@ -95,6 +101,9 @@ configuration_manager = ConfigurationManager()
95
101
 
96
102
  cycode_api_url = configuration_manager.get_cycode_api_url()
97
103
  if not is_valid_url(cycode_api_url):
104
+ logger.warning(
105
+ 'Invalid Cycode API URL: %s, using default value (%s)', cycode_api_url, consts.DEFAULT_CYCODE_API_URL
106
+ )
98
107
  cycode_api_url = consts.DEFAULT_CYCODE_API_URL
99
108
 
100
109
  timeout = get_val_as_int(consts.CYCODE_CLI_REQUEST_TIMEOUT_ENV_VAR_NAME)
@@ -44,7 +44,10 @@ class CycodeClientBase:
44
44
  **kwargs,
45
45
  ) -> Response:
46
46
  url = self.build_full_url(self.api_url, endpoint)
47
- logger.debug(f'Executing {method.upper()} request to {url}')
47
+ logger.debug(
48
+ 'Executing request, %s',
49
+ {'method': method.upper(), 'url': url},
50
+ )
48
51
 
49
52
  timeout = self.timeout
50
53
  if 'timeout' in kwargs:
@@ -56,7 +59,10 @@ class CycodeClientBase:
56
59
  response = request(method=method, url=url, timeout=timeout, headers=headers, **kwargs)
57
60
 
58
61
  content = 'HIDDEN' if hide_response_content_log else response.text
59
- logger.debug(f'Response {response.status_code} from {url}. Content: {content}')
62
+ logger.debug(
63
+ 'Receiving response, %s',
64
+ {'status_code': response.status_code, 'url': url, 'content': content},
65
+ )
60
66
 
61
67
  response.raise_for_status()
62
68
  return response
@@ -38,7 +38,7 @@ class _CorrelationId:
38
38
  if self._id is None:
39
39
  # example: 16fd2706-8baf-433b-82eb-8c7fada847da
40
40
  self._id = str(uuid4())
41
- logger.debug(f'Correlation ID: {self._id}')
41
+ logger.debug('Correlation ID: %s', self._id)
42
42
 
43
43
  return self._id
44
44
 
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "cycode"
3
- version = "1.9.5.dev5" # DON'T TOUCH. Placeholder. Will be filled automatically on poetry build from Git Tag
3
+ version = "1.9.6.dev2" # DON'T TOUCH. Placeholder. Will be filled automatically on poetry build from Git Tag
4
4
  description = "Boost security in your dev lifecycle via SAST, SCA, Secrets & IaC scanning."
5
5
  keywords=["secret-scan", "cycode", "devops", "token", "secret", "security", "cycode", "code"]
6
6
  authors = ["Cycode <support@cycode.com>"]
@@ -96,6 +96,7 @@ extend-select = [
96
96
  "TCH",
97
97
  "TID",
98
98
  "YTT",
99
+ "G",
99
100
  ]
100
101
  line-length = 120
101
102
  target-version = "py37"
@@ -1 +0,0 @@
1
- __version__ = '1.9.5.dev5' # DON'T TOUCH. Placeholder. Will be filled automatically on poetry build from Git Tag