datadog-ci 1.22.1 → 1.23.1
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 +26 -2
- data/lib/datadog/ci/contrib/rspec/example_group.rb +0 -1
- data/lib/datadog/ci/contrib/rspec/runner.rb +2 -2
- data/lib/datadog/ci/ext/dd_test.rb +18 -0
- data/lib/datadog/ci/ext/test_discovery.rb +1 -1
- data/lib/datadog/ci/remote/component.rb +15 -1
- data/lib/datadog/ci/remote/library_settings.rb +11 -3
- data/lib/datadog/ci/remote/library_settings_client.rb +2 -2
- data/lib/datadog/ci/test_discovery/component.rb +1 -0
- data/lib/datadog/ci/test_management/component.rb +33 -5
- data/lib/datadog/ci/test_management/tests_properties.rb +12 -4
- data/lib/datadog/ci/test_optimisation/component.rb +87 -1
- data/lib/datadog/ci/test_optimisation/skippable.rb +13 -5
- data/lib/datadog/ci/test_visibility/component.rb +57 -0
- data/lib/datadog/ci/test_visibility/known_tests.rb +12 -4
- data/lib/datadog/ci/test_visibility/store/process.rb +16 -6
- data/lib/datadog/ci/utils/stateful.rb +30 -0
- data/lib/datadog/ci/version.rb +1 -1
- metadata +2 -2
- data/lib/datadog/ci/contrib/rspec/helpers.rb +0 -16
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d28b3d81843fefd07c4b75b21cfb7e9ffc288525e3368ce5752e209d43276e64
|
4
|
+
data.tar.gz: 3dbd4a467c2e2cee7ebea4cdfdc0487bba97f74d7672eaae729f4c00a2094d3c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3d6cd831349cac64cf1abb7a80490dca5c94a503febf632cf2678bde4a5ef440fd6ecf6172ba870887d7c49e169f81cc82a2410a9acd4f9a40847062bcfcdfea
|
7
|
+
data.tar.gz: 5c84eede97a6985e858d0acade39b2457f38362afa837277d95b40a4372e89f1f5128005a94141d3799d324a0642ddb46c4aaaa93c5f160e5d79b5dbc3d530d9
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,22 @@
|
|
1
1
|
## [Unreleased]
|
2
2
|
|
3
|
+
## [1.23.1] - 2025-10-14
|
4
|
+
|
5
|
+
========== Changelog ==========
|
6
|
+
### Fixed
|
7
|
+
* Drop source end line when it is before start line ([#414][])
|
8
|
+
|
9
|
+
## [1.23.0] - 2025-10-08
|
10
|
+
|
11
|
+
|
12
|
+
### Changed
|
13
|
+
* In test discovery mode output suiteSourceFile for each test ([#400][])
|
14
|
+
* DDTest integration changes ([#407][])
|
15
|
+
* Support context propagation from Datadog test runner ([#399][])
|
16
|
+
|
17
|
+
### Fixed
|
18
|
+
* Fix issue when parallel_tests doesn't track test sessions when using manual instrumentation ([#410][])
|
19
|
+
|
3
20
|
## [1.22.1] - 2025-08-25
|
4
21
|
|
5
22
|
### Fixed
|
@@ -520,7 +537,9 @@ Currently test suite level visibility is not used by our instrumentation: it wil
|
|
520
537
|
|
521
538
|
- Ruby versions < 2.7 no longer supported ([#8][])
|
522
539
|
|
523
|
-
[Unreleased]: https://github.com/DataDog/datadog-ci-rb/compare/v1.
|
540
|
+
[Unreleased]: https://github.com/DataDog/datadog-ci-rb/compare/v1.23.1...main
|
541
|
+
[1.23.1]: https://github.com/DataDog/datadog-ci-rb/compare/v1.23.0...v1.23.1
|
542
|
+
[1.23.0]: https://github.com/DataDog/datadog-ci-rb/compare/v1.22.1...v1.23.0
|
524
543
|
[1.22.1]: https://github.com/DataDog/datadog-ci-rb/compare/v1.22.0...v1.22.1
|
525
544
|
[1.22.0]: https://github.com/DataDog/datadog-ci-rb/compare/v1.21.1...v1.22.0
|
526
545
|
[1.21.1]: https://github.com/DataDog/datadog-ci-rb/compare/v1.21.0...v1.21.1
|
@@ -739,4 +758,9 @@ Currently test suite level visibility is not used by our instrumentation: it wil
|
|
739
758
|
[#393]: https://github.com/DataDog/datadog-ci-rb/issues/393
|
740
759
|
[#394]: https://github.com/DataDog/datadog-ci-rb/issues/394
|
741
760
|
[#396]: https://github.com/DataDog/datadog-ci-rb/issues/396
|
742
|
-
[#
|
761
|
+
[#399]: https://github.com/DataDog/datadog-ci-rb/issues/399
|
762
|
+
[#400]: https://github.com/DataDog/datadog-ci-rb/issues/400
|
763
|
+
[#402]: https://github.com/DataDog/datadog-ci-rb/issues/402
|
764
|
+
[#407]: https://github.com/DataDog/datadog-ci-rb/issues/407
|
765
|
+
[#410]: https://github.com/DataDog/datadog-ci-rb/issues/410
|
766
|
+
[#414]: https://github.com/DataDog/datadog-ci-rb/issues/414
|
@@ -3,7 +3,6 @@
|
|
3
3
|
require_relative "../../ext/test"
|
4
4
|
require_relative "../instrumentation"
|
5
5
|
require_relative "ext"
|
6
|
-
require_relative "helpers"
|
7
6
|
|
8
7
|
module Datadog
|
9
8
|
module CI
|
@@ -33,7 +32,8 @@ module Datadog
|
|
33
32
|
|
34
33
|
result = super
|
35
34
|
return result unless test_module && test_session
|
36
|
-
|
35
|
+
# distributed test session must end in the parent process (for RSpec it would be parallel_tests CLI)
|
36
|
+
return result if test_session.distributed
|
37
37
|
|
38
38
|
if result != 0
|
39
39
|
test_module.failed!
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Datadog
|
4
|
+
module CI
|
5
|
+
module Ext
|
6
|
+
# Constants for integration with DDTest tool: https://github.com/DataDog/ddtest
|
7
|
+
module DDTest
|
8
|
+
PLAN_FOLDER = ".testoptimization"
|
9
|
+
TESTOPTIMIZATION_CACHE_PATH = "#{PLAN_FOLDER}/cache"
|
10
|
+
|
11
|
+
SETTINGS_FILE_NAME = "settings.json"
|
12
|
+
KNOWN_TESTS_FILE_NAME = "known_tests.json"
|
13
|
+
TEST_MANAGEMENT_TESTS_FILE_NAME = "test_management_tests.json"
|
14
|
+
SKIPPABLE_TESTS_FILE_NAME = "skippable_tests.json"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -6,7 +6,7 @@ module Datadog
|
|
6
6
|
# Defines constants for test discovery mode
|
7
7
|
module TestDiscovery
|
8
8
|
# Default output path for test discovery mode
|
9
|
-
DEFAULT_OUTPUT_PATH = "
|
9
|
+
DEFAULT_OUTPUT_PATH = "./#{DDTest::PLAN_FOLDER}/test_discovery/tests.json"
|
10
10
|
|
11
11
|
# Maximum buffer size before writing to file
|
12
12
|
MAX_BUFFER_SIZE = 10_000
|
@@ -54,11 +54,25 @@ module Datadog
|
|
54
54
|
FILE_STORAGE_KEY
|
55
55
|
end
|
56
56
|
|
57
|
+
def restore_state_from_datadog_test_runner
|
58
|
+
Datadog.logger.debug { "Restoring library configuration from DDTest cache" }
|
59
|
+
|
60
|
+
settings = load_json(Ext::DDTest::SETTINGS_FILE_NAME)
|
61
|
+
if settings.nil?
|
62
|
+
Datadog.logger.debug { "Restoring library configuration failed, will request again" }
|
63
|
+
return false
|
64
|
+
end
|
65
|
+
|
66
|
+
Datadog.logger.debug { "Restored library configuration from DDTest: #{settings}" }
|
67
|
+
@library_configuration = LibrarySettings.from_json(settings)
|
68
|
+
true
|
69
|
+
end
|
70
|
+
|
57
71
|
private
|
58
72
|
|
59
73
|
def fetch_library_configuration(test_session)
|
60
74
|
# In test discovery mode, skip backend fetching and use default settings (everything is disabled)
|
61
|
-
return @library_configuration = LibrarySettings.
|
75
|
+
return @library_configuration = LibrarySettings.from_http_response(nil) if @test_discovery_enabled
|
62
76
|
|
63
77
|
# skip backend request if library configuration was loaded by a different process and stored on disk
|
64
78
|
library_configuration_loaded = load_component_state
|
@@ -14,9 +14,12 @@ module Datadog
|
|
14
14
|
module Remote
|
15
15
|
# Wrapper around the settings HTTP response
|
16
16
|
class LibrarySettings
|
17
|
-
def
|
18
|
-
|
19
|
-
|
17
|
+
def self.from_http_response(http_response)
|
18
|
+
new(http_response, nil)
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.from_json(json)
|
22
|
+
new(nil, json)
|
20
23
|
end
|
21
24
|
|
22
25
|
def ok?
|
@@ -148,6 +151,11 @@ module Datadog
|
|
148
151
|
|
149
152
|
private
|
150
153
|
|
154
|
+
def initialize(http_response, json)
|
155
|
+
@http_response = http_response
|
156
|
+
@json = json
|
157
|
+
end
|
158
|
+
|
151
159
|
def test_management_payload
|
152
160
|
payload.fetch(
|
153
161
|
Ext::Transport::DD_API_SETTINGS_RESPONSE_TEST_MANAGEMENT_KEY,
|
@@ -25,7 +25,7 @@ module Datadog
|
|
25
25
|
|
26
26
|
def fetch(test_session)
|
27
27
|
api = @api
|
28
|
-
return LibrarySettings.
|
28
|
+
return LibrarySettings.from_http_response(nil) unless api
|
29
29
|
|
30
30
|
request_payload = payload(test_session)
|
31
31
|
Datadog.logger.debug("Fetching library settings with request: #{request_payload}")
|
@@ -51,7 +51,7 @@ module Datadog
|
|
51
51
|
)
|
52
52
|
end
|
53
53
|
|
54
|
-
library_settings = LibrarySettings.
|
54
|
+
library_settings = LibrarySettings.from_http_response(http_response)
|
55
55
|
|
56
56
|
Utils::Telemetry.inc(
|
57
57
|
Ext::Telemetry::METRIC_GIT_REQUESTS_SETTINGS_RESPONSE,
|
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
require_relative "../ext/telemetry"
|
4
4
|
require_relative "../ext/test"
|
5
|
+
require_relative "../ext/dd_test"
|
5
6
|
require_relative "../utils/stateful"
|
6
7
|
require_relative "../utils/telemetry"
|
7
8
|
require_relative "../utils/test_run"
|
@@ -35,11 +36,11 @@ module Datadog
|
|
35
36
|
|
36
37
|
test_session.set_tag(Ext::Test::TAG_TEST_MANAGEMENT_ENABLED, "true")
|
37
38
|
|
38
|
-
|
39
|
-
if
|
40
|
-
|
41
|
-
|
42
|
-
|
39
|
+
return if restore_state_from_datadog_test_runner
|
40
|
+
return if load_component_state
|
41
|
+
|
42
|
+
@tests_properties = @tests_properties_client.fetch(test_session)
|
43
|
+
store_component_state if test_session.distributed
|
43
44
|
|
44
45
|
Utils::Telemetry.distribution(
|
45
46
|
Ext::Telemetry::METRIC_TEST_MANAGEMENT_TESTS_RESPONSE_TESTS,
|
@@ -74,6 +75,33 @@ module Datadog
|
|
74
75
|
test_properties.fetch("attempt_to_fix", false)
|
75
76
|
end
|
76
77
|
|
78
|
+
def restore_state_from_datadog_test_runner
|
79
|
+
Datadog.logger.debug { "Restoring test management tests from DDTest cache" }
|
80
|
+
|
81
|
+
test_management_data = load_json(Ext::DDTest::TEST_MANAGEMENT_TESTS_FILE_NAME)
|
82
|
+
if test_management_data.nil?
|
83
|
+
Datadog.logger.debug { "Restoring test management tests failed, will request again" }
|
84
|
+
return false
|
85
|
+
end
|
86
|
+
|
87
|
+
Datadog.logger.debug { "Restored test management tests from DDTest: #{test_management_data}" }
|
88
|
+
|
89
|
+
# Use the TestsProperties::Response class method to parse the JSON data
|
90
|
+
# Wrap the data in the expected backend API format
|
91
|
+
wrapped_data = {
|
92
|
+
"data" => {
|
93
|
+
"attributes" => test_management_data
|
94
|
+
}
|
95
|
+
}
|
96
|
+
|
97
|
+
tests_properties_response = TestsProperties::Response.from_json(wrapped_data)
|
98
|
+
@tests_properties = tests_properties_response.tests
|
99
|
+
|
100
|
+
Datadog.logger.debug { "Found [#{@tests_properties.size}] test management tests from context" }
|
101
|
+
|
102
|
+
true
|
103
|
+
end
|
104
|
+
|
77
105
|
# Implementation of Stateful interface
|
78
106
|
def serialize_state
|
79
107
|
{
|
@@ -15,9 +15,12 @@ module Datadog
|
|
15
15
|
# fetches and stores a map of tests to their test management properties from the backend
|
16
16
|
class TestsProperties
|
17
17
|
class Response
|
18
|
-
def
|
19
|
-
|
20
|
-
|
18
|
+
def self.from_http_response(http_response)
|
19
|
+
new(http_response, nil)
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.from_json(json)
|
23
|
+
new(nil, json)
|
21
24
|
end
|
22
25
|
|
23
26
|
def ok?
|
@@ -51,6 +54,11 @@ module Datadog
|
|
51
54
|
|
52
55
|
private
|
53
56
|
|
57
|
+
def initialize(http_response, json)
|
58
|
+
@http_response = http_response
|
59
|
+
@json = json
|
60
|
+
end
|
61
|
+
|
54
62
|
def payload
|
55
63
|
cached = @json
|
56
64
|
return cached unless cached.nil?
|
@@ -106,7 +114,7 @@ module Datadog
|
|
106
114
|
)
|
107
115
|
end
|
108
116
|
|
109
|
-
Response.
|
117
|
+
Response.from_http_response(http_response).tests
|
110
118
|
end
|
111
119
|
|
112
120
|
private
|
@@ -6,6 +6,7 @@ require "datadog/core/telemetry/logging"
|
|
6
6
|
|
7
7
|
require_relative "../ext/test"
|
8
8
|
require_relative "../ext/telemetry"
|
9
|
+
require_relative "../ext/dd_test"
|
9
10
|
|
10
11
|
require_relative "../git/local_repository"
|
11
12
|
|
@@ -84,7 +85,11 @@ module Datadog
|
|
84
85
|
load_datadog_cov! if @code_coverage_enabled
|
85
86
|
|
86
87
|
# Load component state first, and if successful, skip fetching skippable tests
|
87
|
-
|
88
|
+
# Also try to restore from DDTest cache if available
|
89
|
+
if skipping_tests?
|
90
|
+
return if load_component_state
|
91
|
+
return if restore_state_from_datadog_test_runner
|
92
|
+
|
88
93
|
fetch_skippable_tests(test_session)
|
89
94
|
store_component_state if test_session.distributed
|
90
95
|
end
|
@@ -210,8 +215,89 @@ module Datadog
|
|
210
215
|
FILE_STORAGE_KEY
|
211
216
|
end
|
212
217
|
|
218
|
+
def restore_state_from_datadog_test_runner
|
219
|
+
Datadog.logger.debug { "Restoring skippable tests from DDTest cache" }
|
220
|
+
|
221
|
+
skippable_tests_data = load_json(Ext::DDTest::SKIPPABLE_TESTS_FILE_NAME)
|
222
|
+
if skippable_tests_data.nil?
|
223
|
+
Datadog.logger.debug { "Restoring skippable tests failed, will request again" }
|
224
|
+
return false
|
225
|
+
end
|
226
|
+
|
227
|
+
Datadog.logger.debug { "Restored skippable tests from DDTest: #{skippable_tests_data}" }
|
228
|
+
|
229
|
+
transformed_data = transform_test_runner_data(skippable_tests_data)
|
230
|
+
|
231
|
+
Datadog.logger.debug { "Skippable tests after transformation: #{transformed_data}" }
|
232
|
+
|
233
|
+
# Use the Skippable::Response class to parse the transformed data
|
234
|
+
skippable_response = Skippable::Response.from_json(transformed_data)
|
235
|
+
|
236
|
+
@mutex.synchronize do
|
237
|
+
@correlation_id = skippable_response.correlation_id
|
238
|
+
@skippable_tests = skippable_response.tests
|
239
|
+
end
|
240
|
+
|
241
|
+
Datadog.logger.debug { "Found [#{@skippable_tests.size}] skippable tests from context" }
|
242
|
+
Datadog.logger.debug { "ITR correlation ID from context: #{@correlation_id}" }
|
243
|
+
|
244
|
+
true
|
245
|
+
end
|
246
|
+
|
213
247
|
private
|
214
248
|
|
249
|
+
# Transforms Test Runner skippable tests data format to the format expected by Skippable::Response
|
250
|
+
#
|
251
|
+
# Test Runner format:
|
252
|
+
# {
|
253
|
+
# "correlationId": "abc123",
|
254
|
+
# "skippableTests": {
|
255
|
+
# "suite_name": {
|
256
|
+
# "test_name": [{"suite": "suite_name", "name": "test_name", "parameters": "{...}", "configurations": {}}]
|
257
|
+
# }
|
258
|
+
# }
|
259
|
+
# }
|
260
|
+
#
|
261
|
+
# Expected format:
|
262
|
+
# {
|
263
|
+
# "meta": {"correlation_id": "abc123"},
|
264
|
+
# "data": [{"type": "test", "attributes": {"suite": "suite_name", "name": "test_name", "parameters": "{...}"}}]
|
265
|
+
# }
|
266
|
+
def transform_test_runner_data(skippable_tests_data)
|
267
|
+
skippable_tests = skippable_tests_data.fetch("skippableTests", {})
|
268
|
+
|
269
|
+
# Pre-calculate array size for better memory allocation
|
270
|
+
total_test_configs = skippable_tests.sum do |_, tests_hash|
|
271
|
+
tests_hash.sum { |_, test_configs| test_configs.size }
|
272
|
+
end
|
273
|
+
|
274
|
+
data_array = Array.new(total_test_configs)
|
275
|
+
index = 0
|
276
|
+
|
277
|
+
skippable_tests.each_value do |tests_hash|
|
278
|
+
tests_hash.each_value do |test_configs|
|
279
|
+
test_configs.each do |test_config|
|
280
|
+
data_array[index] = {
|
281
|
+
"type" => Ext::Test::ITR_TEST_SKIPPING_MODE,
|
282
|
+
"attributes" => {
|
283
|
+
"suite" => test_config["suite"],
|
284
|
+
"name" => test_config["name"],
|
285
|
+
"parameters" => test_config["parameters"]
|
286
|
+
}
|
287
|
+
}
|
288
|
+
index += 1
|
289
|
+
end
|
290
|
+
end
|
291
|
+
end
|
292
|
+
|
293
|
+
{
|
294
|
+
"meta" => {
|
295
|
+
"correlation_id" => skippable_tests_data["correlationId"]
|
296
|
+
},
|
297
|
+
"data" => data_array
|
298
|
+
}
|
299
|
+
end
|
300
|
+
|
215
301
|
def write(event)
|
216
302
|
# skip sending events if writer is not configured
|
217
303
|
@coverage_writer&.write(event)
|
@@ -14,9 +14,12 @@ module Datadog
|
|
14
14
|
module TestOptimisation
|
15
15
|
class Skippable
|
16
16
|
class Response
|
17
|
-
def
|
18
|
-
|
19
|
-
|
17
|
+
def self.from_http_response(http_response)
|
18
|
+
new(http_response, nil)
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.from_json(json)
|
22
|
+
new(nil, json)
|
20
23
|
end
|
21
24
|
|
22
25
|
def ok?
|
@@ -50,6 +53,11 @@ module Datadog
|
|
50
53
|
|
51
54
|
private
|
52
55
|
|
56
|
+
def initialize(http_response, json)
|
57
|
+
@http_response = http_response
|
58
|
+
@json = json
|
59
|
+
end
|
60
|
+
|
53
61
|
def payload
|
54
62
|
cached = @json
|
55
63
|
return cached unless cached.nil?
|
@@ -74,7 +82,7 @@ module Datadog
|
|
74
82
|
|
75
83
|
def fetch_skippable_tests(test_session)
|
76
84
|
api = @api
|
77
|
-
return Response.
|
85
|
+
return Response.from_http_response(nil) unless api
|
78
86
|
|
79
87
|
request_payload = payload(test_session)
|
80
88
|
Datadog.logger.debug("Fetching skippable tests with request: #{request_payload}")
|
@@ -105,7 +113,7 @@ module Datadog
|
|
105
113
|
)
|
106
114
|
end
|
107
115
|
|
108
|
-
Response.
|
116
|
+
Response.from_http_response(http_response)
|
109
117
|
end
|
110
118
|
|
111
119
|
private
|
@@ -6,6 +6,7 @@ require "rbconfig"
|
|
6
6
|
require "datadog/core/utils/forking"
|
7
7
|
|
8
8
|
require_relative "context"
|
9
|
+
require_relative "known_tests"
|
9
10
|
require_relative "telemetry"
|
10
11
|
require_relative "total_coverage"
|
11
12
|
|
@@ -226,6 +227,36 @@ module Datadog
|
|
226
227
|
(forked? && !@context_service_uri.nil? && !@context_service_uri.empty?) || @is_client_process
|
227
228
|
end
|
228
229
|
|
230
|
+
def restore_state_from_datadog_test_runner
|
231
|
+
Datadog.logger.debug { "Restoring known tests from DDTest cache" }
|
232
|
+
|
233
|
+
known_tests_data = load_json(Ext::DDTest::KNOWN_TESTS_FILE_NAME)
|
234
|
+
if known_tests_data.nil?
|
235
|
+
Datadog.logger.debug { "Restoring known tests failed, will request again" }
|
236
|
+
return false
|
237
|
+
end
|
238
|
+
|
239
|
+
Datadog.logger.debug { "Restored known tests from DDTest: #{known_tests_data}" }
|
240
|
+
|
241
|
+
# Use the KnownTests class method to parse the JSON data
|
242
|
+
known_tests_data = {
|
243
|
+
"data" => {
|
244
|
+
"attributes" => known_tests_data
|
245
|
+
}
|
246
|
+
}
|
247
|
+
|
248
|
+
@known_tests = KnownTests::Response.from_json(known_tests_data).tests
|
249
|
+
@known_tests_enabled = !@known_tests.empty?
|
250
|
+
|
251
|
+
unless @known_tests_enabled
|
252
|
+
Datadog.logger.debug("Empty set of known tests from the DDTest cache file")
|
253
|
+
end
|
254
|
+
|
255
|
+
Datadog.logger.debug { "Found [#{@known_tests.size}] known tests from context" }
|
256
|
+
|
257
|
+
true
|
258
|
+
end
|
259
|
+
|
229
260
|
private
|
230
261
|
|
231
262
|
# DOMAIN EVENTS
|
@@ -309,6 +340,8 @@ module Datadog
|
|
309
340
|
test_optimisation.stop_coverage(test)
|
310
341
|
test_optimisation.on_test_finished(test, maybe_remote_context)
|
311
342
|
|
343
|
+
validate_source_location(test)
|
344
|
+
|
312
345
|
test_retries.record_test_finished(test)
|
313
346
|
Telemetry.event_finished(test)
|
314
347
|
end
|
@@ -344,6 +377,27 @@ module Datadog
|
|
344
377
|
span.set_tag(Ext::Test::TAG_CODEOWNERS, owners) unless owners.nil?
|
345
378
|
end
|
346
379
|
|
380
|
+
def validate_source_location(test)
|
381
|
+
source_start = test.get_tag(Ext::Test::TAG_SOURCE_START)
|
382
|
+
source_end = test.get_tag(Ext::Test::TAG_SOURCE_END)
|
383
|
+
|
384
|
+
return if source_start.nil? || source_end.nil?
|
385
|
+
# tags must be strings, if they are not, they were redefined by someone
|
386
|
+
return unless source_start.is_a?(String) && source_end.is_a?(String)
|
387
|
+
|
388
|
+
start_line = source_start.to_i
|
389
|
+
end_line = source_end.to_i
|
390
|
+
|
391
|
+
if end_line < start_line
|
392
|
+
Datadog.logger.debug do
|
393
|
+
"Invalid source location for test [#{test.name}]: " \
|
394
|
+
"end line (#{end_line}) is before the start line (#{start_line}). " \
|
395
|
+
"Removing #{Ext::Test::TAG_SOURCE_END} tag."
|
396
|
+
end
|
397
|
+
test.clear_tag(Ext::Test::TAG_SOURCE_END)
|
398
|
+
end
|
399
|
+
end
|
400
|
+
|
347
401
|
def fix_test_suite!(test)
|
348
402
|
return unless test_suite_level_visibility_enabled
|
349
403
|
|
@@ -398,6 +452,9 @@ module Datadog
|
|
398
452
|
end
|
399
453
|
|
400
454
|
def new_test?(test_span)
|
455
|
+
# check if @known_tests set is empty again
|
456
|
+
# to ensure that we don't tag tests as new unnecessarily
|
457
|
+
@known_tests_enabled = false if @known_tests_enabled && @known_tests.empty?
|
401
458
|
return false unless @known_tests_enabled
|
402
459
|
|
403
460
|
test_id = Utils::TestRun.datadog_test_id(test_span.name, test_span.test_suite_name)
|
@@ -14,9 +14,12 @@ module Datadog
|
|
14
14
|
# fetches and stores a list of known tests from the backend
|
15
15
|
class KnownTests
|
16
16
|
class Response
|
17
|
-
def
|
18
|
-
|
19
|
-
|
17
|
+
def self.from_http_response(http_response)
|
18
|
+
new(http_response, nil)
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.from_json(json)
|
22
|
+
new(nil, json)
|
20
23
|
end
|
21
24
|
|
22
25
|
def ok?
|
@@ -44,6 +47,11 @@ module Datadog
|
|
44
47
|
|
45
48
|
private
|
46
49
|
|
50
|
+
def initialize(http_response, json)
|
51
|
+
@http_response = http_response
|
52
|
+
@json = json
|
53
|
+
end
|
54
|
+
|
47
55
|
def payload
|
48
56
|
cached = @json
|
49
57
|
return cached unless cached.nil?
|
@@ -99,7 +107,7 @@ module Datadog
|
|
99
107
|
)
|
100
108
|
end
|
101
109
|
|
102
|
-
Response.
|
110
|
+
Response.from_http_response(http_response).tests
|
103
111
|
end
|
104
112
|
|
105
113
|
private
|
@@ -9,8 +9,6 @@ module Datadog
|
|
9
9
|
module Store
|
10
10
|
# This context is shared between threads and represents the current test session and test module.
|
11
11
|
class Process
|
12
|
-
attr_reader :readonly_test_session, :readonly_test_module
|
13
|
-
|
14
12
|
def initialize
|
15
13
|
# we are using Monitor instead of Mutex because it is reentrant
|
16
14
|
@mutex = Monitor.new
|
@@ -52,11 +50,11 @@ module Datadog
|
|
52
50
|
end
|
53
51
|
|
54
52
|
def active_test_module
|
55
|
-
@test_module
|
53
|
+
@mutex.synchronize { @test_module }
|
56
54
|
end
|
57
55
|
|
58
56
|
def active_test_session
|
59
|
-
@test_session
|
57
|
+
@mutex.synchronize { @test_session }
|
60
58
|
end
|
61
59
|
|
62
60
|
def active_test_suite(test_suite_name)
|
@@ -82,16 +80,28 @@ module Datadog
|
|
82
80
|
@mutex.synchronize { @test_suites.delete(test_suite_name) }
|
83
81
|
end
|
84
82
|
|
83
|
+
def readonly_test_session
|
84
|
+
@mutex.synchronize { @readonly_test_session }
|
85
|
+
end
|
86
|
+
|
87
|
+
def readonly_test_module
|
88
|
+
@mutex.synchronize { @readonly_test_module }
|
89
|
+
end
|
90
|
+
|
85
91
|
def set_readonly_test_session(remote_test_session)
|
86
92
|
return if remote_test_session.nil?
|
87
93
|
|
88
|
-
@
|
94
|
+
@mutex.synchronize do
|
95
|
+
@readonly_test_session = Datadog::CI::ReadonlyTestSession.new(remote_test_session)
|
96
|
+
end
|
89
97
|
end
|
90
98
|
|
91
99
|
def set_readonly_test_module(remote_test_module)
|
92
100
|
return if remote_test_module.nil?
|
93
101
|
|
94
|
-
@
|
102
|
+
@mutex.synchronize do
|
103
|
+
@readonly_test_module = Datadog::CI::ReadonlyTestModule.new(remote_test_module)
|
104
|
+
end
|
95
105
|
end
|
96
106
|
end
|
97
107
|
end
|
@@ -1,6 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "json"
|
3
4
|
require_relative "file_storage"
|
5
|
+
require_relative "../ext/dd_test"
|
4
6
|
|
5
7
|
module Datadog
|
6
8
|
module CI
|
@@ -19,6 +21,12 @@ module Datadog
|
|
19
21
|
|
20
22
|
# Load component state
|
21
23
|
def load_component_state
|
24
|
+
# Check for DDTest cache first
|
25
|
+
if Dir.exist?(Ext::DDTest::TESTOPTIMIZATION_CACHE_PATH)
|
26
|
+
Datadog.logger.debug { "DDTest cache found" }
|
27
|
+
return true if restore_state_from_datadog_test_runner
|
28
|
+
end
|
29
|
+
|
22
30
|
test_visibility_component = Datadog.send(:components).test_visibility
|
23
31
|
return false unless test_visibility_component.client_process?
|
24
32
|
|
@@ -46,6 +54,28 @@ module Datadog
|
|
46
54
|
def storage_key
|
47
55
|
raise NotImplementedError, "Components must implement #storage_key"
|
48
56
|
end
|
57
|
+
|
58
|
+
def restore_state_from_datadog_test_runner
|
59
|
+
false
|
60
|
+
end
|
61
|
+
|
62
|
+
def load_json(file_name)
|
63
|
+
file_path = File.join(Ext::DDTest::TESTOPTIMIZATION_CACHE_PATH, file_name)
|
64
|
+
|
65
|
+
unless File.exist?(file_path)
|
66
|
+
Datadog.logger.debug { "JSON file not found: #{file_path}" }
|
67
|
+
return nil
|
68
|
+
end
|
69
|
+
|
70
|
+
content = File.read(file_path)
|
71
|
+
JSON.parse(content)
|
72
|
+
rescue JSON::ParserError => e
|
73
|
+
Datadog.logger.debug { "Failed to parse JSON file #{file_path}: #{e.message}" }
|
74
|
+
nil
|
75
|
+
rescue => e
|
76
|
+
Datadog.logger.debug { "Failed to load JSON file #{file_path}: #{e.message}" }
|
77
|
+
nil
|
78
|
+
end
|
49
79
|
end
|
50
80
|
end
|
51
81
|
end
|
data/lib/datadog/ci/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: datadog-ci
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.23.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Datadog, Inc.
|
@@ -143,7 +143,6 @@ files:
|
|
143
143
|
- lib/datadog/ci/contrib/rspec/example.rb
|
144
144
|
- lib/datadog/ci/contrib/rspec/example_group.rb
|
145
145
|
- lib/datadog/ci/contrib/rspec/ext.rb
|
146
|
-
- lib/datadog/ci/contrib/rspec/helpers.rb
|
147
146
|
- lib/datadog/ci/contrib/rspec/integration.rb
|
148
147
|
- lib/datadog/ci/contrib/rspec/patcher.rb
|
149
148
|
- lib/datadog/ci/contrib/rspec/runner.rb
|
@@ -166,6 +165,7 @@ files:
|
|
166
165
|
- lib/datadog/ci/contrib/simplecov/patcher.rb
|
167
166
|
- lib/datadog/ci/contrib/simplecov/result_extractor.rb
|
168
167
|
- lib/datadog/ci/ext/app_types.rb
|
168
|
+
- lib/datadog/ci/ext/dd_test.rb
|
169
169
|
- lib/datadog/ci/ext/environment.rb
|
170
170
|
- lib/datadog/ci/ext/environment/configuration_discrepancy_checker.rb
|
171
171
|
- lib/datadog/ci/ext/environment/extractor.rb
|
@@ -1,16 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Datadog
|
4
|
-
module CI
|
5
|
-
module Contrib
|
6
|
-
module RSpec
|
7
|
-
# Helper methods for RSpec instrumentation
|
8
|
-
module Helpers
|
9
|
-
def self.parallel_tests?
|
10
|
-
!!ENV.fetch("TEST_ENV_NUMBER", nil) && !!ENV.fetch("PARALLEL_TEST_GROUPS", nil)
|
11
|
-
end
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|