datadog-ci 1.30.0 → 1.32.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 (35) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +29 -2
  3. data/ext/datadog_ci_native/ci.c +1 -1
  4. data/ext/datadog_ci_native/iseq_collector.c +1 -1
  5. data/ext/datadog_ci_native/iseq_collector.h +1 -1
  6. data/lib/datadog/ci/configuration/components.rb +15 -2
  7. data/lib/datadog/ci/configuration/settings.rb +21 -0
  8. data/lib/datadog/ci/contrib/minitest/helpers.rb +5 -2
  9. data/lib/datadog/ci/contrib/minitest/run_method_capture.rb +47 -0
  10. data/lib/datadog/ci/contrib/minitest/test.rb +72 -14
  11. data/lib/datadog/ci/ext/environment/providers/jenkins.rb +2 -1
  12. data/lib/datadog/ci/ext/test_discovery.rb +3 -1
  13. data/lib/datadog/ci/ext/test_optimization_cache.rb +31 -0
  14. data/lib/datadog/ci/git/tree_uploader.rb +6 -3
  15. data/lib/datadog/ci/remote/component.rb +4 -4
  16. data/lib/datadog/ci/remote/library_settings.rb +7 -1
  17. data/lib/datadog/ci/test_impact_analysis/component.rb +5 -65
  18. data/lib/datadog/ci/test_management/component.rb +4 -14
  19. data/lib/datadog/ci/test_optimization_cache/component.rb +82 -0
  20. data/lib/datadog/ci/test_optimization_cache/locator.rb +96 -0
  21. data/lib/datadog/ci/test_optimization_cache/null_component.rb +32 -0
  22. data/lib/datadog/ci/test_optimization_cache/readers/base.rb +39 -0
  23. data/lib/datadog/ci/test_optimization_cache/readers/legacy.rb +74 -0
  24. data/lib/datadog/ci/test_optimization_cache/readers/missing.rb +33 -0
  25. data/lib/datadog/ci/test_optimization_cache/readers/v1.rb +56 -0
  26. data/lib/datadog/ci/test_tracing/component.rb +4 -11
  27. data/lib/datadog/ci/test_tracing/serializers/base.rb +4 -1
  28. data/lib/datadog/ci/test_tracing/serializers/meta_truncation.rb +23 -0
  29. data/lib/datadog/ci/test_tracing/transport.rb +10 -7
  30. data/lib/datadog/ci/utils/json.rb +23 -0
  31. data/lib/datadog/ci/utils/stateful.rb +18 -20
  32. data/lib/datadog/ci/utils/test_run.rb +0 -6
  33. data/lib/datadog/ci/version.rb +1 -1
  34. metadata +12 -2
  35. data/lib/datadog/ci/ext/dd_test.rb +0 -18
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 129bc549b30318587b435c3836517faa058dac0860f07eca408fc5562186e52f
4
- data.tar.gz: 4a8c2756b9c846a4b5b225c51e0d1b3910e24c550f60adce4b47f968981a2b8d
3
+ metadata.gz: 9525584d2c9951d35efe82ecfead3c45e104ced47bddaa5c11146147dfab1ed8
4
+ data.tar.gz: 438719f7fb308e58196321706bf03beeda21c717875e9a23d88027a485d5dfba
5
5
  SHA512:
6
- metadata.gz: ee1ceadbb2c83d09c780bfe517d52dd4a55b5a4a4dc6802fea1e653fe06b308e7eda9a90a420c1ff855b59b27a7ada8253f319f55664ade19cceb5cab79e3c60
7
- data.tar.gz: f297af41a17c77ef5c123ad71a79e92a489218bea1b081d802f414a8496fe7e7ca4da50cde169c290ea3a6c0b189a3987f88f07cdf54bb4c822958527ac26117
6
+ metadata.gz: d1537eb0f893513d6ba2b2ccfacecfd2ff424c8f0d1f84ef27045d03d0d4963046b8c1df0611c7360cfbdd6a6a893e74804377b725b6439a559e27fe8e9ce57b
7
+ data.tar.gz: 31d30f06434ec6305d17000499879d1133a7f472ba01c3300d30effe2abf770b0f7bb002390a984baf9b77febbc3e4dc9b9390f249a2c81a66aa68ecd37bf344
data/CHANGELOG.md CHANGED
@@ -1,5 +1,24 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [1.32.0] - 2026-06-08
4
+
5
+ ### Changed
6
+
7
+ * Truncate CI Visibility meta tag values ([#515][])
8
+
9
+ ### Fixed
10
+
11
+ * Fix Minitest TIA skipped hooks ([#516][])
12
+ * Fix: use Gem::Version for Ruby allocation tracing check ([#522][])
13
+ * Fix symbol collision with a debug gem ([#521][])
14
+
15
+ ## [1.31.0] - 2026-05-20
16
+
17
+ ### Added
18
+
19
+ * Add Test Optimization cache readers for Bazel support and DDTest (test parallelization) ([#511][])
20
+ * Add Jenkins custom parent id env var ([#509][])
21
+
3
22
  ## [1.30.0] - 2026-05-12
4
23
 
5
24
  ### Changed
@@ -634,7 +653,9 @@ Currently test suite level visibility is not used by our instrumentation: it wil
634
653
 
635
654
  - Ruby versions < 2.7 no longer supported ([#8][])
636
655
 
637
- [Unreleased]: https://github.com/DataDog/datadog-ci-rb/compare/v1.30.0...main
656
+ [Unreleased]: https://github.com/DataDog/datadog-ci-rb/compare/v1.32.0...main
657
+ [1.32.0]: https://github.com/DataDog/datadog-ci-rb/compare/v1.31.0...v1.32.0
658
+ [1.31.0]: https://github.com/DataDog/datadog-ci-rb/compare/v1.30.0...v1.31.0
638
659
  [1.30.0]: https://github.com/DataDog/datadog-ci-rb/compare/v1.29.0...v1.30.0
639
660
  [1.29.0]: https://github.com/DataDog/datadog-ci-rb/compare/v1.28.0...v1.29.0
640
661
  [1.28.0]: https://github.com/DataDog/datadog-ci-rb/compare/v1.27.0...v1.28.0
@@ -898,4 +919,10 @@ Currently test suite level visibility is not used by our instrumentation: it wil
898
919
  [#499]: https://github.com/DataDog/datadog-ci-rb/issues/499
899
920
  [#500]: https://github.com/DataDog/datadog-ci-rb/issues/500
900
921
  [#501]: https://github.com/DataDog/datadog-ci-rb/issues/501
901
- [#506]: https://github.com/DataDog/datadog-ci-rb/issues/506
922
+ [#506]: https://github.com/DataDog/datadog-ci-rb/issues/506
923
+ [#509]: https://github.com/DataDog/datadog-ci-rb/issues/509
924
+ [#511]: https://github.com/DataDog/datadog-ci-rb/issues/511
925
+ [#515]: https://github.com/DataDog/datadog-ci-rb/issues/515
926
+ [#516]: https://github.com/DataDog/datadog-ci-rb/issues/516
927
+ [#521]: https://github.com/DataDog/datadog-ci-rb/issues/521
928
+ [#522]: https://github.com/DataDog/datadog-ci-rb/issues/522
@@ -8,5 +8,5 @@ void Init_datadog_ci_native(void) {
8
8
 
9
9
  // SourceCode
10
10
  Init_datadog_method_inspect();
11
- Init_iseq_collector();
11
+ Init_dd_ci_iseq_collector();
12
12
  }
@@ -54,7 +54,7 @@ static VALUE iseq_collector_collect(VALUE self) {
54
54
 
55
55
  /* ---- Module initialization ---------------------------------------------- */
56
56
 
57
- void Init_iseq_collector(void) {
57
+ void Init_dd_ci_iseq_collector(void) {
58
58
  VALUE mDatadog = rb_define_module("Datadog");
59
59
  VALUE mCI = rb_define_module_under(mDatadog, "CI");
60
60
  VALUE mSourceCode = rb_define_module_under(mCI, "SourceCode");
@@ -1,6 +1,6 @@
1
1
  #ifndef ISEQ_COLLECTOR_H
2
2
  #define ISEQ_COLLECTOR_H
3
3
 
4
- void Init_iseq_collector(void);
4
+ void Init_dd_ci_iseq_collector(void);
5
5
 
6
6
  #endif /* ISEQ_COLLECTOR_H */
@@ -17,6 +17,8 @@ require_relative "../remote/library_settings_client"
17
17
  require_relative "../test_management/component"
18
18
  require_relative "../test_management/null_component"
19
19
  require_relative "../test_management/tests_properties"
20
+ require_relative "../test_optimization_cache/component"
21
+ require_relative "../test_optimization_cache/null_component"
20
22
  require_relative "../test_impact_analysis/null_component"
21
23
  require_relative "../test_impact_analysis/component"
22
24
  require_relative "../test_impact_analysis/coverage/transport"
@@ -45,7 +47,8 @@ module Datadog
45
47
  # Adds CI behavior to Datadog trace components
46
48
  module Components
47
49
  attr_reader :test_tracing, :test_impact_analysis, :git_tree_upload_worker, :ci_remote, :test_retries,
48
- :test_management, :agentless_logs_submission, :impacted_tests_detection, :test_discovery, :code_coverage
50
+ :test_management, :agentless_logs_submission, :impacted_tests_detection, :test_discovery, :code_coverage,
51
+ :test_optimization_cache
49
52
 
50
53
  def initialize(settings)
51
54
  @test_impact_analysis = TestImpactAnalysis::NullComponent.new
@@ -57,6 +60,7 @@ module Datadog
57
60
  @impacted_tests_detection = ImpactedTestsDetection::NullComponent.new
58
61
  @test_discovery = TestDiscovery::NullComponent.new
59
62
  @code_coverage = CodeCoverage::NullComponent.new
63
+ @test_optimization_cache = TestOptimizationCache::NullComponent.new
60
64
 
61
65
  # Activate CI mode if enabled
62
66
  if settings.ci.enabled
@@ -69,6 +73,7 @@ module Datadog
69
73
  def shutdown!(replacement = nil)
70
74
  super
71
75
 
76
+ @test_optimization_cache&.shutdown!
72
77
  @test_tracing&.shutdown!
73
78
  @test_impact_analysis&.shutdown!
74
79
  @agentless_logs_submission&.shutdown!
@@ -113,6 +118,13 @@ module Datadog
113
118
  )
114
119
  @test_discovery.disable_features_for_test_discovery!(settings)
115
120
 
121
+ @test_optimization_cache = TestOptimizationCache::Component.new(
122
+ manifest_file: settings.ci.test_optimization_cache_manifest_file,
123
+ runfiles_dir: settings.ci.test_optimization_cache_runfiles_dir,
124
+ runfiles_manifest_file: settings.ci.test_optimization_cache_runfiles_manifest_file,
125
+ test_srcdir: settings.ci.test_optimization_cache_test_srcdir
126
+ )
127
+
116
128
  # Configure Datadog::Tracing module
117
129
 
118
130
  # No need not use 128-bit trace ids for test visibility,
@@ -180,7 +192,8 @@ module Datadog
180
192
  settings.ci.itr_test_impact_analysis_use_allocation_tracing = false
181
193
  end
182
194
 
183
- if RUBY_VERSION.start_with?("3.2.") && RUBY_VERSION < "3.2.3" &&
195
+ if RUBY_VERSION.start_with?("3.2.") &&
196
+ Gem::Version.new(RUBY_VERSION) < Gem::Version.new("3.2.3") &&
184
197
  settings.ci.itr_test_impact_analysis_use_allocation_tracing
185
198
  Datadog.logger.warn(
186
199
  "Test Impact Analysis: Allocation tracing is not supported in Ruby versions 3.2.0, 3.2.1 and 3.2.2 and will be forcibly " \
@@ -2,6 +2,7 @@
2
2
 
3
3
  require_relative "../contrib/instrumentation"
4
4
  require_relative "../ext/settings"
5
+ require_relative "../ext/test_optimization_cache"
5
6
  require_relative "../utils/bundle"
6
7
  require_relative "../utils/parsing"
7
8
 
@@ -180,6 +181,26 @@ module Datadog
180
181
  o.env CI::Ext::Settings::ENV_TEST_DISCOVERY_OUTPUT_PATH
181
182
  end
182
183
 
184
+ option :test_optimization_cache_manifest_file do |o|
185
+ o.type :string, nilable: true
186
+ o.env CI::Ext::TestOptimizationCache::ENV_MANIFEST_FILE
187
+ end
188
+
189
+ option :test_optimization_cache_runfiles_dir do |o|
190
+ o.type :string, nilable: true
191
+ o.env CI::Ext::TestOptimizationCache::ENV_RUNFILES_DIR
192
+ end
193
+
194
+ option :test_optimization_cache_runfiles_manifest_file do |o|
195
+ o.type :string, nilable: true
196
+ o.env CI::Ext::TestOptimizationCache::ENV_RUNFILES_MANIFEST_FILE
197
+ end
198
+
199
+ option :test_optimization_cache_test_srcdir do |o|
200
+ o.type :string, nilable: true
201
+ o.env CI::Ext::TestOptimizationCache::ENV_TEST_SRCDIR
202
+ end
203
+
183
204
  option :tia_static_dependencies_tracking_enabled do |o|
184
205
  o.type :bool
185
206
  o.env CI::Ext::Settings::ENV_TIA_STATIC_DEPENDENCIES_TRACKING_ENABLED
@@ -61,8 +61,11 @@ module Datadog
61
61
  end
62
62
 
63
63
  def self.parallel?(klass)
64
- klass.ancestors.include?(::Minitest::Parallel::Test) ||
65
- (defined?(::Minitest::Queue) && ::Minitest.singleton_class.ancestors.include?(::Minitest::Queue))
64
+ klass.ancestors.include?(::Minitest::Parallel::Test) || ci_queue?
65
+ end
66
+
67
+ def self.ci_queue?
68
+ !!(defined?(::Minitest::Queue) && ::Minitest.singleton_class.ancestors.include?(::Minitest::Queue))
66
69
  end
67
70
 
68
71
  def self.extract_source_location_from_class(klass)
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Datadog
4
+ module CI
5
+ module Contrib
6
+ module Minitest
7
+ # Captures the concrete Minitest::Test#run implementation below Datadog.
8
+ #
9
+ # This exists because ci-queue loads minitest-reporters, and minitest-reporters
10
+ # aliases the current Minitest::Test#run as run_without_hooks before replacing it
11
+ # with its own wrapper. If Datadog has already prepended its run method, that alias
12
+ # points back to Datadog and re-enters the same active test span.
13
+ #
14
+ # Auto-instrumentation makes this trickier: it patches from a script_compiled
15
+ # TracePoint, so it can observe Minitest::Test while `require "minitest"` is still
16
+ # evaluating the class body. In that window Minitest::Test exists, but its concrete
17
+ # #run has not been defined yet, so instance_method(:run) resolves to the abstract
18
+ # Minitest::Runnable#run. The one-shot method_added path below replaces that early
19
+ # abstract capture with the concrete Minitest::Test#run, before later plugin wrappers
20
+ # like minitest-reporters can alias Datadog's wrapper.
21
+ module RunMethodCapture
22
+ class << self
23
+ def capture_concrete_pre_datadog_run!(storage, owner, datadog_run_owner)
24
+ saved_run = storage._dd_pre_datadog_minitest_run
25
+ return if concrete_pre_datadog_run?(saved_run, datadog_run_owner)
26
+ return if !defined?(::Minitest::Test) || !owner.equal?(::Minitest::Test)
27
+
28
+ datadog_run = owner.instance_method(:run)
29
+ return unless datadog_run.owner == datadog_run_owner
30
+
31
+ candidate_run = datadog_run.super_method
32
+ if concrete_pre_datadog_run?(candidate_run, datadog_run_owner)
33
+ storage._dd_pre_datadog_minitest_run = candidate_run
34
+ end
35
+ end
36
+
37
+ def concrete_pre_datadog_run?(method, datadog_run_owner)
38
+ method &&
39
+ method.owner != datadog_run_owner &&
40
+ (!defined?(::Minitest::Runnable) || method.owner != ::Minitest::Runnable)
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -6,6 +6,7 @@ require_relative "../../source_code/method_inspect"
6
6
  require_relative "../instrumentation"
7
7
  require_relative "ext"
8
8
  require_relative "helpers"
9
+ require_relative "run_method_capture"
9
10
 
10
11
  module Datadog
11
12
  module CI
@@ -13,16 +14,68 @@ module Datadog
13
14
  module Minitest
14
15
  # Lifecycle hooks to instrument Minitest::Test
15
16
  module Test
17
+ class << self
18
+ attr_accessor :_dd_pre_datadog_minitest_run
19
+ end
20
+
16
21
  def self.included(base)
17
- base.prepend(InstanceMethods)
18
- base.singleton_class.prepend(ClassMethods)
22
+ unless base < InstanceMethods
23
+ # Preserve the run implementation that existed before Datadog was prepended.
24
+ # RunMethodCapture repairs this if auto-instrumentation observes Minitest::Test
25
+ # before Minitest defines its concrete #run. See that helper for the ci-queue
26
+ # and minitest-reporters load-order details.
27
+ self._dd_pre_datadog_minitest_run = base.instance_method(:run)
28
+ base.prepend(InstanceMethods)
29
+ end
30
+
31
+ base.singleton_class.prepend(ClassMethods) unless base.singleton_class < ClassMethods
19
32
  end
20
33
 
21
34
  module InstanceMethods
22
- def before_setup
35
+ def run
36
+ return super unless datadog_configuration[:enabled]
37
+
38
+ return run_without_datadog_reentry if datadog_run_reentered?
39
+
40
+ test_span = start_datadog_test
41
+ return skip_datadog_test(test_span) if test_span&.should_skip?
42
+
43
+ super
44
+ end
45
+
46
+ def after_teardown
47
+ test_span = _dd_test_tracing_component.active_test
48
+ return super unless test_span
49
+
50
+ finish_with_result(test_span, result_code)
51
+
52
+ # remove failures if failure can be ignored because of retries
53
+ self.failures = [] if test_span.should_ignore_failures?
54
+
23
55
  super
24
- return unless datadog_configuration[:enabled]
56
+ end
57
+
58
+ private
25
59
 
60
+ def datadog_run_reentered?
61
+ !!_dd_test_tracing_component.active_test
62
+ end
63
+
64
+ def run_without_datadog_reentry
65
+ Datadog.logger.debug do
66
+ "Datadog Minitest instrumentation re-entered for #{self.class}##{name}; running pre-Datadog Minitest run without starting another test span"
67
+ end
68
+
69
+ pre_datadog_minitest_run = Test._dd_pre_datadog_minitest_run
70
+ if RunMethodCapture.concrete_pre_datadog_run?(pre_datadog_minitest_run, InstanceMethods)
71
+ return pre_datadog_minitest_run.bind_call(self)
72
+ end
73
+
74
+ raise "Datadog Minitest instrumentation re-entered for #{self.class}##{name}, " \
75
+ "but the concrete pre-Datadog Minitest::Test#run method was not captured"
76
+ end
77
+
78
+ def start_datadog_test
26
79
  if Helpers.parallel?(self.class)
27
80
  Helpers.start_test_suite(self.class)
28
81
  end
@@ -55,23 +108,22 @@ module Datadog
55
108
  # steep:ignore:start
56
109
  test_span&.itr_unskippable! if self.class.dd_suite_unskippable? || self.class.dd_test_unskippable?(name)
57
110
  # steep:ignore:end
58
- skip(test_span&.datadog_skip_reason) if test_span&.should_skip?
111
+
112
+ test_span
59
113
  end
60
114
 
61
- def after_teardown
62
- test_span = _dd_test_tracing_component.active_test
63
- return super unless test_span
115
+ def skip_datadog_test(test_span)
116
+ time_it do
117
+ capture_exceptions do
118
+ skip(test_span.datadog_skip_reason)
119
+ end
120
+ end
64
121
 
65
122
  finish_with_result(test_span, result_code)
66
123
 
67
- # remove failures if failure can be ignored because of retries
68
- self.failures = [] if test_span.should_ignore_failures?
69
-
70
- super
124
+ ::Minitest::Result.from(self)
71
125
  end
72
126
 
73
- private
74
-
75
127
  def finish_with_result(span, result_code)
76
128
  return unless span
77
129
 
@@ -101,6 +153,12 @@ module Datadog
101
153
  end
102
154
 
103
155
  module ClassMethods
156
+ def method_added(method_name)
157
+ RunMethodCapture.capture_concrete_pre_datadog_run!(Test, self, InstanceMethods) if method_name == :run
158
+ ensure
159
+ super
160
+ end
161
+
104
162
  def datadog_itr_unskippable(*args)
105
163
  if args.nil? || args.empty?
106
164
  @datadog_itr_unskippable_suite = true
@@ -75,7 +75,8 @@ module Datadog
75
75
 
76
76
  def ci_env_vars
77
77
  {
78
- "DD_CUSTOM_TRACE_ID" => env["DD_CUSTOM_TRACE_ID"]
78
+ "DD_CUSTOM_TRACE_ID" => env["DD_CUSTOM_TRACE_ID"],
79
+ "DD_CUSTOM_PARENT_ID" => env["DD_CUSTOM_PARENT_ID"]
79
80
  }.to_json
80
81
  end
81
82
  end
@@ -1,12 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative "test_optimization_cache"
4
+
3
5
  module Datadog
4
6
  module CI
5
7
  module Ext
6
8
  # Defines constants for test discovery mode
7
9
  module TestDiscovery
8
10
  # Default output path for test discovery mode
9
- DEFAULT_OUTPUT_PATH = "./#{DDTest::PLAN_FOLDER}/test_discovery/tests.json"
11
+ DEFAULT_OUTPUT_PATH = "./#{TestOptimizationCache::PLAN_FOLDER}/test_discovery/tests.json"
10
12
 
11
13
  # Maximum buffer size before writing to file
12
14
  MAX_BUFFER_SIZE = 10_000
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Datadog
4
+ module CI
5
+ module Ext
6
+ # Constants for Test Optimization cache generated by ddtest or Bazel.
7
+ module TestOptimizationCache
8
+ ENV_MANIFEST_FILE = "TEST_OPTIMIZATION_MANIFEST_FILE"
9
+ ENV_RUNFILES_DIR = "RUNFILES_DIR"
10
+ ENV_RUNFILES_MANIFEST_FILE = "RUNFILES_MANIFEST_FILE"
11
+ ENV_TEST_SRCDIR = "TEST_SRCDIR"
12
+
13
+ PLAN_FOLDER = ".testoptimization"
14
+ MANIFEST_FILE_NAME = "manifest.txt"
15
+ SUPPORTED_MANIFEST_VERSION = "1"
16
+
17
+ CACHE_FOLDER_NAME = "cache"
18
+ HTTP_CACHE_FOLDER_NAME = "http"
19
+
20
+ TESTOPTIMIZATION_CACHE_PATH = "#{PLAN_FOLDER}/#{CACHE_FOLDER_NAME}"
21
+ TESTOPTIMIZATION_HTTP_CACHE_PATH = "#{TESTOPTIMIZATION_CACHE_PATH}/#{HTTP_CACHE_FOLDER_NAME}"
22
+
23
+ SETTINGS_FILE_NAME = "settings.json"
24
+ KNOWN_TESTS_FILE_NAME = "known_tests.json"
25
+ TEST_MANAGEMENT_FILE_NAME = "test_management.json"
26
+ LEGACY_TEST_MANAGEMENT_TESTS_FILE_NAME = "test_management_tests.json"
27
+ SKIPPABLE_TESTS_FILE_NAME = "skippable_tests.json"
28
+ end
29
+ end
30
+ end
31
+ end
@@ -10,7 +10,6 @@ require_relative "packfiles"
10
10
 
11
11
  require_relative "../ext/telemetry"
12
12
  require_relative "../utils/telemetry"
13
- require_relative "../utils/test_run"
14
13
 
15
14
  module Datadog
16
15
  module CI
@@ -34,8 +33,8 @@ module Datadog
34
33
  return
35
34
  end
36
35
 
37
- if Utils::TestRun.test_optimization_data_cached?
38
- Datadog.logger.debug("DDTest cache found, git upload already done by DDTest tool, skipping git upload")
36
+ if test_optimization_cache.cache_available?
37
+ Datadog.logger.debug("Test Optimization cache found, git upload already done, skipping git upload")
39
38
  return
40
39
  end
41
40
 
@@ -113,6 +112,10 @@ module Datadog
113
112
  def test_tracing_component
114
113
  Datadog.send(:components).test_tracing
115
114
  end
115
+
116
+ def test_optimization_cache
117
+ Datadog.send(:components).test_optimization_cache
118
+ end
116
119
  end
117
120
  end
118
121
  end
@@ -56,15 +56,15 @@ module Datadog
56
56
  end
57
57
 
58
58
  def restore_state_from_datadog_test_runner
59
- Datadog.logger.debug { "Restoring library configuration from DDTest cache" }
59
+ Datadog.logger.debug { "Restoring library configuration from Test Optimization cache" }
60
60
 
61
- settings = load_json(Ext::DDTest::SETTINGS_FILE_NAME)
61
+ settings = load_cached_settings
62
62
  if settings.nil?
63
63
  Datadog.logger.debug { "Restoring library configuration failed, will request again" }
64
64
  return false
65
65
  end
66
66
 
67
- Datadog.logger.debug { "Restored library configuration from DDTest: #{settings}" }
67
+ Datadog.logger.debug { "Restored library configuration from Test Optimization: #{settings}" }
68
68
  @library_configuration = LibrarySettings.from_json(settings)
69
69
  true
70
70
  end
@@ -75,7 +75,7 @@ module Datadog
75
75
  # In test discovery mode, skip backend fetching and use default settings (everything is disabled)
76
76
  return @library_configuration = LibrarySettings.from_http_response(nil) if @test_discovery_enabled
77
77
 
78
- # skip backend request if library configuration was loaded by a different process and stored on disk
78
+ # skip backend request if library configuration was loaded from external cache or stored on disk
79
79
  library_configuration_loaded = load_component_state
80
80
  return @library_configuration if library_configuration_loaded
81
81
 
@@ -19,7 +19,13 @@ module Datadog
19
19
  end
20
20
 
21
21
  def self.from_json(json)
22
- new(nil, json)
22
+ new(nil, normalize_json(json))
23
+ end
24
+
25
+ def self.normalize_json(json)
26
+ return nil if json.nil?
27
+
28
+ json.dig(*Ext::Transport::DD_API_SETTINGS_RESPONSE_DIG_KEYS) || json
23
29
  end
24
30
 
25
31
  def ok?
@@ -6,7 +6,6 @@ require "datadog/core/telemetry/logging"
6
6
 
7
7
  require_relative "../ext/test"
8
8
  require_relative "../ext/telemetry"
9
- require_relative "../ext/dd_test"
10
9
 
11
10
  require_relative "../git/local_repository"
12
11
 
@@ -102,11 +101,9 @@ module Datadog
102
101
  populate_static_dependencies_map!
103
102
  end
104
103
 
105
- # Load component state first, and if successful, skip fetching skippable tests
106
- # Also try to restore from DDTest cache if available
104
+ # Load external cache or component state first, and if successful, skip fetching skippable tests
107
105
  if skipping_tests?
108
106
  return if load_component_state
109
- return if restore_state_from_datadog_test_runner
110
107
 
111
108
  fetch_skippable_tests(test_session)
112
109
  store_component_state if test_session.distributed
@@ -333,22 +330,17 @@ module Datadog
333
330
  end
334
331
 
335
332
  def restore_state_from_datadog_test_runner
336
- Datadog.logger.debug { "Restoring skippable tests from DDTest cache" }
333
+ Datadog.logger.debug { "Restoring skippable tests from Test Optimization cache" }
337
334
 
338
- skippable_tests_data = load_json(Ext::DDTest::SKIPPABLE_TESTS_FILE_NAME)
335
+ skippable_tests_data = load_cached_skippable_tests
339
336
  if skippable_tests_data.nil?
340
337
  Datadog.logger.debug { "Restoring skippable tests failed, will request again" }
341
338
  return false
342
339
  end
343
340
 
344
- Datadog.logger.debug { "Restored skippable tests from DDTest: #{skippable_tests_data}" }
341
+ Datadog.logger.debug { "Restored skippable tests from Test Optimization: #{skippable_tests_data}" }
345
342
 
346
- transformed_data = transform_test_runner_data(skippable_tests_data)
347
-
348
- Datadog.logger.debug { "Skippable tests after transformation: #{transformed_data}" }
349
-
350
- # Use the Skippable::Response class to parse the transformed data
351
- skippable_response = Skippable::Response.from_json(transformed_data)
343
+ skippable_response = Skippable::Response.from_json(skippable_tests_data)
352
344
 
353
345
  @mutex.synchronize do
354
346
  @correlation_id = skippable_response.correlation_id
@@ -363,58 +355,6 @@ module Datadog
363
355
 
364
356
  private
365
357
 
366
- # Transforms Test Runner skippable tests data format to the format expected by Skippable::Response
367
- #
368
- # Test Runner format:
369
- # {
370
- # "correlationId": "abc123",
371
- # "skippableTests": {
372
- # "suite_name": {
373
- # "test_name": [{"suite": "suite_name", "name": "test_name", "parameters": "{...}", "configurations": {}}]
374
- # }
375
- # }
376
- # }
377
- #
378
- # Expected format:
379
- # {
380
- # "meta": {"correlation_id": "abc123"},
381
- # "data": [{"type": "test", "attributes": {"suite": "suite_name", "name": "test_name", "parameters": "{...}"}}]
382
- # }
383
- def transform_test_runner_data(skippable_tests_data)
384
- skippable_tests = skippable_tests_data.fetch("skippableTests", {}) || {}
385
-
386
- # Pre-calculate array size for better memory allocation
387
- total_test_configs = skippable_tests.sum do |_, tests_hash|
388
- tests_hash.sum { |_, test_configs| test_configs.size }
389
- end
390
-
391
- data_array = Array.new(total_test_configs)
392
- index = 0
393
-
394
- skippable_tests.each_value do |tests_hash|
395
- tests_hash.each_value do |test_configs|
396
- test_configs.each do |test_config|
397
- data_array[index] = {
398
- "type" => Ext::Test::ITR_TEST_SKIPPING_MODE,
399
- "attributes" => {
400
- "suite" => test_config["suite"],
401
- "name" => test_config["name"],
402
- "parameters" => test_config["parameters"]
403
- }
404
- }
405
- index += 1
406
- end
407
- end
408
- end
409
-
410
- {
411
- "meta" => {
412
- "correlation_id" => skippable_tests_data["correlationId"]
413
- },
414
- "data" => data_array
415
- }
416
- end
417
-
418
358
  def write(event)
419
359
  # skip sending events if writer is not configured
420
360
  @coverage_writer&.write(event)
@@ -2,7 +2,6 @@
2
2
 
3
3
  require_relative "../ext/telemetry"
4
4
  require_relative "../ext/test"
5
- require_relative "../ext/dd_test"
6
5
  require_relative "../utils/stateful"
7
6
  require_relative "../utils/telemetry"
8
7
  require_relative "../utils/test_run"
@@ -36,7 +35,6 @@ module Datadog
36
35
 
37
36
  test_session.set_tag(Ext::Test::TAG_TEST_MANAGEMENT_ENABLED, "true")
38
37
 
39
- return if restore_state_from_datadog_test_runner
40
38
  return if load_component_state
41
39
 
42
40
  @tests_properties = @tests_properties_client.fetch(test_session)
@@ -85,25 +83,17 @@ module Datadog
85
83
  end
86
84
 
87
85
  def restore_state_from_datadog_test_runner
88
- Datadog.logger.debug { "Restoring test management tests from DDTest cache" }
86
+ Datadog.logger.debug { "Restoring test management tests from Test Optimization cache" }
89
87
 
90
- test_management_data = load_json(Ext::DDTest::TEST_MANAGEMENT_TESTS_FILE_NAME)
88
+ test_management_data = load_cached_test_management
91
89
  if test_management_data.nil?
92
90
  Datadog.logger.debug { "Restoring test management tests failed, will request again" }
93
91
  return false
94
92
  end
95
93
 
96
- Datadog.logger.debug { "Restored test management tests from DDTest: #{test_management_data}" }
94
+ Datadog.logger.debug { "Restored test management tests from Test Optimization: #{test_management_data}" }
97
95
 
98
- # Use the TestsProperties::Response class method to parse the JSON data
99
- # Wrap the data in the expected backend API format
100
- wrapped_data = {
101
- "data" => {
102
- "attributes" => test_management_data
103
- }
104
- }
105
-
106
- tests_properties_response = TestsProperties::Response.from_json(wrapped_data)
96
+ tests_properties_response = TestsProperties::Response.from_json(test_management_data)
107
97
  @tests_properties = tests_properties_response.tests
108
98
 
109
99
  Datadog.logger.debug { "Found [#{@tests_properties.size}] test management tests from context" }