datadog-ci 1.12.0 → 1.13.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 +4 -4
- data/CHANGELOG.md +12 -2
- data/lib/datadog/ci/configuration/components.rb +27 -15
- data/lib/datadog/ci/configuration/settings.rb +12 -0
- data/lib/datadog/ci/contrib/cucumber/instrumentation.rb +5 -2
- data/lib/datadog/ci/contrib/minitest/test.rb +3 -3
- data/lib/datadog/ci/contrib/rspec/example.rb +3 -3
- data/lib/datadog/ci/ext/app_types.rb +1 -1
- data/lib/datadog/ci/ext/settings.rb +2 -0
- data/lib/datadog/ci/ext/telemetry.rb +17 -5
- data/lib/datadog/ci/ext/test.rb +42 -4
- data/lib/datadog/ci/ext/transport.rb +6 -0
- data/lib/datadog/ci/remote/component.rb +11 -1
- data/lib/datadog/ci/remote/library_settings.rb +31 -0
- data/lib/datadog/ci/remote/library_settings_client.rb +2 -1
- data/lib/datadog/ci/test.rb +67 -9
- data/lib/datadog/ci/test_management/component.rb +61 -0
- data/lib/datadog/ci/test_management/null_component.rb +25 -0
- data/lib/datadog/ci/test_management/tests_properties.rb +128 -0
- data/lib/datadog/ci/test_optimisation/component.rb +3 -3
- data/lib/datadog/ci/test_retries/component.rb +37 -7
- data/lib/datadog/ci/test_retries/driver/base.rb +5 -0
- data/lib/datadog/ci/test_retries/driver/retry_failed.rb +4 -0
- data/lib/datadog/ci/test_retries/driver/retry_flaky_fixed.rb +38 -0
- data/lib/datadog/ci/test_retries/driver/retry_new.rb +2 -7
- data/lib/datadog/ci/test_retries/strategy/retry_flaky_fixed.rb +43 -0
- data/lib/datadog/ci/test_retries/strategy/retry_new.rb +4 -46
- data/lib/datadog/ci/test_suite.rb +21 -2
- data/lib/datadog/ci/test_visibility/capabilities.rb +36 -0
- data/lib/datadog/ci/test_visibility/component.rb +70 -2
- data/lib/datadog/ci/test_visibility/context.rb +0 -4
- data/lib/datadog/ci/{test_retries/unique_tests_client.rb → test_visibility/known_tests.rb} +10 -10
- data/lib/datadog/ci/test_visibility/null_component.rb +3 -0
- data/lib/datadog/ci/test_visibility/serializers/factories/test_level.rb +1 -1
- data/lib/datadog/ci/test_visibility/telemetry.rb +11 -2
- data/lib/datadog/ci/test_visibility/transport.rb +15 -2
- data/lib/datadog/ci/version.rb +1 -1
- data/lib/datadog/ci.rb +13 -5
- metadata +11 -5
@@ -18,9 +18,10 @@ module Datadog
|
|
18
18
|
module TestVisibility
|
19
19
|
# Common behavior for CI tests
|
20
20
|
class Component
|
21
|
-
attr_reader :test_suite_level_visibility_enabled, :logical_test_session_name
|
21
|
+
attr_reader :test_suite_level_visibility_enabled, :logical_test_session_name, :known_tests, :known_tests_enabled
|
22
22
|
|
23
23
|
def initialize(
|
24
|
+
known_tests_client:,
|
24
25
|
test_suite_level_visibility_enabled: false,
|
25
26
|
codeowners: Codeowners::Parser.new(Git::LocalRepository.root).parse,
|
26
27
|
logical_test_session_name: nil
|
@@ -29,6 +30,21 @@ module Datadog
|
|
29
30
|
@context = Context.new
|
30
31
|
@codeowners = codeowners
|
31
32
|
@logical_test_session_name = logical_test_session_name
|
33
|
+
|
34
|
+
# "Known tests" feature fetches a list of all tests known to Datadog for this repository
|
35
|
+
# and uses this list to determine if a test is new or not. New tests are marked with "test.is_new" tag.
|
36
|
+
@known_tests_enabled = false
|
37
|
+
@known_tests_client = known_tests_client
|
38
|
+
@known_tests = Set.new
|
39
|
+
end
|
40
|
+
|
41
|
+
def configure(library_configuration, test_session)
|
42
|
+
return unless test_suite_level_visibility_enabled
|
43
|
+
|
44
|
+
if library_configuration.known_tests_enabled?
|
45
|
+
@known_tests_enabled = true
|
46
|
+
fetch_known_tests(test_session)
|
47
|
+
end
|
32
48
|
end
|
33
49
|
|
34
50
|
def start_test_session(service: nil, tags: {}, total_tests_count: 0)
|
@@ -158,7 +174,8 @@ module Datadog
|
|
158
174
|
# sets logical test session name if none provided by the user
|
159
175
|
override_logical_test_session_name!(test_session) if logical_test_session_name.nil?
|
160
176
|
|
161
|
-
#
|
177
|
+
# Signal Remote::Component to configure the library.
|
178
|
+
# Note that it will call this component back (unfortunate circular dependency).
|
162
179
|
remote.configure(test_session)
|
163
180
|
end
|
164
181
|
|
@@ -182,6 +199,10 @@ module Datadog
|
|
182
199
|
|
183
200
|
Telemetry.event_created(test)
|
184
201
|
|
202
|
+
mark_test_as_new(test) if new_test?(test)
|
203
|
+
|
204
|
+
test_management.tag_test_from_properties(test)
|
205
|
+
|
185
206
|
test_optimisation.mark_if_skippable(test)
|
186
207
|
test_optimisation.start_coverage(test)
|
187
208
|
end
|
@@ -287,6 +308,49 @@ module Datadog
|
|
287
308
|
end
|
288
309
|
end
|
289
310
|
|
311
|
+
def new_test?(test_span)
|
312
|
+
return false unless @known_tests_enabled
|
313
|
+
|
314
|
+
test_id = Utils::TestRun.datadog_test_id(test_span.name, test_span.test_suite_name)
|
315
|
+
result = !@known_tests.include?(test_id)
|
316
|
+
|
317
|
+
if result
|
318
|
+
Datadog.logger.debug do
|
319
|
+
"#{test_id} is not found in the known tests set, it is a new test"
|
320
|
+
end
|
321
|
+
end
|
322
|
+
|
323
|
+
result
|
324
|
+
end
|
325
|
+
|
326
|
+
def fetch_known_tests(test_session)
|
327
|
+
@known_tests = @known_tests_client.fetch(test_session)
|
328
|
+
|
329
|
+
if @known_tests.empty?
|
330
|
+
@known_tests_enabled = false
|
331
|
+
|
332
|
+
# this adds unfortunate knowledge on EFD from Testvisibility, rethink this
|
333
|
+
test_session&.set_tag(Ext::Test::TAG_EARLY_FLAKE_ABORT_REASON, Ext::Test::EARLY_FLAKE_FAULTY)
|
334
|
+
|
335
|
+
Datadog.logger.warn("Empty set of tests known to Datadog")
|
336
|
+
end
|
337
|
+
|
338
|
+
# report how many known tests were found
|
339
|
+
Datadog.logger.debug do
|
340
|
+
"Found [#{@known_tests.size}] known tests"
|
341
|
+
end
|
342
|
+
Utils::Telemetry.distribution(
|
343
|
+
Ext::Telemetry::METRIC_KNOWN_TESTS_RESPONSE_TESTS,
|
344
|
+
@known_tests.size.to_f
|
345
|
+
)
|
346
|
+
|
347
|
+
@known_tests
|
348
|
+
end
|
349
|
+
|
350
|
+
def mark_test_as_new(test_span)
|
351
|
+
test_span.set_tag(Ext::Test::TAG_IS_NEW, "true")
|
352
|
+
end
|
353
|
+
|
290
354
|
def test_optimisation
|
291
355
|
Datadog.send(:components).test_optimisation
|
292
356
|
end
|
@@ -302,6 +366,10 @@ module Datadog
|
|
302
366
|
def remote
|
303
367
|
Datadog.send(:components).ci_remote
|
304
368
|
end
|
369
|
+
|
370
|
+
def test_management
|
371
|
+
Datadog.send(:components).test_management
|
372
|
+
end
|
305
373
|
end
|
306
374
|
end
|
307
375
|
end
|
@@ -208,10 +208,6 @@ module Datadog
|
|
208
208
|
ci_span.set_tags(@environment_tags)
|
209
209
|
|
210
210
|
ci_span.set_metric(Ext::Test::METRIC_CPU_COUNT, Utils::TestRun.virtual_cpu_count)
|
211
|
-
ci_span.set_tag(
|
212
|
-
Ext::Test::TAG_USER_PROVIDED_TEST_SERVICE,
|
213
|
-
Utils::Configuration.service_name_provided_by_user?.to_s
|
214
|
-
)
|
215
211
|
end
|
216
212
|
|
217
213
|
# PROPAGATING CONTEXT FROM TOP-LEVEL TO THE LOWER LEVELS
|
@@ -10,9 +10,9 @@ require_relative "../utils/test_run"
|
|
10
10
|
|
11
11
|
module Datadog
|
12
12
|
module CI
|
13
|
-
module
|
14
|
-
#
|
15
|
-
class
|
13
|
+
module TestVisibility
|
14
|
+
# fetches and stores a list of known tests from the backend
|
15
|
+
class KnownTests
|
16
16
|
class Response
|
17
17
|
def initialize(http_response)
|
18
18
|
@http_response = http_response
|
@@ -66,7 +66,7 @@ module Datadog
|
|
66
66
|
@config_tags = config_tags
|
67
67
|
end
|
68
68
|
|
69
|
-
def
|
69
|
+
def fetch(test_session)
|
70
70
|
api = @api
|
71
71
|
return Set.new unless api
|
72
72
|
|
@@ -78,21 +78,21 @@ module Datadog
|
|
78
78
|
payload: request_payload
|
79
79
|
)
|
80
80
|
|
81
|
-
Transport::Telemetry.api_requests(
|
82
|
-
Ext::Telemetry::
|
81
|
+
CI::Transport::Telemetry.api_requests(
|
82
|
+
Ext::Telemetry::METRIC_KNOWN_TESTS_REQUEST,
|
83
83
|
1,
|
84
84
|
compressed: http_response.request_compressed
|
85
85
|
)
|
86
|
-
Utils::Telemetry.distribution(Ext::Telemetry::
|
86
|
+
Utils::Telemetry.distribution(Ext::Telemetry::METRIC_KNOWN_TESTS_REQUEST_MS, http_response.duration_ms)
|
87
87
|
Utils::Telemetry.distribution(
|
88
|
-
Ext::Telemetry::
|
88
|
+
Ext::Telemetry::METRIC_KNOWN_TESTS_RESPONSE_BYTES,
|
89
89
|
http_response.response_size.to_f,
|
90
90
|
{Ext::Telemetry::TAG_RESPONSE_COMPRESSED => http_response.gzipped_content?.to_s}
|
91
91
|
)
|
92
92
|
|
93
93
|
unless http_response.ok?
|
94
|
-
Transport::Telemetry.api_requests_errors(
|
95
|
-
Ext::Telemetry::
|
94
|
+
CI::Transport::Telemetry.api_requests_errors(
|
95
|
+
Ext::Telemetry::METRIC_KNOWN_TESTS_REQUEST_ERRORS,
|
96
96
|
1,
|
97
97
|
error_type: http_response.telemetry_error_type,
|
98
98
|
status_code: http_response.code
|
@@ -9,7 +9,7 @@ module Datadog
|
|
9
9
|
module Serializers
|
10
10
|
module Factories
|
11
11
|
# This factory takes care of creating msgpack serializers when test-level visibility is enabled
|
12
|
-
# NOTE: citestcycle is a protocol Datadog uses to submit test execution tracing information to
|
12
|
+
# NOTE: citestcycle is a protocol Datadog uses to submit test execution tracing information to Test Optimization
|
13
13
|
# backend
|
14
14
|
module TestLevel
|
15
15
|
module_function
|
@@ -54,8 +54,11 @@ module Datadog
|
|
54
54
|
# codeowner tag
|
55
55
|
tags[Ext::Telemetry::TAG_HAS_CODEOWNER] = "true" if span.get_tag(Ext::Test::TAG_CODEOWNERS)
|
56
56
|
|
57
|
-
# set is_retry
|
58
|
-
|
57
|
+
# set is_retry and retry_reason tags if span represents a retried test
|
58
|
+
if span.get_tag(Ext::Test::TAG_IS_RETRY)
|
59
|
+
tags[Ext::Telemetry::TAG_IS_RETRY] = "true"
|
60
|
+
tags[Ext::Telemetry::TAG_RETRY_REASON] = span.get_tag(Ext::Test::TAG_RETRY_REASON)
|
61
|
+
end
|
59
62
|
|
60
63
|
# is_new
|
61
64
|
tags[Ext::Telemetry::TAG_IS_NEW] = "true" if span.get_tag(Ext::Test::TAG_IS_NEW)
|
@@ -66,6 +69,12 @@ module Datadog
|
|
66
69
|
tags[Ext::Telemetry::TAG_EARLY_FLAKE_DETECTION_ABORT_REASON] = early_flake_detection_abort_reason
|
67
70
|
end
|
68
71
|
|
72
|
+
# test management tags
|
73
|
+
tags[Ext::Telemetry::TAG_IS_ATTEMPT_TO_FIX] = "true" if span.get_tag(Ext::Test::TAG_IS_ATTEMPT_TO_FIX)
|
74
|
+
tags[Ext::Telemetry::TAG_IS_QUARANTINED] = "true" if span.get_tag(Ext::Test::TAG_IS_QUARANTINED)
|
75
|
+
tags[Ext::Telemetry::TAG_IS_TEST_DISABLED] = "true" if span.get_tag(Ext::Test::TAG_IS_TEST_DISABLED)
|
76
|
+
tags[Ext::Telemetry::TAG_HAS_FAILED_ALL_RETRIES] = "true" if span.get_tag(Ext::Test::TAG_HAS_FAILED_ALL_RETRIES)
|
77
|
+
|
69
78
|
tags
|
70
79
|
end
|
71
80
|
|
@@ -4,12 +4,15 @@ 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"
|
7
8
|
require_relative "serializers/factories/test_level"
|
9
|
+
|
8
10
|
require_relative "../ext/app_types"
|
9
11
|
require_relative "../ext/telemetry"
|
10
12
|
require_relative "../ext/transport"
|
11
13
|
require_relative "../transport/event_platform_transport"
|
12
14
|
require_relative "../transport/telemetry"
|
15
|
+
require_relative "../utils/configuration"
|
13
16
|
|
14
17
|
module Datadog
|
15
18
|
module CI
|
@@ -114,12 +117,22 @@ module Datadog
|
|
114
117
|
packer.write("library_version")
|
115
118
|
packer.write(Datadog::CI::VERSION::STRING)
|
116
119
|
|
120
|
+
library_capabilities_tags = Capabilities.tags
|
121
|
+
|
117
122
|
Ext::AppTypes::CI_SPAN_TYPES.each do |ci_span_type|
|
118
123
|
packer.write(ci_span_type)
|
119
|
-
packer.write_map_header(
|
124
|
+
packer.write_map_header(2 + library_capabilities_tags.count)
|
120
125
|
|
121
|
-
packer.write(Ext::Test::
|
126
|
+
packer.write(Ext::Test::TAG_TEST_SESSION_NAME)
|
122
127
|
packer.write(test_visibility&.logical_test_session_name)
|
128
|
+
|
129
|
+
packer.write(Ext::Test::TAG_USER_PROVIDED_TEST_SERVICE)
|
130
|
+
packer.write(Utils::Configuration.service_name_provided_by_user?.to_s)
|
131
|
+
|
132
|
+
library_capabilities_tags.each do |tag, value|
|
133
|
+
packer.write(tag)
|
134
|
+
packer.write(value)
|
135
|
+
end
|
123
136
|
end
|
124
137
|
|
125
138
|
packer.write("events")
|
data/lib/datadog/ci/version.rb
CHANGED
data/lib/datadog/ci.rb
CHANGED
@@ -10,7 +10,7 @@ require "datadog"
|
|
10
10
|
require "datadog/core"
|
11
11
|
|
12
12
|
module Datadog
|
13
|
-
# Datadog
|
13
|
+
# Datadog Test Optimization public API.
|
14
14
|
#
|
15
15
|
# @public_api
|
16
16
|
module CI
|
@@ -319,16 +319,16 @@ module Datadog
|
|
319
319
|
# @return [Object] If a block is provided, returns the result of the block execution.
|
320
320
|
# @return [Datadog::CI::Span] If no block is provided, returns the active,
|
321
321
|
# unfinished {Datadog::CI::Span}.
|
322
|
-
# @return [nil] if
|
323
|
-
# @raise [ReservedTypeError] if provided type is reserved for Datadog
|
322
|
+
# @return [nil] if Test Optimization is disabled
|
323
|
+
# @raise [ReservedTypeError] if provided type is reserved for Datadog Test Optimization
|
324
324
|
# @yield Optional block where newly created {Datadog::CI::Span} captures the execution.
|
325
325
|
# @yieldparam [Datadog::CI::Span] ci_span the newly created and active [Datadog::CI::Span]
|
326
|
-
# @yieldparam [nil] ci_span if
|
326
|
+
# @yieldparam [nil] ci_span if Test Optimization is disabled
|
327
327
|
def trace(span_name, type: "span", tags: {}, &block)
|
328
328
|
if Ext::AppTypes::CI_SPAN_TYPES.include?(type)
|
329
329
|
raise(
|
330
330
|
ReservedTypeError,
|
331
|
-
"Span type #{type} is reserved for Datadog
|
331
|
+
"Span type #{type} is reserved for Datadog Test Optimization. " \
|
332
332
|
"Reserved types are: #{Ext::AppTypes::CI_SPAN_TYPES}"
|
333
333
|
)
|
334
334
|
end
|
@@ -401,6 +401,14 @@ module Datadog
|
|
401
401
|
def test_optimisation
|
402
402
|
components.test_optimisation
|
403
403
|
end
|
404
|
+
|
405
|
+
def test_management
|
406
|
+
components.test_management
|
407
|
+
end
|
408
|
+
|
409
|
+
def test_retries
|
410
|
+
components.test_retries
|
411
|
+
end
|
404
412
|
end
|
405
413
|
end
|
406
414
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: datadog-ci
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.13.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Datadog, Inc.
|
8
8
|
bindir: exe
|
9
9
|
cert_chain: []
|
10
|
-
date: 2025-
|
10
|
+
date: 2025-02-25 00:00:00.000000000 Z
|
11
11
|
dependencies:
|
12
12
|
- !ruby/object:Gem::Dependency
|
13
13
|
name: datadog
|
@@ -38,7 +38,7 @@ dependencies:
|
|
38
38
|
- !ruby/object:Gem::Version
|
39
39
|
version: '0'
|
40
40
|
description: |2
|
41
|
-
datadog-ci is a Datadog's
|
41
|
+
datadog-ci is a Datadog's Test Optimization library for Ruby. It traces
|
42
42
|
tests as they are being executed and brings developers visibility into
|
43
43
|
their CI pipelines.
|
44
44
|
email:
|
@@ -164,6 +164,9 @@ files:
|
|
164
164
|
- lib/datadog/ci/remote/slow_test_retries.rb
|
165
165
|
- lib/datadog/ci/span.rb
|
166
166
|
- lib/datadog/ci/test.rb
|
167
|
+
- lib/datadog/ci/test_management/component.rb
|
168
|
+
- lib/datadog/ci/test_management/null_component.rb
|
169
|
+
- lib/datadog/ci/test_management/tests_properties.rb
|
167
170
|
- lib/datadog/ci/test_module.rb
|
168
171
|
- lib/datadog/ci/test_optimisation/component.rb
|
169
172
|
- lib/datadog/ci/test_optimisation/coverage/ddcov.rb
|
@@ -179,18 +182,21 @@ files:
|
|
179
182
|
- lib/datadog/ci/test_retries/driver/base.rb
|
180
183
|
- lib/datadog/ci/test_retries/driver/no_retry.rb
|
181
184
|
- lib/datadog/ci/test_retries/driver/retry_failed.rb
|
185
|
+
- lib/datadog/ci/test_retries/driver/retry_flaky_fixed.rb
|
182
186
|
- lib/datadog/ci/test_retries/driver/retry_new.rb
|
183
187
|
- lib/datadog/ci/test_retries/null_component.rb
|
184
188
|
- lib/datadog/ci/test_retries/strategy/base.rb
|
185
189
|
- lib/datadog/ci/test_retries/strategy/no_retry.rb
|
186
190
|
- lib/datadog/ci/test_retries/strategy/retry_failed.rb
|
191
|
+
- lib/datadog/ci/test_retries/strategy/retry_flaky_fixed.rb
|
187
192
|
- lib/datadog/ci/test_retries/strategy/retry_new.rb
|
188
|
-
- lib/datadog/ci/test_retries/unique_tests_client.rb
|
189
193
|
- lib/datadog/ci/test_session.rb
|
190
194
|
- lib/datadog/ci/test_suite.rb
|
195
|
+
- lib/datadog/ci/test_visibility/capabilities.rb
|
191
196
|
- lib/datadog/ci/test_visibility/component.rb
|
192
197
|
- lib/datadog/ci/test_visibility/context.rb
|
193
198
|
- lib/datadog/ci/test_visibility/flush.rb
|
199
|
+
- lib/datadog/ci/test_visibility/known_tests.rb
|
194
200
|
- lib/datadog/ci/test_visibility/null_component.rb
|
195
201
|
- lib/datadog/ci/test_visibility/null_transport.rb
|
196
202
|
- lib/datadog/ci/test_visibility/serializers/base.rb
|
@@ -254,5 +260,5 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
254
260
|
requirements: []
|
255
261
|
rubygems_version: 3.6.2
|
256
262
|
specification_version: 4
|
257
|
-
summary: Datadog
|
263
|
+
summary: Datadog Test Optimization for your ruby application
|
258
264
|
test_files: []
|