datadog-ci 1.31.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: de36af96e9eef5f7bffcfe3a3cb8e80ff08461b8f10795bff6a54e53d340a1c6
4
- data.tar.gz: 5bdf32ef644ecaac3c57b55f94338359db56e18bea76fec6c40c76fbd1a907bd
3
+ metadata.gz: 9525584d2c9951d35efe82ecfead3c45e104ced47bddaa5c11146147dfab1ed8
4
+ data.tar.gz: 438719f7fb308e58196321706bf03beeda21c717875e9a23d88027a485d5dfba
5
5
  SHA512:
6
- metadata.gz: 702a1219da6c81acc12d6eca8743de08ff97dd5cdf728ff02556bb282673ac913502f49dd4db02bb4ddd119e8102a9ceacc4a081624a48fe256d3f402efa1887
7
- data.tar.gz: 2470ec968a63e625234fe7cb70e9faadf7ce1ccc5a9cf9f04c668c271b693f6b3a3b38f3b5821e27908f299bf58773122b268decbbf3e65596a63cc39509be04
6
+ metadata.gz: d1537eb0f893513d6ba2b2ccfacecfd2ff424c8f0d1f84ef27045d03d0d4963046b8c1df0611c7360cfbdd6a6a893e74804377b725b6439a559e27fe8e9ce57b
7
+ data.tar.gz: 31d30f06434ec6305d17000499879d1133a7f472ba01c3300d30effe2abf770b0f7bb002390a984baf9b77febbc3e4dc9b9390f249a2c81a66aa68ecd37bf344
data/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
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
+
3
15
  ## [1.31.0] - 2026-05-20
4
16
 
5
17
  ### Added
@@ -641,7 +653,8 @@ Currently test suite level visibility is not used by our instrumentation: it wil
641
653
 
642
654
  - Ruby versions < 2.7 no longer supported ([#8][])
643
655
 
644
- [Unreleased]: https://github.com/DataDog/datadog-ci-rb/compare/v1.31.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
645
658
  [1.31.0]: https://github.com/DataDog/datadog-ci-rb/compare/v1.30.0...v1.31.0
646
659
  [1.30.0]: https://github.com/DataDog/datadog-ci-rb/compare/v1.29.0...v1.30.0
647
660
  [1.29.0]: https://github.com/DataDog/datadog-ci-rb/compare/v1.28.0...v1.29.0
@@ -909,3 +922,7 @@ Currently test suite level visibility is not used by our instrumentation: it wil
909
922
  [#506]: https://github.com/DataDog/datadog-ci-rb/issues/506
910
923
  [#509]: https://github.com/DataDog/datadog-ci-rb/issues/509
911
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 */
@@ -192,7 +192,8 @@ module Datadog
192
192
  settings.ci.itr_test_impact_analysis_use_allocation_tracing = false
193
193
  end
194
194
 
195
- 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") &&
196
197
  settings.ci.itr_test_impact_analysis_use_allocation_tracing
197
198
  Datadog.logger.warn(
198
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 " \
@@ -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
@@ -3,6 +3,7 @@
3
3
  require "set"
4
4
 
5
5
  require_relative "../../ext/test"
6
+ require_relative "meta_truncation"
6
7
 
7
8
  module Datadog
8
9
  module CI
@@ -29,7 +30,9 @@ module Datadog
29
30
  @span = span
30
31
  @options = options
31
32
 
32
- @meta = @span.meta.reject { |key, _| Ext::Test::TRANSIENT_TAGS.include?(key) }
33
+ @meta = MetaTruncation.truncate_string_values(
34
+ @span.meta.reject { |key, _| Ext::Test::TRANSIENT_TAGS.include?(key) }
35
+ )
33
36
 
34
37
  @errors = {}
35
38
  @validated = false
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Datadog
4
+ module CI
5
+ module TestTracing
6
+ module Serializers
7
+ module MetaTruncation
8
+ MAX_META_STRING_LENGTH = 5000
9
+
10
+ def self.truncate_value(value)
11
+ return value unless value.is_a?(String) && value.length > MAX_META_STRING_LENGTH
12
+
13
+ value[0, MAX_META_STRING_LENGTH]
14
+ end
15
+
16
+ def self.truncate_string_values(tags)
17
+ tags.transform_values { |value| truncate_value(value) }
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -5,6 +5,7 @@ require "datadog/core/telemetry/logging"
5
5
  require "datadog/core/utils/only_once"
6
6
 
7
7
  require_relative "serializers/factories/test_level"
8
+ require_relative "serializers/meta_truncation"
8
9
 
9
10
  require_relative "../ext/app_types"
10
11
  require_relative "../ext/telemetry"
@@ -105,17 +106,17 @@ module Datadog
105
106
 
106
107
  if dd_env
107
108
  packer.write("env")
108
- packer.write(dd_env)
109
+ packer.write(Serializers::MetaTruncation.truncate_value(dd_env))
109
110
  end
110
111
 
111
112
  packer.write("runtime-id")
112
- packer.write(Datadog::Core::Environment::Identity.id)
113
+ packer.write(Serializers::MetaTruncation.truncate_value(Datadog::Core::Environment::Identity.id))
113
114
 
114
115
  packer.write("language")
115
- packer.write(Datadog::Core::Environment::Identity.lang)
116
+ packer.write(Serializers::MetaTruncation.truncate_value(Datadog::Core::Environment::Identity.lang))
116
117
 
117
118
  packer.write("library_version")
118
- packer.write(Datadog::CI::VERSION::STRING)
119
+ packer.write(Serializers::MetaTruncation.truncate_value(Datadog::CI::VERSION::STRING))
119
120
 
120
121
  library_capabilities_tags = Ext::Test::LibraryCapabilities::CAPABILITY_VERSIONS
121
122
 
@@ -124,14 +125,16 @@ module Datadog
124
125
  packer.write_map_header(2 + library_capabilities_tags.count)
125
126
 
126
127
  packer.write(Ext::Test::TAG_TEST_SESSION_NAME)
127
- packer.write(test_tracing&.logical_test_session_name)
128
+ packer.write(Serializers::MetaTruncation.truncate_value(test_tracing&.logical_test_session_name))
128
129
 
129
130
  packer.write(Ext::Test::TAG_USER_PROVIDED_TEST_SERVICE)
130
- packer.write(Utils::Configuration.service_name_provided_by_user?.to_s)
131
+ packer.write(
132
+ Serializers::MetaTruncation.truncate_value(Utils::Configuration.service_name_provided_by_user?.to_s)
133
+ )
131
134
 
132
135
  library_capabilities_tags.each do |tag, value|
133
136
  packer.write(tag)
134
- packer.write(value)
137
+ packer.write(Serializers::MetaTruncation.truncate_value(value))
135
138
  end
136
139
  end
137
140
 
@@ -4,7 +4,7 @@ module Datadog
4
4
  module CI
5
5
  module VERSION
6
6
  MAJOR = 1
7
- MINOR = 31
7
+ MINOR = 32
8
8
  PATCH = 0
9
9
  PRE = nil
10
10
  BUILD = nil
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: datadog-ci
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.31.0
4
+ version: 1.32.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Datadog, Inc.
@@ -140,6 +140,7 @@ files:
140
140
  - lib/datadog/ci/contrib/minitest/parallel_executor_minitest_6.rb
141
141
  - lib/datadog/ci/contrib/minitest/patcher.rb
142
142
  - lib/datadog/ci/contrib/minitest/reporter.rb
143
+ - lib/datadog/ci/contrib/minitest/run_method_capture.rb
143
144
  - lib/datadog/ci/contrib/minitest/runnable.rb
144
145
  - lib/datadog/ci/contrib/minitest/runnable_minitest_6.rb
145
146
  - lib/datadog/ci/contrib/minitest/runner.rb
@@ -288,6 +289,7 @@ files:
288
289
  - lib/datadog/ci/test_tracing/serializers/base.rb
289
290
  - lib/datadog/ci/test_tracing/serializers/factories/test_level.rb
290
291
  - lib/datadog/ci/test_tracing/serializers/factories/test_suite_level.rb
292
+ - lib/datadog/ci/test_tracing/serializers/meta_truncation.rb
291
293
  - lib/datadog/ci/test_tracing/serializers/span.rb
292
294
  - lib/datadog/ci/test_tracing/serializers/test_module.rb
293
295
  - lib/datadog/ci/test_tracing/serializers/test_session.rb