datadog-ci 1.38.1 → 1.39.0

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 (47) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +27 -2
  3. data/lib/datadog/ci/cli/cli.rb +7 -11
  4. data/lib/datadog/ci/cli/command/exec.rb +1 -6
  5. data/lib/datadog/ci/code_coverage/component.rb +7 -0
  6. data/lib/datadog/ci/configuration/components.rb +46 -94
  7. data/lib/datadog/ci/configuration/settings.rb +45 -2
  8. data/lib/datadog/ci/configuration/tracing_compatibility.rb +41 -0
  9. data/lib/datadog/ci/contrib/instrumentation.rb +4 -0
  10. data/lib/datadog/ci/contrib/knapsack/runner.rb +16 -12
  11. data/lib/datadog/ci/contrib/minitest/test.rb +18 -14
  12. data/lib/datadog/ci/contrib/rspec/example.rb +2 -2
  13. data/lib/datadog/ci/ext/settings.rb +3 -0
  14. data/lib/datadog/ci/ext/telemetry.rb +3 -0
  15. data/lib/datadog/ci/logs/component.rb +11 -0
  16. data/lib/datadog/ci/remote/component.rb +15 -0
  17. data/lib/datadog/ci/remote/null_component.rb +17 -0
  18. data/lib/datadog/ci/remote/slow_test_retries.rb +43 -0
  19. data/lib/datadog/ci/test.rb +3 -3
  20. data/lib/datadog/ci/test_impact_analysis/component.rb +18 -9
  21. data/lib/datadog/ci/test_impact_analysis/null_component.rb +30 -7
  22. data/lib/datadog/ci/test_impact_analysis/skippable.rb +0 -6
  23. data/lib/datadog/ci/test_impact_analysis/telemetry.rb +0 -9
  24. data/lib/datadog/ci/test_management/component.rb +5 -0
  25. data/lib/datadog/ci/test_management/null_component.rb +17 -0
  26. data/lib/datadog/ci/test_retries/component.rb +11 -2
  27. data/lib/datadog/ci/test_retries/driver/retry_failed_dynamic.rb +64 -0
  28. data/lib/datadog/ci/test_retries/null_component.rb +1 -1
  29. data/lib/datadog/ci/test_retries/strategy/retry_failed.rb +17 -2
  30. data/lib/datadog/ci/test_tracing/component.rb +18 -31
  31. data/lib/datadog/ci/test_tracing/context.rb +1 -6
  32. data/lib/datadog/ci/test_tracing/null_component.rb +27 -6
  33. data/lib/datadog/ci/test_tracing/serializers/test_v2.rb +16 -4
  34. data/lib/datadog/ci/test_tracing/transport.rb +3 -5
  35. data/lib/datadog/ci/transport/api/builder.rb +12 -10
  36. data/lib/datadog/ci/utils/telemetry.rb +20 -0
  37. data/lib/datadog/ci/version.rb +2 -2
  38. metadata +3 -10
  39. data/lib/datadog/ci/cli/command/base.rb +0 -59
  40. data/lib/datadog/ci/cli/command/skippable_tests_percentage.rb +0 -26
  41. data/lib/datadog/ci/cli/command/skippable_tests_percentage_estimate.rb +0 -21
  42. data/lib/datadog/ci/test_impact_analysis/skippable_percentage/base.rb +0 -55
  43. data/lib/datadog/ci/test_impact_analysis/skippable_percentage/calculator.rb +0 -84
  44. data/lib/datadog/ci/test_impact_analysis/skippable_percentage/estimator.rb +0 -63
  45. data/lib/datadog/ci/test_tracing/flush.rb +0 -40
  46. data/lib/datadog/ci/test_tracing/serializers/factories/test_level.rb +0 -30
  47. data/lib/datadog/ci/test_tracing/serializers/test_v1.rb +0 -46
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f4dd154e6dcabba4e7cdaf9a886fef6cc7c75087848e6e8fadadadfede53875c
4
- data.tar.gz: a668428a02e681d00cd9c2b7780d5661af2ec743f6f6c0ce1f8396dec634224b
3
+ metadata.gz: 18d2efca66b50be67262fdc2ea7adda5a8c0c90a05b6753c441a9dd229372dfe
4
+ data.tar.gz: 80cb89011890b2617933cac62889e6b18979e8a97a34cfb5298aea43b1afa34b
5
5
  SHA512:
6
- metadata.gz: cb58faace75e6406b996c68f936d5ccbceed04ca3b651c8d747c208c127812dbeb73804e663cae19e1185238da2a2a98469a861ff54dceb7ec094c8d90ea9067
7
- data.tar.gz: 2ab27ce6a1522e135d96ccabdb000dcb45acf7d38035790cb83daeea928b2f97c7c8ae092c638da8759d97c550a6ddb3d131e2232db120c65f58bc7c5aad001c
6
+ metadata.gz: d39ff56e9a2fb16615bf40c58621b6c3e9a7197c6c4e63f9568866afe162a4d9bd65778243b41b5e0a3d3127b58bc91dd5bcb26205c215e95c56f4c9c3e4f446
7
+ data.tar.gz: c3220f31a0f5aabbca8eb905800ed902ae68726567800cf40de2cee33651e7f58c1e72763239a498cc3d44270a13d81698a7172d2e4b3f602d36c6119adf08bb
data/CHANGELOG.md CHANGED
@@ -1,5 +1,24 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [1.39.0] - 2026-09-21
4
+
5
+ ### Added
6
+
7
+ * Dynamic retries for failed tests ([#615][])
8
+
9
+ ### Changed
10
+
11
+ * Make setup and teardown tracing opt-in ([#617][])
12
+
13
+ ### Fixed
14
+
15
+ * Finalize interrupted Knapsack test runs ([#619][])
16
+
17
+ ### Removed
18
+
19
+ * Remove skippable percentage CLI commands ([#612][])
20
+ * Remove legacy Datadog Agent support (older than 7.40.0) ([#610][])
21
+
3
22
  ## [1.38.1] - 2026-09-07
4
23
 
5
24
  ### Fixed
@@ -704,7 +723,8 @@ Currently test suite level visibility is not used by our instrumentation: it wil
704
723
 
705
724
  - Ruby versions < 2.7 no longer supported ([#8][])
706
725
 
707
- [Unreleased]: https://github.com/DataDog/datadog-ci-rb/compare/v1.38.1...main
726
+ [Unreleased]: https://github.com/DataDog/datadog-ci-rb/compare/v1.39.0...main
727
+ [1.39.0]: https://github.com/DataDog/datadog-ci-rb/compare/v1.38.1...v1.39.0
708
728
  [1.38.1]: https://github.com/DataDog/datadog-ci-rb/compare/v1.38.0...v1.38.1
709
729
  [1.38.0]: https://github.com/DataDog/datadog-ci-rb/compare/v1.37.0...v1.38.0
710
730
  [1.37.0]: https://github.com/DataDog/datadog-ci-rb/compare/v1.36.1...v1.37.0
@@ -997,4 +1017,9 @@ Currently test suite level visibility is not used by our instrumentation: it wil
997
1017
  [#593]: https://github.com/DataDog/datadog-ci-rb/issues/593
998
1018
  [#594]: https://github.com/DataDog/datadog-ci-rb/issues/594
999
1019
  [#595]: https://github.com/DataDog/datadog-ci-rb/issues/595
1000
- [#606]: https://github.com/DataDog/datadog-ci-rb/issues/606
1020
+ [#606]: https://github.com/DataDog/datadog-ci-rb/issues/606
1021
+ [#610]: https://github.com/DataDog/datadog-ci-rb/issues/610
1022
+ [#612]: https://github.com/DataDog/datadog-ci-rb/issues/612
1023
+ [#615]: https://github.com/DataDog/datadog-ci-rb/issues/615
1024
+ [#617]: https://github.com/DataDog/datadog-ci-rb/issues/617
1025
+ [#619]: https://github.com/DataDog/datadog-ci-rb/issues/619
@@ -1,25 +1,21 @@
1
- require "datadog"
2
- require "datadog/ci"
3
-
4
1
  require_relative "command/exec"
5
- require_relative "command/skippable_tests_percentage"
6
- require_relative "command/skippable_tests_percentage_estimate"
7
2
 
8
3
  module Datadog
9
4
  module CI
10
5
  module CLI
6
+ SKIPPABLE_PERCENTAGE_REMOVAL_MESSAGE =
7
+ "Skippable percentage calculation is no longer available in ddcirb. " \
8
+ "This functionality has moved to ddtest: https://github.com/DataDog/ddtest"
9
+
11
10
  def self.exec(action, args = [])
12
11
  case action
13
12
  when "exec"
14
13
  Command::Exec.new(args).exec
15
- when "skipped-tests", "skippable-tests"
16
- Command::SkippableTestsPercentage.new.exec
17
- when "skipped-tests-estimate", "skippable-tests-estimate"
18
- Command::SkippableTestsPercentageEstimate.new.exec
14
+ when "skipped-tests", "skippable-tests", "skipped-tests-estimate", "skippable-tests-estimate"
15
+ warn(SKIPPABLE_PERCENTAGE_REMOVAL_MESSAGE)
16
+ Kernel.exit(1)
19
17
  else
20
18
  puts("Usage: bundle exec ddcirb [command] [options]. Available commands:")
21
- puts(" skippable-tests - calculates the exact percentage of skipped tests and prints it to stdout or file")
22
- puts(" skippable-tests-estimate - estimates the percentage of skipped tests and prints it to stdout or file")
23
19
  puts(" exec YOUR_TEST_COMMAND - automatically instruments your test command with Datadog and executes it")
24
20
  end
25
21
  end
@@ -1,14 +1,9 @@
1
- require_relative "base"
2
- require_relative "../../test_impact_analysis/skippable_percentage/estimator"
3
-
4
1
  module Datadog
5
2
  module CI
6
3
  module CLI
7
4
  module Command
8
- class Exec < Base
5
+ class Exec
9
6
  def initialize(args)
10
- super()
11
-
12
7
  @args = args
13
8
  end
14
9
 
@@ -2,6 +2,7 @@
2
2
 
3
3
  require_relative "../ext/environment"
4
4
  require_relative "../ext/settings"
5
+ require_relative "null_component"
5
6
  require_relative "transport"
6
7
 
7
8
  module Datadog
@@ -15,6 +16,12 @@ module Datadog
15
16
 
16
17
  attr_reader :enabled
17
18
 
19
+ def self.build(enabled:, api:, discard_traces:, flags:)
20
+ return NullComponent.new if api.nil? || discard_traces
21
+
22
+ new(enabled: enabled, transport: Transport.new(api: api), flags: flags)
23
+ end
24
+
18
25
  def initialize(enabled:, transport:, flags:)
19
26
  @enabled = enabled
20
27
  @transport = transport
@@ -2,44 +2,33 @@
2
2
 
3
3
  require "datadog/core/telemetry/ext"
4
4
 
5
+ require_relative "tracing_compatibility"
5
6
  require_relative "../ext/settings"
6
7
  require_relative "../code_coverage/component"
7
8
  require_relative "../code_coverage/null_component"
8
- require_relative "../code_coverage/transport"
9
9
  require_relative "../git/tree_uploader"
10
10
  require_relative "../impacted_tests_detection/component"
11
11
  require_relative "../impacted_tests_detection/null_component"
12
12
  require_relative "../logs/component"
13
- require_relative "../logs/transport"
14
13
  require_relative "../remote/null_component"
15
14
  require_relative "../remote/component"
16
- require_relative "../remote/library_settings_client"
17
15
  require_relative "../test_management/component"
18
16
  require_relative "../test_management/null_component"
19
- require_relative "../test_management/tests_properties"
20
17
  require_relative "../test_optimization_cache/component"
21
18
  require_relative "../test_optimization_cache/null_component"
22
19
  require_relative "../test_impact_analysis/null_component"
23
20
  require_relative "../test_impact_analysis/component"
24
- require_relative "../test_impact_analysis/coverage/transport"
25
21
  require_relative "../test_retries/component"
26
22
  require_relative "../test_retries/null_component"
27
23
  require_relative "../test_discovery/component"
28
24
  require_relative "../test_discovery/null_component"
29
25
  require_relative "../test_tracing/component"
30
- require_relative "../test_tracing/flush"
31
- require_relative "../test_tracing/known_tests"
32
26
  require_relative "../test_tracing/null_component"
33
- require_relative "../test_tracing/serializers/factories/test_level"
34
- require_relative "../test_tracing/serializers/factories/test_suite_level"
35
- require_relative "../test_tracing/null_transport"
36
- require_relative "../test_tracing/transport"
37
27
  require_relative "../transport/adapters/telemetry_webmock_safe_adapter"
38
28
  require_relative "../transport/api/builder"
39
29
  require_relative "../utils/parsing"
40
30
  require_relative "../utils/runtime_tags_overrides"
41
31
  require_relative "../utils/test_run"
42
- require_relative "../async_writer"
43
32
  require_relative "../worker"
44
33
 
45
34
  module Datadog
@@ -100,7 +89,7 @@ module Datadog
100
89
  # Builds test visibility API layer in agentless or EvP proxy mode
101
90
  test_visibility_api = build_test_visibility_api(settings)
102
91
  # bail out early if api is misconfigured
103
- return unless settings.ci.enabled
92
+ return unless settings.ci.enabled && test_visibility_api
104
93
 
105
94
  # Configure datadog gem for test visibility mode
106
95
  configure_telemetry(settings)
@@ -138,19 +127,27 @@ module Datadog
138
127
  # Activate underlying tracing test mode with async worker
139
128
  settings.tracing.test_mode.enabled = true
140
129
  settings.tracing.test_mode.async = true
141
- settings.tracing.test_mode.trace_flush = settings.ci.trace_flush || CI::TestTracing::Flush::Partial.new
130
+ settings.tracing.test_mode.trace_flush =
131
+ settings.ci.trace_flush || TracingCompatibility::Flush::Partial.new
142
132
 
143
133
  trace_writer_options = settings.ci.writer_options
144
134
  trace_writer_options[:shutdown_timeout] = 60
145
135
  trace_writer_options[:buffer_size] = 10_000
146
- tracing_transport = build_tracing_transport(settings, test_visibility_api)
136
+ tracing_transport = TestTracing::Component.build_transport(
137
+ api: test_visibility_api,
138
+ discard_traces: settings.ci.discard_traces,
139
+ dd_env: settings.env
140
+ )
147
141
  trace_writer_options[:transport] = tracing_transport if tracing_transport
148
142
 
149
143
  settings.tracing.test_mode.writer_options = trace_writer_options
150
144
 
151
145
  @git_tree_upload_worker = build_git_upload_worker(settings, test_visibility_api)
152
- @ci_remote = Remote::Component.new(
153
- library_settings_client: build_library_settings_client(settings, test_visibility_api),
146
+ @ci_remote = Remote::Component.build(
147
+ api: test_visibility_api,
148
+ dd_env: settings.env,
149
+ test_skipping_mode: settings.ci.tia_test_skipping_mode,
150
+ config_tags: custom_configuration(settings),
154
151
  test_discovery_enabled: settings.ci.test_discovery_enabled
155
152
  )
156
153
  @test_retries = TestRetries::Component.new(
@@ -159,22 +156,26 @@ module Datadog
159
156
  retry_failed_tests_total_limit: settings.ci.retry_failed_tests_total_limit,
160
157
  retry_new_tests_enabled: settings.ci.retry_new_tests_enabled,
161
158
  retry_flaky_fixed_tests_enabled: settings.ci.test_management_enabled,
162
- retry_flaky_fixed_tests_max_attempts: settings.ci.test_management_attempt_to_fix_retries_count
159
+ retry_flaky_fixed_tests_max_attempts: settings.ci.test_management_attempt_to_fix_retries_count,
160
+ dynamic_atr_enabled: settings.ci.dynamic_atr_enabled,
161
+ dynamic_atr_buckets: settings.ci.dynamic_atr_buckets
163
162
  )
164
163
 
165
- @test_management = TestManagement::Component.new(
164
+ @test_management = TestManagement::Component.build(
166
165
  enabled: settings.ci.test_management_enabled,
167
- tests_properties_client: TestManagement::TestsProperties.new(api: test_visibility_api)
166
+ api: test_visibility_api
168
167
  )
169
168
 
170
169
  # @type ivar @test_impact_analysis: Datadog::CI::TestImpactAnalysis::Component
171
170
  @test_impact_analysis = build_test_impact_analysis(settings, test_visibility_api)
172
- @test_tracing = TestTracing::Component.new(
173
- test_suite_level_visibility_enabled: !settings.ci.force_test_level_visibility,
171
+ @test_tracing = TestTracing::Component.build(
172
+ api: test_visibility_api,
173
+ dd_env: settings.env,
174
+ config_tags: custom_configuration(settings),
174
175
  logical_test_session_name: settings.ci.test_session_name,
175
- known_tests_client: build_known_tests_client(settings, test_visibility_api),
176
176
  runtime_tags_overrides: Utils::RuntimeTagsOverrides.parse(settings.ci.runtime_tags_overrides),
177
- context_service_uri: settings.ci.test_visibility_drb_server_uri
177
+ context_service_uri: settings.ci.test_visibility_drb_server_uri,
178
+ trace_setup_teardown_enabled: settings.ci.trace_setup_teardown_enabled
178
179
  )
179
180
 
180
181
  @agentless_logs_submission = build_agentless_logs_component(settings, test_visibility_api)
@@ -209,12 +210,12 @@ module Datadog
209
210
  settings.ci.itr_test_impact_analysis_use_allocation_tracing = false
210
211
  end
211
212
 
212
- TestImpactAnalysis::Component.new(
213
+ TestImpactAnalysis::Component.build(
213
214
  api: test_visibility_api,
215
+ discard_traces: settings.ci.discard_traces,
214
216
  dd_env: settings.env,
215
217
  config_tags: custom_configuration(settings),
216
218
  test_skipping_mode: settings.ci.tia_test_skipping_mode,
217
- coverage_writer: build_coverage_writer(settings, test_visibility_api),
218
219
  enabled: settings.ci.enabled && settings.ci.itr_enabled,
219
220
  bundle_location: settings.ci.itr_code_coverage_excluded_bundle_path,
220
221
  use_single_threaded_coverage: settings.ci.itr_code_coverage_use_single_threaded_mode,
@@ -243,45 +244,27 @@ module Datadog
243
244
  else
244
245
  Datadog.logger.debug("Test Optimization configured to use agent transport via EVP proxy")
245
246
 
246
- api = Transport::Api::Builder.build_evp_proxy_api(settings)
247
+ api, agent_available = Transport::Api::Builder.build_evp_proxy_api(settings)
247
248
  if api.nil?
248
- Datadog.logger.debug(
249
- "Old agent version detected, no evp_proxy support. Forcing test level visibility mode"
250
- )
251
-
252
- # only legacy APM protocol is supported, so no test suite level visibility
253
- settings.ci.force_test_level_visibility = true
249
+ if agent_available
250
+ Datadog.logger.error(
251
+ "Test Optimization cannot use the configured Datadog Agent because it does not support EVP proxy. " \
252
+ "Disabling Test Optimization. Please upgrade the Datadog Agent."
253
+ )
254
+ else
255
+ Datadog.logger.error(
256
+ "Test Optimization cannot connect to the Datadog Agent. " \
257
+ "Disabling Test Optimization. Please ensure the Agent is running and configured to accept traces."
258
+ )
259
+ end
254
260
 
255
- # ITR is not supported with APM protocol
256
- settings.ci.itr_enabled = false
261
+ settings.ci.enabled = false
257
262
  end
258
263
  end
259
264
 
260
265
  api
261
266
  end
262
267
 
263
- def build_tracing_transport(settings, api)
264
- # NullTransport ignores traces
265
- return TestTracing::NullTransport.new if settings.ci.discard_traces
266
- # nil means that default legacy APM transport will be used (only for very old Datadog Agent versions)
267
- return nil if api.nil?
268
-
269
- TestTracing::Transport.new(
270
- api: api,
271
- serializers_factory: serializers_factory(settings),
272
- dd_env: settings.env
273
- )
274
- end
275
-
276
- def build_coverage_writer(settings, api)
277
- # nil means that coverage event will be ignored
278
- return nil if api.nil? || settings.ci.discard_traces
279
-
280
- AsyncWriter.new(
281
- transport: TestImpactAnalysis::Coverage::Transport.new(api: api)
282
- )
283
- end
284
-
285
268
  def build_git_upload_worker(settings, api)
286
269
  if settings.ci.git_metadata_upload_enabled
287
270
  git_tree_uploader = Git::TreeUploader.new(api: api, force_unshallow: settings.ci.impacted_tests_detection_enabled)
@@ -293,29 +276,11 @@ module Datadog
293
276
  end
294
277
  end
295
278
 
296
- def build_library_settings_client(settings, api)
297
- Remote::LibrarySettingsClient.new(
298
- api: api,
299
- dd_env: settings.env,
300
- test_skipping_mode: settings.ci.tia_test_skipping_mode,
301
- config_tags: custom_configuration(settings)
302
- )
303
- end
304
-
305
- def build_known_tests_client(settings, api)
306
- TestTracing::KnownTests.new(
307
- api: api,
308
- dd_env: settings.env,
309
- config_tags: custom_configuration(settings)
310
- )
311
- end
312
-
313
279
  def build_code_coverage(settings, api)
314
- return CodeCoverage::NullComponent.new if api.nil? || settings.ci.discard_traces
315
-
316
- CodeCoverage::Component.new(
280
+ CodeCoverage::Component.build(
317
281
  enabled: settings.ci.code_coverage_report_upload_enabled,
318
- transport: CodeCoverage::Transport.new(api: api),
282
+ api: api,
283
+ discard_traces: settings.ci.discard_traces,
319
284
  flags: settings.ci.code_coverage_flags
320
285
  )
321
286
  end
@@ -331,32 +296,19 @@ module Datadog
331
296
  settings.ci.agentless_logs_submission_enabled = false
332
297
  end
333
298
 
334
- Logs::Component.new(
299
+ Logs::Component.build(
335
300
  enabled: settings.ci.agentless_logs_submission_enabled,
336
- writer: build_logs_writer(settings, api)
301
+ api: api,
302
+ discard_traces: settings.ci.discard_traces
337
303
  )
338
304
  end
339
305
 
340
- def build_logs_writer(settings, api)
341
- return nil if api.nil? || settings.ci.discard_traces
342
-
343
- AsyncWriter.new(transport: Logs::Transport.new(api: api), options: {buffer_size: 1024})
344
- end
345
-
346
306
  # fetch custom tags provided by the user in DD_TAGS env var
347
307
  # with prefix test.configuration.
348
308
  def custom_configuration(settings)
349
309
  @custom_configuration ||= Utils::TestRun.custom_configuration(settings.tags)
350
310
  end
351
311
 
352
- def serializers_factory(settings)
353
- if settings.ci.force_test_level_visibility
354
- TestTracing::Serializers::Factories::TestLevel
355
- else
356
- TestTracing::Serializers::Factories::TestSuiteLevel
357
- end
358
- end
359
-
360
312
  def check_dd_site(settings)
361
313
  return if settings.site.nil?
362
314
  return if Ext::Settings::DD_SITE_ALLOWLIST.include?(settings.site)
@@ -58,6 +58,13 @@ module Datadog
58
58
  o.type :bool
59
59
  o.env CI::Ext::Settings::ENV_FORCE_TEST_LEVEL_VISIBILITY
60
60
  o.default false
61
+ o.after_set do |value|
62
+ if value
63
+ Datadog::Core.log_deprecation do
64
+ "The force_test_level_visibility setting has no effect because test-level visibility is no longer supported."
65
+ end
66
+ end
67
+ end
61
68
  end
62
69
 
63
70
  option :experimental_test_suite_level_visibility_enabled do |o|
@@ -68,13 +75,18 @@ module Datadog
68
75
  if value
69
76
  Datadog::Core.log_deprecation do
70
77
  "The experimental_test_suite_level_visibility_enabled setting has no effect and will be removed in 2.0. " \
71
- "Test suite level visibility is now enabled by default. " \
72
- "If you want to disable test suite level visibility set configuration.ci.force_test_level_visibility = true."
78
+ "Test suite level visibility is always enabled."
73
79
  end
74
80
  end
75
81
  end
76
82
  end
77
83
 
84
+ option :trace_setup_teardown_enabled do |o|
85
+ o.type :bool
86
+ o.env CI::Ext::Settings::ENV_TRACE_SETUP_TEARDOWN_ENABLED
87
+ o.default false
88
+ end
89
+
78
90
  option :itr_enabled do |o|
79
91
  o.type :bool
80
92
  o.env CI::Ext::Settings::ENV_ITR_ENABLED
@@ -140,6 +152,37 @@ module Datadog
140
152
  o.default true
141
153
  end
142
154
 
155
+ option :dynamic_atr_enabled do |o|
156
+ o.type :bool
157
+ o.env CI::Ext::Settings::ENV_DYNAMIC_ATR_ENABLED
158
+ o.default false
159
+ end
160
+
161
+ option :dynamic_atr_buckets do |o|
162
+ o.type :array, nilable: true
163
+ o.env CI::Ext::Settings::ENV_DYNAMIC_ATR_BUCKETS
164
+ o.setter do |values|
165
+ if values.nil? || values.empty?
166
+ nil
167
+ else
168
+ buckets = values.map do |value|
169
+ normalized = value.to_s.strip
170
+ normalized.to_i if normalized.match?(/\A\d+\z/)
171
+ end
172
+
173
+ if buckets.length == 5 && buckets.all? { |value| value&.between?(1, 20) }
174
+ buckets
175
+ else
176
+ Datadog.logger.warn(
177
+ "Invalid #{CI::Ext::Settings::ENV_DYNAMIC_ATR_BUCKETS} value '#{values.join(",")}'; " \
178
+ "expected five comma-separated integers in [1, 20]"
179
+ )
180
+ nil
181
+ end
182
+ end
183
+ end
184
+ end
185
+
143
186
  option :test_management_enabled do |o|
144
187
  o.type :bool
145
188
  o.env CI::Ext::Settings::ENV_TEST_MANAGEMENT_ENABLED
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "datadog/tracing/metadata/ext"
4
+ require "datadog/tracing/flush"
5
+
6
+ module Datadog
7
+ module CI
8
+ module Configuration
9
+ # Compatibility layer between Test Optimization and Datadog tracing.
10
+ module TracingCompatibility
11
+ module Flush
12
+ # Adds Test Optimization metadata required by the trace intake.
13
+ module Tagging
14
+ def get_trace(trace_op)
15
+ trace = trace_op.flush!
16
+
17
+ trace.spans.each do |span|
18
+ span.set_tag(
19
+ Tracing::Metadata::Ext::Distributed::TAG_ORIGIN,
20
+ trace.origin
21
+ )
22
+ end
23
+
24
+ trace
25
+ end
26
+ end
27
+
28
+ # Consumes only completed traces (where all spans have finished).
29
+ class Finished < Tracing::Flush::Finished
30
+ prepend Tagging
31
+ end
32
+
33
+ # Flushes partial traces so large test sessions do not remain in memory.
34
+ class Partial < Tracing::Flush::Partial
35
+ prepend Tagging
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -49,6 +49,10 @@ module Datadog
49
49
  next unless integration.loaded?
50
50
 
51
51
  auto_configure_datadog
52
+ unless Datadog.configuration.ci.enabled
53
+ tp.disable
54
+ break
55
+ end
52
56
 
53
57
  Datadog.logger.debug("#{integration.class} is loaded")
54
58
  patch_integration(integration)
@@ -31,24 +31,28 @@ module Datadog
31
31
  # @type var test_module: Datadog::CI::TestModule?
32
32
  test_module = test_tracing_component.start_test_module(CI::Contrib::RSpec::Ext::FRAMEWORK)
33
33
 
34
- result = super
35
- return result unless test_module && test_session
34
+ return super unless test_module && test_session
36
35
 
37
- if result != 0
38
- test_module.failed!
39
- test_session.failed!
40
- else
41
- test_module.passed!
42
- test_session.passed!
36
+ result = nil
37
+ begin
38
+ result = super
39
+ ensure
40
+ [test_module, test_session].each do |span|
41
+ _dd_cleanup { (result == 0) ? span.passed! : span.failed! }
42
+ end
43
+ _dd_cleanup { test_module.finish }
44
+ _dd_cleanup { test_session.finish }
43
45
  end
44
- test_module.finish
45
- test_session.finish
46
-
47
- result
48
46
  end
49
47
 
50
48
  private
51
49
 
50
+ def _dd_cleanup
51
+ yield
52
+ rescue => error
53
+ Datadog.logger.warn("Knapsack cleanup failed: #{error.class}: #{error.message}")
54
+ end
55
+
52
56
  def datadog_integration
53
57
  CI::Contrib::Instrumentation.fetch_integration(:rspec)
54
58
  end
@@ -33,24 +33,30 @@ module Datadog
33
33
 
34
34
  module InstanceMethods
35
35
  def run
36
- return super unless datadog_configuration[:enabled]
36
+ return run_without_datadog_reentry if @_dd_run_in_progress
37
37
 
38
- return run_without_datadog_reentry if datadog_run_reentered?
38
+ @_dd_run_in_progress = true
39
+ begin
40
+ return super unless Datadog.configuration.ci.enabled
41
+ return super unless datadog_configuration[:enabled]
39
42
 
40
- test_suite = start_datadog_test_suite_if_parallel
41
- if test_suite&.should_skip?
42
- return skip_datadog_suite(test_suite)
43
- end
43
+ test_suite = start_datadog_test_suite_if_parallel
44
+ if test_suite&.should_skip?
45
+ return skip_datadog_suite(test_suite)
46
+ end
44
47
 
45
- test_span = start_datadog_test
46
- return skip_datadog_test(test_span) if test_span&.should_skip?
48
+ test_span = start_datadog_test
49
+ return skip_datadog_test(test_span) if test_span&.should_skip?
47
50
 
48
- super
51
+ super
52
+ ensure
53
+ @_dd_run_in_progress = false
54
+ end
49
55
  end
50
56
 
51
57
  def before_setup
52
58
  test_span = _dd_test_tracing_component.active_test
53
- return super unless test_span
59
+ return super unless test_span && _dd_test_tracing_component.trace_setup_teardown_enabled
54
60
 
55
61
  @datadog_before_step_failures_count = failures.length
56
62
  @datadog_before_step_span = _dd_test_tracing_component.trace(
@@ -75,6 +81,8 @@ module Datadog
75
81
  # close a still-active before span before teardown begins.
76
82
  finish_datadog_before_step
77
83
 
84
+ return super unless _dd_test_tracing_component.trace_setup_teardown_enabled
85
+
78
86
  @datadog_after_step_failures_count = failures.length
79
87
  @datadog_after_step_span = _dd_test_tracing_component.trace(
80
88
  Ext::AFTER_STEP_SPAN_NAME,
@@ -101,10 +109,6 @@ module Datadog
101
109
 
102
110
  private
103
111
 
104
- def datadog_run_reentered?
105
- !!_dd_test_tracing_component.active_test
106
- end
107
-
108
112
  def run_without_datadog_reentry
109
113
  Datadog.logger.debug do
110
114
  "Datadog Minitest instrumentation re-entered for #{self.class}##{name}; running pre-Datadog Minitest run without starting another test span"
@@ -197,7 +197,7 @@ module Datadog
197
197
  # ============================================
198
198
 
199
199
  def run_before_example
200
- return super unless @datadog_test_tracing_component
200
+ return super unless @datadog_test_tracing_component&.trace_setup_teardown_enabled
201
201
 
202
202
  skip_exception = nil
203
203
  # @type var skip_exception: ::RSpec::Core::Pending::SkipDeclaredInExample?
@@ -213,7 +213,7 @@ module Datadog
213
213
  end
214
214
 
215
215
  def run_after_example
216
- return super unless @datadog_test_tracing_component
216
+ return super unless @datadog_test_tracing_component&.trace_setup_teardown_enabled
217
217
 
218
218
  exception_before_hooks = exception
219
219
 
@@ -11,6 +11,7 @@ module Datadog
11
11
  ENV_AGENTLESS_URL = "DD_CIVISIBILITY_AGENTLESS_URL"
12
12
  ENV_EXPERIMENTAL_TEST_SUITE_LEVEL_VISIBILITY_ENABLED = "DD_CIVISIBILITY_EXPERIMENTAL_TEST_SUITE_LEVEL_VISIBILITY_ENABLED"
13
13
  ENV_FORCE_TEST_LEVEL_VISIBILITY = "DD_CIVISIBILITY_FORCE_TEST_LEVEL_VISIBILITY"
14
+ ENV_TRACE_SETUP_TEARDOWN_ENABLED = "DD_TRACE_SETUP_TEARDOWN_ENABLED"
14
15
  ENV_ITR_ENABLED = "DD_CIVISIBILITY_ITR_ENABLED"
15
16
  ENV_TIA_TEST_SKIPPING_MODE = "DD_TESTOPTIMIZATION_TIA_TEST_SKIPPING_MODE"
16
17
  ENV_GIT_METADATA_UPLOAD_ENABLED = "DD_CIVISIBILITY_GIT_METADATA_UPLOAD_ENABLED"
@@ -21,6 +22,8 @@ module Datadog
21
22
  ENV_RETRY_FAILED_TESTS_MAX_ATTEMPTS = "DD_CIVISIBILITY_FLAKY_RETRY_COUNT"
22
23
  ENV_RETRY_FAILED_TESTS_TOTAL_LIMIT = "DD_CIVISIBILITY_TOTAL_FLAKY_RETRY_COUNT"
23
24
  ENV_RETRY_NEW_TESTS_ENABLED = "DD_CIVISIBILITY_EARLY_FLAKE_DETECTION_ENABLED"
25
+ ENV_DYNAMIC_ATR_ENABLED = "DD_CIVISIBILITY_DYNAMIC_ATR_ENABLED"
26
+ ENV_DYNAMIC_ATR_BUCKETS = "DD_CIVISIBILITY_DYNAMIC_ATR_BUCKETS"
24
27
  ENV_TEST_SESSION_NAME = "DD_TEST_SESSION_NAME"
25
28
  ENV_TEST_MANAGEMENT_ENABLED = "DD_TEST_MANAGEMENT_ENABLED"
26
29
  ENV_TEST_MANAGEMENT_ATTEMPT_TO_FIX_RETRIES = "DD_TEST_MANAGEMENT_ATTEMPT_TO_FIX_RETRIES"