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.
Files changed (67) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +31 -2
  3. data/ext/datadog_cov/datadog_cov.c +259 -67
  4. data/lib/datadog/ci/configuration/components.rb +149 -80
  5. data/lib/datadog/ci/configuration/settings.rb +6 -0
  6. data/lib/datadog/ci/contrib/cucumber/formatter.rb +13 -9
  7. data/lib/datadog/ci/contrib/minitest/runnable.rb +5 -1
  8. data/lib/datadog/ci/contrib/minitest/runner.rb +6 -2
  9. data/lib/datadog/ci/contrib/minitest/test.rb +7 -3
  10. data/lib/datadog/ci/contrib/rspec/example.rb +6 -2
  11. data/lib/datadog/ci/contrib/rspec/example_group.rb +5 -1
  12. data/lib/datadog/ci/contrib/rspec/knapsack_pro/runner.rb +6 -2
  13. data/lib/datadog/ci/contrib/rspec/runner.rb +6 -2
  14. data/lib/datadog/ci/ext/environment/providers/appveyor.rb +1 -1
  15. data/lib/datadog/ci/ext/environment/providers/aws_code_pipeline.rb +1 -1
  16. data/lib/datadog/ci/ext/environment/providers/azure.rb +1 -1
  17. data/lib/datadog/ci/ext/environment/providers/bitbucket.rb +1 -1
  18. data/lib/datadog/ci/ext/environment/providers/bitrise.rb +1 -1
  19. data/lib/datadog/ci/ext/environment/providers/buddy.rb +1 -1
  20. data/lib/datadog/ci/ext/environment/providers/buildkite.rb +1 -1
  21. data/lib/datadog/ci/ext/environment/providers/circleci.rb +1 -1
  22. data/lib/datadog/ci/ext/environment/providers/codefresh.rb +1 -1
  23. data/lib/datadog/ci/ext/environment/providers/github_actions.rb +1 -1
  24. data/lib/datadog/ci/ext/environment/providers/gitlab.rb +1 -1
  25. data/lib/datadog/ci/ext/environment/providers/jenkins.rb +1 -1
  26. data/lib/datadog/ci/ext/environment/providers/teamcity.rb +1 -1
  27. data/lib/datadog/ci/ext/environment/providers/travis.rb +1 -1
  28. data/lib/datadog/ci/ext/environment.rb +17 -0
  29. data/lib/datadog/ci/ext/settings.rb +1 -0
  30. data/lib/datadog/ci/ext/telemetry.rb +120 -0
  31. data/lib/datadog/ci/git/local_repository.rb +116 -25
  32. data/lib/datadog/ci/git/search_commits.rb +20 -1
  33. data/lib/datadog/ci/git/telemetry.rb +37 -0
  34. data/lib/datadog/ci/git/tree_uploader.rb +7 -0
  35. data/lib/datadog/ci/git/upload_packfile.rb +22 -1
  36. data/lib/datadog/ci/span.rb +3 -3
  37. data/lib/datadog/ci/test.rb +6 -1
  38. data/lib/datadog/ci/test_module.rb +1 -1
  39. data/lib/datadog/ci/{itr/runner.rb → test_optimisation/component.rb} +29 -12
  40. data/lib/datadog/ci/{itr → test_optimisation}/coverage/ddcov.rb +1 -1
  41. data/lib/datadog/ci/{itr → test_optimisation}/coverage/event.rb +1 -1
  42. data/lib/datadog/ci/{itr → test_optimisation}/coverage/transport.rb +11 -2
  43. data/lib/datadog/ci/{itr → test_optimisation}/coverage/writer.rb +1 -1
  44. data/lib/datadog/ci/{itr → test_optimisation}/skippable.rb +25 -1
  45. data/lib/datadog/ci/test_optimisation/telemetry.rb +56 -0
  46. data/lib/datadog/ci/test_session.rb +1 -1
  47. data/lib/datadog/ci/test_suite.rb +1 -1
  48. data/lib/datadog/ci/test_visibility/component.rb +282 -0
  49. data/lib/datadog/ci/test_visibility/{recorder.rb → context.rb} +39 -187
  50. data/lib/datadog/ci/test_visibility/{null_recorder.rb → null_component.rb} +6 -4
  51. data/lib/datadog/ci/test_visibility/{context → store}/global.rb +1 -1
  52. data/lib/datadog/ci/test_visibility/{context → store}/local.rb +1 -1
  53. data/lib/datadog/ci/test_visibility/telemetry.rb +69 -0
  54. data/lib/datadog/ci/test_visibility/transport.rb +9 -10
  55. data/lib/datadog/ci/transport/adapters/net.rb +42 -11
  56. data/lib/datadog/ci/transport/adapters/net_http_client.rb +17 -0
  57. data/lib/datadog/ci/transport/adapters/telemetry_webmock_safe_adapter.rb +28 -0
  58. data/lib/datadog/ci/transport/event_platform_transport.rb +42 -5
  59. data/lib/datadog/ci/transport/http.rb +49 -21
  60. data/lib/datadog/ci/transport/remote_settings_api.rb +39 -1
  61. data/lib/datadog/ci/transport/telemetry.rb +93 -0
  62. data/lib/datadog/ci/utils/identity.rb +20 -0
  63. data/lib/datadog/ci/utils/parsing.rb +2 -1
  64. data/lib/datadog/ci/utils/telemetry.rb +23 -0
  65. data/lib/datadog/ci/version.rb +1 -1
  66. data/lib/datadog/ci.rb +45 -15
  67. 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 ITR
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 Runner
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("ITR Runner initialized with enabled: #{@enabled}")
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 ITR Runner with remote configuration: #{remote_configuration}")
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 ITR Runner with enabled: #{@enabled}, skipping_tests: #{@test_skipping_enabled}, code_coverage: #{@code_coverage_enabled}")
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
- return if coverage.nil? || coverage.empty?
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 { "ITR is not supported for forking test runners yet" }
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 { "ITR is not supported for forking test runners yet" }
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 ITR session with test skipping enabled: #{@test_skipping_enabled}" }
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
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Datadog
4
4
  module CI
5
- module ITR
5
+ module TestOptimisation
6
6
  module Coverage
7
7
  # Placeholder for code coverage collection
8
8
  # Implementation in ext/datadog_cov
@@ -6,7 +6,7 @@ require_relative "../../git/local_repository"
6
6
 
7
7
  module Datadog
8
8
  module CI
9
- module ITR
9
+ module TestOptimisation
10
10
  module Coverage
11
11
  class Event
12
12
  attr_reader :test_id, :test_suite_id, :test_session_id, :coverage
@@ -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 ITR
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
- next unless event.valid?
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)
@@ -11,7 +11,7 @@ require "datadog/core/environment/ext"
11
11
 
12
12
  module Datadog
13
13
  module CI
14
- module ITR
14
+ module TestOptimisation
15
15
  module Coverage
16
16
  class Writer
17
17
  include Core::Workers::Queue
@@ -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 ITR
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
@@ -15,7 +15,7 @@ module Datadog
15
15
  # Finishes the current test session.
16
16
  # @return [void]
17
17
  def finish
18
- recorder.deactivate_test_session
18
+ test_visibility.deactivate_test_session
19
19
 
20
20
  super
21
21
  end
@@ -26,7 +26,7 @@ module Datadog
26
26
  # we try to derive test suite status from execution stats if no status was set explicitly
27
27
  set_status_from_stats! if undefined?
28
28
 
29
- recorder.deactivate_test_suite(name)
29
+ test_visibility.deactivate_test_suite(name)
30
30
 
31
31
  super
32
32
  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