datadog-ci 1.0.1 → 1.2.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 +16 -2
- data/ext/datadog_cov/datadog_cov.c +259 -67
- data/lib/datadog/ci/configuration/components.rb +121 -79
- data/lib/datadog/ci/configuration/settings.rb +6 -0
- data/lib/datadog/ci/contrib/rspec/example.rb +1 -1
- data/lib/datadog/ci/contrib/rspec/patcher.rb +3 -3
- data/lib/datadog/ci/ext/settings.rb +1 -0
- data/lib/datadog/ci/span.rb +3 -3
- data/lib/datadog/ci/test.rb +1 -1
- data/lib/datadog/ci/test_module.rb +1 -1
- data/lib/datadog/ci/{itr/runner.rb → test_optimisation/component.rb} +13 -10
- 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 +1 -1
- data/lib/datadog/ci/{itr → test_optimisation}/coverage/writer.rb +1 -1
- data/lib/datadog/ci/{itr → test_optimisation}/skippable.rb +1 -1
- data/lib/datadog/ci/test_session.rb +1 -1
- data/lib/datadog/ci/test_suite.rb +1 -1
- data/lib/datadog/ci/test_visibility/{recorder.rb → component.rb} +10 -10
- data/lib/datadog/ci/test_visibility/{null_recorder.rb → null_component.rb} +6 -4
- data/lib/datadog/ci/test_visibility/transport.rb +1 -1
- data/lib/datadog/ci/transport/adapters/net.rb +138 -0
- data/lib/datadog/ci/transport/api/agentless.rb +2 -2
- data/lib/datadog/ci/transport/api/evp_proxy.rb +1 -1
- data/lib/datadog/ci/transport/http.rb +7 -57
- data/lib/datadog/ci/version.rb +2 -2
- data/lib/datadog/ci.rb +15 -15
- metadata +12 -11
@@ -0,0 +1,138 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "datadog/core/transport/response"
|
4
|
+
require "datadog/core/transport/ext"
|
5
|
+
|
6
|
+
require_relative "../gzip"
|
7
|
+
require_relative "../../ext/transport"
|
8
|
+
|
9
|
+
module Datadog
|
10
|
+
module CI
|
11
|
+
module Transport
|
12
|
+
module Adapters
|
13
|
+
# Adapter for Net::HTTP
|
14
|
+
class Net
|
15
|
+
attr_reader \
|
16
|
+
:hostname,
|
17
|
+
:port,
|
18
|
+
:timeout,
|
19
|
+
:ssl
|
20
|
+
|
21
|
+
def initialize(hostname:, port:, ssl:, timeout_seconds:)
|
22
|
+
@hostname = hostname
|
23
|
+
@port = port
|
24
|
+
@timeout = timeout_seconds
|
25
|
+
@ssl = ssl
|
26
|
+
end
|
27
|
+
|
28
|
+
def open(&block)
|
29
|
+
req = net_http_client.new(hostname, port)
|
30
|
+
|
31
|
+
req.use_ssl = ssl
|
32
|
+
req.open_timeout = req.read_timeout = timeout
|
33
|
+
|
34
|
+
req.start(&block)
|
35
|
+
end
|
36
|
+
|
37
|
+
def call(path:, payload:, headers:, verb:)
|
38
|
+
headers ||= {}
|
39
|
+
# skip tracing for internal DD requests
|
40
|
+
headers[Core::Transport::Ext::HTTP::HEADER_DD_INTERNAL_UNTRACED_REQUEST] = "1"
|
41
|
+
|
42
|
+
if respond_to?(verb)
|
43
|
+
send(verb, path: path, payload: payload, headers: headers)
|
44
|
+
else
|
45
|
+
raise "Unknown HTTP method [#{verb}]"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def post(path:, payload:, headers:)
|
50
|
+
post = ::Net::HTTP::Post.new(path, headers)
|
51
|
+
post.body = payload
|
52
|
+
|
53
|
+
# Connect and send the request
|
54
|
+
http_response = open do |http|
|
55
|
+
http.request(post)
|
56
|
+
end
|
57
|
+
|
58
|
+
# Build and return response
|
59
|
+
Response.new(http_response)
|
60
|
+
end
|
61
|
+
|
62
|
+
class Response
|
63
|
+
include Datadog::Core::Transport::Response
|
64
|
+
|
65
|
+
attr_reader :http_response
|
66
|
+
|
67
|
+
def initialize(http_response)
|
68
|
+
@http_response = http_response
|
69
|
+
end
|
70
|
+
|
71
|
+
def payload
|
72
|
+
return @decompressed_payload if defined?(@decompressed_payload)
|
73
|
+
return http_response.body unless gzipped_content?
|
74
|
+
return http_response.body unless gzipped_body?(http_response.body)
|
75
|
+
|
76
|
+
Datadog.logger.debug("Decompressing gzipped response payload")
|
77
|
+
@decompressed_payload = Gzip.decompress(http_response.body)
|
78
|
+
end
|
79
|
+
|
80
|
+
def header(name)
|
81
|
+
http_response[name]
|
82
|
+
end
|
83
|
+
|
84
|
+
def code
|
85
|
+
http_response.code.to_i
|
86
|
+
end
|
87
|
+
|
88
|
+
def ok?
|
89
|
+
code.between?(200, 299)
|
90
|
+
end
|
91
|
+
|
92
|
+
def unsupported?
|
93
|
+
code == 415
|
94
|
+
end
|
95
|
+
|
96
|
+
def not_found?
|
97
|
+
code == 404
|
98
|
+
end
|
99
|
+
|
100
|
+
def client_error?
|
101
|
+
code.between?(400, 499)
|
102
|
+
end
|
103
|
+
|
104
|
+
def server_error?
|
105
|
+
code.between?(500, 599)
|
106
|
+
end
|
107
|
+
|
108
|
+
def gzipped_content?
|
109
|
+
header(Ext::Transport::HEADER_CONTENT_ENCODING) == Ext::Transport::CONTENT_ENCODING_GZIP
|
110
|
+
end
|
111
|
+
|
112
|
+
def gzipped_body?(body)
|
113
|
+
return false if body.nil? || body.empty?
|
114
|
+
|
115
|
+
# no-dd-sa
|
116
|
+
first_bytes = body[0, 2]
|
117
|
+
return false if first_bytes.nil? || first_bytes.empty?
|
118
|
+
|
119
|
+
first_bytes.b == Ext::Transport::GZIP_MAGIC_NUMBER
|
120
|
+
end
|
121
|
+
|
122
|
+
def inspect
|
123
|
+
"#{super}, http_response:#{http_response}"
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
private
|
128
|
+
|
129
|
+
def net_http_client
|
130
|
+
return ::Net::HTTP unless defined?(WebMock::HttpLibAdapters::NetHttpAdapter::OriginalNetHTTP)
|
131
|
+
|
132
|
+
WebMock::HttpLibAdapters::NetHttpAdapter::OriginalNetHTTP
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
@@ -37,7 +37,7 @@ module Datadog
|
|
37
37
|
end
|
38
38
|
|
39
39
|
def citestcov_request(path:, payload:, headers: {}, verb: "post")
|
40
|
-
super
|
40
|
+
super
|
41
41
|
|
42
42
|
perform_request(@citestcov_http, path: path, payload: @citestcov_payload, headers: headers, verb: verb)
|
43
43
|
end
|
@@ -60,7 +60,7 @@ module Datadog
|
|
60
60
|
|
61
61
|
Datadog::CI::Transport::HTTP.new(
|
62
62
|
host: uri.host,
|
63
|
-
port: uri.port,
|
63
|
+
port: uri.port || 80,
|
64
64
|
ssl: uri.scheme == "https" || uri.port == 443,
|
65
65
|
compress: compress
|
66
66
|
)
|
@@ -39,7 +39,7 @@ module Datadog
|
|
39
39
|
end
|
40
40
|
|
41
41
|
def citestcov_request(path:, payload:, headers: {}, verb: "post")
|
42
|
-
super
|
42
|
+
super
|
43
43
|
|
44
44
|
headers[Ext::Transport::HEADER_EVP_SUBDOMAIN] = Ext::Transport::TEST_COVERAGE_INTAKE_HOST_PREFIX
|
45
45
|
|
@@ -1,12 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "delegate"
|
4
|
-
require "datadog/core/transport/http/adapters/net"
|
5
|
-
require "datadog/core/transport/http/env"
|
6
|
-
require "datadog/core/transport/request"
|
7
4
|
require "socket"
|
8
5
|
|
9
6
|
require_relative "gzip"
|
7
|
+
require_relative "adapters/net"
|
10
8
|
require_relative "../ext/transport"
|
11
9
|
|
12
10
|
module Datadog
|
@@ -24,7 +22,7 @@ module Datadog
|
|
24
22
|
MAX_RETRIES = 3
|
25
23
|
INITIAL_BACKOFF = 1
|
26
24
|
|
27
|
-
def initialize(host:, timeout: DEFAULT_TIMEOUT,
|
25
|
+
def initialize(host:, port:, timeout: DEFAULT_TIMEOUT, ssl: true, compress: false)
|
28
26
|
@host = host
|
29
27
|
@port = port
|
30
28
|
@timeout = timeout
|
@@ -70,7 +68,7 @@ module Datadog
|
|
70
68
|
|
71
69
|
def perform_http_call(path:, payload:, headers:, verb:, retries: MAX_RETRIES, backoff: INITIAL_BACKOFF)
|
72
70
|
adapter.call(
|
73
|
-
|
71
|
+
path: path, payload: payload, headers: headers, verb: verb
|
74
72
|
)
|
75
73
|
rescue Timeout::Error, Errno::EINVAL, Errno::ECONNRESET, EOFError, SocketError, Net::HTTPBadResponse => e
|
76
74
|
Datadog.logger.debug("Failed to send request with #{e} (#{e.message})")
|
@@ -87,65 +85,17 @@ module Datadog
|
|
87
85
|
end
|
88
86
|
end
|
89
87
|
|
90
|
-
def build_env(path:, payload:, headers:, verb:)
|
91
|
-
env = Datadog::Core::Transport::HTTP::Env.new(
|
92
|
-
Datadog::Core::Transport::Request.new
|
93
|
-
)
|
94
|
-
env.body = payload
|
95
|
-
env.path = path
|
96
|
-
env.headers = headers
|
97
|
-
env.verb = verb
|
98
|
-
env
|
99
|
-
end
|
100
|
-
|
101
88
|
def adapter
|
102
|
-
|
103
|
-
|
89
|
+
@adapter ||= Datadog::CI::Transport::Adapters::Net.new(
|
90
|
+
hostname: host, port: port, ssl: ssl, timeout_seconds: timeout
|
91
|
+
)
|
104
92
|
end
|
105
93
|
|
106
|
-
# adds compatibility with Datadog::Tracing transport
|
107
|
-
# provides ungzipping capabilities
|
94
|
+
# adds compatibility with Datadog::Tracing transport
|
108
95
|
class ResponseDecorator < ::SimpleDelegator
|
109
|
-
def payload
|
110
|
-
return @decompressed_payload if defined?(@decompressed_payload)
|
111
|
-
|
112
|
-
if gzipped?(__getobj__.payload)
|
113
|
-
Datadog.logger.debug("Decompressing gzipped response payload")
|
114
|
-
@decompressed_payload = Gzip.decompress(__getobj__.payload)
|
115
|
-
else
|
116
|
-
__getobj__.payload
|
117
|
-
end
|
118
|
-
end
|
119
|
-
|
120
96
|
def trace_count
|
121
97
|
0
|
122
98
|
end
|
123
|
-
|
124
|
-
def gzipped?(payload)
|
125
|
-
return false if payload.nil? || payload.empty?
|
126
|
-
|
127
|
-
# no-dd-sa
|
128
|
-
first_bytes = payload[0, 2]
|
129
|
-
return false if first_bytes.nil? || first_bytes.empty?
|
130
|
-
|
131
|
-
first_bytes.b == Datadog::CI::Ext::Transport::GZIP_MAGIC_NUMBER
|
132
|
-
end
|
133
|
-
end
|
134
|
-
|
135
|
-
class AdapterSettings
|
136
|
-
attr_reader :hostname, :port, :ssl, :timeout_seconds
|
137
|
-
|
138
|
-
def initialize(hostname:, port: nil, ssl: true, timeout_seconds: nil)
|
139
|
-
@hostname = hostname
|
140
|
-
@port = port
|
141
|
-
@ssl = ssl
|
142
|
-
@timeout_seconds = timeout_seconds
|
143
|
-
end
|
144
|
-
|
145
|
-
def ==(other)
|
146
|
-
hostname == other.hostname && port == other.port && ssl == other.ssl &&
|
147
|
-
timeout_seconds == other.timeout_seconds
|
148
|
-
end
|
149
99
|
end
|
150
100
|
end
|
151
101
|
end
|
data/lib/datadog/ci/version.rb
CHANGED
data/lib/datadog/ci.rb
CHANGED
@@ -39,7 +39,7 @@ module Datadog
|
|
39
39
|
# @return [Datadog::CI::TestSession] the active, running {Datadog::CI::TestSession}.
|
40
40
|
# @return [nil] if test suite level visibility is disabled or CI mode is disabled.
|
41
41
|
def start_test_session(service: Utils::Configuration.fetch_service_name("test"), tags: {})
|
42
|
-
|
42
|
+
test_visibility.start_test_session(service: service, tags: tags)
|
43
43
|
end
|
44
44
|
|
45
45
|
# The active, unfinished test session.
|
@@ -61,7 +61,7 @@ module Datadog
|
|
61
61
|
# @return [Datadog::CI::TestSession] the active test session
|
62
62
|
# @return [nil] if no test session is active
|
63
63
|
def active_test_session
|
64
|
-
|
64
|
+
test_visibility.active_test_session
|
65
65
|
end
|
66
66
|
|
67
67
|
# Starts a {Datadog::CI::TestModule ci_test_module} that represents a single test module (for most Ruby test frameworks
|
@@ -93,7 +93,7 @@ module Datadog
|
|
93
93
|
# @return [Datadog::CI::TestModule] the active, running {Datadog::CI::TestModule}.
|
94
94
|
# @return [nil] if test suite level visibility is disabled or CI mode is disabled.
|
95
95
|
def start_test_module(test_module_name, service: nil, tags: {})
|
96
|
-
|
96
|
+
test_visibility.start_test_module(test_module_name, service: service, tags: tags)
|
97
97
|
end
|
98
98
|
|
99
99
|
# The active, unfinished test module.
|
@@ -116,7 +116,7 @@ module Datadog
|
|
116
116
|
# @return [Datadog::CI::TestModule] the active test module
|
117
117
|
# @return [nil] if no test module is active
|
118
118
|
def active_test_module
|
119
|
-
|
119
|
+
test_visibility.active_test_module
|
120
120
|
end
|
121
121
|
|
122
122
|
# Starts a {Datadog::CI::TestSuite ci_test_suite} that represents a single test suite.
|
@@ -145,7 +145,7 @@ module Datadog
|
|
145
145
|
# @return [Datadog::CI::TestSuite] the active, running {Datadog::CI::TestSuite}.
|
146
146
|
# @return [nil] if test suite level visibility is disabled or CI mode is disabled.
|
147
147
|
def start_test_suite(test_suite_name, service: nil, tags: {})
|
148
|
-
|
148
|
+
test_visibility.start_test_suite(test_suite_name, service: service, tags: tags)
|
149
149
|
end
|
150
150
|
|
151
151
|
# The active, unfinished test suite.
|
@@ -168,7 +168,7 @@ module Datadog
|
|
168
168
|
# @return [Datadog::CI::TestSuite] the active test suite
|
169
169
|
# @return [nil] if no test suite with given name is active
|
170
170
|
def active_test_suite(test_suite_name)
|
171
|
-
|
171
|
+
test_visibility.active_test_suite(test_suite_name)
|
172
172
|
end
|
173
173
|
|
174
174
|
# Return a {Datadog::CI::Test ci_test} that will trace a test called `test_name`.
|
@@ -222,7 +222,7 @@ module Datadog
|
|
222
222
|
# @yieldparam [Datadog::CI::Test] ci_test the newly created and active [Datadog::CI::Test]
|
223
223
|
# @yieldparam [nil] if CI mode is disabled
|
224
224
|
def trace_test(test_name, test_suite_name, service: nil, tags: {}, &block)
|
225
|
-
|
225
|
+
test_visibility.trace_test(test_name, test_suite_name, service: service, tags: tags, &block)
|
226
226
|
end
|
227
227
|
|
228
228
|
# Same as {.trace_test} but it does not accept a block.
|
@@ -248,7 +248,7 @@ module Datadog
|
|
248
248
|
# @return [Datadog::CI::Test] the active, unfinished {Datadog::CI::Test}.
|
249
249
|
# @return [nil] if CI mode is disabled.
|
250
250
|
def start_test(test_name, test_suite_name, service: nil, tags: {})
|
251
|
-
|
251
|
+
test_visibility.trace_test(test_name, test_suite_name, service: service, tags: tags)
|
252
252
|
end
|
253
253
|
|
254
254
|
# Trace any custom span inside a test. For example, you could trace:
|
@@ -300,7 +300,7 @@ module Datadog
|
|
300
300
|
)
|
301
301
|
end
|
302
302
|
|
303
|
-
|
303
|
+
test_visibility.trace(span_name, type: type, tags: tags, &block)
|
304
304
|
end
|
305
305
|
|
306
306
|
# The active, unfinished custom (i.e. not test/suite/module/session) span.
|
@@ -326,7 +326,7 @@ module Datadog
|
|
326
326
|
# @return [Datadog::CI::Span] the active span
|
327
327
|
# @return [nil] if no span is active, or if the active span is not a custom span
|
328
328
|
def active_span
|
329
|
-
span =
|
329
|
+
span = test_visibility.active_span
|
330
330
|
span if span && !Ext::AppTypes::CI_SPAN_TYPES.include?(span.type)
|
331
331
|
end
|
332
332
|
|
@@ -352,7 +352,7 @@ module Datadog
|
|
352
352
|
# @return [Datadog::CI::Test] the active test
|
353
353
|
# @return [nil] if no test is active
|
354
354
|
def active_test
|
355
|
-
|
355
|
+
test_visibility.active_test
|
356
356
|
end
|
357
357
|
|
358
358
|
private
|
@@ -361,12 +361,12 @@ module Datadog
|
|
361
361
|
Datadog.send(:components)
|
362
362
|
end
|
363
363
|
|
364
|
-
def
|
365
|
-
components.
|
364
|
+
def test_visibility
|
365
|
+
components.test_visibility
|
366
366
|
end
|
367
367
|
|
368
|
-
def
|
369
|
-
components.
|
368
|
+
def test_optimisation
|
369
|
+
components.test_optimisation
|
370
370
|
end
|
371
371
|
end
|
372
372
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: datadog-ci
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0
|
4
|
+
version: 1.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Datadog, Inc.
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-07-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: datadog
|
@@ -134,22 +134,22 @@ files:
|
|
134
134
|
- lib/datadog/ci/git/tree_uploader.rb
|
135
135
|
- lib/datadog/ci/git/upload_packfile.rb
|
136
136
|
- lib/datadog/ci/git/user.rb
|
137
|
-
- lib/datadog/ci/itr/coverage/ddcov.rb
|
138
|
-
- lib/datadog/ci/itr/coverage/event.rb
|
139
|
-
- lib/datadog/ci/itr/coverage/transport.rb
|
140
|
-
- lib/datadog/ci/itr/coverage/writer.rb
|
141
|
-
- lib/datadog/ci/itr/runner.rb
|
142
|
-
- lib/datadog/ci/itr/skippable.rb
|
143
137
|
- lib/datadog/ci/span.rb
|
144
138
|
- lib/datadog/ci/test.rb
|
145
139
|
- lib/datadog/ci/test_module.rb
|
140
|
+
- lib/datadog/ci/test_optimisation/component.rb
|
141
|
+
- lib/datadog/ci/test_optimisation/coverage/ddcov.rb
|
142
|
+
- lib/datadog/ci/test_optimisation/coverage/event.rb
|
143
|
+
- lib/datadog/ci/test_optimisation/coverage/transport.rb
|
144
|
+
- lib/datadog/ci/test_optimisation/coverage/writer.rb
|
145
|
+
- lib/datadog/ci/test_optimisation/skippable.rb
|
146
146
|
- lib/datadog/ci/test_session.rb
|
147
147
|
- lib/datadog/ci/test_suite.rb
|
148
|
+
- lib/datadog/ci/test_visibility/component.rb
|
148
149
|
- lib/datadog/ci/test_visibility/context/global.rb
|
149
150
|
- lib/datadog/ci/test_visibility/context/local.rb
|
150
151
|
- lib/datadog/ci/test_visibility/flush.rb
|
151
|
-
- lib/datadog/ci/test_visibility/
|
152
|
-
- lib/datadog/ci/test_visibility/recorder.rb
|
152
|
+
- lib/datadog/ci/test_visibility/null_component.rb
|
153
153
|
- lib/datadog/ci/test_visibility/serializers/base.rb
|
154
154
|
- lib/datadog/ci/test_visibility/serializers/factories/test_level.rb
|
155
155
|
- lib/datadog/ci/test_visibility/serializers/factories/test_suite_level.rb
|
@@ -160,6 +160,7 @@ files:
|
|
160
160
|
- lib/datadog/ci/test_visibility/serializers/test_v1.rb
|
161
161
|
- lib/datadog/ci/test_visibility/serializers/test_v2.rb
|
162
162
|
- lib/datadog/ci/test_visibility/transport.rb
|
163
|
+
- lib/datadog/ci/transport/adapters/net.rb
|
163
164
|
- lib/datadog/ci/transport/api/agentless.rb
|
164
165
|
- lib/datadog/ci/transport/api/base.rb
|
165
166
|
- lib/datadog/ci/transport/api/builder.rb
|
@@ -201,7 +202,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
201
202
|
- !ruby/object:Gem::Version
|
202
203
|
version: 2.0.0
|
203
204
|
requirements: []
|
204
|
-
rubygems_version: 3.5.
|
205
|
+
rubygems_version: 3.5.11
|
205
206
|
signing_key:
|
206
207
|
specification_version: 4
|
207
208
|
summary: Datadog CI visibility for your ruby application
|