datadog-ci 1.4.1 → 1.5.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 (44) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +17 -2
  3. data/lib/datadog/ci/configuration/components.rb +12 -6
  4. data/lib/datadog/ci/configuration/settings.rb +6 -0
  5. data/lib/datadog/ci/contrib/cucumber/filter.rb +40 -0
  6. data/lib/datadog/ci/contrib/cucumber/instrumentation.rb +15 -1
  7. data/lib/datadog/ci/contrib/cucumber/patcher.rb +0 -2
  8. data/lib/datadog/ci/contrib/minitest/runner.rb +6 -1
  9. data/lib/datadog/ci/contrib/minitest/test.rb +4 -0
  10. data/lib/datadog/ci/contrib/rspec/example.rb +11 -10
  11. data/lib/datadog/ci/contrib/rspec/runner.rb +2 -1
  12. data/lib/datadog/ci/ext/settings.rb +1 -0
  13. data/lib/datadog/ci/ext/telemetry.rb +9 -0
  14. data/lib/datadog/ci/ext/test.rb +6 -1
  15. data/lib/datadog/ci/ext/transport.rb +7 -0
  16. data/lib/datadog/ci/remote/component.rb +13 -2
  17. data/lib/datadog/ci/remote/library_settings.rb +48 -7
  18. data/lib/datadog/ci/remote/library_settings_client.rb +2 -1
  19. data/lib/datadog/ci/remote/slow_test_retries.rb +53 -0
  20. data/lib/datadog/ci/test.rb +15 -2
  21. data/lib/datadog/ci/test_optimisation/component.rb +9 -6
  22. data/lib/datadog/ci/test_optimisation/skippable.rb +1 -1
  23. data/lib/datadog/ci/test_retries/component.rb +68 -39
  24. data/lib/datadog/ci/test_retries/driver/base.rb +25 -0
  25. data/lib/datadog/ci/test_retries/driver/no_retry.rb +16 -0
  26. data/lib/datadog/ci/test_retries/driver/retry_failed.rb +37 -0
  27. data/lib/datadog/ci/test_retries/driver/retry_new.rb +50 -0
  28. data/lib/datadog/ci/test_retries/null_component.rb +7 -6
  29. data/lib/datadog/ci/test_retries/strategy/base.rb +11 -4
  30. data/lib/datadog/ci/test_retries/strategy/no_retry.rb +0 -2
  31. data/lib/datadog/ci/test_retries/strategy/retry_failed.rb +30 -13
  32. data/lib/datadog/ci/test_retries/strategy/retry_new.rb +132 -0
  33. data/lib/datadog/ci/test_retries/unique_tests_client.rb +132 -0
  34. data/lib/datadog/ci/test_session.rb +2 -0
  35. data/lib/datadog/ci/test_suite.rb +8 -0
  36. data/lib/datadog/ci/test_visibility/component.rb +23 -13
  37. data/lib/datadog/ci/test_visibility/null_component.rb +1 -1
  38. data/lib/datadog/ci/test_visibility/telemetry.rb +9 -0
  39. data/lib/datadog/ci/utils/test_run.rb +1 -1
  40. data/lib/datadog/ci/version.rb +2 -2
  41. data/lib/datadog/ci.rb +6 -3
  42. metadata +11 -5
  43. data/lib/datadog/ci/contrib/cucumber/configuration_override.rb +0 -37
  44. data/lib/datadog/ci/utils/identity.rb +0 -20
@@ -51,6 +51,14 @@ module Datadog
51
51
  end
52
52
  end
53
53
 
54
+ # @internal
55
+ def any_test_retry_passed?(test_id)
56
+ synchronize do
57
+ stats = @execution_stats_per_test[test_id]
58
+ stats && stats[Ext::Test::Status::PASS] > 0
59
+ end
60
+ end
61
+
54
62
  # @internal
55
63
  def test_executed?(test_id)
56
64
  synchronize do
@@ -19,8 +19,6 @@ module Datadog
19
19
  class Component
20
20
  attr_reader :test_suite_level_visibility_enabled
21
21
 
22
- FIBER_LOCAL_TEST_FINISHED_CALLBACK_KEY = :__dd_test_finished_callback
23
-
24
22
  def initialize(
25
23
  test_suite_level_visibility_enabled: false,
26
24
  codeowners: Codeowners::Parser.new(Git::LocalRepository.root).parse
@@ -30,10 +28,12 @@ module Datadog
30
28
  @codeowners = codeowners
31
29
  end
32
30
 
33
- def start_test_session(service: nil, tags: {})
31
+ def start_test_session(service: nil, tags: {}, total_tests_count: 0)
34
32
  return skip_tracing unless test_suite_level_visibility_enabled
35
33
 
36
34
  test_session = @context.start_test_session(service: service, tags: tags)
35
+ test_session.total_tests_count = total_tests_count
36
+
37
37
  on_test_session_started(test_session)
38
38
  test_session
39
39
  end
@@ -57,6 +57,8 @@ module Datadog
57
57
  def trace_test(test_name, test_suite_name, service: nil, tags: {}, &block)
58
58
  if block
59
59
  @context.trace_test(test_name, test_suite_name, service: service, tags: tags) do |test|
60
+ subscribe_to_after_stop_event(test.tracer_span)
61
+
60
62
  on_test_started(test)
61
63
  res = block.call(test)
62
64
  on_test_finished(test)
@@ -64,6 +66,7 @@ module Datadog
64
66
  end
65
67
  else
66
68
  test = @context.trace_test(test_name, test_suite_name, service: service, tags: tags)
69
+ subscribe_to_after_stop_event(test.tracer_span)
67
70
  on_test_started(test)
68
71
  test
69
72
  end
@@ -127,15 +130,6 @@ module Datadog
127
130
  @context.deactivate_test_suite(test_suite_name)
128
131
  end
129
132
 
130
- # sets fiber-local callback to be called when test is finished
131
- def set_test_finished_callback(callback)
132
- Thread.current[FIBER_LOCAL_TEST_FINISHED_CALLBACK_KEY] = callback
133
- end
134
-
135
- def remove_test_finished_callback
136
- Thread.current[FIBER_LOCAL_TEST_FINISHED_CALLBACK_KEY] = nil
137
- end
138
-
139
133
  def itr_enabled?
140
134
  test_optimisation.enabled?
141
135
  end
@@ -204,7 +198,11 @@ module Datadog
204
198
 
205
199
  Telemetry.event_finished(test)
206
200
 
207
- Thread.current[FIBER_LOCAL_TEST_FINISHED_CALLBACK_KEY]&.call(test)
201
+ test_retries.record_test_finished(test)
202
+ end
203
+
204
+ def on_after_test_span_finished(tracer_span)
205
+ test_retries.record_test_span_duration(tracer_span)
208
206
  end
209
207
 
210
208
  # HELPERS
@@ -212,6 +210,14 @@ module Datadog
212
210
  block&.call(nil)
213
211
  end
214
212
 
213
+ def subscribe_to_after_stop_event(tracer_span)
214
+ events = tracer_span.send(:events)
215
+
216
+ events.after_stop.subscribe do |span|
217
+ on_after_test_span_finished(span)
218
+ end
219
+ end
220
+
215
221
  def set_codeowners(test)
216
222
  source = test.source_file
217
223
  owners = @codeowners.list_owners(source) if source
@@ -267,6 +273,10 @@ module Datadog
267
273
  Datadog.send(:components).test_optimisation
268
274
  end
269
275
 
276
+ def test_retries
277
+ Datadog.send(:components).test_retries
278
+ end
279
+
270
280
  def git_tree_upload_worker
271
281
  Datadog.send(:components).git_tree_upload_worker
272
282
  end
@@ -5,7 +5,7 @@ module Datadog
5
5
  module TestVisibility
6
6
  # Special test visibility component that does not record anything
7
7
  class NullComponent
8
- def start_test_session(service: nil, tags: {})
8
+ def start_test_session(service: nil, tags: {}, total_tests_count: 0)
9
9
  skip_tracing
10
10
  end
11
11
 
@@ -58,6 +58,15 @@ module Datadog
58
58
  # set is_retry tag if span represents a retried test
59
59
  tags[Ext::Telemetry::TAG_IS_RETRY] = "true" if span.get_tag(Ext::Test::TAG_IS_RETRY)
60
60
 
61
+ # is_new
62
+ tags[Ext::Telemetry::TAG_IS_NEW] = "true" if span.get_tag(Ext::Test::TAG_IS_NEW)
63
+
64
+ # session-level tag - early_flake_detection_abort_reason
65
+ early_flake_detection_abort_reason = span.get_tag(Ext::Test::TAG_EARLY_FLAKE_ABORT_REASON)
66
+ if early_flake_detection_abort_reason
67
+ tags[Ext::Telemetry::TAG_EARLY_FLAKE_DETECTION_ABORT_REASON] = early_flake_detection_abort_reason
68
+ end
69
+
61
70
  tags
62
71
  end
63
72
 
@@ -10,7 +10,7 @@ module Datadog
10
10
  @command = "#{$0} #{ARGV.join(" ")}"
11
11
  end
12
12
 
13
- def self.skippable_test_id(test_name, suite, parameters = nil)
13
+ def self.datadog_test_id(test_name, suite, parameters = nil)
14
14
  "#{suite}.#{test_name}.#{parameters}"
15
15
  end
16
16
 
@@ -4,8 +4,8 @@ module Datadog
4
4
  module CI
5
5
  module VERSION
6
6
  MAJOR = 1
7
- MINOR = 4
8
- PATCH = 1
7
+ MINOR = 5
8
+ PATCH = 0
9
9
  PRE = nil
10
10
  BUILD = nil
11
11
  # PRE and BUILD above are modified for dev gems during gem build GHA workflow
data/lib/datadog/ci.rb CHANGED
@@ -6,6 +6,7 @@ require_relative "ci/utils/telemetry"
6
6
  require_relative "ci/ext/app_types"
7
7
  require_relative "ci/ext/telemetry"
8
8
 
9
+ require "datadog"
9
10
  require "datadog/core"
10
11
 
11
12
  module Datadog
@@ -27,7 +28,8 @@ module Datadog
27
28
  # ```
28
29
  # Datadog::CI.start_test_session(
29
30
  # service: "my-web-site-tests",
30
- # tags: { Datadog::CI::Ext::Test::TAG_FRAMEWORK => "my-test-framework" }
31
+ # tags: { Datadog::CI::Ext::Test::TAG_FRAMEWORK => "my-test-framework" },
32
+ # total_tests_count: 100
31
33
  # )
32
34
  #
33
35
  # # Somewhere else after test run has ended
@@ -38,15 +40,16 @@ module Datadog
38
40
  #
39
41
  # @param [String] service the service name for this session (optional, defaults to DD_SERVICE or repository name)
40
42
  # @param [Hash<String,String>] tags extra tags which should be added to the test session.
43
+ # @param [Integer] total_tests_count the total number of tests in the test session (optional, defaults to 0) - it is used to limit the number of new tests retried within session if early flake detection is enabled
41
44
  # @return [Datadog::CI::TestSession] the active, running {Datadog::CI::TestSession}.
42
45
  # @return [nil] if test suite level visibility is disabled or CI mode is disabled.
43
- def start_test_session(service: Utils::Configuration.fetch_service_name("test"), tags: {})
46
+ def start_test_session(service: Utils::Configuration.fetch_service_name("test"), tags: {}, total_tests_count: 0)
44
47
  Utils::Telemetry.inc(
45
48
  Ext::Telemetry::METRIC_MANUAL_API_EVENTS,
46
49
  1,
47
50
  {Ext::Telemetry::TAG_EVENT_TYPE => Ext::Telemetry::EventType::SESSION}
48
51
  )
49
- test_visibility.start_test_session(service: service, tags: tags)
52
+ test_visibility.start_test_session(service: service, tags: tags, total_tests_count: total_tests_count)
50
53
  end
51
54
 
52
55
  # The active, unfinished test session.
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: datadog-ci
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.1
4
+ version: 1.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Datadog, Inc.
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-08-28 00:00:00.000000000 Z
11
+ date: 2024-09-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: datadog
@@ -68,8 +68,8 @@ files:
68
68
  - lib/datadog/ci/configuration/settings.rb
69
69
  - lib/datadog/ci/contrib/contrib.rb
70
70
  - lib/datadog/ci/contrib/cucumber/configuration/settings.rb
71
- - lib/datadog/ci/contrib/cucumber/configuration_override.rb
72
71
  - lib/datadog/ci/contrib/cucumber/ext.rb
72
+ - lib/datadog/ci/contrib/cucumber/filter.rb
73
73
  - lib/datadog/ci/contrib/cucumber/formatter.rb
74
74
  - lib/datadog/ci/contrib/cucumber/instrumentation.rb
75
75
  - lib/datadog/ci/contrib/cucumber/integration.rb
@@ -139,6 +139,7 @@ files:
139
139
  - lib/datadog/ci/remote/component.rb
140
140
  - lib/datadog/ci/remote/library_settings.rb
141
141
  - lib/datadog/ci/remote/library_settings_client.rb
142
+ - lib/datadog/ci/remote/slow_test_retries.rb
142
143
  - lib/datadog/ci/span.rb
143
144
  - lib/datadog/ci/test.rb
144
145
  - lib/datadog/ci/test_module.rb
@@ -150,10 +151,16 @@ files:
150
151
  - lib/datadog/ci/test_optimisation/skippable.rb
151
152
  - lib/datadog/ci/test_optimisation/telemetry.rb
152
153
  - lib/datadog/ci/test_retries/component.rb
154
+ - lib/datadog/ci/test_retries/driver/base.rb
155
+ - lib/datadog/ci/test_retries/driver/no_retry.rb
156
+ - lib/datadog/ci/test_retries/driver/retry_failed.rb
157
+ - lib/datadog/ci/test_retries/driver/retry_new.rb
153
158
  - lib/datadog/ci/test_retries/null_component.rb
154
159
  - lib/datadog/ci/test_retries/strategy/base.rb
155
160
  - lib/datadog/ci/test_retries/strategy/no_retry.rb
156
161
  - lib/datadog/ci/test_retries/strategy/retry_failed.rb
162
+ - lib/datadog/ci/test_retries/strategy/retry_new.rb
163
+ - lib/datadog/ci/test_retries/unique_tests_client.rb
157
164
  - lib/datadog/ci/test_session.rb
158
165
  - lib/datadog/ci/test_suite.rb
159
166
  - lib/datadog/ci/test_visibility/component.rb
@@ -187,7 +194,6 @@ files:
187
194
  - lib/datadog/ci/utils/bundle.rb
188
195
  - lib/datadog/ci/utils/configuration.rb
189
196
  - lib/datadog/ci/utils/git.rb
190
- - lib/datadog/ci/utils/identity.rb
191
197
  - lib/datadog/ci/utils/parsing.rb
192
198
  - lib/datadog/ci/utils/telemetry.rb
193
199
  - lib/datadog/ci/utils/test_run.rb
@@ -219,7 +225,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
219
225
  - !ruby/object:Gem::Version
220
226
  version: 2.0.0
221
227
  requirements: []
222
- rubygems_version: 3.5.11
228
+ rubygems_version: 3.5.16
223
229
  signing_key:
224
230
  specification_version: 4
225
231
  summary: Datadog CI visibility for your ruby application
@@ -1,37 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative "formatter"
4
-
5
- module Datadog
6
- module CI
7
- module Contrib
8
- module Cucumber
9
- # Changes behaviour of Cucumber::Configuration class
10
- module ConfigurationOverride
11
- def self.included(base)
12
- base.prepend(InstanceMethods)
13
- end
14
-
15
- # Instance methods for configuration
16
- module InstanceMethods
17
- def retry_attempts
18
- super if !datadog_test_retries_component&.retry_failed_tests_enabled
19
-
20
- datadog_test_retries_component&.retry_failed_tests_max_attempts
21
- end
22
-
23
- def retry_total_tests
24
- super if !datadog_test_retries_component&.retry_failed_tests_enabled
25
-
26
- datadog_test_retries_component&.retry_failed_tests_total_limit
27
- end
28
-
29
- def datadog_test_retries_component
30
- Datadog.send(:components).test_retries
31
- end
32
- end
33
- end
34
- end
35
- end
36
- end
37
- end
@@ -1,20 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Datadog
4
- module CI
5
- module Utils
6
- module Identity
7
- def self.included(base)
8
- base.singleton_class.prepend(ClassMethods)
9
- end
10
-
11
- module ClassMethods
12
- # return datadog-ci gem version instead of datadog gem version
13
- def gem_datadog_version
14
- Datadog::CI::VERSION::STRING
15
- end
16
- end
17
- end
18
- end
19
- end
20
- end