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
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bc134bf501f298c7803572320d3c82d93b64b0dbfc59b2d8219d42fd5fed24e6
|
4
|
+
data.tar.gz: 4714f599fef9eae12cb3dc99dfb17dc0431a9dfee7d9337da9fada542429c6c5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e54fa5b48885accd1c304fca925292470930f6c916e318c5a02eed24989d089e431b99aa56c3eab75f1ed4445c3ab8bd14b1783baa01c32e52bf3d0df5f3813b
|
7
|
+
data.tar.gz: 0f42913850d53736f3b058db3c7bea7e2f4cc0c5ccf511545d052afb142967084185075888511887185dbf5b82ee4b6931b7da76f91b91fe0c99760efb1b9574
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,12 @@
|
|
1
1
|
## [Unreleased]
|
2
2
|
|
3
|
+
## [1.13.0] - 2025-02-25
|
4
|
+
|
5
|
+
### Added
|
6
|
+
|
7
|
+
* Flaky test management support ([#289][])
|
8
|
+
* Always request the list of known tests and mark new tests ([#286][])
|
9
|
+
|
3
10
|
## [1.12.0] - 2025-01-23
|
4
11
|
|
5
12
|
### Added
|
@@ -386,7 +393,8 @@ Currently test suite level visibility is not used by our instrumentation: it wil
|
|
386
393
|
|
387
394
|
- Ruby versions < 2.7 no longer supported ([#8][])
|
388
395
|
|
389
|
-
[Unreleased]: https://github.com/DataDog/datadog-ci-rb/compare/v1.
|
396
|
+
[Unreleased]: https://github.com/DataDog/datadog-ci-rb/compare/v1.13.0...main
|
397
|
+
[1.13.0]: https://github.com/DataDog/datadog-ci-rb/compare/v1.12.0...v1.13.0
|
390
398
|
[1.12.0]: https://github.com/DataDog/datadog-ci-rb/compare/v1.11.0...v1.12.0
|
391
399
|
[1.11.0]: https://github.com/DataDog/datadog-ci-rb/compare/v1.10.0...v1.11.0
|
392
400
|
[1.10.0]: https://github.com/DataDog/datadog-ci-rb/compare/v1.9.0...v1.10.0
|
@@ -554,4 +562,6 @@ Currently test suite level visibility is not used by our instrumentation: it wil
|
|
554
562
|
[#271]: https://github.com/DataDog/datadog-ci-rb/issues/271
|
555
563
|
[#272]: https://github.com/DataDog/datadog-ci-rb/issues/272
|
556
564
|
[#275]: https://github.com/DataDog/datadog-ci-rb/issues/275
|
557
|
-
[#283]: https://github.com/DataDog/datadog-ci-rb/issues/283
|
565
|
+
[#283]: https://github.com/DataDog/datadog-ci-rb/issues/283
|
566
|
+
[#286]: https://github.com/DataDog/datadog-ci-rb/issues/286
|
567
|
+
[#289]: https://github.com/DataDog/datadog-ci-rb/issues/289
|
@@ -6,14 +6,17 @@ require_relative "../ext/settings"
|
|
6
6
|
require_relative "../git/tree_uploader"
|
7
7
|
require_relative "../remote/component"
|
8
8
|
require_relative "../remote/library_settings_client"
|
9
|
+
require_relative "../test_management/component"
|
10
|
+
require_relative "../test_management/null_component"
|
11
|
+
require_relative "../test_management/tests_properties"
|
9
12
|
require_relative "../test_optimisation/component"
|
10
13
|
require_relative "../test_optimisation/coverage/transport"
|
11
14
|
require_relative "../test_optimisation/coverage/writer"
|
12
15
|
require_relative "../test_retries/component"
|
13
16
|
require_relative "../test_retries/null_component"
|
14
|
-
require_relative "../test_retries/unique_tests_client"
|
15
17
|
require_relative "../test_visibility/component"
|
16
18
|
require_relative "../test_visibility/flush"
|
19
|
+
require_relative "../test_visibility/known_tests"
|
17
20
|
require_relative "../test_visibility/null_component"
|
18
21
|
require_relative "../test_visibility/serializers/factories/test_level"
|
19
22
|
require_relative "../test_visibility/serializers/factories/test_suite_level"
|
@@ -30,7 +33,7 @@ module Datadog
|
|
30
33
|
module Configuration
|
31
34
|
# Adds CI behavior to Datadog trace components
|
32
35
|
module Components
|
33
|
-
attr_reader :test_visibility, :test_optimisation, :git_tree_upload_worker, :ci_remote, :test_retries
|
36
|
+
attr_reader :test_visibility, :test_optimisation, :git_tree_upload_worker, :ci_remote, :test_retries, :test_management
|
34
37
|
|
35
38
|
def initialize(settings)
|
36
39
|
@test_optimisation = nil
|
@@ -38,6 +41,7 @@ module Datadog
|
|
38
41
|
@git_tree_upload_worker = DummyWorker.new
|
39
42
|
@ci_remote = nil
|
40
43
|
@test_retries = TestRetries::NullComponent.new
|
44
|
+
@test_management = TestManagement::NullComponent.new
|
41
45
|
|
42
46
|
# Activate CI mode if enabled
|
43
47
|
if settings.ci.enabled
|
@@ -58,7 +62,7 @@ module Datadog
|
|
58
62
|
def activate_ci!(settings)
|
59
63
|
unless settings.tracing.enabled
|
60
64
|
Datadog.logger.error(
|
61
|
-
"
|
65
|
+
"Test Optimization requires tracing to be enabled. Disabling Test Optimization. " \
|
62
66
|
"NOTE: if you didn't disable tracing intentionally, add `c.tracing.enabled = true` to " \
|
63
67
|
"your Datadog.configure block."
|
64
68
|
)
|
@@ -111,13 +115,21 @@ module Datadog
|
|
111
115
|
retry_failed_tests_max_attempts: settings.ci.retry_failed_tests_max_attempts,
|
112
116
|
retry_failed_tests_total_limit: settings.ci.retry_failed_tests_total_limit,
|
113
117
|
retry_new_tests_enabled: settings.ci.retry_new_tests_enabled,
|
114
|
-
|
118
|
+
retry_flaky_fixed_tests_enabled: settings.ci.test_management_enabled,
|
119
|
+
retry_flaky_fixed_tests_max_attempts: settings.ci.test_management_attempt_to_fix_retries_count
|
115
120
|
)
|
121
|
+
|
122
|
+
@test_management = TestManagement::Component.new(
|
123
|
+
enabled: settings.ci.test_management_enabled,
|
124
|
+
tests_properties_client: TestManagement::TestsProperties.new(api: test_visibility_api)
|
125
|
+
)
|
126
|
+
|
116
127
|
# @type ivar @test_optimisation: Datadog::CI::TestOptimisation::Component
|
117
128
|
@test_optimisation = build_test_optimisation(settings, test_visibility_api)
|
118
129
|
@test_visibility = TestVisibility::Component.new(
|
119
130
|
test_suite_level_visibility_enabled: !settings.ci.force_test_level_visibility,
|
120
|
-
logical_test_session_name: settings.ci.test_session_name
|
131
|
+
logical_test_session_name: settings.ci.test_session_name,
|
132
|
+
known_tests_client: build_known_tests_client(settings, test_visibility_api)
|
121
133
|
)
|
122
134
|
end
|
123
135
|
|
@@ -125,7 +137,7 @@ module Datadog
|
|
125
137
|
if settings.ci.itr_code_coverage_use_single_threaded_mode &&
|
126
138
|
settings.ci.itr_test_impact_analysis_use_allocation_tracing
|
127
139
|
Datadog.logger.warn(
|
128
|
-
"
|
140
|
+
"Test Impact Analysis: Single threaded coverage mode is incompatible with allocation tracing. " \
|
129
141
|
"Allocation tracing will be disabled. It means that test impact analysis will not be able to detect " \
|
130
142
|
"instantiations of objects in your code, which is important for ActiveRecord models. " \
|
131
143
|
"Please add your app/model folder to the list of tracked files or disable single threaded coverage mode."
|
@@ -137,7 +149,7 @@ module Datadog
|
|
137
149
|
if RUBY_VERSION.start_with?("3.2.") && RUBY_VERSION < "3.2.3" &&
|
138
150
|
settings.ci.itr_test_impact_analysis_use_allocation_tracing
|
139
151
|
Datadog.logger.warn(
|
140
|
-
"
|
152
|
+
"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 " \
|
141
153
|
"disabled. This is due to a VM bug that can lead to crashes (https://bugs.ruby-lang.org/issues/19482). " \
|
142
154
|
"Please update your Ruby version or add your app/model folder to the list of tracked files." \
|
143
155
|
"Set env variable DD_CIVISIBILITY_ITR_TEST_IMPACT_ANALYSIS_USE_ALLOCATION_TRACING to 0 to disable this warning."
|
@@ -161,21 +173,21 @@ module Datadog
|
|
161
173
|
if settings.ci.agentless_mode_enabled
|
162
174
|
check_dd_site(settings)
|
163
175
|
|
164
|
-
Datadog.logger.debug("
|
176
|
+
Datadog.logger.debug("Test Optimization configured to use agentless transport")
|
165
177
|
|
166
178
|
api = Transport::Api::Builder.build_agentless_api(settings)
|
167
179
|
if api.nil?
|
168
180
|
Datadog.logger.error do
|
169
|
-
"DATADOG CONFIGURATION -
|
170
|
-
"Agentless mode was enabled but DD_API_KEY is not set:
|
181
|
+
"DATADOG CONFIGURATION - TEST OPTIMIZATION - ATTENTION - " \
|
182
|
+
"Agentless mode was enabled but DD_API_KEY is not set: Test Optimization is disabled. " \
|
171
183
|
"Please make sure to set valid api key in DD_API_KEY environment variable"
|
172
184
|
end
|
173
185
|
|
174
|
-
# Tests are running without
|
186
|
+
# Tests are running without Test Optimization enabled
|
175
187
|
settings.ci.enabled = false
|
176
188
|
end
|
177
189
|
else
|
178
|
-
Datadog.logger.debug("
|
190
|
+
Datadog.logger.debug("Test Optimization configured to use agent transport via EVP proxy")
|
179
191
|
|
180
192
|
api = Transport::Api::Builder.build_evp_proxy_api(settings)
|
181
193
|
if api.nil?
|
@@ -235,8 +247,8 @@ module Datadog
|
|
235
247
|
)
|
236
248
|
end
|
237
249
|
|
238
|
-
def
|
239
|
-
|
250
|
+
def build_known_tests_client(settings, api)
|
251
|
+
TestVisibility::KnownTests.new(
|
240
252
|
api: api,
|
241
253
|
dd_env: settings.env,
|
242
254
|
config_tags: custom_configuration(settings)
|
@@ -262,7 +274,7 @@ module Datadog
|
|
262
274
|
return if Ext::Settings::DD_SITE_ALLOWLIST.include?(settings.site)
|
263
275
|
|
264
276
|
Datadog.logger.warn do
|
265
|
-
"
|
277
|
+
"TEST OPTIMIZATION CONFIGURATION " \
|
266
278
|
"Agentless mode was enabled but DD_SITE is not set to one of the following: #{Ext::Settings::DD_SITE_ALLOWLIST.join(", ")}. " \
|
267
279
|
"Please make sure to set valid site in DD_SITE environment variable"
|
268
280
|
end
|
@@ -116,6 +116,18 @@ module Datadog
|
|
116
116
|
o.default true
|
117
117
|
end
|
118
118
|
|
119
|
+
option :test_management_enabled do |o|
|
120
|
+
o.type :bool
|
121
|
+
o.env CI::Ext::Settings::ENV_TEST_MANAGEMENT_ENABLED
|
122
|
+
o.default true
|
123
|
+
end
|
124
|
+
|
125
|
+
option :test_management_attempt_to_fix_retries_count do |o|
|
126
|
+
o.type :int
|
127
|
+
o.env CI::Ext::Settings::ENV_TEST_MANAGEMENT_ATTEMPT_TO_FIX_RETRIES
|
128
|
+
o.default 20
|
129
|
+
end
|
130
|
+
|
119
131
|
# internal only
|
120
132
|
option :discard_traces do |o|
|
121
133
|
o.type :bool
|
@@ -37,8 +37,11 @@ module Datadog
|
|
37
37
|
end
|
38
38
|
|
39
39
|
def begin_scenario(test_case)
|
40
|
-
|
41
|
-
|
40
|
+
datadog_test = Datadog::CI.active_test
|
41
|
+
|
42
|
+
# special case for cucumber-ruby: we skip quarantined tests, thus for cucumber quarantined is the same as disabled
|
43
|
+
if datadog_test&.should_skip? || datadog_test&.quarantined?
|
44
|
+
raise ::Cucumber::Core::Test::Result::Skipped, datadog_test.datadog_skip_reason
|
42
45
|
end
|
43
46
|
|
44
47
|
super
|
@@ -44,7 +44,7 @@ module Datadog
|
|
44
44
|
service: datadog_configuration[:service_name]
|
45
45
|
)
|
46
46
|
test_span&.itr_unskippable! if self.class.dd_suite_unskippable? || self.class.dd_test_unskippable?(name)
|
47
|
-
skip(
|
47
|
+
skip(test_span&.datadog_skip_reason) if test_span&.should_skip?
|
48
48
|
end
|
49
49
|
|
50
50
|
def after_teardown
|
@@ -53,8 +53,8 @@ module Datadog
|
|
53
53
|
|
54
54
|
finish_with_result(test_span, result_code)
|
55
55
|
|
56
|
-
# remove failures if test passed at least once on retries
|
57
|
-
self.failures = [] if test_span.
|
56
|
+
# remove failures if test passed at least once on retries or quarantined
|
57
|
+
self.failures = [] if test_span.should_ignore_failures?
|
58
58
|
|
59
59
|
if Helpers.parallel?(self.class)
|
60
60
|
finish_with_result(test_span.test_suite, result_code)
|
@@ -41,7 +41,7 @@ module Datadog
|
|
41
41
|
) do |test_span|
|
42
42
|
test_span&.itr_unskippable! if datadog_unskippable?
|
43
43
|
|
44
|
-
metadata[:skip] =
|
44
|
+
metadata[:skip] = test_span&.datadog_skip_reason if test_span&.should_skip?
|
45
45
|
|
46
46
|
# before each run remove any previous exception
|
47
47
|
@exception = nil
|
@@ -58,8 +58,8 @@ module Datadog
|
|
58
58
|
test_span&.passed!
|
59
59
|
when :failed
|
60
60
|
test_span&.failed!(exception: execution_result.exception)
|
61
|
-
# if any of the retries passed, we don't fail the test run
|
62
|
-
@exception = nil if test_span&.
|
61
|
+
# if any of the retries passed or test is quarantined, we don't fail the test run
|
62
|
+
@exception = nil if test_span&.should_ignore_failures?
|
63
63
|
else
|
64
64
|
# :pending or nil
|
65
65
|
test_span&.skipped!(
|
@@ -20,6 +20,8 @@ module Datadog
|
|
20
20
|
ENV_RETRY_FAILED_TESTS_TOTAL_LIMIT = "DD_CIVISIBILITY_TOTAL_FLAKY_RETRY_COUNT"
|
21
21
|
ENV_RETRY_NEW_TESTS_ENABLED = "DD_CIVISIBILITY_EARLY_FLAKE_DETECTION_ENABLED"
|
22
22
|
ENV_TEST_SESSION_NAME = "DD_TEST_SESSION_NAME"
|
23
|
+
ENV_TEST_MANAGEMENT_ENABLED = "DD_TEST_MANAGEMENT_ENABLED"
|
24
|
+
ENV_TEST_MANAGEMENT_ATTEMPT_TO_FIX_RETRIES = "DD_TEST_MANAGEMENT_ATTEMPT_TO_FIX_RETRIES"
|
23
25
|
|
24
26
|
# Source: https://docs.datadoghq.com/getting_started/site/
|
25
27
|
DD_SITE_ALLOWLIST = %w[
|
@@ -54,11 +54,17 @@ module Datadog
|
|
54
54
|
METRIC_CODE_COVERAGE_IS_EMPTY = "code_coverage.is_empty"
|
55
55
|
METRIC_CODE_COVERAGE_FILES = "code_coverage.files"
|
56
56
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
57
|
+
METRIC_KNOWN_TESTS_REQUEST = "known_tests.request"
|
58
|
+
METRIC_KNOWN_TESTS_REQUEST_MS = "known_tests.request_ms"
|
59
|
+
METRIC_KNOWN_TESTS_REQUEST_ERRORS = "known_tests.request_errors"
|
60
|
+
METRIC_KNOWN_TESTS_RESPONSE_BYTES = "known_tests.response_bytes"
|
61
|
+
METRIC_KNOWN_TESTS_RESPONSE_TESTS = "known_tests.response_tests"
|
62
|
+
|
63
|
+
METRIC_TEST_MANAGEMENT_TESTS_REQUEST = "test_management_tests.request"
|
64
|
+
METRIC_TEST_MANAGEMENT_TESTS_REQUEST_MS = "test_management_tests.request_ms"
|
65
|
+
METRIC_TEST_MANAGEMENT_TESTS_REQUEST_ERRORS = "test_management_tests.request_errors"
|
66
|
+
METRIC_TEST_MANAGEMENT_TESTS_RESPONSE_BYTES = "test_management_tests.response_bytes"
|
67
|
+
METRIC_TEST_MANAGEMENT_TESTS_RESPONSE_TESTS = "test_management_tests.response_tests"
|
62
68
|
|
63
69
|
METRIC_TEST_SESSION = "test_session"
|
64
70
|
|
@@ -69,6 +75,7 @@ module Datadog
|
|
69
75
|
TAG_BROWSER_DRIVER = "browser_driver"
|
70
76
|
TAG_IS_RUM = "is_rum"
|
71
77
|
TAG_IS_RETRY = "is_retry"
|
78
|
+
TAG_RETRY_REASON = "retry_reason"
|
72
79
|
TAG_EARLY_FLAKE_DETECTION_ABORT_REASON = "early_flake_detection_abort_reason"
|
73
80
|
TAG_IS_NEW = "is_new"
|
74
81
|
TAG_LIBRARY = "library"
|
@@ -79,6 +86,10 @@ module Datadog
|
|
79
86
|
TAG_REQUEST_COMPRESSED = "rq_compressed"
|
80
87
|
TAG_RESPONSE_COMPRESSED = "rs_compressed"
|
81
88
|
TAG_COMMAND = "command"
|
89
|
+
TAG_IS_ATTEMPT_TO_FIX = "is_attempt_to_fix"
|
90
|
+
TAG_IS_QUARANTINED = "is_quarantined"
|
91
|
+
TAG_IS_TEST_DISABLED = "is_disabled"
|
92
|
+
TAG_HAS_FAILED_ALL_RETRIES = "has_failed_all_retries"
|
82
93
|
# tags for git_requests.settings_response metric
|
83
94
|
TAG_COVERAGE_ENABLED = "coverage_enabled"
|
84
95
|
TAG_ITR_ENABLED = "itr_enabled"
|
@@ -86,6 +97,7 @@ module Datadog
|
|
86
97
|
TAG_REQUIRE_GIT = "require_git"
|
87
98
|
TAG_EARLY_FLAKE_DETECTION_ENABLED = "early_flake_detection_enabled"
|
88
99
|
TAG_FLAKY_TEST_RETRIES_ENABLED = "flaky_test_retries_enabled"
|
100
|
+
TAG_KNOWN_TESTS_ENABLED = "known_tests_enabled"
|
89
101
|
# tags for test_session metric
|
90
102
|
TAG_PROVIDER = "provider"
|
91
103
|
TAG_AUTO_INJECTED = "auto_injected"
|
data/lib/datadog/ci/ext/test.rb
CHANGED
@@ -58,21 +58,42 @@ module Datadog
|
|
58
58
|
# version of the browser, if multiple browsers or multiple versions then this tag is empty
|
59
59
|
TAG_BROWSER_VERSION = "test.browser.version"
|
60
60
|
|
61
|
+
# known and new tests
|
62
|
+
TAG_IS_NEW = "test.is_new" # true if test is new (it was not known to Datadog before)
|
63
|
+
|
61
64
|
# Tags for retries
|
62
65
|
TAG_IS_RETRY = "test.is_retry" # true if test was retried by datadog-ci library
|
63
|
-
|
66
|
+
TAG_RETRY_REASON = "test.retry_reason" # reason why test was retried
|
64
67
|
TAG_EARLY_FLAKE_ENABLED = "test.early_flake.enabled" # true if early flake detection is enabled
|
65
68
|
TAG_EARLY_FLAKE_ABORT_REASON = "test.early_flake.abort_reason" # reason why early flake detection was aborted
|
66
69
|
|
67
70
|
# Tags for total code coverage
|
68
71
|
TAG_CODE_COVERAGE_LINES_PCT = "test.code_coverage.lines_pct"
|
69
72
|
|
73
|
+
# Tags for test managament
|
74
|
+
TAG_TEST_MANAGEMENT_ENABLED = "test.test_management.enabled" # true if test management is enabled, set on test_session_end event
|
75
|
+
TAG_IS_ATTEMPT_TO_FIX = "test.test_management.is_attempt_to_fix" # true if test is marked as "attempted to fix"
|
76
|
+
TAG_IS_TEST_DISABLED = "test.test_management.is_test_disabled" # true if test is marked as disabled in test management view
|
77
|
+
TAG_IS_QUARANTINED = "test.test_management.is_quarantined" # true if test is quarantined in test management view
|
78
|
+
TAG_HAS_FAILED_ALL_RETRIES = "test.has_failed_all_retries" # true if test was retried and none of the retries passed
|
79
|
+
TAG_ATTEMPT_TO_FIX_PASSED = "test.test_management.attempt_to_fix_passed" # true if test was marked as "attempted to fix" and all of the retries passed
|
80
|
+
|
81
|
+
# a set of tag indicating which capabilities (features) are supported by the library
|
82
|
+
module LibraryCapabilities
|
83
|
+
TAG_TEST_IMPACT_ANALYSIS = "_dd.library_capabilities.test_impact_analysis"
|
84
|
+
TAG_EARLY_FLAKE_DETECTION = "_dd.library_capabilities.early_flake_detection"
|
85
|
+
TAG_AUTO_TEST_RETRIES = "_dd.library_capabilities.auto_test_retries"
|
86
|
+
TAG_TEST_MANAGEMENT_QUARANTINE = "_dd.library_capabilities.test_management.quarantine"
|
87
|
+
TAG_TEST_MANAGEMENT_DISABLE = "_dd.library_capabilities.test_management.disable"
|
88
|
+
TAG_TEST_MANAGEMENT_ATTEMPT_TO_FIX = "_dd.library_capabilities.test_management.attempt_to_fix"
|
89
|
+
end
|
90
|
+
|
70
91
|
# internal APM tag to mark a span as a test span
|
71
92
|
TAG_SPAN_KIND = "span.kind"
|
72
93
|
SPAN_KIND_TEST = "test"
|
73
94
|
|
74
|
-
#
|
75
|
-
|
95
|
+
# DD_TEST_SESSION_NAME value
|
96
|
+
TAG_TEST_SESSION_NAME = "test_session.name"
|
76
97
|
|
77
98
|
# internal tag indicating if datadog service was configured by the user
|
78
99
|
TAG_USER_PROVIDED_TEST_SERVICE = "_dd.test.is_user_provided_service"
|
@@ -85,7 +106,6 @@ module Datadog
|
|
85
106
|
|
86
107
|
# could be either "test" or "suite" depending on whether we skip individual tests or whole suites
|
87
108
|
ITR_TEST_SKIPPING_MODE = "test" # we always skip tests (not suites) in Ruby
|
88
|
-
ITR_TEST_SKIP_REASON = "Skipped by Datadog's intelligent test runner"
|
89
109
|
ITR_UNSKIPPABLE_OPTION = :datadog_itr_unskippable
|
90
110
|
|
91
111
|
EARLY_FLAKE_FAULTY = "faulty"
|
@@ -97,12 +117,30 @@ module Datadog
|
|
97
117
|
SKIP = "skip"
|
98
118
|
end
|
99
119
|
|
120
|
+
# test statuses that we use for execution stats but don't report to Datadog (e.g. fail_ignored)
|
121
|
+
module ExecutionStatsStatus
|
122
|
+
FAIL_IGNORED = "fail_ignored"
|
123
|
+
end
|
124
|
+
|
100
125
|
# test types (e.g. test, benchmark, browser)
|
101
126
|
module Type
|
102
127
|
TEST = "test"
|
103
128
|
BROWSER = "browser"
|
104
129
|
BENCHMARK = "benchmark" # DEV: not used yet, will be used when benchmarks are supported
|
105
130
|
end
|
131
|
+
|
132
|
+
# possible reasons why a test was retried
|
133
|
+
module RetryReason
|
134
|
+
RETRY_NEW = "efd"
|
135
|
+
RETRY_FAILED = "atr"
|
136
|
+
RETRY_FLAKY_FIXED = "attempt_to_fix"
|
137
|
+
end
|
138
|
+
|
139
|
+
# possible reasons why a test was skipped
|
140
|
+
module SkipReason
|
141
|
+
TEST_IMPACT_ANALYSIS = "Skipped by Datadog's Test Impact Analysis"
|
142
|
+
TEST_MANAGEMENT_DISABLED = "Flaky test is disabled by Datadog"
|
143
|
+
end
|
106
144
|
end
|
107
145
|
end
|
108
146
|
end
|
@@ -38,10 +38,13 @@ module Datadog
|
|
38
38
|
DD_API_SETTINGS_RESPONSE_TESTS_SKIPPING_KEY = "tests_skipping"
|
39
39
|
DD_API_SETTINGS_RESPONSE_REQUIRE_GIT_KEY = "require_git"
|
40
40
|
DD_API_SETTINGS_RESPONSE_FLAKY_TEST_RETRIES_KEY = "flaky_test_retries_enabled"
|
41
|
+
DD_API_SETTINGS_RESPONSE_KNOWN_TESTS_ENABLED_KEY = "known_tests_enabled"
|
41
42
|
DD_API_SETTINGS_RESPONSE_EARLY_FLAKE_DETECTION_KEY = "early_flake_detection"
|
42
43
|
DD_API_SETTINGS_RESPONSE_ENABLED_KEY = "enabled"
|
43
44
|
DD_API_SETTINGS_RESPONSE_SLOW_TEST_RETRIES_KEY = "slow_test_retries"
|
44
45
|
DD_API_SETTINGS_RESPONSE_FAULTY_SESSION_THRESHOLD_KEY = "faulty_session_threshold"
|
46
|
+
DD_API_SETTINGS_RESPONSE_TEST_MANAGEMENT_KEY = "test_management"
|
47
|
+
DD_API_SETTINGS_RESPONSE_ATTEMPT_TO_FIX_RETRIES_KEY = "attempt_to_fix_retries"
|
45
48
|
DD_API_SETTINGS_RESPONSE_DEFAULT = {DD_API_SETTINGS_RESPONSE_ITR_ENABLED_KEY => false}.freeze
|
46
49
|
|
47
50
|
DD_API_GIT_SEARCH_COMMITS_PATH = "/api/v2/git/repository/search_commits"
|
@@ -54,6 +57,9 @@ module Datadog
|
|
54
57
|
DD_API_UNIQUE_TESTS_PATH = "/api/v2/ci/libraries/tests"
|
55
58
|
DD_API_UNIQUE_TESTS_TYPE = "ci_app_libraries_tests_request"
|
56
59
|
|
60
|
+
DD_API_TEST_MANAGEMENT_TESTS_PATH = "/api/v2/test/libraries/test-management/tests"
|
61
|
+
DD_API_TEST_MANAGEMENT_TESTS_TYPE = "ci_app_libraries_tests_request"
|
62
|
+
|
57
63
|
CONTENT_TYPE_MESSAGEPACK = "application/msgpack"
|
58
64
|
CONTENT_TYPE_JSON = "application/json"
|
59
65
|
CONTENT_TYPE_MULTIPART_FORM_DATA = "multipart/form-data"
|
@@ -32,7 +32,9 @@ module Datadog
|
|
32
32
|
# configure different components in parallel because they might block on HTTP requests
|
33
33
|
configuration_workers = [
|
34
34
|
Worker.new { test_optimisation.configure(library_configuration, test_session) },
|
35
|
-
Worker.new { test_retries.configure(library_configuration, test_session) }
|
35
|
+
Worker.new { test_retries.configure(library_configuration, test_session) },
|
36
|
+
Worker.new { test_visibility.configure(library_configuration, test_session) },
|
37
|
+
Worker.new { test_management.configure(library_configuration, test_session) }
|
36
38
|
]
|
37
39
|
|
38
40
|
# launch configuration workers
|
@@ -44,6 +46,14 @@ module Datadog
|
|
44
46
|
|
45
47
|
private
|
46
48
|
|
49
|
+
def test_management
|
50
|
+
Datadog.send(:components).test_management
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_visibility
|
54
|
+
Datadog.send(:components).test_visibility
|
55
|
+
end
|
56
|
+
|
47
57
|
def test_optimisation
|
48
58
|
Datadog.send(:components).test_optimisation
|
49
59
|
end
|
@@ -98,6 +98,14 @@ module Datadog
|
|
98
98
|
)
|
99
99
|
end
|
100
100
|
|
101
|
+
def known_tests_enabled?
|
102
|
+
return @known_tests_enabled if defined?(@known_tests_enabled)
|
103
|
+
|
104
|
+
@known_tests_enabled = Utils::Parsing.convert_to_bool(
|
105
|
+
payload.fetch(Ext::Transport::DD_API_SETTINGS_RESPONSE_KNOWN_TESTS_ENABLED_KEY, false)
|
106
|
+
)
|
107
|
+
end
|
108
|
+
|
101
109
|
def slow_test_retries
|
102
110
|
return @slow_test_retries if defined?(@slow_test_retries)
|
103
111
|
|
@@ -114,8 +122,31 @@ module Datadog
|
|
114
122
|
)
|
115
123
|
end
|
116
124
|
|
125
|
+
def test_management_enabled?
|
126
|
+
return @test_management_enabled if defined?(@test_management_enabled)
|
127
|
+
|
128
|
+
@test_management_enabled = Utils::Parsing.convert_to_bool(
|
129
|
+
test_management_payload.fetch(Ext::Transport::DD_API_SETTINGS_RESPONSE_ENABLED_KEY, false)
|
130
|
+
)
|
131
|
+
end
|
132
|
+
|
133
|
+
def attempt_to_fix_retries_count
|
134
|
+
return @attempt_to_fix_retries_count if defined?(@attempt_to_fix_retries_count)
|
135
|
+
|
136
|
+
@attempt_to_fix_retries_count = test_management_payload.fetch(
|
137
|
+
Ext::Transport::DD_API_SETTINGS_RESPONSE_ATTEMPT_TO_FIX_RETRIES_KEY, nil
|
138
|
+
)
|
139
|
+
end
|
140
|
+
|
117
141
|
private
|
118
142
|
|
143
|
+
def test_management_payload
|
144
|
+
payload.fetch(
|
145
|
+
Ext::Transport::DD_API_SETTINGS_RESPONSE_TEST_MANAGEMENT_KEY,
|
146
|
+
{}
|
147
|
+
)
|
148
|
+
end
|
149
|
+
|
119
150
|
def early_flake_detection_payload
|
120
151
|
payload.fetch(
|
121
152
|
Ext::Transport::DD_API_SETTINGS_RESPONSE_EARLY_FLAKE_DETECTION_KEY,
|
@@ -62,7 +62,8 @@ module Datadog
|
|
62
62
|
Ext::Telemetry::TAG_EARLY_FLAKE_DETECTION_ENABLED => library_settings.early_flake_detection_enabled?.to_s,
|
63
63
|
Ext::Telemetry::TAG_FLAKY_TEST_RETRIES_ENABLED => library_settings.flaky_test_retries_enabled?.to_s,
|
64
64
|
Ext::Telemetry::TAG_ITR_ENABLED => library_settings.itr_enabled?.to_s,
|
65
|
-
Ext::Telemetry::TAG_REQUIRE_GIT => library_settings.require_git?.to_s
|
65
|
+
Ext::Telemetry::TAG_REQUIRE_GIT => library_settings.require_git?.to_s,
|
66
|
+
Ext::Telemetry::TAG_KNOWN_TESTS_ENABLED => library_settings.known_tests_enabled?.to_s
|
66
67
|
}
|
67
68
|
)
|
68
69
|
|
data/lib/datadog/ci/test.rb
CHANGED
@@ -62,19 +62,37 @@ module Datadog
|
|
62
62
|
get_tag(Ext::Test::TAG_TEST_SESSION_ID)
|
63
63
|
end
|
64
64
|
|
65
|
-
# Returns "true" if the test is skipped by the intelligent test runner.
|
66
|
-
# @return [Boolean] true if the test is skipped by the intelligent test runner, false otherwise.
|
67
|
-
def skipped_by_itr?
|
68
|
-
get_tag(Ext::Test::TAG_ITR_SKIPPED_BY_ITR) == "true"
|
69
|
-
end
|
70
|
-
|
71
65
|
# Returns "true" if test span represents a retry.
|
72
66
|
# @return [Boolean] true if this test is a retry, false otherwise.
|
73
67
|
def is_retry?
|
74
68
|
get_tag(Ext::Test::TAG_IS_RETRY) == "true"
|
75
69
|
end
|
76
70
|
|
77
|
-
#
|
71
|
+
# Returns "true" if this span represents a test that wasn't known to Datadog before.
|
72
|
+
# @return [Boolean] true if this test is a new one, false otherwise.
|
73
|
+
def is_new?
|
74
|
+
get_tag(Ext::Test::TAG_IS_NEW) == "true"
|
75
|
+
end
|
76
|
+
|
77
|
+
# Returns "true" if this test is quarantined by Datadog test management.
|
78
|
+
# @return [Boolean] true if this test is quarantined, false otherwise.
|
79
|
+
def quarantined?
|
80
|
+
get_tag(Ext::Test::TAG_IS_QUARANTINED) == "true"
|
81
|
+
end
|
82
|
+
|
83
|
+
# Returns "true" if this test is disabled by Datadog test management.
|
84
|
+
# @return [Boolean] true if this test is disabled, false otherwise.
|
85
|
+
def disabled?
|
86
|
+
get_tag(Ext::Test::TAG_IS_TEST_DISABLED) == "true"
|
87
|
+
end
|
88
|
+
|
89
|
+
# Returns "true" if this flaky test has fixing attempts (determined by Datadog backend).
|
90
|
+
# @return [Boolean] true if this test is attempted to be fixed.
|
91
|
+
def attempt_to_fix?
|
92
|
+
get_tag(Ext::Test::TAG_IS_ATTEMPT_TO_FIX) == "true"
|
93
|
+
end
|
94
|
+
|
95
|
+
# Marks this test as unskippable by the Test Impact Analysis.
|
78
96
|
# This must be done before the test execution starts.
|
79
97
|
#
|
80
98
|
# Examples of tests that should be unskippable:
|
@@ -88,7 +106,7 @@ module Datadog
|
|
88
106
|
TestOptimisation::Telemetry.itr_unskippable
|
89
107
|
set_tag(Ext::Test::TAG_ITR_UNSKIPPABLE, "true")
|
90
108
|
|
91
|
-
if
|
109
|
+
if skipped_by_test_impact_analysis?
|
92
110
|
clear_tag(Ext::Test::TAG_ITR_SKIPPED_BY_ITR)
|
93
111
|
|
94
112
|
TestOptimisation::Telemetry.itr_forced_run
|
@@ -110,7 +128,13 @@ module Datadog
|
|
110
128
|
def failed!(exception: nil)
|
111
129
|
super
|
112
130
|
|
113
|
-
|
131
|
+
# if we should ignore failures, we consider this test to be passed
|
132
|
+
if should_ignore_failures?
|
133
|
+
# use a special "fail_ignored" status to mark this test as failed but ignored
|
134
|
+
record_test_result(Ext::Test::ExecutionStatsStatus::FAIL_IGNORED)
|
135
|
+
else
|
136
|
+
record_test_result(Ext::Test::Status::FAIL)
|
137
|
+
end
|
114
138
|
end
|
115
139
|
|
116
140
|
# Sets the status of the span to "skip".
|
@@ -148,6 +172,40 @@ module Datadog
|
|
148
172
|
!!test_suite&.any_test_retry_passed?(datadog_test_id)
|
149
173
|
end
|
150
174
|
|
175
|
+
# @internal
|
176
|
+
def all_executions_failed?
|
177
|
+
!!test_suite&.all_executions_failed?(datadog_test_id)
|
178
|
+
end
|
179
|
+
|
180
|
+
# @internal
|
181
|
+
def all_executions_passed?
|
182
|
+
!!test_suite&.all_executions_passed?(datadog_test_id)
|
183
|
+
end
|
184
|
+
|
185
|
+
# @internal
|
186
|
+
def datadog_skip_reason
|
187
|
+
if skipped_by_test_impact_analysis?
|
188
|
+
Ext::Test::SkipReason::TEST_IMPACT_ANALYSIS
|
189
|
+
elsif disabled? || quarantined?
|
190
|
+
Ext::Test::SkipReason::TEST_MANAGEMENT_DISABLED
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
# @internal
|
195
|
+
def should_skip?
|
196
|
+
skipped_by_test_impact_analysis? || (disabled? && !attempt_to_fix?)
|
197
|
+
end
|
198
|
+
|
199
|
+
# @internal
|
200
|
+
def should_ignore_failures?
|
201
|
+
quarantined? || disabled? || any_retry_passed?
|
202
|
+
end
|
203
|
+
|
204
|
+
# @internal
|
205
|
+
def skipped_by_test_impact_analysis?
|
206
|
+
get_tag(Ext::Test::TAG_ITR_SKIPPED_BY_ITR) == "true"
|
207
|
+
end
|
208
|
+
|
151
209
|
private
|
152
210
|
|
153
211
|
def record_test_result(datadog_status)
|