datadog-ci 1.1.0 → 1.3.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 +31 -2
- data/ext/datadog_cov/datadog_cov.c +259 -67
- data/lib/datadog/ci/configuration/components.rb +149 -80
- data/lib/datadog/ci/configuration/settings.rb +6 -0
- data/lib/datadog/ci/contrib/cucumber/formatter.rb +13 -9
- data/lib/datadog/ci/contrib/minitest/runnable.rb +5 -1
- data/lib/datadog/ci/contrib/minitest/runner.rb +6 -2
- data/lib/datadog/ci/contrib/minitest/test.rb +7 -3
- data/lib/datadog/ci/contrib/rspec/example.rb +6 -2
- data/lib/datadog/ci/contrib/rspec/example_group.rb +5 -1
- data/lib/datadog/ci/contrib/rspec/knapsack_pro/runner.rb +6 -2
- data/lib/datadog/ci/contrib/rspec/runner.rb +6 -2
- data/lib/datadog/ci/ext/environment/providers/appveyor.rb +1 -1
- data/lib/datadog/ci/ext/environment/providers/aws_code_pipeline.rb +1 -1
- data/lib/datadog/ci/ext/environment/providers/azure.rb +1 -1
- data/lib/datadog/ci/ext/environment/providers/bitbucket.rb +1 -1
- data/lib/datadog/ci/ext/environment/providers/bitrise.rb +1 -1
- data/lib/datadog/ci/ext/environment/providers/buddy.rb +1 -1
- data/lib/datadog/ci/ext/environment/providers/buildkite.rb +1 -1
- data/lib/datadog/ci/ext/environment/providers/circleci.rb +1 -1
- data/lib/datadog/ci/ext/environment/providers/codefresh.rb +1 -1
- data/lib/datadog/ci/ext/environment/providers/github_actions.rb +1 -1
- data/lib/datadog/ci/ext/environment/providers/gitlab.rb +1 -1
- data/lib/datadog/ci/ext/environment/providers/jenkins.rb +1 -1
- data/lib/datadog/ci/ext/environment/providers/teamcity.rb +1 -1
- data/lib/datadog/ci/ext/environment/providers/travis.rb +1 -1
- data/lib/datadog/ci/ext/environment.rb +17 -0
- data/lib/datadog/ci/ext/settings.rb +1 -0
- data/lib/datadog/ci/ext/telemetry.rb +120 -0
- data/lib/datadog/ci/git/local_repository.rb +116 -25
- data/lib/datadog/ci/git/search_commits.rb +20 -1
- data/lib/datadog/ci/git/telemetry.rb +37 -0
- data/lib/datadog/ci/git/tree_uploader.rb +7 -0
- data/lib/datadog/ci/git/upload_packfile.rb +22 -1
- data/lib/datadog/ci/span.rb +3 -3
- data/lib/datadog/ci/test.rb +6 -1
- data/lib/datadog/ci/test_module.rb +1 -1
- data/lib/datadog/ci/{itr/runner.rb → test_optimisation/component.rb} +29 -12
- data/lib/datadog/ci/{itr → test_optimisation}/coverage/ddcov.rb +1 -1
- data/lib/datadog/ci/{itr → test_optimisation}/coverage/event.rb +1 -1
- data/lib/datadog/ci/{itr → test_optimisation}/coverage/transport.rb +11 -2
- data/lib/datadog/ci/{itr → test_optimisation}/coverage/writer.rb +1 -1
- data/lib/datadog/ci/{itr → test_optimisation}/skippable.rb +25 -1
- data/lib/datadog/ci/test_optimisation/telemetry.rb +56 -0
- data/lib/datadog/ci/test_session.rb +1 -1
- data/lib/datadog/ci/test_suite.rb +1 -1
- data/lib/datadog/ci/test_visibility/component.rb +282 -0
- data/lib/datadog/ci/test_visibility/{recorder.rb → context.rb} +39 -187
- data/lib/datadog/ci/test_visibility/{null_recorder.rb → null_component.rb} +6 -4
- data/lib/datadog/ci/test_visibility/{context → store}/global.rb +1 -1
- data/lib/datadog/ci/test_visibility/{context → store}/local.rb +1 -1
- data/lib/datadog/ci/test_visibility/telemetry.rb +69 -0
- data/lib/datadog/ci/test_visibility/transport.rb +9 -10
- data/lib/datadog/ci/transport/adapters/net.rb +42 -11
- data/lib/datadog/ci/transport/adapters/net_http_client.rb +17 -0
- data/lib/datadog/ci/transport/adapters/telemetry_webmock_safe_adapter.rb +28 -0
- data/lib/datadog/ci/transport/event_platform_transport.rb +42 -5
- data/lib/datadog/ci/transport/http.rb +49 -21
- data/lib/datadog/ci/transport/remote_settings_api.rb +39 -1
- data/lib/datadog/ci/transport/telemetry.rb +93 -0
- data/lib/datadog/ci/utils/identity.rb +20 -0
- data/lib/datadog/ci/utils/parsing.rb +2 -1
- data/lib/datadog/ci/utils/telemetry.rb +23 -0
- data/lib/datadog/ci/version.rb +1 -1
- data/lib/datadog/ci.rb +45 -15
- metadata +24 -14
@@ -5,22 +5,25 @@ require "pp"
|
|
5
5
|
require "datadog/core/utils/forking"
|
6
6
|
|
7
7
|
require_relative "../ext/test"
|
8
|
+
require_relative "../ext/telemetry"
|
8
9
|
require_relative "../ext/transport"
|
9
10
|
|
10
11
|
require_relative "../git/local_repository"
|
11
12
|
|
12
13
|
require_relative "../utils/parsing"
|
14
|
+
require_relative "../utils/telemetry"
|
13
15
|
|
14
16
|
require_relative "coverage/event"
|
15
17
|
require_relative "skippable"
|
18
|
+
require_relative "telemetry"
|
16
19
|
|
17
20
|
module Datadog
|
18
21
|
module CI
|
19
|
-
module
|
22
|
+
module TestOptimisation
|
20
23
|
# Intelligent test runner implementation
|
21
24
|
# Integrates with backend to provide test impact analysis data and
|
22
25
|
# skip tests that are not impacted by the changes
|
23
|
-
class
|
26
|
+
class Component
|
24
27
|
include Core::Utils::Forking
|
25
28
|
|
26
29
|
attr_reader :correlation_id, :skippable_tests, :skipped_tests_count
|
@@ -32,7 +35,8 @@ module Datadog
|
|
32
35
|
coverage_writer: nil,
|
33
36
|
enabled: false,
|
34
37
|
bundle_location: nil,
|
35
|
-
use_single_threaded_coverage: false
|
38
|
+
use_single_threaded_coverage: false,
|
39
|
+
use_allocation_tracing: true
|
36
40
|
)
|
37
41
|
@enabled = enabled
|
38
42
|
@api = api
|
@@ -45,6 +49,7 @@ module Datadog
|
|
45
49
|
bundle_location
|
46
50
|
end
|
47
51
|
@use_single_threaded_coverage = use_single_threaded_coverage
|
52
|
+
@use_allocation_tracing = use_allocation_tracing
|
48
53
|
|
49
54
|
@test_skipping_enabled = false
|
50
55
|
@code_coverage_enabled = false
|
@@ -57,11 +62,11 @@ module Datadog
|
|
57
62
|
@skipped_tests_count = 0
|
58
63
|
@mutex = Mutex.new
|
59
64
|
|
60
|
-
Datadog.logger.debug("
|
65
|
+
Datadog.logger.debug("TestOptimisation initialized with enabled: #{@enabled}")
|
61
66
|
end
|
62
67
|
|
63
68
|
def configure(remote_configuration, test_session:, git_tree_upload_worker:)
|
64
|
-
Datadog.logger.debug("Configuring
|
69
|
+
Datadog.logger.debug("Configuring TestOptimisation with remote configuration: #{remote_configuration}")
|
65
70
|
|
66
71
|
@enabled = Utils::Parsing.convert_to_bool(
|
67
72
|
remote_configuration.fetch(Ext::Transport::DD_API_SETTINGS_RESPONSE_ITR_ENABLED_KEY, false)
|
@@ -83,7 +88,7 @@ module Datadog
|
|
83
88
|
|
84
89
|
load_datadog_cov! if @code_coverage_enabled
|
85
90
|
|
86
|
-
Datadog.logger.debug("Configured
|
91
|
+
Datadog.logger.debug("Configured TestOptimisation with enabled: #{@enabled}, skipping_tests: #{@test_skipping_enabled}, code_coverage: #{@code_coverage_enabled}")
|
87
92
|
|
88
93
|
fetch_skippable_tests(test_session: test_session, git_tree_upload_worker: git_tree_upload_worker)
|
89
94
|
end
|
@@ -102,15 +107,20 @@ module Datadog
|
|
102
107
|
|
103
108
|
def start_coverage(test)
|
104
109
|
return if !enabled? || !code_coverage?
|
105
|
-
|
110
|
+
Telemetry.code_coverage_started(test)
|
106
111
|
coverage_collector&.start
|
107
112
|
end
|
108
113
|
|
109
114
|
def stop_coverage(test)
|
110
115
|
return if !enabled? || !code_coverage?
|
111
116
|
|
117
|
+
Telemetry.code_coverage_finished(test)
|
118
|
+
|
112
119
|
coverage = coverage_collector&.stop
|
113
|
-
|
120
|
+
if coverage.nil? || coverage.empty?
|
121
|
+
Telemetry.code_coverage_is_empty
|
122
|
+
return
|
123
|
+
end
|
114
124
|
|
115
125
|
return if test.skipped?
|
116
126
|
|
@@ -119,6 +129,8 @@ module Datadog
|
|
119
129
|
# cucumber's gherkin files are not covered by the code coverage collector
|
120
130
|
ensure_test_source_covered(test_source_file, coverage) unless test_source_file.nil?
|
121
131
|
|
132
|
+
Telemetry.code_coverage_files(coverage.size)
|
133
|
+
|
122
134
|
event = Coverage::Event.new(
|
123
135
|
test_id: test.id.to_s,
|
124
136
|
test_suite_id: test.test_suite_id.to_s,
|
@@ -139,7 +151,7 @@ module Datadog
|
|
139
151
|
skippable_test_id = Utils::TestRun.skippable_test_id(test.name, test.test_suite_name, test.parameters)
|
140
152
|
if @skippable_tests.include?(skippable_test_id)
|
141
153
|
if forked?
|
142
|
-
Datadog.logger.warn { "
|
154
|
+
Datadog.logger.warn { "Intelligent test runner is not supported for forking test runners yet" }
|
143
155
|
return
|
144
156
|
end
|
145
157
|
|
@@ -155,11 +167,13 @@ module Datadog
|
|
155
167
|
return if !test.skipped? || !test.skipped_by_itr?
|
156
168
|
|
157
169
|
if forked?
|
158
|
-
Datadog.logger.warn { "
|
170
|
+
Datadog.logger.warn { "Intelligent test runner is not supported for forking test runners yet" }
|
159
171
|
return
|
160
172
|
end
|
161
173
|
|
162
174
|
@mutex.synchronize do
|
175
|
+
Telemetry.itr_skipped
|
176
|
+
|
163
177
|
@skipped_tests_count += 1
|
164
178
|
end
|
165
179
|
end
|
@@ -167,7 +181,7 @@ module Datadog
|
|
167
181
|
def write_test_session_tags(test_session)
|
168
182
|
return if !enabled?
|
169
183
|
|
170
|
-
Datadog.logger.debug { "Finished
|
184
|
+
Datadog.logger.debug { "Finished optimised session with test skipping enabled: #{@test_skipping_enabled}" }
|
171
185
|
Datadog.logger.debug { "#{@skipped_tests_count} tests were skipped" }
|
172
186
|
|
173
187
|
test_session.set_tag(Ext::Test::TAG_ITR_TESTS_SKIPPED, @skipped_tests_count.positive?.to_s)
|
@@ -189,7 +203,8 @@ module Datadog
|
|
189
203
|
Thread.current[:dd_coverage_collector] ||= Coverage::DDCov.new(
|
190
204
|
root: Git::LocalRepository.root,
|
191
205
|
ignored_path: @bundle_location,
|
192
|
-
threading_mode: code_coverage_mode
|
206
|
+
threading_mode: code_coverage_mode,
|
207
|
+
use_allocation_tracing: @use_allocation_tracing
|
193
208
|
)
|
194
209
|
end
|
195
210
|
|
@@ -226,6 +241,8 @@ module Datadog
|
|
226
241
|
Datadog.logger.debug { "Fetched skippable tests: \n #{@skippable_tests}" }
|
227
242
|
Datadog.logger.debug { "Found #{@skippable_tests.count} skippable tests." }
|
228
243
|
Datadog.logger.debug { "ITR correlation ID: #{@correlation_id}" }
|
244
|
+
|
245
|
+
Utils::Telemetry.inc(Ext::Telemetry::METRIC_ITR_SKIPPABLE_TESTS_RESPONSE_TESTS, @skippable_tests.count)
|
229
246
|
end
|
230
247
|
|
231
248
|
def code_coverage_mode
|
@@ -1,15 +1,21 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative "event"
|
4
|
+
require_relative "../../ext/telemetry"
|
4
5
|
require_relative "../../transport/event_platform_transport"
|
6
|
+
require_relative "../../transport/telemetry"
|
5
7
|
|
6
8
|
module Datadog
|
7
9
|
module CI
|
8
|
-
module
|
10
|
+
module TestOptimisation
|
9
11
|
module Coverage
|
10
12
|
class Transport < Datadog::CI::Transport::EventPlatformTransport
|
11
13
|
private
|
12
14
|
|
15
|
+
def telemetry_endpoint_tag
|
16
|
+
Ext::Telemetry::Endpoint::CODE_COVERAGE
|
17
|
+
end
|
18
|
+
|
13
19
|
def send_payload(encoded_payload)
|
14
20
|
api.citestcov_request(
|
15
21
|
path: Ext::Transport::TEST_COVERAGE_INTAKE_PATH,
|
@@ -19,7 +25,10 @@ module Datadog
|
|
19
25
|
|
20
26
|
def encode_events(events)
|
21
27
|
events.filter_map do |event|
|
22
|
-
|
28
|
+
unless event.valid?
|
29
|
+
CI::Transport::Telemetry.endpoint_payload_dropped(1, endpoint: telemetry_endpoint_tag)
|
30
|
+
next
|
31
|
+
end
|
23
32
|
|
24
33
|
encoded = encoder.encode(event)
|
25
34
|
next if event_too_large?(event, encoded)
|
@@ -2,13 +2,16 @@
|
|
2
2
|
|
3
3
|
require "json"
|
4
4
|
|
5
|
+
require_relative "../ext/telemetry"
|
5
6
|
require_relative "../ext/transport"
|
6
7
|
require_relative "../ext/test"
|
8
|
+
require_relative "../transport/telemetry"
|
7
9
|
require_relative "../utils/test_run"
|
10
|
+
require_relative "../utils/telemetry"
|
8
11
|
|
9
12
|
module Datadog
|
10
13
|
module CI
|
11
|
-
module
|
14
|
+
module TestOptimisation
|
12
15
|
class Skippable
|
13
16
|
class Response
|
14
17
|
def initialize(http_response)
|
@@ -75,6 +78,27 @@ module Datadog
|
|
75
78
|
payload: request_payload
|
76
79
|
)
|
77
80
|
|
81
|
+
Transport::Telemetry.api_requests(
|
82
|
+
Ext::Telemetry::METRIC_ITR_SKIPPABLE_TESTS_REQUEST,
|
83
|
+
1,
|
84
|
+
compressed: http_response.request_compressed
|
85
|
+
)
|
86
|
+
Utils::Telemetry.distribution(Ext::Telemetry::METRIC_ITR_SKIPPABLE_TESTS_REQUEST_MS, http_response.duration_ms)
|
87
|
+
Utils::Telemetry.distribution(
|
88
|
+
Ext::Telemetry::METRIC_ITR_SKIPPABLE_TESTS_RESPONSE_BYTES,
|
89
|
+
http_response.response_size.to_f,
|
90
|
+
{Ext::Telemetry::TAG_RESPONSE_COMPRESSED => http_response.gzipped_content?.to_s}
|
91
|
+
)
|
92
|
+
|
93
|
+
unless http_response.ok?
|
94
|
+
Transport::Telemetry.api_requests_errors(
|
95
|
+
Ext::Telemetry::METRIC_ITR_SKIPPABLE_TESTS_REQUEST_ERRORS,
|
96
|
+
1,
|
97
|
+
error_type: http_response.telemetry_error_type,
|
98
|
+
status_code: http_response.code
|
99
|
+
)
|
100
|
+
end
|
101
|
+
|
78
102
|
Response.new(http_response)
|
79
103
|
end
|
80
104
|
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../ext/telemetry"
|
4
|
+
require_relative "../ext/test"
|
5
|
+
require_relative "../utils/telemetry"
|
6
|
+
require_relative "../test_visibility/telemetry"
|
7
|
+
|
8
|
+
module Datadog
|
9
|
+
module CI
|
10
|
+
module TestOptimisation
|
11
|
+
# Telemetry for test optimisation component
|
12
|
+
module Telemetry
|
13
|
+
def self.code_coverage_started(test)
|
14
|
+
Utils::Telemetry.inc(Ext::Telemetry::METRIC_CODE_COVERAGE_STARTED, 1, tags_for_test(test))
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.code_coverage_finished(test)
|
18
|
+
Utils::Telemetry.inc(Ext::Telemetry::METRIC_CODE_COVERAGE_FINISHED, 1, tags_for_test(test))
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.code_coverage_is_empty
|
22
|
+
Utils::Telemetry.inc(Ext::Telemetry::METRIC_CODE_COVERAGE_IS_EMPTY, 1)
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.code_coverage_files(count)
|
26
|
+
Utils::Telemetry.distribution(Ext::Telemetry::METRIC_CODE_COVERAGE_FILES, count.to_f)
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.itr_skipped
|
30
|
+
Utils::Telemetry.inc(Ext::Telemetry::METRIC_ITR_SKIPPED, 1, tags_for_itr_metrics)
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.itr_forced_run
|
34
|
+
Utils::Telemetry.inc(Ext::Telemetry::METRIC_ITR_FORCED_RUN, 1, tags_for_itr_metrics)
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.itr_unskippable
|
38
|
+
Utils::Telemetry.inc(Ext::Telemetry::METRIC_ITR_UNSKIPPABLE, 1, tags_for_itr_metrics)
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.tags_for_test(test)
|
42
|
+
{
|
43
|
+
Ext::Telemetry::TAG_TEST_FRAMEWORK => test.get_tag(Ext::Test::TAG_FRAMEWORK),
|
44
|
+
Ext::Telemetry::TAG_LIBRARY => Ext::Telemetry::Library::CUSTOM
|
45
|
+
}
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.tags_for_itr_metrics
|
49
|
+
{
|
50
|
+
Ext::Telemetry::TAG_EVENT_TYPE => Ext::Telemetry::EventType::TEST
|
51
|
+
}
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,282 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rbconfig"
|
4
|
+
|
5
|
+
require_relative "context"
|
6
|
+
require_relative "telemetry"
|
7
|
+
|
8
|
+
require_relative "../codeowners/parser"
|
9
|
+
require_relative "../contrib/contrib"
|
10
|
+
require_relative "../ext/test"
|
11
|
+
require_relative "../git/local_repository"
|
12
|
+
|
13
|
+
require_relative "../worker"
|
14
|
+
|
15
|
+
module Datadog
|
16
|
+
module CI
|
17
|
+
module TestVisibility
|
18
|
+
# Common behavior for CI tests
|
19
|
+
class Component
|
20
|
+
attr_reader :test_suite_level_visibility_enabled
|
21
|
+
|
22
|
+
def initialize(
|
23
|
+
test_optimisation:,
|
24
|
+
remote_settings_api:,
|
25
|
+
git_tree_upload_worker: DummyWorker.new,
|
26
|
+
test_suite_level_visibility_enabled: false,
|
27
|
+
codeowners: Codeowners::Parser.new(Git::LocalRepository.root).parse
|
28
|
+
)
|
29
|
+
@test_suite_level_visibility_enabled = test_suite_level_visibility_enabled
|
30
|
+
@context = Context.new
|
31
|
+
@codeowners = codeowners
|
32
|
+
@test_optimisation = test_optimisation
|
33
|
+
@remote_settings_api = remote_settings_api
|
34
|
+
@git_tree_upload_worker = git_tree_upload_worker
|
35
|
+
end
|
36
|
+
|
37
|
+
def shutdown!
|
38
|
+
@git_tree_upload_worker.stop
|
39
|
+
end
|
40
|
+
|
41
|
+
def start_test_session(service: nil, tags: {})
|
42
|
+
return skip_tracing unless test_suite_level_visibility_enabled
|
43
|
+
|
44
|
+
test_session = @context.start_test_session(service: service, tags: tags)
|
45
|
+
on_test_session_started(test_session)
|
46
|
+
test_session
|
47
|
+
end
|
48
|
+
|
49
|
+
def start_test_module(test_module_name, service: nil, tags: {})
|
50
|
+
return skip_tracing unless test_suite_level_visibility_enabled
|
51
|
+
|
52
|
+
test_module = @context.start_test_module(test_module_name, service: service, tags: tags)
|
53
|
+
on_test_module_started(test_module)
|
54
|
+
test_module
|
55
|
+
end
|
56
|
+
|
57
|
+
def start_test_suite(test_suite_name, service: nil, tags: {})
|
58
|
+
return skip_tracing unless test_suite_level_visibility_enabled
|
59
|
+
|
60
|
+
test_suite = @context.start_test_suite(test_suite_name, service: service, tags: tags)
|
61
|
+
on_test_suite_started(test_suite)
|
62
|
+
test_suite
|
63
|
+
end
|
64
|
+
|
65
|
+
def trace_test(test_name, test_suite_name, service: nil, tags: {}, &block)
|
66
|
+
if block
|
67
|
+
@context.trace_test(test_name, test_suite_name, service: service, tags: tags) do |test|
|
68
|
+
on_test_started(test)
|
69
|
+
res = block.call(test)
|
70
|
+
on_test_finished(test)
|
71
|
+
res
|
72
|
+
end
|
73
|
+
else
|
74
|
+
test = @context.trace_test(test_name, test_suite_name, service: service, tags: tags)
|
75
|
+
on_test_started(test)
|
76
|
+
test
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def trace(span_name, type: "span", tags: {}, &block)
|
81
|
+
if block
|
82
|
+
@context.trace(span_name, type: type, tags: tags) do |span|
|
83
|
+
block.call(span)
|
84
|
+
end
|
85
|
+
else
|
86
|
+
@context.trace(span_name, type: type, tags: tags)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def active_span
|
91
|
+
@context.active_span
|
92
|
+
end
|
93
|
+
|
94
|
+
def active_test
|
95
|
+
@context.active_test
|
96
|
+
end
|
97
|
+
|
98
|
+
def active_test_session
|
99
|
+
@context.active_test_session
|
100
|
+
end
|
101
|
+
|
102
|
+
def active_test_module
|
103
|
+
@context.active_test_module
|
104
|
+
end
|
105
|
+
|
106
|
+
def active_test_suite(test_suite_name)
|
107
|
+
@context.active_test_suite(test_suite_name)
|
108
|
+
end
|
109
|
+
|
110
|
+
def deactivate_test
|
111
|
+
test = active_test
|
112
|
+
on_test_finished(test) if test
|
113
|
+
|
114
|
+
@context.deactivate_test
|
115
|
+
end
|
116
|
+
|
117
|
+
def deactivate_test_session
|
118
|
+
test_session = active_test_session
|
119
|
+
on_test_session_finished(test_session) if test_session
|
120
|
+
|
121
|
+
@context.deactivate_test_session
|
122
|
+
end
|
123
|
+
|
124
|
+
def deactivate_test_module
|
125
|
+
test_module = active_test_module
|
126
|
+
on_test_module_finished(test_module) if test_module
|
127
|
+
|
128
|
+
@context.deactivate_test_module
|
129
|
+
end
|
130
|
+
|
131
|
+
def deactivate_test_suite(test_suite_name)
|
132
|
+
test_suite = active_test_suite(test_suite_name)
|
133
|
+
on_test_suite_finished(test_suite) if test_suite
|
134
|
+
|
135
|
+
@context.deactivate_test_suite(test_suite_name)
|
136
|
+
end
|
137
|
+
|
138
|
+
def itr_enabled?
|
139
|
+
@test_optimisation.enabled?
|
140
|
+
end
|
141
|
+
|
142
|
+
private
|
143
|
+
|
144
|
+
# DOMAIN EVENTS
|
145
|
+
def on_test_session_started(test_session)
|
146
|
+
Telemetry.event_created(test_session)
|
147
|
+
Telemetry.test_session_started(test_session)
|
148
|
+
|
149
|
+
# finds and instruments additional test libraries that we support (ex: selenium-webdriver)
|
150
|
+
Contrib.auto_instrument_on_session_start!
|
151
|
+
|
152
|
+
@git_tree_upload_worker.perform(test_session.git_repository_url)
|
153
|
+
configure_library(test_session)
|
154
|
+
end
|
155
|
+
|
156
|
+
def on_test_module_started(test_module)
|
157
|
+
Telemetry.event_created(test_module)
|
158
|
+
end
|
159
|
+
|
160
|
+
def on_test_suite_started(test_suite)
|
161
|
+
Telemetry.event_created(test_suite)
|
162
|
+
end
|
163
|
+
|
164
|
+
def on_test_started(test)
|
165
|
+
# sometimes test suite is not being assigned correctly
|
166
|
+
# fix it by fetching the one single running test suite from the global context
|
167
|
+
fix_test_suite!(test) if test.test_suite_id.nil?
|
168
|
+
|
169
|
+
validate_test_suite_level_visibility_correctness(test)
|
170
|
+
set_codeowners(test)
|
171
|
+
|
172
|
+
Telemetry.event_created(test)
|
173
|
+
|
174
|
+
@test_optimisation.mark_if_skippable(test)
|
175
|
+
@test_optimisation.start_coverage(test)
|
176
|
+
end
|
177
|
+
|
178
|
+
def on_test_session_finished(test_session)
|
179
|
+
@test_optimisation.write_test_session_tags(test_session)
|
180
|
+
|
181
|
+
Telemetry.event_finished(test_session)
|
182
|
+
end
|
183
|
+
|
184
|
+
def on_test_module_finished(test_module)
|
185
|
+
Telemetry.event_finished(test_module)
|
186
|
+
end
|
187
|
+
|
188
|
+
def on_test_suite_finished(test_suite)
|
189
|
+
Telemetry.event_finished(test_suite)
|
190
|
+
end
|
191
|
+
|
192
|
+
def on_test_finished(test)
|
193
|
+
@test_optimisation.stop_coverage(test)
|
194
|
+
@test_optimisation.count_skipped_test(test)
|
195
|
+
|
196
|
+
Telemetry.event_finished(test)
|
197
|
+
end
|
198
|
+
|
199
|
+
# TODO: move this to CI::Configuration::Remote
|
200
|
+
def configure_library(test_session)
|
201
|
+
# this will change when EFD is implemented
|
202
|
+
return unless itr_enabled?
|
203
|
+
|
204
|
+
remote_configuration = @remote_settings_api.fetch_library_settings(test_session)
|
205
|
+
# sometimes we can skip code coverage for default branch if there are no changes in the repository
|
206
|
+
# backend needs git metadata uploaded for this test session to check if we can skip code coverage
|
207
|
+
if remote_configuration.require_git?
|
208
|
+
Datadog.logger.debug { "Library configuration endpoint requires git upload to be finished, waiting..." }
|
209
|
+
@git_tree_upload_worker.wait_until_done
|
210
|
+
|
211
|
+
Datadog.logger.debug { "Requesting library configuration again..." }
|
212
|
+
remote_configuration = @remote_settings_api.fetch_library_settings(test_session)
|
213
|
+
|
214
|
+
if remote_configuration.require_git?
|
215
|
+
Datadog.logger.debug { "git metadata upload did not complete in time when configuring library" }
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
@test_optimisation.configure(
|
220
|
+
remote_configuration.payload,
|
221
|
+
test_session: test_session,
|
222
|
+
git_tree_upload_worker: @git_tree_upload_worker
|
223
|
+
)
|
224
|
+
end
|
225
|
+
|
226
|
+
# HELPERS
|
227
|
+
def skip_tracing(block = nil)
|
228
|
+
block&.call(nil)
|
229
|
+
end
|
230
|
+
|
231
|
+
def set_codeowners(test)
|
232
|
+
source = test.source_file
|
233
|
+
owners = @codeowners.list_owners(source) if source
|
234
|
+
test.set_tag(Ext::Test::TAG_CODEOWNERS, owners) unless owners.nil?
|
235
|
+
end
|
236
|
+
|
237
|
+
def fix_test_suite!(test)
|
238
|
+
test_suite = @context.single_active_test_suite
|
239
|
+
unless test_suite
|
240
|
+
Datadog.logger.debug do
|
241
|
+
"Trying to fix test suite for test [#{test.name}] but no single test suite is running."
|
242
|
+
end
|
243
|
+
return
|
244
|
+
end
|
245
|
+
|
246
|
+
Datadog.logger.debug do
|
247
|
+
"For test [#{test.name}]: expected test suite [#{test.test_suite_name}] to be running, " \
|
248
|
+
"but it was not found. Fixing it by assigning test suite [#{test_suite.name}] to the test."
|
249
|
+
end
|
250
|
+
|
251
|
+
test.set_tag(Ext::Test::TAG_TEST_SUITE_ID, test_suite.id.to_s)
|
252
|
+
test.set_tag(Ext::Test::TAG_SUITE, test_suite.name)
|
253
|
+
end
|
254
|
+
|
255
|
+
def validate_test_suite_level_visibility_correctness(test)
|
256
|
+
return unless test_suite_level_visibility_enabled
|
257
|
+
|
258
|
+
if test.test_suite_id.nil?
|
259
|
+
Datadog.logger.debug do
|
260
|
+
"Test [#{test.name}] does not have a test suite associated with it. " \
|
261
|
+
"Expected test suite [#{test.test_suite_name}] to be running."
|
262
|
+
end
|
263
|
+
end
|
264
|
+
|
265
|
+
if test.test_module_id.nil?
|
266
|
+
Datadog.logger.debug do
|
267
|
+
"Test [#{test.name}] does not have a test module associated with it. " \
|
268
|
+
"Make sure that there is a test module running within a session."
|
269
|
+
end
|
270
|
+
end
|
271
|
+
|
272
|
+
if test.test_session_id.nil?
|
273
|
+
Datadog.logger.debug do
|
274
|
+
"Test [#{test.name}] does not have a test session associated with it. " \
|
275
|
+
"Make sure that there is a test session running."
|
276
|
+
end
|
277
|
+
end
|
278
|
+
end
|
279
|
+
end
|
280
|
+
end
|
281
|
+
end
|
282
|
+
end
|