datadog-ci 1.13.0 → 1.14.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bc134bf501f298c7803572320d3c82d93b64b0dbfc59b2d8219d42fd5fed24e6
4
- data.tar.gz: 4714f599fef9eae12cb3dc99dfb17dc0431a9dfee7d9337da9fada542429c6c5
3
+ metadata.gz: 694421f4e4621608a9aa6d8deb0b1407fa348fec68820a28ced1a567c56ed289
4
+ data.tar.gz: 12b586d1eabe233af428c7294564f8b7a46ff8bbb64d44f222762afd371a2c1c
5
5
  SHA512:
6
- metadata.gz: e54fa5b48885accd1c304fca925292470930f6c916e318c5a02eed24989d089e431b99aa56c3eab75f1ed4445c3ab8bd14b1783baa01c32e52bf3d0df5f3813b
7
- data.tar.gz: 0f42913850d53736f3b058db3c7bea7e2f4cc0c5ccf511545d052afb142967084185075888511887185dbf5b82ee4b6931b7da76f91b91fe0c99760efb1b9574
6
+ metadata.gz: 81c173cb2b22a8e0e3853d21d4e1ac023569142d51bb266c287ef7d4c7c5f2dfd97d2f3914acd1ac766d3e60ac15929cbee849b7284d300644113e6a14dea331
7
+ data.tar.gz: c1f1f93f35850cf9b6d1e360d53f2a26e2e46961aeed8e69f216327513e4001c45a42c363c20609ad0b525a4aeaf0fdec59e32f38d9302289c9e256ccf5aa81c
data/CHANGELOG.md CHANGED
@@ -1,5 +1,16 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [1.14.0] - 2025-03-11
4
+
5
+ ### Added
6
+
7
+ * Test impact analysis: add rails parallel testing support ([#294][])
8
+ * Add parallel testing support to minitest framework ([#295][])
9
+
10
+ ### Changed
11
+
12
+ * Test knapsack_pro v8 ([#292][])
13
+
3
14
  ## [1.13.0] - 2025-02-25
4
15
 
5
16
  ### Added
@@ -393,7 +404,8 @@ Currently test suite level visibility is not used by our instrumentation: it wil
393
404
 
394
405
  - Ruby versions < 2.7 no longer supported ([#8][])
395
406
 
396
- [Unreleased]: https://github.com/DataDog/datadog-ci-rb/compare/v1.13.0...main
407
+ [Unreleased]: https://github.com/DataDog/datadog-ci-rb/compare/v1.14.0...main
408
+ [1.14.0]: https://github.com/DataDog/datadog-ci-rb/compare/v1.13.0...v1.14.0
397
409
  [1.13.0]: https://github.com/DataDog/datadog-ci-rb/compare/v1.12.0...v1.13.0
398
410
  [1.12.0]: https://github.com/DataDog/datadog-ci-rb/compare/v1.11.0...v1.12.0
399
411
  [1.11.0]: https://github.com/DataDog/datadog-ci-rb/compare/v1.10.0...v1.11.0
@@ -564,4 +576,7 @@ Currently test suite level visibility is not used by our instrumentation: it wil
564
576
  [#275]: https://github.com/DataDog/datadog-ci-rb/issues/275
565
577
  [#283]: https://github.com/DataDog/datadog-ci-rb/issues/283
566
578
  [#286]: https://github.com/DataDog/datadog-ci-rb/issues/286
567
- [#289]: https://github.com/DataDog/datadog-ci-rb/issues/289
579
+ [#289]: https://github.com/DataDog/datadog-ci-rb/issues/289
580
+ [#292]: https://github.com/DataDog/datadog-ci-rb/issues/292
581
+ [#294]: https://github.com/DataDog/datadog-ci-rb/issues/294
582
+ [#295]: https://github.com/DataDog/datadog-ci-rb/issues/295
@@ -5,6 +5,32 @@ module Datadog
5
5
  module Contrib
6
6
  module Minitest
7
7
  module Helpers
8
+ def self.start_test_suite(klass)
9
+ method = klass.runnable_methods.first
10
+ return nil if method.nil?
11
+
12
+ test_suite_name = test_suite_name(klass, method)
13
+ source_file, line_number = extract_source_location_from_class(klass)
14
+
15
+ test_suite_tags = if source_file
16
+ {
17
+ CI::Ext::Test::TAG_SOURCE_FILE => (Git::LocalRepository.relative_to_root(source_file) if source_file),
18
+ CI::Ext::Test::TAG_SOURCE_START => line_number&.to_s
19
+ }
20
+ else
21
+ {}
22
+ end
23
+
24
+ test_visibility_component = Datadog.send(:components).test_visibility
25
+ test_suite = test_visibility_component.start_test_suite(
26
+ test_suite_name,
27
+ tags: test_suite_tags
28
+ )
29
+ test_suite&.set_expected_tests!(klass.runnable_methods)
30
+
31
+ test_suite
32
+ end
33
+
8
34
  def self.test_suite_name(klass, method_name)
9
35
  source_location = extract_source_location_from_class(klass)&.first
10
36
  # if we are in anonymous class, fallback to the method source location
@@ -14,25 +14,7 @@ module Datadog
14
14
  return super unless datadog_configuration[:enabled]
15
15
  return super if Helpers.parallel?(self)
16
16
 
17
- method = runnable_methods.first
18
- return super if method.nil?
19
-
20
- test_suite_name = Helpers.test_suite_name(self, method)
21
- source_file, line_number = Helpers.extract_source_location_from_class(self)
22
-
23
- test_suite_tags = if source_file
24
- {
25
- CI::Ext::Test::TAG_SOURCE_FILE => (Git::LocalRepository.relative_to_root(source_file) if source_file),
26
- CI::Ext::Test::TAG_SOURCE_START => line_number&.to_s
27
- }
28
- else
29
- {}
30
- end
31
-
32
- test_suite = test_visibility_component.start_test_suite(
33
- test_suite_name,
34
- tags: test_suite_tags
35
- )
17
+ test_suite = Helpers.start_test_suite(self)
36
18
 
37
19
  results = super
38
20
  return results unless test_suite
@@ -9,8 +9,6 @@ module Datadog
9
9
  module Contrib
10
10
  module Minitest
11
11
  module Runner
12
- DD_ESTIMATED_TESTS_PER_SUITE = 5
13
-
14
12
  def self.included(base)
15
13
  base.singleton_class.prepend(ClassMethods)
16
14
  end
@@ -21,15 +19,15 @@ module Datadog
21
19
 
22
20
  return unless datadog_configuration[:enabled]
23
21
 
24
- # minitest does not store the total number of tests, so we can't pass it to the test session
25
- # instead, we use the number of test suites * DD_ESTIMATED_TESTS_PER_SUITE as a rough estimate
22
+ tests_count = ::Minitest::Runnable.runnables.sum { |runnable| runnable.runnable_methods.size }
23
+
26
24
  test_visibility_component.start_test_session(
27
25
  tags: {
28
26
  CI::Ext::Test::TAG_FRAMEWORK => Ext::FRAMEWORK,
29
27
  CI::Ext::Test::TAG_FRAMEWORK_VERSION => datadog_integration.version.to_s
30
28
  },
31
29
  service: datadog_configuration[:service_name],
32
- total_tests_count: (DD_ESTIMATED_TESTS_PER_SUITE * ::Minitest::Runnable.runnables.size).to_i
30
+ estimated_total_tests_count: tests_count
33
31
  )
34
32
  test_visibility_component.start_test_module(Ext::FRAMEWORK)
35
33
  end
@@ -43,6 +41,12 @@ module Datadog
43
41
  result = super
44
42
  end
45
43
 
44
+ # get the current test suite and mark this method as done, so we can check if all tests were executed
45
+ # for this test suite
46
+ test_suite_name = Helpers.test_suite_name(klass, method_name)
47
+ test_suite = test_visibility_component.active_test_suite(test_suite_name)
48
+ test_suite&.expected_test_done!(method_name)
49
+
46
50
  result
47
51
  end
48
52
 
@@ -22,14 +22,11 @@ module Datadog
22
22
  super
23
23
  return unless datadog_configuration[:enabled]
24
24
 
25
- test_suite_name = Helpers.test_suite_name(self.class, name)
26
25
  if Helpers.parallel?(self.class)
27
- test_suite_name = "#{test_suite_name} (#{name} concurrently)"
28
-
29
- # for parallel execution we need to start a new test suite for each test
30
- test_visibility_component.start_test_suite(test_suite_name)
26
+ Helpers.start_test_suite(self.class)
31
27
  end
32
28
 
29
+ test_suite_name = Helpers.test_suite_name(self.class, name)
33
30
  source_file, line_number = method(name).source_location
34
31
 
35
32
  test_span = test_visibility_component.trace_test(
@@ -56,10 +53,6 @@ module Datadog
56
53
  # remove failures if test passed at least once on retries or quarantined
57
54
  self.failures = [] if test_span.should_ignore_failures?
58
55
 
59
- if Helpers.parallel?(self.class)
60
- finish_with_result(test_span.test_suite, result_code)
61
- end
62
-
63
56
  super
64
57
  end
65
58
 
@@ -25,7 +25,7 @@ module Datadog
25
25
  CI::Ext::Test::TAG_FRAMEWORK_VERSION => datadog_integration.version.to_s
26
26
  },
27
27
  service: datadog_configuration[:service_name],
28
- total_tests_count: ::RSpec.world.example_count
28
+ estimated_total_tests_count: ::RSpec.world.example_count
29
29
  )
30
30
 
31
31
  test_module = test_visibility_component.start_test_module(Ext::FRAMEWORK)
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "drb"
4
+
3
5
  require "datadog/core/environment/platform"
4
6
 
5
7
  require_relative "ext/test"
@@ -12,6 +14,8 @@ module Datadog
12
14
  #
13
15
  # @public_api
14
16
  class Span
17
+ include DRb::DRbUndumped
18
+
15
19
  attr_reader :tracer_span
16
20
 
17
21
  def initialize(tracer_span)
@@ -3,7 +3,6 @@
3
3
  require "pp"
4
4
 
5
5
  require "datadog/core/telemetry/logging"
6
- require "datadog/core/utils/forking"
7
6
 
8
7
  require_relative "../ext/test"
9
8
  require_relative "../ext/telemetry"
@@ -24,10 +23,7 @@ module Datadog
24
23
  # Integrates with backend to provide test impact analysis data and
25
24
  # skip tests that are not impacted by the changes
26
25
  class Component
27
- include Core::Utils::Forking
28
-
29
26
  attr_reader :correlation_id, :skippable_tests, :skippable_tests_fetch_error,
30
- :skipped_tests_count, :total_tests_count,
31
27
  :enabled, :test_skipping_enabled, :code_coverage_enabled
32
28
 
33
29
  def initialize(
@@ -61,9 +57,6 @@ module Datadog
61
57
  @correlation_id = nil
62
58
  @skippable_tests = Set.new
63
59
 
64
- @total_tests_count = 0
65
- @skipped_tests_count = 0
66
-
67
60
  @mutex = Mutex.new
68
61
 
69
62
  Datadog.logger.debug("TestOptimisation initialized with enabled: #{@enabled}")
@@ -155,11 +148,6 @@ module Datadog
155
148
  return if !enabled? || !skipping_tests?
156
149
 
157
150
  if skippable?(test)
158
- if forked?
159
- Datadog.logger.warn { "Test Impact Analysis is not supported for forking test runners yet" }
160
- return
161
- end
162
-
163
151
  test.set_tag(Ext::Test::TAG_ITR_SKIPPED_BY_ITR, "true")
164
152
 
165
153
  Datadog.logger.debug { "Marked test as skippable: #{test.datadog_test_id}" }
@@ -168,31 +156,22 @@ module Datadog
168
156
  end
169
157
  end
170
158
 
171
- def count_skipped_test(test)
172
- @mutex.synchronize do
173
- @total_tests_count += 1
159
+ def on_test_finished(test, context)
160
+ return if !test.skipped? || !test.skipped_by_test_impact_analysis?
174
161
 
175
- return if !test.skipped? || !test.skipped_by_test_impact_analysis?
162
+ Telemetry.itr_skipped
176
163
 
177
- if forked?
178
- Datadog.logger.warn { "ITR is not supported for forking test runners yet" }
179
- return
180
- end
181
-
182
- Telemetry.itr_skipped
183
-
184
- @skipped_tests_count += 1
185
- end
164
+ context.incr_tests_skipped_by_tia_count
186
165
  end
187
166
 
188
- def write_test_session_tags(test_session)
167
+ def write_test_session_tags(test_session, skipped_tests_count)
189
168
  return if !enabled?
190
169
 
191
170
  Datadog.logger.debug { "Finished optimised session with test skipping enabled: #{@test_skipping_enabled}" }
192
- Datadog.logger.debug { "#{@skipped_tests_count} tests were skipped" }
171
+ Datadog.logger.debug { "#{skipped_tests_count} tests were skipped" }
193
172
 
194
- test_session.set_tag(Ext::Test::TAG_ITR_TESTS_SKIPPED, @skipped_tests_count.positive?.to_s)
195
- test_session.set_tag(Ext::Test::TAG_ITR_TEST_SKIPPING_COUNT, @skipped_tests_count)
173
+ test_session.set_tag(Ext::Test::TAG_ITR_TESTS_SKIPPED, skipped_tests_count.positive?.to_s)
174
+ test_session.set_tag(Ext::Test::TAG_ITR_TEST_SKIPPING_COUNT, skipped_tests_count)
196
175
  end
197
176
 
198
177
  def skippable_tests_count
@@ -44,6 +44,10 @@ module Datadog
44
44
  def test_optimisation
45
45
  Datadog.send(:components).test_optimisation
46
46
  end
47
+
48
+ def test_visibility
49
+ Datadog.send(:components).test_visibility
50
+ end
47
51
  end
48
52
  end
49
53
  end
@@ -34,11 +34,11 @@ module Datadog
34
34
  return 0.0
35
35
  end
36
36
 
37
- log("Total tests count: #{test_optimisation.total_tests_count}")
38
- log("Skipped tests count: #{test_optimisation.skipped_tests_count}")
37
+ log("Total tests count: #{test_visibility.total_tests_count}")
38
+ log("Skipped tests count: #{test_visibility.tests_skipped_by_tia_count}")
39
39
  validate_test_optimisation_state!
40
40
 
41
- (test_optimisation.skipped_tests_count.to_f / test_optimisation.total_tests_count.to_f).floor(2)
41
+ (test_visibility.tests_skipped_by_tia_count.to_f / test_visibility.total_tests_count.to_f).floor(2)
42
42
  end
43
43
 
44
44
  private
@@ -70,7 +70,7 @@ module Datadog
70
70
 
71
71
  def calculate_total_retries_limit(library_settings, test_session)
72
72
  percentage_limit = library_settings.faulty_session_threshold
73
- tests_count = test_session.total_tests_count.to_i
73
+ tests_count = test_session.estimated_total_tests_count.to_i
74
74
  if tests_count.zero?
75
75
  Datadog.logger.debug do
76
76
  "Total tests count is zero, using default value for the total number of tests: [#{DEFAULT_TOTAL_TESTS_COUNT}]"
@@ -12,7 +12,7 @@ module Datadog
12
12
  #
13
13
  # @public_api
14
14
  class TestSession < ConcurrentSpan
15
- attr_accessor :total_tests_count
15
+ attr_accessor :estimated_total_tests_count
16
16
 
17
17
  # Finishes the current test session.
18
18
  # @return [void]
@@ -84,6 +84,24 @@ module Datadog
84
84
  end
85
85
  end
86
86
 
87
+ # @internal
88
+ def set_expected_tests!(expected_tests)
89
+ synchronize do
90
+ return if @expected_tests_set
91
+
92
+ @expected_tests_set = Set.new(expected_tests)
93
+ end
94
+ end
95
+
96
+ # @internal
97
+ def expected_test_done!(test_name)
98
+ synchronize do
99
+ @expected_tests_set.delete(test_name)
100
+
101
+ finish if @expected_tests_set.empty?
102
+ end
103
+ end
104
+
87
105
  private
88
106
 
89
107
  def set_status_from_stats!
@@ -1,7 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "drb"
3
4
  require "rbconfig"
4
5
 
6
+ require "datadog/core/utils/forking"
7
+
5
8
  require_relative "context"
6
9
  require_relative "telemetry"
7
10
  require_relative "total_coverage"
@@ -16,9 +19,12 @@ require_relative "../worker"
16
19
  module Datadog
17
20
  module CI
18
21
  module TestVisibility
19
- # Common behavior for CI tests
22
+ # Core functionality of the library: tracing tests' execution
20
23
  class Component
21
- attr_reader :test_suite_level_visibility_enabled, :logical_test_session_name, :known_tests, :known_tests_enabled
24
+ include Core::Utils::Forking
25
+
26
+ attr_reader :test_suite_level_visibility_enabled, :logical_test_session_name,
27
+ :known_tests, :known_tests_enabled
22
28
 
23
29
  def initialize(
24
30
  known_tests_client:,
@@ -27,7 +33,9 @@ module Datadog
27
33
  logical_test_session_name: nil
28
34
  )
29
35
  @test_suite_level_visibility_enabled = test_suite_level_visibility_enabled
36
+
30
37
  @context = Context.new
38
+
31
39
  @codeowners = codeowners
32
40
  @logical_test_session_name = logical_test_session_name
33
41
 
@@ -47,11 +55,13 @@ module Datadog
47
55
  end
48
56
  end
49
57
 
50
- def start_test_session(service: nil, tags: {}, total_tests_count: 0)
58
+ def start_test_session(service: nil, tags: {}, estimated_total_tests_count: 0)
51
59
  return skip_tracing unless test_suite_level_visibility_enabled
52
60
 
61
+ start_drb_service
62
+
53
63
  test_session = @context.start_test_session(service: service, tags: tags)
54
- test_session.total_tests_count = total_tests_count
64
+ test_session.estimated_total_tests_count = estimated_total_tests_count
55
65
 
56
66
  on_test_session_started(test_session)
57
67
  test_session
@@ -68,14 +78,17 @@ module Datadog
68
78
  def start_test_suite(test_suite_name, service: nil, tags: {})
69
79
  return skip_tracing unless test_suite_level_visibility_enabled
70
80
 
71
- test_suite = @context.start_test_suite(test_suite_name, service: service, tags: tags)
81
+ test_suite = maybe_remote_context.start_test_suite(test_suite_name, service: service, tags: tags)
72
82
  on_test_suite_started(test_suite)
73
83
  test_suite
74
84
  end
75
85
 
76
86
  def trace_test(test_name, test_suite_name, service: nil, tags: {}, &block)
87
+ test_suite = maybe_remote_context.active_test_suite(test_suite_name)
88
+ tags[Ext::Test::TAG_SUITE] ||= test_suite_name
89
+
77
90
  if block
78
- @context.trace_test(test_name, test_suite_name, service: service, tags: tags) do |test|
91
+ @context.trace_test(test_name, test_suite, service: service, tags: tags) do |test|
79
92
  subscribe_to_after_stop_event(test.tracer_span)
80
93
 
81
94
  on_test_started(test)
@@ -84,7 +97,7 @@ module Datadog
84
97
  res
85
98
  end
86
99
  else
87
- test = @context.trace_test(test_name, test_suite_name, service: service, tags: tags)
100
+ test = @context.trace_test(test_name, test_suite, service: service, tags: tags)
88
101
  subscribe_to_after_stop_event(test.tracer_span)
89
102
  on_test_started(test)
90
103
  test
@@ -118,7 +131,7 @@ module Datadog
118
131
  end
119
132
 
120
133
  def active_test_suite(test_suite_name)
121
- @context.active_test_suite(test_suite_name)
134
+ maybe_remote_context.active_test_suite(test_suite_name)
122
135
  end
123
136
 
124
137
  def deactivate_test
@@ -146,7 +159,15 @@ module Datadog
146
159
  test_suite = active_test_suite(test_suite_name)
147
160
  on_test_suite_finished(test_suite) if test_suite
148
161
 
149
- @context.deactivate_test_suite(test_suite_name)
162
+ maybe_remote_context.deactivate_test_suite(test_suite_name)
163
+ end
164
+
165
+ def total_tests_count
166
+ maybe_remote_context.total_tests_count
167
+ end
168
+
169
+ def tests_skipped_by_tia_count
170
+ maybe_remote_context.tests_skipped_by_tia_count
150
171
  end
151
172
 
152
173
  def itr_enabled?
@@ -190,6 +211,8 @@ module Datadog
190
211
  end
191
212
 
192
213
  def on_test_started(test)
214
+ maybe_remote_context.incr_total_tests_count
215
+
193
216
  # sometimes test suite is not being assigned correctly
194
217
  # fix it by fetching the one single running test suite from the global context
195
218
  fix_test_suite!(test) if test.test_suite_id.nil?
@@ -208,7 +231,7 @@ module Datadog
208
231
  end
209
232
 
210
233
  def on_test_session_finished(test_session)
211
- test_optimisation.write_test_session_tags(test_session)
234
+ test_optimisation.write_test_session_tags(test_session, maybe_remote_context.tests_skipped_by_tia_count)
212
235
 
213
236
  TotalCoverage.extract_lines_pct(test_session)
214
237
 
@@ -216,6 +239,8 @@ module Datadog
216
239
  end
217
240
 
218
241
  def on_test_module_finished(test_module)
242
+ @context.stop_all_test_suites
243
+
219
244
  Telemetry.event_finished(test_module)
220
245
  end
221
246
 
@@ -225,7 +250,7 @@ module Datadog
225
250
 
226
251
  def on_test_finished(test)
227
252
  test_optimisation.stop_coverage(test)
228
- test_optimisation.count_skipped_test(test)
253
+ test_optimisation.on_test_finished(test, maybe_remote_context)
229
254
 
230
255
  Telemetry.event_finished(test)
231
256
 
@@ -258,7 +283,7 @@ module Datadog
258
283
  def fix_test_suite!(test)
259
284
  return unless test_suite_level_visibility_enabled
260
285
 
261
- test_suite = @context.single_active_test_suite
286
+ test_suite = maybe_remote_context.single_active_test_suite
262
287
  unless test_suite
263
288
  Datadog.logger.debug do
264
289
  "Trying to fix test suite for test [#{test.name}] but no single test suite is running."
@@ -370,6 +395,27 @@ module Datadog
370
395
  def test_management
371
396
  Datadog.send(:components).test_management
372
397
  end
398
+
399
+ # DISTRIBUTED RUBY CONTEXT
400
+ def start_drb_service
401
+ return if @context_service_uri
402
+ return if forked?
403
+
404
+ @context_service = DRb.start_service("drbunix:", @context)
405
+ @context_service_uri = @context_service.uri
406
+ end
407
+
408
+ # depending on whether we are in a forked process or not, returns either the global context or its DRbObject
409
+ def maybe_remote_context
410
+ return @context unless forked?
411
+ return @context_client if defined?(@context_client)
412
+
413
+ # once per fork we must stop the running DRb server that was copied from the parent process
414
+ # otherwise, client will be confused thinking it's server which leads to terrible bugs
415
+ @context_service.stop_service
416
+
417
+ @context_client = DRbObject.new_with_uri(@context_service_uri)
418
+ end
373
419
  end
374
420
  end
375
421
  end
@@ -27,9 +27,16 @@ module Datadog
27
27
  # Its responsibility includes building domain models for test visibility as well.
28
28
  # Internally it uses Datadog::Tracing module to create spans.
29
29
  class Context
30
+ attr_reader :total_tests_count, :tests_skipped_by_tia_count
31
+
30
32
  def initialize
31
33
  @local_context = Store::Local.new
32
34
  @global_context = Store::Global.new
35
+
36
+ @mutex = Mutex.new
37
+
38
+ @total_tests_count = 0
39
+ @tests_skipped_by_tia_count = 0
33
40
  end
34
41
 
35
42
  def start_test_session(service: nil, tags: {})
@@ -66,17 +73,17 @@ module Datadog
66
73
  tracer_span = start_datadog_tracer_span(
67
74
  test_suite_name, build_tracing_span_options(service, Ext::AppTypes::TYPE_TEST_SUITE)
68
75
  )
69
- set_suite_context(tags, span: tracer_span)
76
+ set_suite_context(tags, test_suite: tracer_span)
70
77
 
71
78
  build_test_suite(tracer_span, tags)
72
79
  end
73
80
  end
74
81
 
75
- def trace_test(test_name, test_suite_name, service: nil, tags: {}, &block)
82
+ def trace_test(test_name, test_suite, service: nil, tags: {}, &block)
76
83
  set_inherited_globals(tags)
77
84
  set_session_context(tags)
78
85
  set_module_context(tags)
79
- set_suite_context(tags, name: test_suite_name)
86
+ set_suite_context(tags, test_suite: test_suite)
80
87
 
81
88
  tags[Ext::Test::TAG_NAME] = test_name
82
89
  tags[Ext::Test::TAG_TYPE] ||= Ext::Test::Type::TEST
@@ -148,6 +155,10 @@ module Datadog
148
155
  @global_context.fetch_single_test_suite
149
156
  end
150
157
 
158
+ def stop_all_test_suites
159
+ @global_context.stop_all_test_suites
160
+ end
161
+
151
162
  def deactivate_test
152
163
  @local_context.deactivate_test
153
164
  end
@@ -164,6 +175,14 @@ module Datadog
164
175
  @global_context.deactivate_test_suite!(test_suite_name)
165
176
  end
166
177
 
178
+ def incr_total_tests_count
179
+ @mutex.synchronize { @total_tests_count += 1 }
180
+ end
181
+
182
+ def incr_tests_skipped_by_tia_count
183
+ @mutex.synchronize { @tests_skipped_by_tia_count += 1 }
184
+ end
185
+
167
186
  private
168
187
 
169
188
  # BUILDING DOMAIN MODELS
@@ -232,17 +251,11 @@ module Datadog
232
251
  end
233
252
  end
234
253
 
235
- def set_suite_context(tags, span: nil, name: nil)
236
- return if span.nil? && name.nil?
254
+ def set_suite_context(tags, test_suite: nil)
255
+ return if test_suite.nil?
237
256
 
238
- test_suite = span || active_test_suite(name)
239
-
240
- if test_suite
241
- tags[Ext::Test::TAG_TEST_SUITE_ID] = test_suite.id.to_s
242
- tags[Ext::Test::TAG_SUITE] = test_suite.name
243
- else
244
- tags[Ext::Test::TAG_SUITE] = name
245
- end
257
+ tags[Ext::Test::TAG_TEST_SUITE_ID] = test_suite.id.to_s
258
+ tags[Ext::Test::TAG_SUITE] = test_suite.name
246
259
  end
247
260
 
248
261
  # INTERACTIONS WITH TRACING
@@ -8,7 +8,7 @@ module Datadog
8
8
  def configure(_, _)
9
9
  end
10
10
 
11
- def start_test_session(service: nil, tags: {}, total_tests_count: 0)
11
+ def start_test_session(service: nil, tags: {}, estimated_total_tests_count: 0)
12
12
  skip_tracing
13
13
  end
14
14
 
@@ -59,6 +59,13 @@ module Datadog
59
59
  end
60
60
  end
61
61
 
62
+ def stop_all_test_suites
63
+ @mutex.synchronize do
64
+ @test_suites.each_value(&:finish)
65
+ @test_suites.clear
66
+ end
67
+ end
68
+
62
69
  def inheritable_session_tags
63
70
  @mutex.synchronize do
64
71
  test_session = @test_session
@@ -4,7 +4,7 @@ module Datadog
4
4
  module CI
5
5
  module VERSION
6
6
  MAJOR = 1
7
- MINOR = 13
7
+ MINOR = 14
8
8
  PATCH = 0
9
9
  PRE = nil
10
10
  BUILD = nil
data/lib/datadog/ci.rb CHANGED
@@ -49,7 +49,7 @@ module Datadog
49
49
  1,
50
50
  {Ext::Telemetry::TAG_EVENT_TYPE => Ext::Telemetry::EventType::SESSION}
51
51
  )
52
- test_visibility.start_test_session(service: service, tags: tags, total_tests_count: total_tests_count)
52
+ test_visibility.start_test_session(service: service, tags: tags, estimated_total_tests_count: total_tests_count)
53
53
  end
54
54
 
55
55
  # The active, unfinished test session.
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: datadog-ci
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.13.0
4
+ version: 1.14.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Datadog, Inc.
8
8
  bindir: exe
9
9
  cert_chain: []
10
- date: 2025-02-25 00:00:00.000000000 Z
10
+ date: 2025-03-11 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: datadog
@@ -37,6 +37,20 @@ dependencies:
37
37
  - - ">="
38
38
  - !ruby/object:Gem::Version
39
39
  version: '0'
40
+ - !ruby/object:Gem::Dependency
41
+ name: drb
42
+ requirement: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: '0'
47
+ type: :runtime
48
+ prerelease: false
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
40
54
  description: |2
41
55
  datadog-ci is a Datadog's Test Optimization library for Ruby. It traces
42
56
  tests as they are being executed and brings developers visibility into