datadog-ci 0.6.0 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (143) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +63 -2
  3. data/README.md +21 -2
  4. data/lib/datadog/ci/codeowners/matcher.rb +102 -0
  5. data/lib/datadog/ci/codeowners/parser.rb +42 -0
  6. data/lib/datadog/ci/codeowners/rule.rb +33 -0
  7. data/lib/datadog/ci/concurrent_span.rb +2 -1
  8. data/lib/datadog/ci/configuration/components.rb +59 -57
  9. data/lib/datadog/ci/configuration/settings.rb +21 -0
  10. data/lib/datadog/ci/contrib/cucumber/configuration/settings.rb +4 -1
  11. data/lib/datadog/ci/contrib/cucumber/formatter.rb +69 -38
  12. data/lib/datadog/ci/contrib/cucumber/instrumentation.rb +2 -1
  13. data/lib/datadog/ci/contrib/minitest/configuration/settings.rb +4 -1
  14. data/lib/datadog/ci/contrib/minitest/helpers.rb +2 -1
  15. data/lib/datadog/ci/contrib/minitest/hooks.rb +9 -22
  16. data/lib/datadog/ci/contrib/minitest/patcher.rb +9 -6
  17. data/lib/datadog/ci/contrib/minitest/reporter.rb +50 -0
  18. data/lib/datadog/ci/contrib/minitest/runnable.rb +1 -1
  19. data/lib/datadog/ci/contrib/minitest/runner.rb +41 -0
  20. data/lib/datadog/ci/contrib/rspec/configuration/settings.rb +4 -1
  21. data/lib/datadog/ci/contrib/rspec/example.rb +55 -14
  22. data/lib/datadog/ci/contrib/rspec/example_group.rb +12 -7
  23. data/lib/datadog/ci/contrib/rspec/patcher.rb +10 -1
  24. data/lib/datadog/ci/contrib/rspec/runner.rb +7 -8
  25. data/lib/datadog/ci/ext/app_types.rb +2 -0
  26. data/lib/datadog/ci/ext/environment/providers/local_git.rb +8 -29
  27. data/lib/datadog/ci/ext/settings.rb +2 -0
  28. data/lib/datadog/ci/ext/test.rb +29 -7
  29. data/lib/datadog/ci/ext/transport.rb +19 -1
  30. data/lib/datadog/ci/itr/runner.rb +67 -0
  31. data/lib/datadog/ci/span.rb +51 -2
  32. data/lib/datadog/ci/test.rb +67 -2
  33. data/lib/datadog/ci/test_module.rb +1 -1
  34. data/lib/datadog/ci/test_session.rb +10 -2
  35. data/lib/datadog/ci/test_suite.rb +53 -2
  36. data/lib/datadog/ci/test_visibility/context/local.rb +3 -9
  37. data/lib/datadog/ci/test_visibility/null_recorder.rb +2 -22
  38. data/lib/datadog/ci/test_visibility/recorder.rb +46 -20
  39. data/lib/datadog/ci/test_visibility/serializers/base.rb +6 -5
  40. data/lib/datadog/ci/test_visibility/serializers/span.rb +1 -1
  41. data/lib/datadog/ci/test_visibility/serializers/test_module.rb +1 -1
  42. data/lib/datadog/ci/test_visibility/serializers/test_session.rb +1 -1
  43. data/lib/datadog/ci/test_visibility/serializers/test_suite.rb +1 -1
  44. data/lib/datadog/ci/test_visibility/serializers/test_v1.rb +1 -1
  45. data/lib/datadog/ci/test_visibility/transport.rb +1 -5
  46. data/lib/datadog/ci/transport/api/agentless.rb +63 -0
  47. data/lib/datadog/ci/transport/api/base.rb +10 -14
  48. data/lib/datadog/ci/transport/api/builder.rb +25 -22
  49. data/lib/datadog/ci/transport/api/evp_proxy.rb +47 -7
  50. data/lib/datadog/ci/transport/http.rb +7 -1
  51. data/lib/datadog/ci/transport/remote_settings_api.rb +96 -0
  52. data/lib/datadog/ci/utils/configuration.rb +15 -0
  53. data/lib/datadog/ci/utils/git.rb +70 -0
  54. data/lib/datadog/ci/version.rb +1 -1
  55. data/lib/datadog/ci.rb +40 -56
  56. metadata +12 -90
  57. data/lib/datadog/ci/contrib/minitest/plugin.rb +0 -73
  58. data/lib/datadog/ci/null_span.rb +0 -63
  59. data/lib/datadog/ci/transport/api/ci_test_cycle.rb +0 -30
  60. data/sig/datadog/ci/concurrent_span.rbs +0 -23
  61. data/sig/datadog/ci/configuration/components.rbs +0 -21
  62. data/sig/datadog/ci/configuration/extensions.rbs +0 -9
  63. data/sig/datadog/ci/configuration/settings.rbs +0 -16
  64. data/sig/datadog/ci/contrib/cucumber/configuration/settings.rbs +0 -12
  65. data/sig/datadog/ci/contrib/cucumber/ext.rbs +0 -21
  66. data/sig/datadog/ci/contrib/cucumber/formatter.rbs +0 -48
  67. data/sig/datadog/ci/contrib/cucumber/instrumentation.rbs +0 -16
  68. data/sig/datadog/ci/contrib/cucumber/integration.rbs +0 -26
  69. data/sig/datadog/ci/contrib/cucumber/patcher.rbs +0 -15
  70. data/sig/datadog/ci/contrib/integration.rbs +0 -44
  71. data/sig/datadog/ci/contrib/minitest/configuration/settings.rbs +0 -12
  72. data/sig/datadog/ci/contrib/minitest/ext.rbs +0 -19
  73. data/sig/datadog/ci/contrib/minitest/helpers.rbs +0 -13
  74. data/sig/datadog/ci/contrib/minitest/hooks.rbs +0 -27
  75. data/sig/datadog/ci/contrib/minitest/integration.rbs +0 -26
  76. data/sig/datadog/ci/contrib/minitest/patcher.rbs +0 -15
  77. data/sig/datadog/ci/contrib/minitest/plugin.rbs +0 -31
  78. data/sig/datadog/ci/contrib/minitest/runnable.rbs +0 -24
  79. data/sig/datadog/ci/contrib/rspec/configuration/settings.rbs +0 -12
  80. data/sig/datadog/ci/contrib/rspec/example.rbs +0 -20
  81. data/sig/datadog/ci/contrib/rspec/example_group.rbs +0 -21
  82. data/sig/datadog/ci/contrib/rspec/ext.rbs +0 -17
  83. data/sig/datadog/ci/contrib/rspec/integration.rbs +0 -26
  84. data/sig/datadog/ci/contrib/rspec/patcher.rbs +0 -15
  85. data/sig/datadog/ci/contrib/rspec/runner.rbs +0 -21
  86. data/sig/datadog/ci/contrib/settings.rbs +0 -25
  87. data/sig/datadog/ci/ext/app_types.rbs +0 -14
  88. data/sig/datadog/ci/ext/environment/extractor.rbs +0 -25
  89. data/sig/datadog/ci/ext/environment/providers/appveyor.rbs +0 -48
  90. data/sig/datadog/ci/ext/environment/providers/aws_code_pipeline.rbs +0 -19
  91. data/sig/datadog/ci/ext/environment/providers/azure.rbs +0 -56
  92. data/sig/datadog/ci/ext/environment/providers/base.rbs +0 -71
  93. data/sig/datadog/ci/ext/environment/providers/bitbucket.rbs +0 -37
  94. data/sig/datadog/ci/ext/environment/providers/bitrise.rbs +0 -41
  95. data/sig/datadog/ci/ext/environment/providers/buddy.rbs +0 -37
  96. data/sig/datadog/ci/ext/environment/providers/buildkite.rbs +0 -45
  97. data/sig/datadog/ci/ext/environment/providers/circleci.rbs +0 -41
  98. data/sig/datadog/ci/ext/environment/providers/codefresh.rbs +0 -25
  99. data/sig/datadog/ci/ext/environment/providers/github_actions.rbs +0 -42
  100. data/sig/datadog/ci/ext/environment/providers/gitlab.rbs +0 -57
  101. data/sig/datadog/ci/ext/environment/providers/jenkins.rbs +0 -35
  102. data/sig/datadog/ci/ext/environment/providers/local_git.rbs +0 -66
  103. data/sig/datadog/ci/ext/environment/providers/teamcity.rbs +0 -17
  104. data/sig/datadog/ci/ext/environment/providers/travis.rbs +0 -35
  105. data/sig/datadog/ci/ext/environment/providers/user_defined_tags.rbs +0 -33
  106. data/sig/datadog/ci/ext/environment/providers.rbs +0 -13
  107. data/sig/datadog/ci/ext/environment.rbs +0 -44
  108. data/sig/datadog/ci/ext/git.rbs +0 -53
  109. data/sig/datadog/ci/ext/settings.rbs +0 -14
  110. data/sig/datadog/ci/ext/test.rbs +0 -60
  111. data/sig/datadog/ci/ext/transport.rbs +0 -29
  112. data/sig/datadog/ci/null_span.rbs +0 -37
  113. data/sig/datadog/ci/span.rbs +0 -47
  114. data/sig/datadog/ci/test.rbs +0 -12
  115. data/sig/datadog/ci/test_module.rbs +0 -6
  116. data/sig/datadog/ci/test_session.rbs +0 -9
  117. data/sig/datadog/ci/test_suite.rbs +0 -6
  118. data/sig/datadog/ci/test_visibility/context/global.rbs +0 -39
  119. data/sig/datadog/ci/test_visibility/context/local.rbs +0 -23
  120. data/sig/datadog/ci/test_visibility/flush.rbs +0 -17
  121. data/sig/datadog/ci/test_visibility/null_recorder.rbs +0 -45
  122. data/sig/datadog/ci/test_visibility/recorder.rbs +0 -85
  123. data/sig/datadog/ci/test_visibility/serializers/base.rbs +0 -94
  124. data/sig/datadog/ci/test_visibility/serializers/factories/test_level.rbs +0 -13
  125. data/sig/datadog/ci/test_visibility/serializers/factories/test_suite_level.rbs +0 -13
  126. data/sig/datadog/ci/test_visibility/serializers/span.rbs +0 -18
  127. data/sig/datadog/ci/test_visibility/serializers/test_module.rbs +0 -26
  128. data/sig/datadog/ci/test_visibility/serializers/test_session.rbs +0 -26
  129. data/sig/datadog/ci/test_visibility/serializers/test_suite.rbs +0 -26
  130. data/sig/datadog/ci/test_visibility/serializers/test_v1.rbs +0 -23
  131. data/sig/datadog/ci/test_visibility/serializers/test_v2.rbs +0 -25
  132. data/sig/datadog/ci/test_visibility/transport.rbs +0 -35
  133. data/sig/datadog/ci/transport/api/base.rbs +0 -21
  134. data/sig/datadog/ci/transport/api/builder.rbs +0 -12
  135. data/sig/datadog/ci/transport/api/ci_test_cycle.rbs +0 -21
  136. data/sig/datadog/ci/transport/api/evp_proxy.rbs +0 -19
  137. data/sig/datadog/ci/transport/gzip.rbs +0 -9
  138. data/sig/datadog/ci/transport/http.rbs +0 -36
  139. data/sig/datadog/ci/utils/git.rbs +0 -11
  140. data/sig/datadog/ci/utils/test_run.rbs +0 -11
  141. data/sig/datadog/ci/utils/url.rbs +0 -9
  142. data/sig/datadog/ci/version.rbs +0 -16
  143. data/sig/datadog/ci.rbs +0 -37
@@ -8,12 +8,13 @@ require "rbconfig"
8
8
  require_relative "context/global"
9
9
  require_relative "context/local"
10
10
 
11
+ require_relative "../codeowners/parser"
11
12
  require_relative "../ext/app_types"
12
13
  require_relative "../ext/test"
13
14
  require_relative "../ext/environment"
15
+ require_relative "../utils/git"
14
16
 
15
17
  require_relative "../span"
16
- require_relative "../null_span"
17
18
  require_relative "../test"
18
19
  require_relative "../test_session"
19
20
  require_relative "../test_module"
@@ -27,12 +28,20 @@ module Datadog
27
28
  class Recorder
28
29
  attr_reader :environment_tags, :test_suite_level_visibility_enabled
29
30
 
30
- def initialize(test_suite_level_visibility_enabled: false)
31
+ def initialize(
32
+ itr:, remote_settings_api:, test_suite_level_visibility_enabled: false,
33
+ codeowners: Codeowners::Parser.new(Utils::Git.root).parse
34
+ )
31
35
  @test_suite_level_visibility_enabled = test_suite_level_visibility_enabled
32
36
 
33
37
  @environment_tags = Ext::Environment.tags(ENV).freeze
34
38
  @local_context = Context::Local.new
35
39
  @global_context = Context::Global.new
40
+
41
+ @codeowners = codeowners
42
+
43
+ @itr = itr
44
+ @remote_settings_api = remote_settings_api
36
45
  end
37
46
 
38
47
  def start_test_session(service: nil, tags: {})
@@ -44,7 +53,11 @@ module Datadog
44
53
  )
45
54
  set_session_context(tags, tracer_span)
46
55
 
47
- build_test_session(tracer_span, tags)
56
+ test_session = build_test_session(tracer_span, tags)
57
+
58
+ configure_library(test_session)
59
+
60
+ test_session
48
61
  end
49
62
  end
50
63
 
@@ -88,6 +101,7 @@ module Datadog
88
101
  set_suite_context(tags, name: test_suite_name)
89
102
 
90
103
  tags[Ext::Test::TAG_NAME] = test_name
104
+ tags[Ext::Test::TAG_TYPE] ||= Ext::Test::Type::TEST
91
105
 
92
106
  span_options = build_span_options(
93
107
  service,
@@ -101,7 +115,7 @@ module Datadog
101
115
  start_datadog_tracer_span(test_name, span_options) do |tracer_span|
102
116
  test = build_test(tracer_span, tags)
103
117
 
104
- @local_context.activate_test!(test) do
118
+ @local_context.activate_test(test) do
105
119
  block.call(test)
106
120
  end
107
121
  end
@@ -109,15 +123,15 @@ module Datadog
109
123
  tracer_span = start_datadog_tracer_span(test_name, span_options)
110
124
 
111
125
  test = build_test(tracer_span, tags)
112
- @local_context.activate_test!(test)
126
+ @local_context.activate_test(test)
113
127
  test
114
128
  end
115
129
  end
116
130
 
117
- def trace(span_type, span_name, tags: {}, &block)
131
+ def trace(span_name, type: "span", tags: {}, &block)
118
132
  span_options = build_span_options(
119
133
  nil, # service name is completely optional for custom spans
120
- span_type,
134
+ type,
121
135
  {resource: span_name}
122
136
  )
123
137
 
@@ -153,8 +167,8 @@ module Datadog
153
167
  @global_context.active_test_suite(test_suite_name)
154
168
  end
155
169
 
156
- def deactivate_test(test)
157
- @local_context.deactivate_test!(test)
170
+ def deactivate_test
171
+ @local_context.deactivate_test
158
172
  end
159
173
 
160
174
  def deactivate_test_session
@@ -169,14 +183,22 @@ module Datadog
169
183
  @global_context.deactivate_test_suite!(test_suite_name)
170
184
  end
171
185
 
186
+ def itr_enabled?
187
+ @itr.enabled?
188
+ end
189
+
172
190
  private
173
191
 
192
+ def configure_library(test_session)
193
+ # this will change when EFD is implemented
194
+ return unless itr_enabled?
195
+
196
+ remote_configuration = @remote_settings_api.fetch_library_settings(test_session)
197
+ @itr.configure(remote_configuration.payload, test_session)
198
+ end
199
+
174
200
  def skip_tracing(block = nil)
175
- if block
176
- block.call(null_span)
177
- else
178
- null_span
179
- end
201
+ block.call(nil) if block
180
202
  end
181
203
 
182
204
  # Sets trace's origin to ciapp-test
@@ -206,6 +228,8 @@ module Datadog
206
228
  test = Test.new(tracer_span)
207
229
  set_initial_tags(test, tags)
208
230
  validate_test_suite_level_visibility_correctness(test)
231
+ set_codeowners(test)
232
+
209
233
  test
210
234
  end
211
235
 
@@ -215,9 +239,9 @@ module Datadog
215
239
  span
216
240
  end
217
241
 
218
- def build_span_options(service, span_type, other_options = {})
242
+ def build_span_options(service, type, other_options = {})
219
243
  other_options[:service] = service || @global_context.service
220
- other_options[:span_type] = span_type
244
+ other_options[:type] = type
221
245
 
222
246
  other_options
223
247
  end
@@ -251,6 +275,12 @@ module Datadog
251
275
  end
252
276
  end
253
277
 
278
+ def set_codeowners(test)
279
+ source = test.source_file
280
+ owners = @codeowners.list_owners(source) if source
281
+ test.set_tag(Ext::Test::TAG_CODEOWNERS, owners) unless owners.nil?
282
+ end
283
+
254
284
  def set_suite_context(tags, span: nil, name: nil)
255
285
  return if span.nil? && name.nil?
256
286
 
@@ -280,10 +310,6 @@ module Datadog
280
310
  end
281
311
  end
282
312
 
283
- def null_span
284
- @null_span ||= NullSpan.new
285
- end
286
-
287
313
  def validate_test_suite_level_visibility_correctness(test)
288
314
  return unless test_suite_level_visibility_enabled
289
315
 
@@ -34,7 +34,7 @@ module Datadog
34
34
  @trace = trace
35
35
  @span = span
36
36
 
37
- @meta = @span.meta.reject { |key, _| Ext::Test::SPECIAL_TAGS.include?(key) }
37
+ @meta = @span.meta.reject { |key, _| Ext::Test::TRANSIENT_TAGS.include?(key) }
38
38
 
39
39
  @errors = {}
40
40
  @validated = false
@@ -45,7 +45,7 @@ module Datadog
45
45
 
46
46
  packer.write_map_header(3)
47
47
 
48
- write_field(packer, "type")
48
+ write_field(packer, "type", "event_type")
49
49
  write_field(packer, "version")
50
50
 
51
51
  packer.write("content")
@@ -119,9 +119,6 @@ module Datadog
119
119
  to_integer(@span.get_tag(Ext::Test::TAG_TEST_SUITE_ID))
120
120
  end
121
121
 
122
- def type
123
- end
124
-
125
122
  def version
126
123
  1
127
124
  end
@@ -130,6 +127,10 @@ module Datadog
130
127
  @span.type
131
128
  end
132
129
 
130
+ def event_type
131
+ "span"
132
+ end
133
+
133
134
  def name
134
135
  @span.name
135
136
  end
@@ -21,7 +21,7 @@ module Datadog
21
21
  CONTENT_MAP_SIZE
22
22
  end
23
23
 
24
- def type
24
+ def event_type
25
25
  "span"
26
26
  end
27
27
 
@@ -22,7 +22,7 @@ module Datadog
22
22
  CONTENT_MAP_SIZE
23
23
  end
24
24
 
25
- def type
25
+ def event_type
26
26
  Ext::AppTypes::TYPE_TEST_MODULE
27
27
  end
28
28
 
@@ -22,7 +22,7 @@ module Datadog
22
22
  CONTENT_MAP_SIZE
23
23
  end
24
24
 
25
- def type
25
+ def event_type
26
26
  Ext::AppTypes::TYPE_TEST_SESSION
27
27
  end
28
28
 
@@ -22,7 +22,7 @@ module Datadog
22
22
  CONTENT_MAP_SIZE
23
23
  end
24
24
 
25
- def type
25
+ def event_type
26
26
  Ext::AppTypes::TYPE_TEST_SUITE
27
27
  end
28
28
 
@@ -22,7 +22,7 @@ module Datadog
22
22
  CONTENT_MAP_SIZE
23
23
  end
24
24
 
25
- def type
25
+ def event_type
26
26
  Ext::AppTypes::TYPE_TEST
27
27
  end
28
28
 
@@ -55,10 +55,6 @@ module Datadog
55
55
 
56
56
  response = send_payload(encoded_payload)
57
57
 
58
- Datadog.logger.debug do
59
- "Received server response: #{response.inspect}"
60
- end
61
-
62
58
  responses << response
63
59
  end
64
60
 
@@ -68,7 +64,7 @@ module Datadog
68
64
  private
69
65
 
70
66
  def send_payload(encoded_payload)
71
- api.request(
67
+ api.citestcycle_request(
72
68
  path: Datadog::CI::Ext::Transport::TEST_VISIBILITY_INTAKE_PATH,
73
69
  payload: encoded_payload
74
70
  )
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "base"
4
+ require_relative "../../ext/transport"
5
+
6
+ module Datadog
7
+ module CI
8
+ module Transport
9
+ module Api
10
+ class Agentless < Base
11
+ attr_reader :api_key
12
+
13
+ def initialize(api_key:, citestcycle_url:, api_url:)
14
+ @api_key = api_key
15
+ @citestcycle_http = build_http_client(citestcycle_url, compress: true)
16
+ @api_http = build_http_client(api_url, compress: false)
17
+ end
18
+
19
+ def citestcycle_request(path:, payload:, headers: {}, verb: "post")
20
+ super
21
+
22
+ perform_request(@citestcycle_http, path: path, payload: payload, headers: headers, verb: verb)
23
+ end
24
+
25
+ def api_request(path:, payload:, headers: {}, verb: "post")
26
+ super
27
+
28
+ perform_request(@api_http, path: path, payload: payload, headers: headers, verb: verb)
29
+ end
30
+
31
+ private
32
+
33
+ def perform_request(http_client, path:, payload:, headers:, verb:)
34
+ http_client.request(
35
+ path: path,
36
+ payload: payload,
37
+ headers: headers_with_default(headers),
38
+ verb: verb
39
+ )
40
+ end
41
+
42
+ def build_http_client(url, compress:)
43
+ uri = URI.parse(url)
44
+ raise "Invalid agentless mode URL: #{url}" if uri.host.nil?
45
+
46
+ Datadog::CI::Transport::HTTP.new(
47
+ host: uri.host,
48
+ port: uri.port,
49
+ ssl: uri.scheme == "https" || uri.port == 443,
50
+ compress: compress
51
+ )
52
+ end
53
+
54
+ def default_headers
55
+ headers = super
56
+ headers[Ext::Transport::HEADER_DD_API_KEY] = api_key
57
+ headers
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
@@ -7,27 +7,23 @@ module Datadog
7
7
  module Transport
8
8
  module Api
9
9
  class Base
10
- attr_reader :http
10
+ def api_request(path:, payload:, headers: {}, verb: "post")
11
+ headers[Ext::Transport::HEADER_CONTENT_TYPE] ||= Ext::Transport::CONTENT_TYPE_JSON
12
+ end
11
13
 
12
- def initialize(http:)
13
- @http = http
14
+ def citestcycle_request(path:, payload:, headers: {}, verb: "post")
15
+ headers[Ext::Transport::HEADER_CONTENT_TYPE] ||= Ext::Transport::CONTENT_TYPE_MESSAGEPACK
14
16
  end
15
17
 
16
- def request(path:, payload:, verb: "post")
17
- http.request(
18
- path: path,
19
- payload: payload,
20
- verb: verb,
21
- headers: headers
22
- )
18
+ def headers_with_default(headers)
19
+ request_headers = default_headers
20
+ request_headers.merge!(headers)
23
21
  end
24
22
 
25
23
  private
26
24
 
27
- def headers
28
- {
29
- Ext::Transport::HEADER_CONTENT_TYPE => Ext::Transport::CONTENT_TYPE_MESSAGEPACK
30
- }
25
+ def default_headers
26
+ {}
31
27
  end
32
28
  end
33
29
  end
@@ -1,6 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "ci_test_cycle"
3
+ require "datadog/core/configuration/agent_settings_resolver"
4
+ require "datadog/core/remote/negotiation"
5
+
6
+ require_relative "agentless"
4
7
  require_relative "evp_proxy"
5
8
  require_relative "../http"
6
9
  require_relative "../../ext/transport"
@@ -10,34 +13,34 @@ module Datadog
10
13
  module Transport
11
14
  module Api
12
15
  module Builder
13
- def self.build_ci_test_cycle_api(settings)
16
+ def self.build_agentless_api(settings)
17
+ return nil if settings.api_key.nil?
18
+
14
19
  dd_site = settings.site || Ext::Transport::DEFAULT_DD_SITE
15
- url = settings.ci.agentless_url ||
16
- "https://#{Ext::Transport::TEST_VISIBILITY_INTAKE_HOST_PREFIX}.#{dd_site}:443"
17
20
 
18
- uri = URI.parse(url)
19
- raise "Invalid agentless mode URL: #{url}" if uri.host.nil?
21
+ citestcycle_url = settings.ci.agentless_url ||
22
+ "https://#{Ext::Transport::TEST_VISIBILITY_INTAKE_HOST_PREFIX}.#{dd_site}:443"
20
23
 
21
- http = Datadog::CI::Transport::HTTP.new(
22
- host: uri.host,
23
- port: uri.port,
24
- ssl: uri.scheme == "https" || uri.port == 443,
25
- compress: true
26
- )
24
+ api_url = settings.ci.agentless_url ||
25
+ "https://#{Ext::Transport::DD_API_HOST_PREFIX}.#{dd_site}:443"
27
26
 
28
- CiTestCycle.new(api_key: settings.api_key, http: http)
27
+ Agentless.new(api_key: settings.api_key, citestcycle_url: citestcycle_url, api_url: api_url)
29
28
  end
30
29
 
31
- def self.build_evp_proxy_api(agent_settings)
32
- http = Datadog::CI::Transport::HTTP.new(
33
- host: agent_settings.hostname,
34
- port: agent_settings.port,
35
- ssl: agent_settings.ssl,
36
- timeout: agent_settings.timeout_seconds,
37
- compress: false
38
- )
30
+ def self.build_evp_proxy_api(settings)
31
+ agent_settings = Datadog::Core::Configuration::AgentSettingsResolver.call(settings)
32
+ negotiation = Datadog::Core::Remote::Negotiation.new(settings, agent_settings)
33
+
34
+ # temporary, remove this when patch will be accepted in Core to make logging configurable
35
+ negotiation.instance_variable_set(:@logged, {no_config_endpoint: true})
36
+
37
+ evp_proxy_path_prefix = Ext::Transport::EVP_PROXY_PATH_PREFIXES.find do |path_prefix|
38
+ negotiation.endpoint?(path_prefix)
39
+ end
40
+
41
+ return nil if evp_proxy_path_prefix.nil?
39
42
 
40
- EvpProxy.new(http: http)
43
+ EvpProxy.new(agent_settings: agent_settings, path_prefix: evp_proxy_path_prefix)
41
44
  end
42
45
  end
43
46
  end
@@ -10,17 +10,48 @@ module Datadog
10
10
  module Transport
11
11
  module Api
12
12
  class EvpProxy < Base
13
- def request(path:, payload:, verb: "post")
14
- path = "#{Ext::Transport::EVP_PROXY_PATH_PREFIX}#{path.sub(/^\//, "")}"
13
+ def initialize(agent_settings:, path_prefix: Ext::Transport::EVP_PROXY_V2_PATH_PREFIX)
14
+ @agent_intake_http = build_http_client(
15
+ agent_settings,
16
+ compress: Ext::Transport::EVP_PROXY_COMPRESSION_SUPPORTED[path_prefix]
17
+ )
18
+
19
+ @agent_api_http = build_http_client(agent_settings, compress: false)
20
+
21
+ path_prefix = "#{path_prefix}/" unless path_prefix.end_with?("/")
22
+ @path_prefix = path_prefix
23
+ end
24
+
25
+ def citestcycle_request(path:, payload:, headers: {}, verb: "post")
26
+ super
27
+
28
+ headers[Ext::Transport::HEADER_EVP_SUBDOMAIN] = Ext::Transport::TEST_VISIBILITY_INTAKE_HOST_PREFIX
29
+
30
+ perform_request(@agent_intake_http, path: path, payload: payload, headers: headers, verb: verb)
31
+ end
32
+
33
+ def api_request(path:, payload:, headers: {}, verb: "post")
34
+ super
35
+
36
+ headers[Ext::Transport::HEADER_EVP_SUBDOMAIN] = Ext::Transport::DD_API_HOST_PREFIX
15
37
 
16
- super(
17
- path: path,
38
+ perform_request(@agent_api_http, path: path, payload: payload, headers: headers, verb: verb)
39
+ end
40
+
41
+ private
42
+
43
+ def perform_request(http_client, path:, payload:, headers:, verb:)
44
+ http_client.request(
45
+ path: path_with_prefix(path),
18
46
  payload: payload,
47
+ headers: headers_with_default(headers),
19
48
  verb: verb
20
49
  )
21
50
  end
22
51
 
23
- private
52
+ def path_with_prefix(path)
53
+ "#{@path_prefix}#{path.sub(/^\//, "")}"
54
+ end
24
55
 
25
56
  def container_id
26
57
  return @container_id if defined?(@container_id)
@@ -28,15 +59,24 @@ module Datadog
28
59
  @container_id = Datadog::Core::Environment::Container.container_id
29
60
  end
30
61
 
31
- def headers
62
+ def default_headers
32
63
  headers = super
33
- headers[Ext::Transport::HEADER_EVP_SUBDOMAIN] = Ext::Transport::TEST_VISIBILITY_INTAKE_HOST_PREFIX
34
64
 
35
65
  c_id = container_id
36
66
  headers[Ext::Transport::HEADER_CONTAINER_ID] = c_id unless c_id.nil?
37
67
 
38
68
  headers
39
69
  end
70
+
71
+ def build_http_client(agent_settings, compress:)
72
+ Datadog::CI::Transport::HTTP.new(
73
+ host: agent_settings.hostname,
74
+ port: agent_settings.port,
75
+ ssl: agent_settings.ssl,
76
+ timeout: agent_settings.timeout_seconds,
77
+ compress: compress
78
+ )
79
+ end
40
80
  end
41
81
  end
42
82
  end
@@ -40,11 +40,17 @@ module Datadog
40
40
  "compression_enabled=#{compress}; path=#{path}; payload_size=#{payload.size}"
41
41
  end
42
42
 
43
- ResponseDecorator.new(
43
+ response = ResponseDecorator.new(
44
44
  adapter.call(
45
45
  build_env(path: path, payload: payload, headers: headers, verb: verb)
46
46
  )
47
47
  )
48
+
49
+ Datadog.logger.debug do
50
+ "Received server response: #{response.inspect}"
51
+ end
52
+
53
+ response
48
54
  end
49
55
 
50
56
  private
@@ -0,0 +1,96 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "json"
4
+
5
+ require "datadog/core/environment/identity"
6
+
7
+ require_relative "../ext/transport"
8
+
9
+ module Datadog
10
+ module CI
11
+ module Transport
12
+ # Datadog API client
13
+ # Calls settings endpoint to fetch library settings for given service and env
14
+ class RemoteSettingsApi
15
+ class Response
16
+ def initialize(http_response)
17
+ @http_response = http_response
18
+ @json = nil
19
+ end
20
+
21
+ def ok?
22
+ resp = @http_response
23
+ !resp.nil? && resp.ok?
24
+ end
25
+
26
+ def payload
27
+ cached = @json
28
+ return cached unless cached.nil?
29
+
30
+ resp = @http_response
31
+ return @json = default_payload if resp.nil? || !resp.ok?
32
+
33
+ begin
34
+ @json = JSON.parse(resp.payload).dig(*Ext::Transport::DD_API_SETTINGS_RESPONSE_DIG_KEYS) ||
35
+ default_payload
36
+ rescue JSON::ParserError => e
37
+ Datadog.logger.error("Failed to parse settings response payload: #{e}. Payload was: #{resp.payload}")
38
+ @json = default_payload
39
+ end
40
+ end
41
+
42
+ private
43
+
44
+ def default_payload
45
+ Ext::Transport::DD_API_SETTINGS_RESPONSE_DEFAULT
46
+ end
47
+ end
48
+
49
+ def initialize(api: nil, dd_env: nil)
50
+ @api = api
51
+ @dd_env = dd_env
52
+ end
53
+
54
+ def fetch_library_settings(test_session)
55
+ api = @api
56
+ return Response.new(nil) unless api
57
+
58
+ request_payload = payload(test_session)
59
+ Datadog.logger.debug("Fetching library settings with request: #{request_payload}")
60
+
61
+ http_response = api.api_request(
62
+ path: Ext::Transport::DD_API_SETTINGS_PATH,
63
+ payload: request_payload
64
+ )
65
+
66
+ Response.new(http_response)
67
+ end
68
+
69
+ private
70
+
71
+ def payload(test_session)
72
+ {
73
+ "data" => {
74
+ "id" => Datadog::Core::Environment::Identity.id,
75
+ "type" => Ext::Transport::DD_API_SETTINGS_TYPE,
76
+ "attributes" => {
77
+ "service" => test_session.service,
78
+ "env" => @dd_env,
79
+ "repository_url" => test_session.git_repository_url,
80
+ "branch" => test_session.git_branch,
81
+ "sha" => test_session.git_commit_sha,
82
+ "test_level" => Ext::Test::ITR_TEST_SKIPPING_MODE,
83
+ "configurations" => {
84
+ "os.platform" => test_session.os_platform,
85
+ "os.arch" => test_session.os_architecture,
86
+ "runtime.name" => test_session.runtime_name,
87
+ "runtime.version" => test_session.runtime_version
88
+ }
89
+ }
90
+ }
91
+ }.to_json
92
+ end
93
+ end
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "git"
4
+
5
+ module Datadog
6
+ module CI
7
+ module Utils
8
+ module Configuration
9
+ def self.fetch_service_name(default)
10
+ Datadog.configuration.service_without_fallback || Git.repository_name || default
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end