datadog-ci 1.14.0 → 1.16.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 (64) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +35 -2
  3. data/lib/datadog/ci/async_writer.rb +112 -0
  4. data/lib/datadog/ci/configuration/components.rb +36 -6
  5. data/lib/datadog/ci/configuration/settings.rb +17 -0
  6. data/lib/datadog/ci/contrib/activesupport/configuration/settings.rb +25 -0
  7. data/lib/datadog/ci/contrib/activesupport/ext.rb +14 -0
  8. data/lib/datadog/ci/contrib/activesupport/integration.rb +43 -0
  9. data/lib/datadog/ci/contrib/activesupport/logs_formatter.rb +41 -0
  10. data/lib/datadog/ci/contrib/activesupport/patcher.rb +50 -0
  11. data/lib/datadog/ci/contrib/lograge/configuration/settings.rb +25 -0
  12. data/lib/datadog/ci/contrib/lograge/ext.rb +14 -0
  13. data/lib/datadog/ci/contrib/lograge/integration.rb +43 -0
  14. data/lib/datadog/ci/contrib/lograge/log_subscriber.rb +41 -0
  15. data/lib/datadog/ci/contrib/lograge/patcher.rb +32 -0
  16. data/lib/datadog/ci/contrib/minitest/runner.rb +4 -1
  17. data/lib/datadog/ci/contrib/parallel_tests/cli.rb +84 -0
  18. data/lib/datadog/ci/contrib/parallel_tests/configuration/settings.rb +32 -0
  19. data/lib/datadog/ci/contrib/parallel_tests/ext.rb +16 -0
  20. data/lib/datadog/ci/contrib/parallel_tests/integration.rb +42 -0
  21. data/lib/datadog/ci/contrib/parallel_tests/patcher.rb +23 -0
  22. data/lib/datadog/ci/contrib/rspec/example.rb +7 -0
  23. data/lib/datadog/ci/contrib/rspec/example_group.rb +18 -8
  24. data/lib/datadog/ci/contrib/rspec/helpers.rb +18 -0
  25. data/lib/datadog/ci/contrib/rspec/runner.rb +2 -0
  26. data/lib/datadog/ci/contrib/semantic_logger/configuration/settings.rb +25 -0
  27. data/lib/datadog/ci/contrib/semantic_logger/ext.rb +14 -0
  28. data/lib/datadog/ci/contrib/semantic_logger/integration.rb +42 -0
  29. data/lib/datadog/ci/contrib/semantic_logger/logger.rb +32 -0
  30. data/lib/datadog/ci/contrib/semantic_logger/patcher.rb +32 -0
  31. data/lib/datadog/ci/ext/settings.rb +3 -0
  32. data/lib/datadog/ci/ext/test.rb +23 -2
  33. data/lib/datadog/ci/ext/transport.rb +2 -0
  34. data/lib/datadog/ci/git/local_repository.rb +1 -1
  35. data/lib/datadog/ci/git/tree_uploader.rb +9 -0
  36. data/lib/datadog/ci/logs/component.rb +46 -0
  37. data/lib/datadog/ci/logs/transport.rb +73 -0
  38. data/lib/datadog/ci/readonly_test_module.rb +28 -0
  39. data/lib/datadog/ci/readonly_test_session.rb +31 -0
  40. data/lib/datadog/ci/remote/component.rb +43 -16
  41. data/lib/datadog/ci/test.rb +10 -0
  42. data/lib/datadog/ci/test_management/component.rb +34 -1
  43. data/lib/datadog/ci/test_management/tests_properties.rb +2 -1
  44. data/lib/datadog/ci/test_optimisation/component.rb +31 -5
  45. data/lib/datadog/ci/test_retries/driver/retry_new.rb +1 -1
  46. data/lib/datadog/ci/test_session.rb +7 -1
  47. data/lib/datadog/ci/test_visibility/component.rb +82 -28
  48. data/lib/datadog/ci/test_visibility/context.rb +77 -29
  49. data/lib/datadog/ci/test_visibility/null_component.rb +7 -1
  50. data/lib/datadog/ci/test_visibility/store/{local.rb → fiber_local.rb} +1 -1
  51. data/lib/datadog/ci/test_visibility/store/{global.rb → process.rb} +23 -18
  52. data/lib/datadog/ci/test_visibility/transport.rb +1 -2
  53. data/lib/datadog/ci/transport/api/agentless.rb +8 -1
  54. data/lib/datadog/ci/transport/api/base.rb +4 -0
  55. data/lib/datadog/ci/transport/api/builder.rb +5 -1
  56. data/lib/datadog/ci/transport/api/evp_proxy.rb +4 -0
  57. data/lib/datadog/ci/transport/http.rb +1 -1
  58. data/lib/datadog/ci/utils/file_storage.rb +57 -0
  59. data/lib/datadog/ci/utils/stateful.rb +52 -0
  60. data/lib/datadog/ci/version.rb +1 -1
  61. data/lib/datadog/ci.rb +7 -3
  62. metadata +32 -6
  63. data/lib/datadog/ci/test_optimisation/coverage/writer.rb +0 -116
  64. data/lib/datadog/ci/test_visibility/capabilities.rb +0 -36
@@ -4,8 +4,9 @@ require "datadog/tracing"
4
4
  require "datadog/tracing/contrib/component"
5
5
  require "datadog/tracing/trace_digest"
6
6
 
7
- require_relative "store/global"
8
- require_relative "store/local"
7
+ require_relative "store/process"
8
+ require_relative "store/fiber_local"
9
+ require_relative "telemetry"
9
10
 
10
11
  require_relative "../ext/app_types"
11
12
  require_relative "../ext/environment"
@@ -29,9 +30,11 @@ module Datadog
29
30
  class Context
30
31
  attr_reader :total_tests_count, :tests_skipped_by_tia_count
31
32
 
32
- def initialize
33
- @local_context = Store::Local.new
34
- @global_context = Store::Global.new
33
+ def initialize(test_visibility_component:)
34
+ @test_visibility_component = test_visibility_component
35
+
36
+ @fiber_local_context = Store::FiberLocal.new
37
+ @process_context = Store::Process.new
35
38
 
36
39
  @mutex = Mutex.new
37
40
 
@@ -40,18 +43,23 @@ module Datadog
40
43
  end
41
44
 
42
45
  def start_test_session(service: nil, tags: {})
43
- @global_context.fetch_or_activate_test_session do
46
+ @process_context.fetch_or_activate_test_session do
44
47
  tracer_span = start_datadog_tracer_span(
45
48
  "test.session", build_tracing_span_options(service, Ext::AppTypes::TYPE_TEST_SESSION)
46
49
  )
47
50
  set_session_context(tags, tracer_span)
48
51
 
49
- build_test_session(tracer_span, tags)
52
+ test_session = build_test_session(tracer_span, tags)
53
+
54
+ Telemetry.test_session_started(test_session)
55
+ Telemetry.event_created(test_session)
56
+
57
+ test_session
50
58
  end
51
59
  end
52
60
 
53
61
  def start_test_module(test_module_name, service: nil, tags: {})
54
- @global_context.fetch_or_activate_test_module do
62
+ @process_context.fetch_or_activate_test_module do
55
63
  set_inherited_globals(tags)
56
64
  set_session_context(tags)
57
65
 
@@ -60,12 +68,16 @@ module Datadog
60
68
  )
61
69
  set_module_context(tags, tracer_span)
62
70
 
63
- build_test_module(tracer_span, tags)
71
+ test_module = build_test_module(tracer_span, tags)
72
+
73
+ Telemetry.event_created(test_module)
74
+
75
+ test_module
64
76
  end
65
77
  end
66
78
 
67
79
  def start_test_suite(test_suite_name, service: nil, tags: {})
68
- @global_context.fetch_or_activate_test_suite(test_suite_name) do
80
+ @process_context.fetch_or_activate_test_suite(test_suite_name) do
69
81
  set_inherited_globals(tags)
70
82
  set_session_context(tags)
71
83
  set_module_context(tags)
@@ -75,7 +87,11 @@ module Datadog
75
87
  )
76
88
  set_suite_context(tags, test_suite: tracer_span)
77
89
 
78
- build_test_suite(tracer_span, tags)
90
+ test_suite = build_test_suite(tracer_span, tags)
91
+
92
+ Telemetry.event_created(test_suite)
93
+
94
+ test_suite
79
95
  end
80
96
  end
81
97
 
@@ -100,14 +116,14 @@ module Datadog
100
116
  start_datadog_tracer_span(test_name, span_options) do |tracer_span|
101
117
  test = build_test(tracer_span, tags)
102
118
 
103
- @local_context.activate_test(test) do
119
+ @fiber_local_context.activate_test(test) do
104
120
  block.call(test)
105
121
  end
106
122
  end
107
123
  else
108
124
  tracer_span = start_datadog_tracer_span(test_name, span_options)
109
125
  test = build_test(tracer_span, tags)
110
- @local_context.activate_test(test)
126
+ @fiber_local_context.activate_test(test)
111
127
  test
112
128
  end
113
129
  end
@@ -136,43 +152,43 @@ module Datadog
136
152
  end
137
153
 
138
154
  def active_test
139
- @local_context.active_test
155
+ @fiber_local_context.active_test
140
156
  end
141
157
 
142
158
  def active_test_session
143
- @global_context.active_test_session
159
+ @process_context.active_test_session
144
160
  end
145
161
 
146
162
  def active_test_module
147
- @global_context.active_test_module
163
+ @process_context.active_test_module
148
164
  end
149
165
 
150
166
  def active_test_suite(test_suite_name)
151
- @global_context.active_test_suite(test_suite_name)
167
+ @process_context.active_test_suite(test_suite_name)
152
168
  end
153
169
 
154
170
  def single_active_test_suite
155
- @global_context.fetch_single_test_suite
171
+ @process_context.fetch_single_test_suite
156
172
  end
157
173
 
158
174
  def stop_all_test_suites
159
- @global_context.stop_all_test_suites
175
+ @process_context.stop_all_test_suites
160
176
  end
161
177
 
162
178
  def deactivate_test
163
- @local_context.deactivate_test
179
+ @fiber_local_context.deactivate_test
164
180
  end
165
181
 
166
182
  def deactivate_test_session
167
- @global_context.deactivate_test_session!
183
+ @process_context.deactivate_test_session!
168
184
  end
169
185
 
170
186
  def deactivate_test_module
171
- @global_context.deactivate_test_module!
187
+ @process_context.deactivate_test_module!
172
188
  end
173
189
 
174
190
  def deactivate_test_suite(test_suite_name)
175
- @global_context.deactivate_test_suite!(test_suite_name)
191
+ @process_context.deactivate_test_suite!(test_suite_name)
176
192
  end
177
193
 
178
194
  def incr_total_tests_count
@@ -231,20 +247,21 @@ module Datadog
231
247
 
232
248
  # PROPAGATING CONTEXT FROM TOP-LEVEL TO THE LOWER LEVELS
233
249
  def set_inherited_globals(tags)
234
- # this code achieves the same as @global_context.inheritable_session_tags.merge(tags)
235
- # but without allocating a new hash
236
- @global_context.inheritable_session_tags.each do |key, value|
250
+ # Copy inheritable tags from the test session context to the provided tags
251
+ test_session_context&.inheritable_tags&.each do |key, value|
237
252
  tags[key] = value unless tags.key?(key)
238
253
  end
239
254
  end
240
255
 
241
256
  def set_session_context(tags, test_session = nil)
242
- test_session ||= active_test_session
257
+ # we need to call TestVisibility::Component here because active test session might be remote
258
+ test_session ||= test_session_context
243
259
  tags[Ext::Test::TAG_TEST_SESSION_ID] = test_session.id.to_s if test_session
244
260
  end
245
261
 
246
262
  def set_module_context(tags, test_module = nil)
247
- test_module ||= active_test_module
263
+ # we need to call TestVisibility::Component here because active test module might be remote
264
+ test_module ||= test_module_context
248
265
  if test_module
249
266
  tags[Ext::Test::TAG_TEST_MODULE_ID] = test_module.id.to_s
250
267
  tags[Ext::Test::TAG_MODULE] = test_module.name
@@ -281,11 +298,42 @@ module Datadog
281
298
  end
282
299
 
283
300
  def build_tracing_span_options(service, type, other_options = {})
284
- other_options[:service] = service || @global_context.service
301
+ other_options[:service] = service || test_session_context&.service
285
302
  other_options[:type] = type
286
303
 
287
304
  other_options
288
305
  end
306
+
307
+ # one of:
308
+ # 1. Currrent test session from the Store::Process
309
+ # 2. Readonly copy of the remote test session (if test session was started by a parent process and local copy was created)
310
+ # 3. Remote test session as DRb::DRbObject link (in this case also local copy will be created)
311
+ def test_session_context
312
+ local_test_session = @process_context.active_test_session
313
+ return local_test_session if local_test_session
314
+
315
+ local_readonly_test_session = @process_context.readonly_test_session
316
+ return local_readonly_test_session if local_readonly_test_session
317
+
318
+ remote_test_session = @test_visibility_component.active_test_session
319
+ @process_context.set_readonly_test_session(remote_test_session)
320
+
321
+ remote_test_session
322
+ end
323
+
324
+ # works similar to test_session_context
325
+ def test_module_context
326
+ local_test_module = @process_context.active_test_module
327
+ return local_test_module if local_test_module
328
+
329
+ local_readonly_test_module = @process_context.readonly_test_module
330
+ return local_readonly_test_module if local_readonly_test_module
331
+
332
+ remote_test_module = @test_visibility_component.active_test_module
333
+ @process_context.set_readonly_test_module(remote_test_module)
334
+
335
+ remote_test_module
336
+ end
289
337
  end
290
338
  end
291
339
  end
@@ -8,7 +8,9 @@ module Datadog
8
8
  def configure(_, _)
9
9
  end
10
10
 
11
- def start_test_session(service: nil, tags: {}, estimated_total_tests_count: 0)
11
+ def start_test_session(
12
+ service: nil, tags: {}, estimated_total_tests_count: 0, distributed: false, local_test_suites_mode: true
13
+ )
12
14
  skip_tracing
13
15
  end
14
16
 
@@ -63,6 +65,10 @@ module Datadog
63
65
  def logical_test_session_name
64
66
  end
65
67
 
68
+ def client_process?
69
+ false
70
+ end
71
+
66
72
  private
67
73
 
68
74
  def skip_tracing(block = nil)
@@ -4,7 +4,7 @@ module Datadog
4
4
  module CI
5
5
  module TestVisibility
6
6
  module Store
7
- class Local
7
+ class FiberLocal
8
8
  def initialize
9
9
  @key = :datadog_ci_active_test
10
10
 
@@ -1,11 +1,16 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative "../../readonly_test_session"
4
+ require_relative "../../readonly_test_module"
5
+
3
6
  module Datadog
4
7
  module CI
5
8
  module TestVisibility
6
9
  module Store
7
10
  # This context is shared between threads and represents the current test session and test module.
8
- class Global
11
+ class Process
12
+ attr_reader :readonly_test_session, :readonly_test_module
13
+
9
14
  def initialize
10
15
  # we are using Monitor instead of Mutex because it is reentrant
11
16
  @mutex = Monitor.new
@@ -13,6 +18,11 @@ module Datadog
13
18
  @test_session = nil
14
19
  @test_module = nil
15
20
  @test_suites = {}
21
+
22
+ # small copies of id, name and some tags: store them in the current process to set session/module context
23
+ # for any spans faster
24
+ @readonly_test_session = nil
25
+ @readonly_test_module = nil
16
26
  end
17
27
 
18
28
  def fetch_or_activate_test_suite(test_suite_name, &block)
@@ -53,12 +63,6 @@ module Datadog
53
63
  @mutex.synchronize { @test_suites[test_suite_name] }
54
64
  end
55
65
 
56
- def service
57
- @mutex.synchronize do
58
- @test_session&.service
59
- end
60
- end
61
-
62
66
  def stop_all_test_suites
63
67
  @mutex.synchronize do
64
68
  @test_suites.each_value(&:finish)
@@ -66,17 +70,6 @@ module Datadog
66
70
  end
67
71
  end
68
72
 
69
- def inheritable_session_tags
70
- @mutex.synchronize do
71
- test_session = @test_session
72
- if test_session
73
- test_session.inheritable_tags
74
- else
75
- {}
76
- end
77
- end
78
- end
79
-
80
73
  def deactivate_test_session!
81
74
  @mutex.synchronize { @test_session = nil }
82
75
  end
@@ -88,6 +81,18 @@ module Datadog
88
81
  def deactivate_test_suite!(test_suite_name)
89
82
  @mutex.synchronize { @test_suites.delete(test_suite_name) }
90
83
  end
84
+
85
+ def set_readonly_test_session(remote_test_session)
86
+ return if remote_test_session.nil?
87
+
88
+ @readonly_test_session = Datadog::CI::ReadonlyTestSession.new(remote_test_session)
89
+ end
90
+
91
+ def set_readonly_test_module(remote_test_module)
92
+ return if remote_test_module.nil?
93
+
94
+ @readonly_test_module = Datadog::CI::ReadonlyTestModule.new(remote_test_module)
95
+ end
91
96
  end
92
97
  end
93
98
  end
@@ -4,7 +4,6 @@ require "datadog/core/environment/identity"
4
4
  require "datadog/core/telemetry/logging"
5
5
  require "datadog/core/utils/only_once"
6
6
 
7
- require_relative "capabilities"
8
7
  require_relative "serializers/factories/test_level"
9
8
 
10
9
  require_relative "../ext/app_types"
@@ -117,7 +116,7 @@ module Datadog
117
116
  packer.write("library_version")
118
117
  packer.write(Datadog::CI::VERSION::STRING)
119
118
 
120
- library_capabilities_tags = Capabilities.tags
119
+ library_capabilities_tags = Ext::Test::LibraryCapabilities::CAPABILITY_VERSIONS
121
120
 
122
121
  Ext::AppTypes::CI_SPAN_TYPES.each do |ci_span_type|
123
122
  packer.write(ci_span_type)
@@ -10,11 +10,12 @@ module Datadog
10
10
  class Agentless < Base
11
11
  attr_reader :api_key
12
12
 
13
- def initialize(api_key:, citestcycle_url:, api_url:, citestcov_url:)
13
+ def initialize(api_key:, citestcycle_url:, api_url:, citestcov_url:, logs_intake_url:)
14
14
  @api_key = api_key
15
15
  @citestcycle_http = build_http_client(citestcycle_url, compress: true)
16
16
  @api_http = build_http_client(api_url, compress: false)
17
17
  @citestcov_http = build_http_client(citestcov_url, compress: true)
18
+ @logs_intake_http = build_http_client(logs_intake_url, compress: true)
18
19
  end
19
20
 
20
21
  def citestcycle_request(path:, payload:, headers: {}, verb: "post")
@@ -42,6 +43,12 @@ module Datadog
42
43
  perform_request(@citestcov_http, path: path, payload: @citestcov_payload, headers: headers, verb: verb)
43
44
  end
44
45
 
46
+ def logs_intake_request(path:, payload:, headers: {}, verb: "post")
47
+ super
48
+
49
+ perform_request(@logs_intake_http, path: path, payload: payload, headers: headers, verb: verb)
50
+ end
51
+
45
52
  private
46
53
 
47
54
  def perform_request(http_client, path:, payload:, headers:, verb:, accept_compressed_response: false)
@@ -38,6 +38,10 @@ module Datadog
38
38
  ].join("\r\n")
39
39
  end
40
40
 
41
+ def logs_intake_request(path:, payload:, headers: {}, verb: "post")
42
+ headers[Ext::Transport::HEADER_CONTENT_TYPE] ||= Ext::Transport::CONTENT_TYPE_JSON
43
+ end
44
+
41
45
  def headers_with_default(headers)
42
46
  request_headers = default_headers
43
47
  request_headers.merge!(headers)
@@ -27,11 +27,15 @@ module Datadog
27
27
  citestcov_url = settings.ci.agentless_url ||
28
28
  "https://#{Ext::Transport::TEST_COVERAGE_INTAKE_HOST_PREFIX}.#{dd_site}:443"
29
29
 
30
+ logs_intake_url = settings.ci.agentless_url ||
31
+ "https://#{Ext::Transport::LOGS_INTAKE_HOST_PREFIX}.#{dd_site}:443"
32
+
30
33
  Agentless.new(
31
34
  api_key: settings.api_key,
32
35
  citestcycle_url: citestcycle_url,
33
36
  api_url: api_url,
34
- citestcov_url: citestcov_url
37
+ citestcov_url: citestcov_url,
38
+ logs_intake_url: logs_intake_url
35
39
  )
36
40
  end
37
41
 
@@ -46,6 +46,10 @@ module Datadog
46
46
  perform_request(@agent_intake_http, path: path, payload: @citestcov_payload, headers: headers, verb: verb)
47
47
  end
48
48
 
49
+ def logs_intake_request(path:, payload:, headers: {}, verb: "post")
50
+ raise NotImplementedError, "Logs intake is not supported in EVP proxy mode"
51
+ end
52
+
49
53
  private
50
54
 
51
55
  def perform_request(http_client, path:, payload:, headers:, verb:)
@@ -29,7 +29,7 @@ module Datadog
29
29
  @host = host
30
30
  @port = port
31
31
  @timeout = timeout
32
- @ssl = ssl.nil? ? true : ssl
32
+ @ssl = ssl.nil? || ssl
33
33
  @compress = compress.nil? ? false : compress
34
34
  end
35
35
 
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "fileutils"
4
+ require "tempfile"
5
+
6
+ module Datadog
7
+ module CI
8
+ module Utils
9
+ # FileStorage module provides functionality for storing and retrieving arbitrary Ruby objects in a temp file
10
+ # to share them between processes.
11
+ module FileStorage
12
+ TEMP_DIR = File.join(Dir.tmpdir, "datadog-ci-storage")
13
+
14
+ def self.store(key, value)
15
+ ensure_temp_dir_exists
16
+ file_path = file_path_for(key)
17
+
18
+ File.binwrite(file_path, Marshal.dump(value))
19
+
20
+ true
21
+ rescue => e
22
+ Datadog.logger.error("Failed to store data for key '#{key}': #{e.class} - #{e.message}")
23
+ false
24
+ end
25
+
26
+ def self.retrieve(key)
27
+ file_path = file_path_for(key)
28
+ return nil unless File.exist?(file_path)
29
+
30
+ Marshal.load(File.binread(file_path))
31
+ rescue => e
32
+ Datadog.logger.error("Failed to retrieve data for key '#{key}': #{e.class} - #{e.message}")
33
+ nil
34
+ end
35
+
36
+ def self.cleanup
37
+ return false unless Dir.exist?(TEMP_DIR)
38
+
39
+ FileUtils.rm_rf(TEMP_DIR)
40
+ true
41
+ rescue => e
42
+ Datadog.logger.error("Failed to cleanup storage directory: #{e.class} - #{e.message}")
43
+ false
44
+ end
45
+
46
+ def self.ensure_temp_dir_exists
47
+ FileUtils.mkdir_p(TEMP_DIR) unless Dir.exist?(TEMP_DIR)
48
+ end
49
+
50
+ def self.file_path_for(key)
51
+ sanitized_key = key.to_s.gsub(/[^a-zA-Z0-9_-]/, "_")
52
+ File.join(TEMP_DIR, "dd-ci-#{sanitized_key}.dat")
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "file_storage"
4
+
5
+ module Datadog
6
+ module CI
7
+ module Utils
8
+ # Module for components that need to persist and restore state
9
+ module Stateful
10
+ # Store component state
11
+ def store_component_state
12
+ state = serialize_state
13
+
14
+ res = Utils::FileStorage.store(storage_key, state)
15
+ Datadog.logger.debug { "Stored component state (key=#{storage_key}): #{res}" }
16
+
17
+ res
18
+ end
19
+
20
+ # Load component state
21
+ def load_component_state
22
+ test_visibility_component = Datadog.send(:components).test_visibility
23
+ return false unless test_visibility_component.client_process?
24
+
25
+ state = Utils::FileStorage.retrieve(storage_key)
26
+ unless state
27
+ Datadog.logger.debug { "No component state found in file storage (key=#{storage_key})" }
28
+ return false
29
+ end
30
+
31
+ restore_state(state)
32
+ Datadog.logger.debug { "Loaded component state from file storage (key=#{storage_key})" }
33
+
34
+ true
35
+ end
36
+
37
+ # These methods must be implemented by including classes
38
+ def serialize_state
39
+ raise NotImplementedError, "Components must implement #serialize_state"
40
+ end
41
+
42
+ def restore_state(state)
43
+ raise NotImplementedError, "Components must implement #restore_state"
44
+ end
45
+
46
+ def storage_key
47
+ raise NotImplementedError, "Components must implement #storage_key"
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
@@ -4,7 +4,7 @@ module Datadog
4
4
  module CI
5
5
  module VERSION
6
6
  MAJOR = 1
7
- MINOR = 14
7
+ MINOR = 16
8
8
  PATCH = 0
9
9
  PRE = nil
10
10
  BUILD = nil
data/lib/datadog/ci.rb CHANGED
@@ -415,19 +415,23 @@ end
415
415
 
416
416
  # Integrations
417
417
 
418
- # Test frameworks (manual instrumentation)
418
+ # Test frameworks
419
419
  require_relative "ci/contrib/cucumber/integration"
420
420
  require_relative "ci/contrib/minitest/integration"
421
421
  require_relative "ci/contrib/rspec/integration"
422
422
 
423
- # Test runners (instrumented automatically when corresponding frameworks are instrumented)
423
+ # Test runners
424
424
  require_relative "ci/contrib/knapsack/integration"
425
425
  require_relative "ci/contrib/ciqueue/integration"
426
+ require_relative "ci/contrib/parallel_tests/integration"
426
427
 
427
- # Additional test libraries (auto instrumented later on test session start)
428
+ # Additional test libraries (auto instrumented on test session start)
428
429
  require_relative "ci/contrib/selenium/integration"
429
430
  require_relative "ci/contrib/cuprite/integration"
430
431
  require_relative "ci/contrib/simplecov/integration"
432
+ require_relative "ci/contrib/activesupport/integration"
433
+ require_relative "ci/contrib/lograge/integration"
434
+ require_relative "ci/contrib/semantic_logger/integration"
431
435
 
432
436
  # Configuration extensions
433
437
  require_relative "ci/configuration/extensions"