datadog-ci 1.3.0 → 1.4.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 +33 -2
- data/lib/datadog/ci/configuration/components.rb +25 -11
- data/lib/datadog/ci/configuration/settings.rb +19 -1
- data/lib/datadog/ci/contrib/cucumber/configuration_override.rb +37 -0
- data/lib/datadog/ci/contrib/cucumber/formatter.rb +5 -5
- data/lib/datadog/ci/contrib/cucumber/instrumentation.rb +9 -1
- data/lib/datadog/ci/contrib/cucumber/patcher.rb +3 -3
- data/lib/datadog/ci/contrib/minitest/runner.rb +16 -0
- data/lib/datadog/ci/contrib/minitest/test.rb +1 -0
- data/lib/datadog/ci/contrib/rspec/example.rb +67 -39
- data/lib/datadog/ci/contrib/rspec/example_group.rb +1 -1
- data/lib/datadog/ci/ext/settings.rb +3 -0
- data/lib/datadog/ci/ext/telemetry.rb +1 -0
- data/lib/datadog/ci/ext/test.rb +11 -11
- data/lib/datadog/ci/ext/transport.rb +1 -0
- data/lib/datadog/ci/git/local_repository.rb +32 -13
- data/lib/datadog/ci/remote/component.rb +50 -0
- data/lib/datadog/ci/remote/library_settings.rb +91 -0
- data/lib/datadog/ci/{transport/remote_settings_api.rb → remote/library_settings_client.rb} +11 -56
- data/lib/datadog/ci/test.rb +8 -1
- data/lib/datadog/ci/test_optimisation/component.rb +12 -16
- data/lib/datadog/ci/test_retries/component.rb +84 -0
- data/lib/datadog/ci/test_retries/null_component.rb +28 -0
- data/lib/datadog/ci/test_retries/strategy/base.rb +19 -0
- data/lib/datadog/ci/test_retries/strategy/no_retry.rb +16 -0
- data/lib/datadog/ci/test_retries/strategy/retry_failed.rb +37 -0
- data/lib/datadog/ci/test_suite.rb +39 -18
- data/lib/datadog/ci/test_visibility/component.rb +45 -47
- data/lib/datadog/ci/test_visibility/null_component.rb +6 -0
- data/lib/datadog/ci/test_visibility/telemetry.rb +3 -0
- data/lib/datadog/ci/version.rb +1 -1
- metadata +13 -6
- data/lib/datadog/ci/contrib/cucumber/step.rb +0 -27
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 614d612dad9b7e29104499934b7e80b44a0cd5f60ec5135593a3bccd9df5fc9c
|
4
|
+
data.tar.gz: bb498cfa7db7871f2ac03aedb2dbbb94fac878ea34ff33d0a205e216fe856735
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7edc6574a2a647e49da0c5ae487f98c89fa097aae064cbfd42b2a08b88ae1611fee948632dca90c6b2bb9166e5f3e02ea3aaffeb0f419f6f84f3905eac384b53
|
7
|
+
data.tar.gz: 815bdb39b87e95ee1a8fe7ed5c9ae9b545491ff0c59beb117a7ff0202b73aede9c14ee4fc5179195d726ed4f4dd0572de95f3bb795f26124062f332e138e8bbe
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,24 @@
|
|
1
1
|
## [Unreleased]
|
2
2
|
|
3
|
+
## [1.4.0] - 2024-08-26
|
4
|
+
|
5
|
+
### Added
|
6
|
+
|
7
|
+
* Auto test retries for cucumber ([#212][])
|
8
|
+
* Auto test retries for RSpec ([#213][])
|
9
|
+
* Auto test retries for minitest ([#214][])
|
10
|
+
* implement auto test retries RFC ([#219][])
|
11
|
+
|
12
|
+
### Changed
|
13
|
+
|
14
|
+
* Skip Before/After hooks in cucumber when scenario is skipped by intelligent test runner ([#211][])
|
15
|
+
* gem datadog 2.3 is now minimal required version ([#220][])
|
16
|
+
* Enable agentless telemetry when library is running in agentless mode ([#221][])
|
17
|
+
* Add Ruby 3.4 to the testing matrix ([#217][])
|
18
|
+
* add different fallbacks for unshallowing remotes ([#218][])
|
19
|
+
* make itr_enabled config parameter true by default ([#216][])
|
20
|
+
* RSpec - don't report test errors if rspec process is quitting ([#215][])
|
21
|
+
|
3
22
|
## [1.3.0] - 2024-07-30
|
4
23
|
|
5
24
|
### Added
|
@@ -290,7 +309,8 @@ Currently test suite level visibility is not used by our instrumentation: it wil
|
|
290
309
|
|
291
310
|
- Ruby versions < 2.7 no longer supported ([#8][])
|
292
311
|
|
293
|
-
[Unreleased]: https://github.com/DataDog/datadog-ci-rb/compare/v1.
|
312
|
+
[Unreleased]: https://github.com/DataDog/datadog-ci-rb/compare/v1.4.0...main
|
313
|
+
[1.4.0]: https://github.com/DataDog/datadog-ci-rb/compare/v1.3.0...v1.4.0
|
294
314
|
[1.3.0]: https://github.com/DataDog/datadog-ci-rb/compare/v1.2.0...v1.3.0
|
295
315
|
[1.2.0]: https://github.com/DataDog/datadog-ci-rb/compare/v1.1.0...v1.2.0
|
296
316
|
[1.1.0]: https://github.com/DataDog/datadog-ci-rb/compare/v1.0.1...v1.1.0
|
@@ -413,4 +433,15 @@ Currently test suite level visibility is not used by our instrumentation: it wil
|
|
413
433
|
[#204]: https://github.com/DataDog/datadog-ci-rb/issues/204
|
414
434
|
[#205]: https://github.com/DataDog/datadog-ci-rb/issues/205
|
415
435
|
[#206]: https://github.com/DataDog/datadog-ci-rb/issues/206
|
416
|
-
[#207]: https://github.com/DataDog/datadog-ci-rb/issues/207
|
436
|
+
[#207]: https://github.com/DataDog/datadog-ci-rb/issues/207
|
437
|
+
[#211]: https://github.com/DataDog/datadog-ci-rb/issues/211
|
438
|
+
[#212]: https://github.com/DataDog/datadog-ci-rb/issues/212
|
439
|
+
[#213]: https://github.com/DataDog/datadog-ci-rb/issues/213
|
440
|
+
[#214]: https://github.com/DataDog/datadog-ci-rb/issues/214
|
441
|
+
[#215]: https://github.com/DataDog/datadog-ci-rb/issues/215
|
442
|
+
[#216]: https://github.com/DataDog/datadog-ci-rb/issues/216
|
443
|
+
[#217]: https://github.com/DataDog/datadog-ci-rb/issues/217
|
444
|
+
[#218]: https://github.com/DataDog/datadog-ci-rb/issues/218
|
445
|
+
[#219]: https://github.com/DataDog/datadog-ci-rb/issues/219
|
446
|
+
[#220]: https://github.com/DataDog/datadog-ci-rb/issues/220
|
447
|
+
[#221]: https://github.com/DataDog/datadog-ci-rb/issues/221
|
@@ -4,9 +4,13 @@ require "datadog/core/telemetry/ext"
|
|
4
4
|
|
5
5
|
require_relative "../ext/settings"
|
6
6
|
require_relative "../git/tree_uploader"
|
7
|
+
require_relative "../remote/component"
|
8
|
+
require_relative "../remote/library_settings_client"
|
7
9
|
require_relative "../test_optimisation/component"
|
8
10
|
require_relative "../test_optimisation/coverage/transport"
|
9
11
|
require_relative "../test_optimisation/coverage/writer"
|
12
|
+
require_relative "../test_retries/component"
|
13
|
+
require_relative "../test_retries/null_component"
|
10
14
|
require_relative "../test_visibility/component"
|
11
15
|
require_relative "../test_visibility/flush"
|
12
16
|
require_relative "../test_visibility/null_component"
|
@@ -15,7 +19,6 @@ require_relative "../test_visibility/serializers/factories/test_suite_level"
|
|
15
19
|
require_relative "../test_visibility/transport"
|
16
20
|
require_relative "../transport/adapters/telemetry_webmock_safe_adapter"
|
17
21
|
require_relative "../transport/api/builder"
|
18
|
-
require_relative "../transport/remote_settings_api"
|
19
22
|
require_relative "../utils/identity"
|
20
23
|
require_relative "../utils/parsing"
|
21
24
|
require_relative "../utils/test_run"
|
@@ -26,11 +29,14 @@ module Datadog
|
|
26
29
|
module Configuration
|
27
30
|
# Adds CI behavior to Datadog trace components
|
28
31
|
module Components
|
29
|
-
attr_reader :test_visibility, :test_optimisation
|
32
|
+
attr_reader :test_visibility, :test_optimisation, :git_tree_upload_worker, :ci_remote, :test_retries
|
30
33
|
|
31
34
|
def initialize(settings)
|
32
35
|
@test_optimisation = nil
|
33
36
|
@test_visibility = TestVisibility::NullComponent.new
|
37
|
+
@git_tree_upload_worker = DummyWorker.new
|
38
|
+
@ci_remote = nil
|
39
|
+
@test_retries = TestRetries::NullComponent.new
|
34
40
|
|
35
41
|
# Activate CI mode if enabled
|
36
42
|
if settings.ci.enabled
|
@@ -45,6 +51,7 @@ module Datadog
|
|
45
51
|
|
46
52
|
@test_visibility&.shutdown!
|
47
53
|
@test_optimisation&.shutdown!
|
54
|
+
@git_tree_upload_worker&.stop
|
48
55
|
end
|
49
56
|
|
50
57
|
def activate_ci!(settings)
|
@@ -102,14 +109,19 @@ module Datadog
|
|
102
109
|
|
103
110
|
settings.tracing.test_mode.writer_options = trace_writer_options
|
104
111
|
|
112
|
+
@git_tree_upload_worker = build_git_upload_worker(settings, test_visibility_api)
|
113
|
+
@ci_remote = Remote::Component.new(
|
114
|
+
library_settings_client: build_library_settings_client(settings, test_visibility_api)
|
115
|
+
)
|
116
|
+
@test_retries = TestRetries::Component.new(
|
117
|
+
retry_failed_tests_enabled: settings.ci.retry_failed_tests_enabled,
|
118
|
+
retry_failed_tests_max_attempts: settings.ci.retry_failed_tests_max_attempts,
|
119
|
+
retry_failed_tests_total_limit: settings.ci.retry_failed_tests_total_limit
|
120
|
+
)
|
105
121
|
# @type ivar @test_optimisation: Datadog::CI::TestOptimisation::Component
|
106
122
|
@test_optimisation = build_test_optimisation(settings, test_visibility_api)
|
107
|
-
|
108
123
|
@test_visibility = TestVisibility::Component.new(
|
109
|
-
|
110
|
-
test_suite_level_visibility_enabled: !settings.ci.force_test_level_visibility,
|
111
|
-
remote_settings_api: build_remote_settings_client(settings, test_visibility_api),
|
112
|
-
git_tree_upload_worker: build_git_upload_worker(settings, test_visibility_api)
|
124
|
+
test_suite_level_visibility_enabled: !settings.ci.force_test_level_visibility
|
113
125
|
)
|
114
126
|
end
|
115
127
|
|
@@ -216,8 +228,8 @@ module Datadog
|
|
216
228
|
end
|
217
229
|
end
|
218
230
|
|
219
|
-
def
|
220
|
-
|
231
|
+
def build_library_settings_client(settings, api)
|
232
|
+
Remote::LibrarySettingsClient.new(
|
221
233
|
api: api,
|
222
234
|
dd_env: settings.env,
|
223
235
|
config_tags: custom_configuration(settings)
|
@@ -254,11 +266,13 @@ module Datadog
|
|
254
266
|
# for test visibility we want to enable it by default unless explicitly disabled
|
255
267
|
# NOTE: before agentless mode is released, we only enable telemetry when running with Datadog Agent
|
256
268
|
env_telemetry_enabled = ENV[Core::Telemetry::Ext::ENV_ENABLED]
|
257
|
-
settings.telemetry.enabled =
|
258
|
-
(env_telemetry_enabled.nil? || Utils::Parsing.convert_to_bool(env_telemetry_enabled))
|
269
|
+
settings.telemetry.enabled = env_telemetry_enabled.nil? || Utils::Parsing.convert_to_bool(env_telemetry_enabled)
|
259
270
|
|
260
271
|
return unless settings.telemetry.enabled
|
261
272
|
|
273
|
+
settings.telemetry.agentless_enabled = true if settings.ci.agentless_mode_enabled
|
274
|
+
settings.telemetry.shutdown_timeout_seconds = 60.0
|
275
|
+
|
262
276
|
begin
|
263
277
|
require "datadog/core/environment/identity"
|
264
278
|
require "datadog/core/telemetry/http/adapters/net"
|
@@ -59,7 +59,7 @@ module Datadog
|
|
59
59
|
option :itr_enabled do |o|
|
60
60
|
o.type :bool
|
61
61
|
o.env CI::Ext::Settings::ENV_ITR_ENABLED
|
62
|
-
o.default
|
62
|
+
o.default true
|
63
63
|
end
|
64
64
|
|
65
65
|
option :git_metadata_upload_enabled do |o|
|
@@ -88,6 +88,24 @@ module Datadog
|
|
88
88
|
o.default true
|
89
89
|
end
|
90
90
|
|
91
|
+
option :retry_failed_tests_enabled do |o|
|
92
|
+
o.type :bool
|
93
|
+
o.env CI::Ext::Settings::ENV_RETRY_FAILED_TESTS_ENABLED
|
94
|
+
o.default true
|
95
|
+
end
|
96
|
+
|
97
|
+
option :retry_failed_tests_max_attempts do |o|
|
98
|
+
o.type :int
|
99
|
+
o.env CI::Ext::Settings::ENV_RETRY_FAILED_TESTS_MAX_ATTEMPTS
|
100
|
+
o.default 5
|
101
|
+
end
|
102
|
+
|
103
|
+
option :retry_failed_tests_total_limit do |o|
|
104
|
+
o.type :int
|
105
|
+
o.env CI::Ext::Settings::ENV_RETRY_FAILED_TESTS_TOTAL_LIMIT
|
106
|
+
o.default 1000
|
107
|
+
end
|
108
|
+
|
91
109
|
define_method(:instrument) do |integration_name, options = {}, &block|
|
92
110
|
return unless enabled
|
93
111
|
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "formatter"
|
4
|
+
|
5
|
+
module Datadog
|
6
|
+
module CI
|
7
|
+
module Contrib
|
8
|
+
module Cucumber
|
9
|
+
# Changes behaviour of Cucumber::Configuration class
|
10
|
+
module ConfigurationOverride
|
11
|
+
def self.included(base)
|
12
|
+
base.prepend(InstanceMethods)
|
13
|
+
end
|
14
|
+
|
15
|
+
# Instance methods for configuration
|
16
|
+
module InstanceMethods
|
17
|
+
def retry_attempts
|
18
|
+
super if !datadog_test_retries_component&.retry_failed_tests_enabled
|
19
|
+
|
20
|
+
datadog_test_retries_component&.retry_failed_tests_max_attempts
|
21
|
+
end
|
22
|
+
|
23
|
+
def retry_total_tests
|
24
|
+
super if !datadog_test_retries_component&.retry_failed_tests_enabled
|
25
|
+
|
26
|
+
datadog_test_retries_component&.retry_failed_tests_total_limit
|
27
|
+
end
|
28
|
+
|
29
|
+
def datadog_test_retries_component
|
30
|
+
Datadog.send(:components).test_retries
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -20,7 +20,7 @@ module Datadog
|
|
20
20
|
|
21
21
|
@current_test_suite = nil
|
22
22
|
|
23
|
-
@
|
23
|
+
@failed_test_suites_count = 0
|
24
24
|
|
25
25
|
bind_events(config)
|
26
26
|
end
|
@@ -46,10 +46,12 @@ module Datadog
|
|
46
46
|
end
|
47
47
|
|
48
48
|
def on_test_run_finished(event)
|
49
|
+
finish_current_test_suite
|
50
|
+
|
49
51
|
if event.respond_to?(:success)
|
50
52
|
finish_session(event.success)
|
51
53
|
else
|
52
|
-
finish_session(@
|
54
|
+
finish_session(@failed_test_suites_count.zero?)
|
53
55
|
end
|
54
56
|
end
|
55
57
|
|
@@ -86,7 +88,6 @@ module Datadog
|
|
86
88
|
return if test_span.nil?
|
87
89
|
|
88
90
|
finish_span(test_span, event.result)
|
89
|
-
@failed_tests_count += 1 if test_span.failed?
|
90
91
|
end
|
91
92
|
|
92
93
|
def on_test_step_started(event)
|
@@ -128,8 +129,6 @@ module Datadog
|
|
128
129
|
end
|
129
130
|
|
130
131
|
def finish_session(result)
|
131
|
-
finish_current_test_suite
|
132
|
-
|
133
132
|
test_session = test_visibility_component.active_test_session
|
134
133
|
test_module = test_visibility_component.active_test_module
|
135
134
|
|
@@ -155,6 +154,7 @@ module Datadog
|
|
155
154
|
|
156
155
|
def finish_current_test_suite
|
157
156
|
@current_test_suite&.finish
|
157
|
+
@failed_test_suites_count += 1 if @current_test_suite&.failed?
|
158
158
|
|
159
159
|
@current_test_suite = nil
|
160
160
|
end
|
@@ -6,7 +6,7 @@ module Datadog
|
|
6
6
|
module CI
|
7
7
|
module Contrib
|
8
8
|
module Cucumber
|
9
|
-
# Instrumentation for Cucumber
|
9
|
+
# Instrumentation for Cucumber::Runtime class
|
10
10
|
module Instrumentation
|
11
11
|
def self.included(base)
|
12
12
|
base.prepend(InstanceMethods)
|
@@ -21,6 +21,14 @@ module Datadog
|
|
21
21
|
@datadog_formatter ||= CI::Contrib::Cucumber::Formatter.new(@configuration)
|
22
22
|
[@datadog_formatter] + existing_formatters
|
23
23
|
end
|
24
|
+
|
25
|
+
def begin_scenario(test_case)
|
26
|
+
if Datadog::CI.active_test&.skipped_by_itr?
|
27
|
+
raise ::Cucumber::Core::Test::Result::Skipped, CI::Ext::Test::ITR_TEST_SKIP_REASON
|
28
|
+
end
|
29
|
+
|
30
|
+
super
|
31
|
+
end
|
24
32
|
end
|
25
33
|
end
|
26
34
|
end
|
@@ -3,13 +3,13 @@
|
|
3
3
|
require "datadog/tracing/contrib/patcher"
|
4
4
|
|
5
5
|
require_relative "instrumentation"
|
6
|
-
require_relative "
|
6
|
+
require_relative "configuration_override"
|
7
7
|
|
8
8
|
module Datadog
|
9
9
|
module CI
|
10
10
|
module Contrib
|
11
11
|
module Cucumber
|
12
|
-
#
|
12
|
+
# Patches 'cucumber' gem.
|
13
13
|
module Patcher
|
14
14
|
include Datadog::Tracing::Contrib::Patcher
|
15
15
|
|
@@ -21,7 +21,7 @@ module Datadog
|
|
21
21
|
|
22
22
|
def patch
|
23
23
|
::Cucumber::Runtime.include(Instrumentation)
|
24
|
-
::Cucumber::
|
24
|
+
::Cucumber::Configuration.include(ConfigurationOverride)
|
25
25
|
end
|
26
26
|
end
|
27
27
|
end
|
@@ -28,6 +28,18 @@ module Datadog
|
|
28
28
|
test_visibility_component.start_test_module(Ext::FRAMEWORK)
|
29
29
|
end
|
30
30
|
|
31
|
+
def run_one_method(klass, method_name)
|
32
|
+
return super unless datadog_configuration[:enabled]
|
33
|
+
|
34
|
+
result = nil
|
35
|
+
|
36
|
+
test_retries_component.with_retries do
|
37
|
+
result = super
|
38
|
+
end
|
39
|
+
|
40
|
+
result
|
41
|
+
end
|
42
|
+
|
31
43
|
private
|
32
44
|
|
33
45
|
def datadog_configuration
|
@@ -37,6 +49,10 @@ module Datadog
|
|
37
49
|
def test_visibility_component
|
38
50
|
Datadog.send(:components).test_visibility
|
39
51
|
end
|
52
|
+
|
53
|
+
def test_retries_component
|
54
|
+
Datadog.send(:components).test_retries
|
55
|
+
end
|
40
56
|
end
|
41
57
|
end
|
42
58
|
end
|
@@ -34,50 +34,74 @@ module Datadog
|
|
34
34
|
|
35
35
|
if ci_queue?
|
36
36
|
suite_name = "#{suite_name} (ci-queue running example [#{test_name}])"
|
37
|
-
|
37
|
+
ci_queue_test_span = test_visibility_component.start_test_suite(suite_name)
|
38
38
|
end
|
39
39
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
#
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
40
|
+
# don't report test to RSpec::Core::Reporter until retries are done
|
41
|
+
@skip_reporting = true
|
42
|
+
|
43
|
+
test_retries_component.with_retries do
|
44
|
+
test_visibility_component.trace_test(
|
45
|
+
test_name,
|
46
|
+
suite_name,
|
47
|
+
tags: {
|
48
|
+
CI::Ext::Test::TAG_FRAMEWORK => Ext::FRAMEWORK,
|
49
|
+
CI::Ext::Test::TAG_FRAMEWORK_VERSION => CI::Contrib::RSpec::Integration.version.to_s,
|
50
|
+
CI::Ext::Test::TAG_SOURCE_FILE => Git::LocalRepository.relative_to_root(metadata[:file_path]),
|
51
|
+
CI::Ext::Test::TAG_SOURCE_START => metadata[:line_number].to_s,
|
52
|
+
CI::Ext::Test::TAG_PARAMETERS => Utils::TestRun.test_parameters(
|
53
|
+
metadata: {"scoped_id" => metadata[:scoped_id]}
|
54
|
+
)
|
55
|
+
},
|
56
|
+
service: datadog_configuration[:service_name]
|
57
|
+
) do |test_span|
|
58
|
+
test_span&.itr_unskippable! if metadata[CI::Ext::Test::ITR_UNSKIPPABLE_OPTION]
|
59
|
+
|
60
|
+
metadata[:skip] = CI::Ext::Test::ITR_TEST_SKIP_REASON if test_span&.skipped_by_itr?
|
61
|
+
|
62
|
+
# before each run remove any previous exception
|
63
|
+
@exception = nil
|
64
|
+
|
65
|
+
result = super
|
66
|
+
|
67
|
+
# In case when test job is canceled and RSpec is quitting we don't want to report the last test
|
68
|
+
# before RSpec context unwinds. This test might have some unrelated errors that we don't want to
|
69
|
+
# report.
|
70
|
+
return result if ::RSpec.world.wants_to_quit
|
71
|
+
|
72
|
+
case execution_result.status
|
73
|
+
when :passed
|
74
|
+
test_span&.passed!
|
75
|
+
when :failed
|
76
|
+
test_span&.failed!(exception: execution_result.exception)
|
77
|
+
else
|
78
|
+
# :pending or nil
|
79
|
+
test_span&.skipped!(
|
80
|
+
reason: execution_result.pending_message,
|
81
|
+
exception: execution_result.pending_exception
|
82
|
+
)
|
83
|
+
end
|
75
84
|
end
|
85
|
+
end
|
76
86
|
|
77
|
-
|
87
|
+
# after retries are done, we can report the test to RSpec
|
88
|
+
@skip_reporting = false
|
78
89
|
|
79
|
-
|
80
|
-
|
90
|
+
# this is a special case for ci-queue, we need to finish the test suite span
|
91
|
+
ci_queue_test_span&.finish
|
92
|
+
|
93
|
+
# Finish spec with latest retry's result
|
94
|
+
# TODO: when implementing new test retries make sure to clean @exception before calling this method
|
95
|
+
# if test passed at least once
|
96
|
+
finish(reporter)
|
97
|
+
end
|
98
|
+
|
99
|
+
def finish(reporter)
|
100
|
+
# by default finish test but do not report it to RSpec::Core::Reporter
|
101
|
+
# it is going to be reported once after retries are done
|
102
|
+
return super unless @skip_reporting
|
103
|
+
|
104
|
+
super(::RSpec::Core::NullReporter)
|
81
105
|
end
|
82
106
|
|
83
107
|
private
|
@@ -103,6 +127,10 @@ module Datadog
|
|
103
127
|
Datadog.send(:components).test_visibility
|
104
128
|
end
|
105
129
|
|
130
|
+
def test_retries_component
|
131
|
+
Datadog.send(:components).test_retries
|
132
|
+
end
|
133
|
+
|
106
134
|
def ci_queue?
|
107
135
|
!!defined?(::RSpec::Queue::ExampleExtension) &&
|
108
136
|
self.class.ancestors.include?(::RSpec::Queue::ExampleExtension)
|
@@ -15,6 +15,9 @@ module Datadog
|
|
15
15
|
ENV_ITR_CODE_COVERAGE_EXCLUDED_BUNDLE_PATH = "DD_CIVISIBILITY_ITR_CODE_COVERAGE_EXCLUDED_BUNDLE_PATH"
|
16
16
|
ENV_ITR_CODE_COVERAGE_USE_SINGLE_THREADED_MODE = "DD_CIVISIBILITY_ITR_CODE_COVERAGE_USE_SINGLE_THREADED_MODE"
|
17
17
|
ENV_ITR_TEST_IMPACT_ANALYSIS_USE_ALLOCATION_TRACING = "DD_CIVISIBILITY_ITR_TEST_IMPACT_ANALYSIS_USE_ALLOCATION_TRACING"
|
18
|
+
ENV_RETRY_FAILED_TESTS_ENABLED = "DD_CIVISIBILITY_FLAKY_RETRY_ENABLED"
|
19
|
+
ENV_RETRY_FAILED_TESTS_MAX_ATTEMPTS = "DD_CIVISIBILITY_FLAKY_RETRY_COUNT"
|
20
|
+
ENV_RETRY_FAILED_TESTS_TOTAL_LIMIT = "DD_CIVISIBILITY_TOTAL_FLAKY_RETRY_COUNT"
|
18
21
|
|
19
22
|
# Source: https://docs.datadoghq.com/getting_started/site/
|
20
23
|
DD_SITE_ALLOWLIST = %w[
|
data/lib/datadog/ci/ext/test.rb
CHANGED
@@ -8,7 +8,7 @@ module Datadog
|
|
8
8
|
module Test
|
9
9
|
CONTEXT_ORIGIN = "ciapp-test"
|
10
10
|
|
11
|
-
#
|
11
|
+
# Test visibility tags
|
12
12
|
TAG_FRAMEWORK = "test.framework"
|
13
13
|
TAG_FRAMEWORK_VERSION = "test.framework_version"
|
14
14
|
TAG_NAME = "test.name"
|
@@ -23,7 +23,8 @@ module Datadog
|
|
23
23
|
TAG_CODEOWNERS = "test.codeowners"
|
24
24
|
TAG_PARAMETERS = "test.parameters"
|
25
25
|
|
26
|
-
#
|
26
|
+
# Test optimisation tags
|
27
|
+
TAG_CODE_COVERAGE_ENABLED = "test.code_coverage.enabled"
|
27
28
|
TAG_ITR_TEST_SKIPPING_ENABLED = "test.itr.tests_skipping.enabled"
|
28
29
|
TAG_ITR_TEST_SKIPPING_TYPE = "test.itr.tests_skipping.type"
|
29
30
|
TAG_ITR_TEST_SKIPPING_COUNT = "test.itr.tests_skipping.count"
|
@@ -32,11 +33,9 @@ module Datadog
|
|
32
33
|
TAG_ITR_UNSKIPPABLE = "test.itr.unskippable"
|
33
34
|
TAG_ITR_FORCED_RUN = "test.itr.forced_run"
|
34
35
|
|
35
|
-
#
|
36
|
-
|
37
|
-
|
38
|
-
# Special tags, not sent to the backend.
|
39
|
-
# these tags are special and used to correlate tests with the test sessions, suites, and modules
|
36
|
+
# Internal tags, they are not sent to the backend.
|
37
|
+
# These tags are internal to this library and used to correlate tests with
|
38
|
+
# the test sessions, suites, and modules.
|
40
39
|
TAG_TEST_SESSION_ID = "_test.session_id"
|
41
40
|
TAG_TEST_MODULE_ID = "_test.module_id"
|
42
41
|
TAG_TEST_SUITE_ID = "_test.suite_id"
|
@@ -50,8 +49,7 @@ module Datadog
|
|
50
49
|
TAG_RUNTIME_VERSION = "runtime.version"
|
51
50
|
|
52
51
|
# Tags for browser tests
|
53
|
-
# true if Datadog RUM was detected in the page(s) loaded by Selenium
|
54
|
-
TAG_IS_RUM_ACTIVE = "test.is_rum_active"
|
52
|
+
TAG_IS_RUM_ACTIVE = "test.is_rum_active" # true if Datadog RUM was detected in the page(s) loaded by Selenium
|
55
53
|
TAG_BROWSER_DRIVER = "test.browser.driver"
|
56
54
|
# version of selenium driver used
|
57
55
|
TAG_BROWSER_DRIVER_VERSION = "test.browser.driver_version"
|
@@ -60,6 +58,9 @@ module Datadog
|
|
60
58
|
# version of the browser, if multiple browsers or multiple versions then this tag is empty
|
61
59
|
TAG_BROWSER_VERSION = "test.browser.version"
|
62
60
|
|
61
|
+
# Tags for test retries
|
62
|
+
TAG_IS_RETRY = "test.is_retry" # true if test was retried by datadog-ci library
|
63
|
+
|
63
64
|
# internal APM tag to mark a span as a test span
|
64
65
|
TAG_SPAN_KIND = "span.kind"
|
65
66
|
SPAN_KIND_TEST = "test"
|
@@ -68,8 +69,7 @@ module Datadog
|
|
68
69
|
INHERITABLE_TAGS = [TAG_FRAMEWORK, TAG_FRAMEWORK_VERSION].freeze
|
69
70
|
|
70
71
|
# could be either "test" or "suite" depending on whether we skip individual tests or whole suites
|
71
|
-
# we
|
72
|
-
ITR_TEST_SKIPPING_MODE = "test"
|
72
|
+
ITR_TEST_SKIPPING_MODE = "test" # we always skip tests (not suites) in Ruby
|
73
73
|
ITR_TEST_SKIP_REASON = "Skipped by Datadog's intelligent test runner"
|
74
74
|
ITR_UNSKIPPABLE_OPTION = :datadog_itr_unskippable
|
75
75
|
|
@@ -36,6 +36,7 @@ module Datadog
|
|
36
36
|
DD_API_SETTINGS_RESPONSE_CODE_COVERAGE_KEY = "code_coverage"
|
37
37
|
DD_API_SETTINGS_RESPONSE_TESTS_SKIPPING_KEY = "tests_skipping"
|
38
38
|
DD_API_SETTINGS_RESPONSE_REQUIRE_GIT_KEY = "require_git"
|
39
|
+
DD_API_SETTINGS_RESPONSE_FLAKY_TEST_RETRIES_KEY = "flaky_test_retries_enabled"
|
39
40
|
DD_API_SETTINGS_RESPONSE_DEFAULT = {DD_API_SETTINGS_RESPONSE_ITR_ENABLED_KEY => false}.freeze
|
40
41
|
|
41
42
|
DD_API_GIT_SEARCH_COMMITS_PATH = "/api/v2/git/repository/search_commits"
|
@@ -238,23 +238,42 @@ module Datadog
|
|
238
238
|
Telemetry.git_command(Ext::Telemetry::Command::UNSHALLOW)
|
239
239
|
res = nil
|
240
240
|
|
241
|
+
unshallow_command =
|
242
|
+
"git fetch " \
|
243
|
+
"--shallow-since=\"1 month ago\" " \
|
244
|
+
"--update-shallow " \
|
245
|
+
"--filter=\"blob:none\" " \
|
246
|
+
"--recurse-submodules=no " \
|
247
|
+
"$(git config --default origin --get clone.defaultRemoteName)"
|
248
|
+
|
249
|
+
unshallow_remotes = [
|
250
|
+
"$(git rev-parse HEAD)",
|
251
|
+
"$(git rev-parse --abbrev-ref --symbolic-full-name @{upstream})",
|
252
|
+
nil
|
253
|
+
]
|
254
|
+
|
241
255
|
duration_ms = Core::Utils::Time.measure(:float_millisecond) do
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
256
|
+
unshallow_remotes.each do |remote|
|
257
|
+
unshallowing_errored = false
|
258
|
+
|
259
|
+
res =
|
260
|
+
begin
|
261
|
+
exec_git_command(
|
262
|
+
"#{unshallow_command} #{remote}"
|
263
|
+
)
|
264
|
+
rescue => e
|
265
|
+
log_failure(e, "git unshallow")
|
266
|
+
telemetry_track_error(e, Ext::Telemetry::Command::UNSHALLOW)
|
267
|
+
unshallowing_errored = true
|
268
|
+
nil
|
269
|
+
end
|
270
|
+
|
271
|
+
break unless unshallowing_errored
|
272
|
+
end
|
250
273
|
end
|
251
|
-
Telemetry.git_command_ms(Ext::Telemetry::Command::UNSHALLOW, duration_ms)
|
252
274
|
|
275
|
+
Telemetry.git_command_ms(Ext::Telemetry::Command::UNSHALLOW, duration_ms)
|
253
276
|
res
|
254
|
-
rescue => e
|
255
|
-
log_failure(e, "git unshallow")
|
256
|
-
telemetry_track_error(e, Ext::Telemetry::Command::UNSHALLOW)
|
257
|
-
nil
|
258
277
|
end
|
259
278
|
|
260
279
|
# makes .exec_git_command private to make sure that this method
|