datadog-ci 1.0.0 → 1.0.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 +10 -1
- data/ext/datadog_cov/datadog_cov.c +115 -85
- data/lib/datadog/ci/configuration/components.rb +2 -1
- data/lib/datadog/ci/configuration/settings.rb +6 -0
- data/lib/datadog/ci/ext/settings.rb +1 -0
- data/lib/datadog/ci/itr/coverage/writer.rb +3 -1
- data/lib/datadog/ci/itr/runner.rb +11 -2
- data/lib/datadog/ci/version.rb +3 -3
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 73bd9b05aba53e1197420cc0e4a529339b6526e13775467fa326b4949e44043a
|
4
|
+
data.tar.gz: 7613c476a2a3f2cf28d7dd99dd53da2fa6c921c9a03de18a6997f25e3fe0f27a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fc66a07d4ccceb71f18b26d290e387b6b403d7efbb46169ced3db9ad0e67e2f29ec163bdaa43a7f7508c6511ca0c68d99257d32d3a25e62b42e00219d7ef44a1
|
7
|
+
data.tar.gz: 6fb71c67ecea77fc61238fa7f739192a7670f51d8f4c052d436d2f4d69743f1202f27e27cf84fa76ce74860145d13badb00862c1c03b37d93dc9a33e597afb3d
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,11 @@
|
|
1
1
|
## [Unreleased]
|
2
2
|
|
3
|
+
## [1.0.1] - 2024-06-11
|
4
|
+
|
5
|
+
### Fixed
|
6
|
+
* multi threaded code coverage support for datadog_cov ([#189][])
|
7
|
+
* code coverage extension fixes and improvements ([#171][])
|
8
|
+
|
3
9
|
## [1.0.0] - 2024-06-06
|
4
10
|
|
5
11
|
|
@@ -261,7 +267,8 @@ Currently test suite level visibility is not used by our instrumentation: it wil
|
|
261
267
|
|
262
268
|
- Ruby versions < 2.7 no longer supported ([#8][])
|
263
269
|
|
264
|
-
[Unreleased]: https://github.com/DataDog/datadog-ci-rb/compare/v1.0.
|
270
|
+
[Unreleased]: https://github.com/DataDog/datadog-ci-rb/compare/v1.0.1...main
|
271
|
+
[1.0.1]: https://github.com/DataDog/datadog-ci-rb/compare/v1.0.0...v1.0.1
|
265
272
|
[1.0.0]: https://github.com/DataDog/datadog-ci-rb/compare/v1.0.0.beta6...v1.0.0
|
266
273
|
[1.0.0.beta6]: https://github.com/DataDog/datadog-ci-rb/compare/v1.0.0.beta5...v1.0.0.beta6
|
267
274
|
[1.0.0.beta5]: https://github.com/DataDog/datadog-ci-rb/compare/v1.0.0.beta4...v1.0.0.beta5
|
@@ -361,6 +368,7 @@ Currently test suite level visibility is not used by our instrumentation: it wil
|
|
361
368
|
[#167]: https://github.com/DataDog/datadog-ci-rb/issues/167
|
362
369
|
[#168]: https://github.com/DataDog/datadog-ci-rb/issues/168
|
363
370
|
[#170]: https://github.com/DataDog/datadog-ci-rb/issues/170
|
371
|
+
[#171]: https://github.com/DataDog/datadog-ci-rb/issues/171
|
364
372
|
[#172]: https://github.com/DataDog/datadog-ci-rb/issues/172
|
365
373
|
[#173]: https://github.com/DataDog/datadog-ci-rb/issues/173
|
366
374
|
[#174]: https://github.com/DataDog/datadog-ci-rb/issues/174
|
@@ -368,4 +376,5 @@ Currently test suite level visibility is not used by our instrumentation: it wil
|
|
368
376
|
[#180]: https://github.com/DataDog/datadog-ci-rb/issues/180
|
369
377
|
[#183]: https://github.com/DataDog/datadog-ci-rb/issues/183
|
370
378
|
[#185]: https://github.com/DataDog/datadog-ci-rb/issues/185
|
379
|
+
[#189]: https://github.com/DataDog/datadog-ci-rb/issues/189
|
371
380
|
[#190]: https://github.com/DataDog/datadog-ci-rb/issues/190
|
@@ -1,55 +1,54 @@
|
|
1
1
|
#include <ruby.h>
|
2
2
|
#include <ruby/debug.h>
|
3
3
|
|
4
|
-
|
5
|
-
#define DD_COV_TARGET_FILES 1
|
6
|
-
#define DD_COV_TARGET_LINES 2
|
4
|
+
#define PROFILE_FRAMES_BUFFER_SIZE 1
|
7
5
|
|
8
|
-
|
6
|
+
// threading modes
|
7
|
+
#define SINGLE_THREADED_COVERAGE_MODE 0
|
8
|
+
#define MULTI_THREADED_COVERAGE_MODE 1
|
9
|
+
|
10
|
+
char *ruby_strndup(const char *str, size_t size)
|
9
11
|
{
|
10
|
-
|
11
|
-
{
|
12
|
-
return 0;
|
13
|
-
}
|
12
|
+
char *dup;
|
14
13
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
return 0;
|
19
|
-
}
|
14
|
+
dup = xmalloc(size + 1);
|
15
|
+
memcpy(dup, str, size);
|
16
|
+
dup[size] = '\0';
|
20
17
|
|
21
|
-
|
22
|
-
if (strncmp(c_prefix, str, prefix_len) == 0)
|
23
|
-
{
|
24
|
-
return 1;
|
25
|
-
}
|
26
|
-
else
|
27
|
-
{
|
28
|
-
return 0;
|
29
|
-
}
|
18
|
+
return dup;
|
30
19
|
}
|
31
20
|
|
32
21
|
// Data structure
|
33
22
|
struct dd_cov_data
|
34
23
|
{
|
35
|
-
|
36
|
-
|
37
|
-
|
24
|
+
char *root;
|
25
|
+
long root_len;
|
26
|
+
|
27
|
+
char *ignored_path;
|
28
|
+
long ignored_path_len;
|
29
|
+
|
38
30
|
VALUE coverage;
|
31
|
+
|
32
|
+
uintptr_t last_filename_ptr;
|
33
|
+
|
34
|
+
// for single threaded mode: thread that is being covered
|
35
|
+
VALUE th_covered;
|
36
|
+
|
37
|
+
int threading_mode;
|
39
38
|
};
|
40
39
|
|
41
40
|
static void dd_cov_mark(void *ptr)
|
42
41
|
{
|
43
42
|
struct dd_cov_data *dd_cov_data = ptr;
|
44
43
|
rb_gc_mark_movable(dd_cov_data->coverage);
|
45
|
-
rb_gc_mark_movable(dd_cov_data->
|
46
|
-
rb_gc_mark_movable(dd_cov_data->ignored_path);
|
44
|
+
rb_gc_mark_movable(dd_cov_data->th_covered);
|
47
45
|
}
|
48
46
|
|
49
47
|
static void dd_cov_free(void *ptr)
|
50
48
|
{
|
51
49
|
struct dd_cov_data *dd_cov_data = ptr;
|
52
|
-
|
50
|
+
xfree(dd_cov_data->root);
|
51
|
+
xfree(dd_cov_data->ignored_path);
|
53
52
|
xfree(dd_cov_data);
|
54
53
|
}
|
55
54
|
|
@@ -57,8 +56,7 @@ static void dd_cov_compact(void *ptr)
|
|
57
56
|
{
|
58
57
|
struct dd_cov_data *dd_cov_data = ptr;
|
59
58
|
dd_cov_data->coverage = rb_gc_location(dd_cov_data->coverage);
|
60
|
-
dd_cov_data->
|
61
|
-
dd_cov_data->ignored_path = rb_gc_location(dd_cov_data->ignored_path);
|
59
|
+
dd_cov_data->th_covered = rb_gc_location(dd_cov_data->th_covered);
|
62
60
|
}
|
63
61
|
|
64
62
|
const rb_data_type_t dd_cov_data_type = {
|
@@ -74,10 +72,15 @@ static VALUE dd_cov_allocate(VALUE klass)
|
|
74
72
|
{
|
75
73
|
struct dd_cov_data *dd_cov_data;
|
76
74
|
VALUE obj = TypedData_Make_Struct(klass, struct dd_cov_data, &dd_cov_data_type, dd_cov_data);
|
75
|
+
|
77
76
|
dd_cov_data->coverage = rb_hash_new();
|
78
|
-
dd_cov_data->root =
|
79
|
-
dd_cov_data->
|
80
|
-
dd_cov_data->
|
77
|
+
dd_cov_data->root = NULL;
|
78
|
+
dd_cov_data->root_len = 0;
|
79
|
+
dd_cov_data->ignored_path = NULL;
|
80
|
+
dd_cov_data->ignored_path_len = 0;
|
81
|
+
dd_cov_data->last_filename_ptr = 0;
|
82
|
+
dd_cov_data->threading_mode = MULTI_THREADED_COVERAGE_MODE;
|
83
|
+
|
81
84
|
return obj;
|
82
85
|
}
|
83
86
|
|
@@ -85,7 +88,6 @@ static VALUE dd_cov_allocate(VALUE klass)
|
|
85
88
|
static VALUE dd_cov_initialize(int argc, VALUE *argv, VALUE self)
|
86
89
|
{
|
87
90
|
VALUE opt;
|
88
|
-
int mode;
|
89
91
|
|
90
92
|
rb_scan_args(argc, argv, "10", &opt);
|
91
93
|
VALUE rb_root = rb_hash_lookup(opt, ID2SYM(rb_intern("root")));
|
@@ -93,113 +95,141 @@ static VALUE dd_cov_initialize(int argc, VALUE *argv, VALUE self)
|
|
93
95
|
{
|
94
96
|
rb_raise(rb_eArgError, "root is required");
|
95
97
|
}
|
96
|
-
|
97
98
|
VALUE rb_ignored_path = rb_hash_lookup(opt, ID2SYM(rb_intern("ignored_path")));
|
98
99
|
|
99
|
-
VALUE
|
100
|
-
|
100
|
+
VALUE rb_threading_mode = rb_hash_lookup(opt, ID2SYM(rb_intern("threading_mode")));
|
101
|
+
int threading_mode;
|
102
|
+
if (rb_threading_mode == ID2SYM(rb_intern("multi")))
|
101
103
|
{
|
102
|
-
|
104
|
+
threading_mode = MULTI_THREADED_COVERAGE_MODE;
|
103
105
|
}
|
104
|
-
else if (
|
106
|
+
else if (rb_threading_mode == ID2SYM(rb_intern("single")))
|
105
107
|
{
|
106
|
-
|
108
|
+
threading_mode = SINGLE_THREADED_COVERAGE_MODE;
|
107
109
|
}
|
108
110
|
else
|
109
111
|
{
|
110
|
-
rb_raise(rb_eArgError, "mode is invalid");
|
112
|
+
rb_raise(rb_eArgError, "threading mode is invalid");
|
111
113
|
}
|
112
114
|
|
113
115
|
struct dd_cov_data *dd_cov_data;
|
114
116
|
TypedData_Get_Struct(self, struct dd_cov_data, &dd_cov_data_type, dd_cov_data);
|
115
117
|
|
116
|
-
dd_cov_data->
|
117
|
-
dd_cov_data->
|
118
|
-
dd_cov_data->
|
118
|
+
dd_cov_data->threading_mode = threading_mode;
|
119
|
+
dd_cov_data->root_len = RSTRING_LEN(rb_root);
|
120
|
+
dd_cov_data->root = ruby_strndup(RSTRING_PTR(rb_root), dd_cov_data->root_len);
|
121
|
+
|
122
|
+
if (RTEST(rb_ignored_path))
|
123
|
+
{
|
124
|
+
dd_cov_data->ignored_path_len = RSTRING_LEN(rb_ignored_path);
|
125
|
+
dd_cov_data->ignored_path = ruby_strndup(RSTRING_PTR(rb_ignored_path), dd_cov_data->ignored_path_len);
|
126
|
+
}
|
119
127
|
|
120
128
|
return Qnil;
|
121
129
|
}
|
122
130
|
|
123
|
-
static void
|
131
|
+
static void dd_cov_update_coverage(rb_event_flag_t event, VALUE data, VALUE self, ID id, VALUE klass)
|
124
132
|
{
|
125
133
|
struct dd_cov_data *dd_cov_data;
|
126
134
|
TypedData_Get_Struct(data, struct dd_cov_data, &dd_cov_data_type, dd_cov_data);
|
127
135
|
|
128
|
-
const char *
|
129
|
-
|
136
|
+
const char *c_filename = rb_sourcefile();
|
137
|
+
|
138
|
+
// skip if we cover the same file again
|
139
|
+
uintptr_t current_filename_ptr = (uintptr_t)c_filename;
|
140
|
+
if (dd_cov_data->last_filename_ptr == current_filename_ptr)
|
130
141
|
{
|
131
142
|
return;
|
132
143
|
}
|
144
|
+
dd_cov_data->last_filename_ptr = current_filename_ptr;
|
133
145
|
|
134
|
-
|
135
|
-
|
146
|
+
VALUE top_frame;
|
147
|
+
int captured_frames = rb_profile_frames(
|
148
|
+
0 /* stack starting depth */,
|
149
|
+
PROFILE_FRAMES_BUFFER_SIZE,
|
150
|
+
&top_frame,
|
151
|
+
NULL);
|
152
|
+
|
153
|
+
if (captured_frames != PROFILE_FRAMES_BUFFER_SIZE)
|
136
154
|
{
|
137
155
|
return;
|
138
156
|
}
|
139
157
|
|
140
|
-
|
141
|
-
|
142
|
-
if (RTEST(dd_cov_data->ignored_path) && is_prefix(dd_cov_data->ignored_path, filename) == 1)
|
158
|
+
VALUE filename = rb_profile_frame_path(top_frame);
|
159
|
+
if (filename == Qnil)
|
143
160
|
{
|
144
161
|
return;
|
145
162
|
}
|
146
163
|
|
147
|
-
|
148
|
-
|
149
|
-
if (dd_cov_data->
|
164
|
+
char *filename_ptr = RSTRING_PTR(filename);
|
165
|
+
// if the current filename is not located under the root, we skip it
|
166
|
+
if (strncmp(dd_cov_data->root, filename_ptr, dd_cov_data->root_len) != 0)
|
150
167
|
{
|
151
|
-
rb_hash_aset(dd_cov_data->coverage, rb_str_source_file, Qtrue);
|
152
168
|
return;
|
153
169
|
}
|
154
170
|
|
155
|
-
//
|
156
|
-
//
|
157
|
-
|
158
|
-
if (dd_cov_data->mode == DD_COV_TARGET_LINES)
|
171
|
+
// if ignored_path is provided and the current filename is located under the ignored_path, we skip it too
|
172
|
+
// this is useful for ignoring bundled gems location
|
173
|
+
if (dd_cov_data->ignored_path_len != 0 && strncmp(dd_cov_data->ignored_path, filename_ptr, dd_cov_data->ignored_path_len) == 0)
|
159
174
|
{
|
160
|
-
|
161
|
-
if (line_number <= 0)
|
162
|
-
{
|
163
|
-
return;
|
164
|
-
}
|
165
|
-
|
166
|
-
VALUE rb_lines = rb_hash_aref(dd_cov_data->coverage, rb_str_source_file);
|
167
|
-
if (rb_lines == Qnil)
|
168
|
-
{
|
169
|
-
rb_lines = rb_hash_new();
|
170
|
-
rb_hash_aset(dd_cov_data->coverage, rb_str_source_file, rb_lines);
|
171
|
-
}
|
172
|
-
|
173
|
-
rb_hash_aset(rb_lines, INT2FIX(line_number), Qtrue);
|
175
|
+
return;
|
174
176
|
}
|
177
|
+
|
178
|
+
rb_hash_aset(dd_cov_data->coverage, filename, Qtrue);
|
175
179
|
}
|
176
180
|
|
177
181
|
static VALUE dd_cov_start(VALUE self)
|
178
182
|
{
|
179
|
-
// get current thread
|
180
|
-
VALUE thval = rb_thread_current();
|
181
183
|
|
182
|
-
|
183
|
-
|
184
|
+
struct dd_cov_data *dd_cov_data;
|
185
|
+
TypedData_Get_Struct(self, struct dd_cov_data, &dd_cov_data_type, dd_cov_data);
|
186
|
+
|
187
|
+
if (dd_cov_data->root_len == 0)
|
188
|
+
{
|
189
|
+
rb_raise(rb_eRuntimeError, "root is required");
|
190
|
+
}
|
191
|
+
|
192
|
+
if (dd_cov_data->threading_mode == SINGLE_THREADED_COVERAGE_MODE)
|
193
|
+
{
|
194
|
+
VALUE thval = rb_thread_current();
|
195
|
+
rb_thread_add_event_hook(thval, dd_cov_update_coverage, RUBY_EVENT_LINE, self);
|
196
|
+
dd_cov_data->th_covered = thval;
|
197
|
+
}
|
198
|
+
else
|
199
|
+
{
|
200
|
+
rb_add_event_hook(dd_cov_update_coverage, RUBY_EVENT_LINE, self);
|
201
|
+
}
|
184
202
|
|
185
203
|
return self;
|
186
204
|
}
|
187
205
|
|
188
206
|
static VALUE dd_cov_stop(VALUE self)
|
189
207
|
{
|
190
|
-
// get current thread
|
191
|
-
VALUE thval = rb_thread_current();
|
192
|
-
// remove event hook for the current thread
|
193
|
-
rb_thread_remove_event_hook(thval, dd_cov_update_line_coverage);
|
194
|
-
|
195
208
|
struct dd_cov_data *dd_cov_data;
|
196
209
|
TypedData_Get_Struct(self, struct dd_cov_data, &dd_cov_data_type, dd_cov_data);
|
197
210
|
|
198
|
-
|
211
|
+
if (dd_cov_data->threading_mode == SINGLE_THREADED_COVERAGE_MODE)
|
212
|
+
{
|
213
|
+
VALUE thval = rb_thread_current();
|
214
|
+
if (!rb_equal(thval, dd_cov_data->th_covered))
|
215
|
+
{
|
216
|
+
rb_raise(rb_eRuntimeError, "Coverage was not started by this thread");
|
217
|
+
}
|
218
|
+
|
219
|
+
rb_thread_remove_event_hook(dd_cov_data->th_covered, dd_cov_update_coverage);
|
220
|
+
dd_cov_data->th_covered = Qnil;
|
221
|
+
}
|
222
|
+
else
|
223
|
+
{
|
224
|
+
rb_remove_event_hook(dd_cov_update_coverage);
|
225
|
+
}
|
226
|
+
|
227
|
+
VALUE res = dd_cov_data->coverage;
|
199
228
|
|
200
229
|
dd_cov_data->coverage = rb_hash_new();
|
230
|
+
dd_cov_data->last_filename_ptr = 0;
|
201
231
|
|
202
|
-
return
|
232
|
+
return res;
|
203
233
|
}
|
204
234
|
|
205
235
|
void Init_datadog_cov(void)
|
@@ -129,7 +129,8 @@ module Datadog
|
|
129
129
|
config_tags: custom_configuration_tags,
|
130
130
|
coverage_writer: coverage_writer,
|
131
131
|
enabled: settings.ci.enabled && settings.ci.itr_enabled,
|
132
|
-
bundle_location: settings.ci.itr_code_coverage_excluded_bundle_path
|
132
|
+
bundle_location: settings.ci.itr_code_coverage_excluded_bundle_path,
|
133
|
+
use_single_threaded_coverage: settings.ci.itr_code_coverage_use_single_threaded_mode
|
133
134
|
)
|
134
135
|
|
135
136
|
git_tree_uploader = Git::TreeUploader.new(api: test_visibility_api)
|
@@ -76,6 +76,12 @@ module Datadog
|
|
76
76
|
end
|
77
77
|
end
|
78
78
|
|
79
|
+
option :itr_code_coverage_use_single_threaded_mode do |o|
|
80
|
+
o.type :bool
|
81
|
+
o.env CI::Ext::Settings::ENV_ITR_CODE_COVERAGE_USE_SINGLE_THREADED_MODE
|
82
|
+
o.default false
|
83
|
+
end
|
84
|
+
|
79
85
|
define_method(:instrument) do |integration_name, options = {}, &block|
|
80
86
|
return unless enabled
|
81
87
|
|
@@ -13,6 +13,7 @@ module Datadog
|
|
13
13
|
ENV_ITR_ENABLED = "DD_CIVISIBILITY_ITR_ENABLED"
|
14
14
|
ENV_GIT_METADATA_UPLOAD_ENABLED = "DD_CIVISIBILITY_GIT_METADATA_UPLOAD_ENABLED"
|
15
15
|
ENV_ITR_CODE_COVERAGE_EXCLUDED_BUNDLE_PATH = "DD_CIVISIBILITY_ITR_CODE_COVERAGE_EXCLUDED_BUNDLE_PATH"
|
16
|
+
ENV_ITR_CODE_COVERAGE_USE_SINGLE_THREADED_MODE = "DD_CIVISIBILITY_ITR_CODE_COVERAGE_USE_SINGLE_THREADED_MODE"
|
16
17
|
|
17
18
|
# Source: https://docs.datadoghq.com/getting_started/site/
|
18
19
|
DD_SITE_ALLOWLIST = %w[
|
@@ -22,6 +22,8 @@ module Datadog
|
|
22
22
|
DEFAULT_BUFFER_MAX_SIZE = 10_000
|
23
23
|
DEFAULT_SHUTDOWN_TIMEOUT = 60
|
24
24
|
|
25
|
+
DEFAULT_INTERVAL = 3
|
26
|
+
|
25
27
|
def initialize(transport:, options: {})
|
26
28
|
@transport = transport
|
27
29
|
|
@@ -32,7 +34,7 @@ module Datadog
|
|
32
34
|
self.fork_policy = Core::Workers::Async::Thread::FORK_POLICY_RESTART
|
33
35
|
|
34
36
|
# Workers::IntervalLoop settings
|
35
|
-
self.loop_base_interval = options[:interval]
|
37
|
+
self.loop_base_interval = options[:interval] || DEFAULT_INTERVAL
|
36
38
|
self.loop_back_off_ratio = options[:back_off_ratio] if options.key?(:back_off_ratio)
|
37
39
|
self.loop_back_off_max = options[:back_off_max] if options.key?(:back_off_max)
|
38
40
|
|
@@ -31,7 +31,8 @@ module Datadog
|
|
31
31
|
api: nil,
|
32
32
|
coverage_writer: nil,
|
33
33
|
enabled: false,
|
34
|
-
bundle_location: nil
|
34
|
+
bundle_location: nil,
|
35
|
+
use_single_threaded_coverage: false
|
35
36
|
)
|
36
37
|
@enabled = enabled
|
37
38
|
@api = api
|
@@ -43,6 +44,7 @@ module Datadog
|
|
43
44
|
else
|
44
45
|
bundle_location
|
45
46
|
end
|
47
|
+
@use_single_threaded_coverage = use_single_threaded_coverage
|
46
48
|
|
47
49
|
@test_skipping_enabled = false
|
48
50
|
@code_coverage_enabled = false
|
@@ -186,12 +188,15 @@ module Datadog
|
|
186
188
|
def coverage_collector
|
187
189
|
Thread.current[:dd_coverage_collector] ||= Coverage::DDCov.new(
|
188
190
|
root: Git::LocalRepository.root,
|
189
|
-
ignored_path: @bundle_location
|
191
|
+
ignored_path: @bundle_location,
|
192
|
+
threading_mode: code_coverage_mode
|
190
193
|
)
|
191
194
|
end
|
192
195
|
|
193
196
|
def load_datadog_cov!
|
194
197
|
require "datadog_cov.#{RUBY_VERSION}_#{RUBY_PLATFORM}"
|
198
|
+
|
199
|
+
Datadog.logger.debug("Loaded Datadog code coverage collector, using coverage mode: #{code_coverage_mode}")
|
195
200
|
rescue LoadError => e
|
196
201
|
Datadog.logger.error("Failed to load coverage collector: #{e}. Code coverage will not be collected.")
|
197
202
|
|
@@ -222,6 +227,10 @@ module Datadog
|
|
222
227
|
Datadog.logger.debug { "Found #{@skippable_tests.count} skippable tests." }
|
223
228
|
Datadog.logger.debug { "ITR correlation ID: #{@correlation_id}" }
|
224
229
|
end
|
230
|
+
|
231
|
+
def code_coverage_mode
|
232
|
+
@use_single_threaded_coverage ? :single : :multi
|
233
|
+
end
|
225
234
|
end
|
226
235
|
end
|
227
236
|
end
|
data/lib/datadog/ci/version.rb
CHANGED
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.0.1
|
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-06-
|
11
|
+
date: 2024-06-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: datadog
|