datadog-ci 1.4.1 → 1.5.0

Sign up to get free protection for your applications and to get access to all the features.
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