datadog-ci 1.0.0 → 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|