datadog-ci 0.8.3 → 1.0.0.beta2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +42 -0
  3. data/LICENSE-3rdparty.csv +1 -1
  4. data/README.md +40 -55
  5. data/ext/datadog_cov/datadog_cov.c +192 -0
  6. data/ext/datadog_cov/extconf.rb +18 -0
  7. data/lib/datadog/ci/configuration/components.rb +43 -9
  8. data/lib/datadog/ci/configuration/settings.rb +7 -1
  9. data/lib/datadog/ci/contrib/cucumber/configuration/settings.rb +0 -15
  10. data/lib/datadog/ci/contrib/cucumber/ext.rb +1 -5
  11. data/lib/datadog/ci/contrib/cucumber/formatter.rb +13 -18
  12. data/lib/datadog/ci/contrib/cucumber/integration.rb +1 -2
  13. data/lib/datadog/ci/contrib/cucumber/patcher.rb +3 -0
  14. data/lib/datadog/ci/contrib/cucumber/step.rb +27 -0
  15. data/lib/datadog/ci/contrib/minitest/configuration/settings.rb +0 -15
  16. data/lib/datadog/ci/contrib/minitest/ext.rb +1 -5
  17. data/lib/datadog/ci/contrib/minitest/helpers.rb +1 -2
  18. data/lib/datadog/ci/contrib/minitest/hooks.rb +4 -2
  19. data/lib/datadog/ci/contrib/minitest/integration.rb +1 -1
  20. data/lib/datadog/ci/contrib/rspec/configuration/settings.rb +0 -15
  21. data/lib/datadog/ci/contrib/rspec/example.rb +25 -23
  22. data/lib/datadog/ci/contrib/rspec/ext.rb +0 -4
  23. data/lib/datadog/ci/contrib/rspec/integration.rb +1 -2
  24. data/lib/datadog/ci/contrib/settings.rb +0 -3
  25. data/lib/datadog/ci/ext/environment/providers/base.rb +1 -1
  26. data/lib/datadog/ci/ext/environment/providers/bitbucket.rb +1 -1
  27. data/lib/datadog/ci/ext/environment/providers/local_git.rb +8 -79
  28. data/lib/datadog/ci/ext/environment.rb +11 -16
  29. data/lib/datadog/ci/ext/settings.rb +1 -0
  30. data/lib/datadog/ci/ext/test.rb +5 -0
  31. data/lib/datadog/ci/ext/transport.rb +12 -0
  32. data/lib/datadog/ci/git/local_repository.rb +238 -0
  33. data/lib/datadog/ci/git/packfiles.rb +70 -0
  34. data/lib/datadog/ci/git/search_commits.rb +77 -0
  35. data/lib/datadog/ci/git/tree_uploader.rb +90 -0
  36. data/lib/datadog/ci/git/upload_packfile.rb +66 -0
  37. data/lib/datadog/ci/git/user.rb +29 -0
  38. data/lib/datadog/ci/itr/coverage/ddcov.rb +14 -0
  39. data/lib/datadog/ci/itr/coverage/event.rb +81 -0
  40. data/lib/datadog/ci/itr/coverage/transport.rb +42 -0
  41. data/lib/datadog/ci/itr/coverage/writer.rb +108 -0
  42. data/lib/datadog/ci/itr/runner.rb +143 -6
  43. data/lib/datadog/ci/itr/skippable.rb +106 -0
  44. data/lib/datadog/ci/span.rb +9 -0
  45. data/lib/datadog/ci/test.rb +20 -14
  46. data/lib/datadog/ci/test_module.rb +2 -2
  47. data/lib/datadog/ci/test_session.rb +2 -2
  48. data/lib/datadog/ci/test_suite.rb +2 -2
  49. data/lib/datadog/ci/test_visibility/context/global.rb +1 -3
  50. data/lib/datadog/ci/test_visibility/null_recorder.rb +5 -2
  51. data/lib/datadog/ci/test_visibility/recorder.rb +63 -8
  52. data/lib/datadog/ci/test_visibility/serializers/base.rb +1 -1
  53. data/lib/datadog/ci/test_visibility/serializers/factories/test_level.rb +1 -1
  54. data/lib/datadog/ci/test_visibility/serializers/factories/test_suite_level.rb +1 -1
  55. data/lib/datadog/ci/test_visibility/transport.rb +11 -54
  56. data/lib/datadog/ci/transport/api/agentless.rb +8 -1
  57. data/lib/datadog/ci/transport/api/base.rb +23 -0
  58. data/lib/datadog/ci/transport/api/builder.rb +9 -1
  59. data/lib/datadog/ci/transport/api/evp_proxy.rb +8 -0
  60. data/lib/datadog/ci/transport/event_platform_transport.rb +88 -0
  61. data/lib/datadog/ci/transport/http.rb +43 -6
  62. data/lib/datadog/ci/transport/remote_settings_api.rb +12 -6
  63. data/lib/datadog/ci/utils/configuration.rb +2 -2
  64. data/lib/datadog/ci/utils/git.rb +6 -67
  65. data/lib/datadog/ci/utils/parsing.rb +16 -0
  66. data/lib/datadog/ci/utils/test_run.rb +13 -0
  67. data/lib/datadog/ci/version.rb +5 -5
  68. data/lib/datadog/ci/worker.rb +35 -0
  69. data/lib/datadog/ci.rb +4 -0
  70. metadata +36 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bf750f24412b0800ba1599f22c5b12e8679dddc1d0e9a30aed98d0a51a6badd3
4
- data.tar.gz: 652631fac9702beb340f136e32d4b72b3b38d7c84a8de7dc8ce4f203dc67983b
3
+ metadata.gz: 6b3e03ab226d98aac3dd518b1c554452a4c3812cb67e9a1d64762e2fe8767633
4
+ data.tar.gz: eac352d2b2488d16f979004f617097efe109364069f1c7b78cecfceef5365efa
5
5
  SHA512:
6
- metadata.gz: 3295d136609aca4be41cc041613873297a5e91bb37a428a6612a1e62f7e547db2bb2c836f4a0348fdd4466d085a29ec78a26962d48f1c59e05163dcb26668783
7
- data.tar.gz: 5446bba62689a4133a75b64437efd47f8369814e863c8ddab0c91d52692b5bf71b5be2a4f4264839ec81374ff3c4ff498e4c2cd7a8c54f566e63558cb1f55cff
6
+ metadata.gz: c56ab91025f2a224e86bd732a5c891e961af184b29618241f8853756780ccba894c11955b00020a70139d72e47f57d22dfdf1f2ed6437f1d4e4a9d998453d7a4
7
+ data.tar.gz: e7c1aa73096d8d8b49800bbed168f288b7676d8fa328011c3e9c4f7024c86c17cf2c210a94a64dcd80f94121a80b36a824f0ca4e3aa6ccb1c35f682a1fb9e18b
data/CHANGELOG.md CHANGED
@@ -1,5 +1,32 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [1.0.0.beta2] - 2024-04-23
4
+
5
+ ### Added
6
+
7
+ * Code coverage events writer ([#150])
8
+ * Git tree upload - git command line integration ([#151])
9
+ * Add Git::SearchCommits api client ([#152])
10
+ * Upload packfiles API client ([#153])
11
+ * Git tree uploader ([#154])
12
+ * Git repository unshallowing logic ([#155])
13
+ * Git upload async worker ([#156])
14
+ * Reduce ITR-induced code coverage overhead for default branch ([#157])
15
+ * Skippable tests api client ([#158])
16
+ * Request skippable tests when configuring ITR ([#159])
17
+ * Test skipping implementation ([#160])
18
+
19
+ ## [1.0.0.beta1] - 2024-03-25
20
+
21
+ ### Added
22
+
23
+ * datadog-cov native extension for per test code coverage ([#137])
24
+ * citestcov transport to serialize and send code coverage events ([#148])
25
+
26
+ ### Removed
27
+
28
+ * Ruby 2.1-2.6 support is dropped
29
+
3
30
  ## [0.8.3] - 2024-03-20
4
31
 
5
32
  ### Fixed
@@ -188,6 +215,8 @@ Currently test suite level visibility is not used by our instrumentation: it wil
188
215
  * Ruby versions < 2.7 no longer supported ([#8][])
189
216
 
190
217
  [Unreleased]: https://github.com/DataDog/datadog-ci-rb/compare/v0.8.3...main
218
+ [1.0.0.beta2]: https://github.com/DataDog/datadog-ci-rb/compare/v1.0.0.beta1...v1.0.0.beta2
219
+ [1.0.0.beta1]: https://github.com/DataDog/datadog-ci-rb/compare/v0.8.3...v1.0.0.beta1
191
220
  [0.8.3]: https://github.com/DataDog/datadog-ci-rb/compare/v0.8.2...v0.8.3
192
221
  [0.8.2]: https://github.com/DataDog/datadog-ci-rb/compare/v0.8.1...v0.8.2
193
222
  [0.8.1]: https://github.com/DataDog/datadog-ci-rb/compare/v0.8.0...v0.8.1
@@ -258,7 +287,20 @@ Currently test suite level visibility is not used by our instrumentation: it wil
258
287
  [#123]: https://github.com/DataDog/datadog-ci-rb/issues/123
259
288
  [#131]: https://github.com/DataDog/datadog-ci-rb/issues/131
260
289
  [#134]: https://github.com/DataDog/datadog-ci-rb/issues/134
290
+ [#137]: https://github.com/DataDog/datadog-ci-rb/issues/137
261
291
  [#139]: https://github.com/DataDog/datadog-ci-rb/issues/139
262
292
  [#141]: https://github.com/DataDog/datadog-ci-rb/issues/141
263
293
  [#142]: https://github.com/DataDog/datadog-ci-rb/issues/142
264
294
  [#145]: https://github.com/DataDog/datadog-ci-rb/issues/145
295
+ [#148]: https://github.com/DataDog/datadog-ci-rb/issues/148
296
+ [#150]: https://github.com/DataDog/datadog-ci-rb/issues/150
297
+ [#151]: https://github.com/DataDog/datadog-ci-rb/issues/151
298
+ [#152]: https://github.com/DataDog/datadog-ci-rb/issues/152
299
+ [#153]: https://github.com/DataDog/datadog-ci-rb/issues/153
300
+ [#154]: https://github.com/DataDog/datadog-ci-rb/issues/154
301
+ [#155]: https://github.com/DataDog/datadog-ci-rb/issues/155
302
+ [#156]: https://github.com/DataDog/datadog-ci-rb/issues/156
303
+ [#157]: https://github.com/DataDog/datadog-ci-rb/issues/157
304
+ [#158]: https://github.com/DataDog/datadog-ci-rb/issues/158
305
+ [#159]: https://github.com/DataDog/datadog-ci-rb/issues/159
306
+ [#160]: https://github.com/DataDog/datadog-ci-rb/issues/160
data/LICENSE-3rdparty.csv CHANGED
@@ -1,3 +1,3 @@
1
1
  Component,Origin,License,Copyright
2
- dd-trace-rb,https://github.com/DataDog/dd-trace-rb,Apache 2.0,"Copyright 2016-Present Datadog, Inc."
2
+ datadog,https://github.com/DataDog/dd-trace-rb,Apache 2.0,"Copyright 2016-Present Datadog, Inc."
3
3
  msgpack,https://rubygems.org/gems/msgpack,Apache-2.0,"Copyright (c) 2008-2015 Sadayuki Furuhashi"
data/README.md CHANGED
@@ -8,19 +8,20 @@
8
8
  Datadog's Ruby Library for instrumenting your test and continuous integration pipeline.
9
9
  Learn more on our [official website](https://docs.datadoghq.com/tests/) and check out our [documentation for this library](https://docs.datadoghq.com/tests/setup/ruby/?tab=cloudciprovideragentless).
10
10
 
11
- > [!IMPORTANT]
12
- > The `datadog-ci` gem is currently a component of [`ddtrace`](https://github.com/datadog/dd-trace-rb) and should not be used without it.
13
- >
14
- > We expect this to change in the future.
15
-
16
11
  ## Installation
17
12
 
18
13
  Add to your Gemfile.
19
14
 
20
15
  ```ruby
21
- gem "ddtrace"
16
+ group :test do
17
+ gem "datadog-ci"
18
+ end
22
19
  ```
23
20
 
21
+ ## Upgrade from ddtrace v1.x
22
+
23
+ If you used [test visibility for Ruby](https://docs.datadoghq.com/tests/setup/ruby/) with [ddtrace](https://github.com/datadog/dd-trace-rb) gem, check out our [upgrade guide](/docs/UpgradeGuide.md).
24
+
24
25
  ## Usage
25
26
 
26
27
  ### RSpec
@@ -34,26 +35,14 @@ require 'datadog/ci'
34
35
  # Only activates test instrumentation on CI
35
36
  if ENV["DD_ENV"] == "ci"
36
37
  Datadog.configure do |c|
37
- # Configures the tracer to ensure results delivery
38
- c.ci.enabled = true
39
-
40
38
  # The name of the service or library under test
41
39
  c.service = 'my-ruby-app'
42
-
43
- # Enables the RSpec instrumentation
44
- c.ci.instrument :rspec, **options
40
+ c.ci.enabled = true
41
+ c.ci.instrument :rspec
45
42
  end
46
43
  end
47
44
  ```
48
45
 
49
- `options` are the following keyword arguments:
50
-
51
- | Key | Description | Default |
52
- | --- | ----------- | ------- |
53
- | `enabled` | Defines whether RSpec tests should be traced. Useful for temporarily disabling tracing. `true` or `false` | `true` |
54
- | `service_name` | Service name used for `rspec` instrumentation. | `'rspec'` |
55
- | `operation_name` | *DEPRECATED, to be removed in 1.0* Operation name used for `rspec` instrumentation (has no effect in agentless mode or when using newer agent versions). | `'rspec.example'` |
56
-
57
46
  ### Minitest
58
47
 
59
48
  The Minitest integration will trace all executions of tests when using `minitest` test framework.
@@ -68,13 +57,10 @@ require 'datadog/ci'
68
57
  if ENV["DD_ENV"] == "ci"
69
58
  # Configure default Minitest integration
70
59
  Datadog.configure do |c|
71
- # Configures the tracer to ensure results delivery
72
- c.ci.enabled = true
73
-
74
60
  # The name of the service or library under test
75
61
  c.service = 'my-ruby-app'
76
-
77
- c.ci.instrument :minitest, **options
62
+ c.ci.enabled = true
63
+ c.ci.instrument :minitest
78
64
  end
79
65
  end
80
66
  ```
@@ -91,21 +77,13 @@ require 'minitest/autorun'
91
77
 
92
78
  if ENV["DD_ENV"] == "ci"
93
79
  Datadog.configure do |c|
94
- c.ci.enabled = true
95
80
  c.service = 'my-ruby-app'
81
+ c.ci.enabled = true
96
82
  c.ci.instrument :minitest
97
83
  end
98
84
  end
99
85
  ```
100
86
 
101
- `options` are the following keyword arguments:
102
-
103
- | Key | Description | Default |
104
- | --- | ----------- | ------- |
105
- | `enabled` | Defines whether Minitest tests should be traced. Useful for temporarily disabling tracing. `true` or `false` | `true` |
106
- | `service_name` | Service name used for `minitest` instrumentation. | `'minitest'` |
107
- | `operation_name` | *DEPRECATED, to be removed in 1.0* Operation name used for `minitest` instrumentation (has no effect in agentless mode or when using newer agent versions). | `'minitest.test'` |
108
-
109
87
  ### Cucumber
110
88
 
111
89
  Activate `Cucumber` integration with configuration
@@ -117,25 +95,31 @@ require 'datadog/ci'
117
95
  # Only activates test instrumentation on CI
118
96
  if ENV["DD_ENV"] == "ci"
119
97
  Datadog.configure do |c|
120
- # Configures the tracer to ensure results delivery
121
- c.ci.enabled = true
122
-
123
98
  # The name of the service or library under test
124
99
  c.service = 'my-ruby-app'
125
-
126
- # Enables the Cucumber instrumentation
127
- c.ci.instrument :cucumber, **options
100
+ c.ci.enabled = true
101
+ c.ci.instrument :cucumber
128
102
  end
129
103
  end
130
104
  ```
131
105
 
132
- `options` are the following keyword arguments:
106
+ ### Instrumentation options
107
+
108
+ Configuration `ci.instrument` accepts the following optional parameters:
109
+
110
+ - `enabled` (default: `true`) - defines whether tests should be traced (useful for temporarily disabling tracing)
111
+ - `service_name` - name of the service or library under test (when you want it to be different for a test framework)
133
112
 
134
- | Key | Description | Default |
135
- | --- | ----------- | ------- |
136
- | `enabled` | Defines whether Cucumber tests should be traced. Useful for temporarily disabling tracing. `true` or `false` | `true` |
137
- | `service_name` | Service name used for `cucumber` instrumentation. | `'cucumber'` |
138
- | `operation_name` | *DEPRECATED, to be removed in 1.0* Operation name used for `cucumber` instrumentation (has no effect in agentless mode or when using newer agent versions). | `'cucumber.test'` |
113
+ Example usage:
114
+
115
+ ```ruby
116
+ Datadog.configure do |c|
117
+ c.service = 'my-ruby-app'
118
+ c.ci.enabled = true
119
+ c.ci.instrument :cucumber, service_name: 'my-cucumber-features', enabled: true
120
+ c.ci.instrument :minitest, service_name: 'my-unit-tests', enabled: false
121
+ end
122
+ ```
139
123
 
140
124
  ## Agentless mode
141
125
 
@@ -160,7 +144,7 @@ or other external calls like here:
160
144
 
161
145
  ![Test trace with redis instrumented](./docs/screenshots/test-trace-with-redis.png)
162
146
 
163
- In order to achieve this you can configure ddtrace instrumentations in your configure block:
147
+ To achieve this, add Datadog tracing instrumentations in your `Datadog.configure` block:
164
148
 
165
149
  ```ruby
166
150
  Datadog.configure do |c|
@@ -173,13 +157,13 @@ end
173
157
  ...or enable auto instrumentation in your test_helper/spec_helper:
174
158
 
175
159
  ```ruby
176
- require "ddtrace/auto_instrument"
160
+ require "datadog/auto_instrument"
177
161
  ```
178
162
 
179
163
  Note: in CI mode these traces are going to be submitted to CI Visibility,
180
164
  they will **not** show up in Datadog APM.
181
165
 
182
- For the full list of available instrumentations see [ddtrace documentation](https://github.com/DataDog/dd-trace-rb/blob/master/docs/GettingStarted.md)
166
+ For the full list of available instrumentations see [datadog documentation](https://github.com/DataDog/dd-trace-rb/blob/master/docs/GettingStarted.md)
183
167
 
184
168
  ### WebMock
185
169
 
@@ -193,8 +177,7 @@ Webmock accordingly.
193
177
 
194
178
  ```ruby
195
179
  # when using agentless mode
196
- # note to use the correct datadog site (e.g. datadoghq.eu, etc)
197
- WebMock.disable_net_connect!(:allow => /datadoghq.com/)
180
+ WebMock.disable_net_connect!(:allow => /datadoghq/)
198
181
 
199
182
  # when using agent
200
183
  WebMock.disable_net_connect!(:allow_localhost => true)
@@ -217,8 +200,10 @@ VCR.configure do |config|
217
200
  config.ignore_hosts "127.0.0.1", "localhost"
218
201
 
219
202
  # when using agentless mode
220
- # note to use the correct datadog site (e.g. datadoghq.eu, etc)
221
- config.ignore_hosts "citestcycle-intake.datadoghq.com", "api.datadoghq.com"
203
+ config.ignore_request do |request|
204
+ # ignore all requests to datadoghq hosts
205
+ request.uri =~ /datadoghq/
206
+ end
222
207
  end
223
208
  ```
224
209
 
@@ -226,7 +211,7 @@ end
226
211
 
227
212
  Startup logs produce a report of tracing state when the application is initially configured.
228
213
  These logs are activated by default in test mode, if you don't want them you can disable this
229
- via `diagnostics.startup_logs.enabled = false` or `DD_TRACE_STARTUP_LOGS=0`.
214
+ via `DD_TRACE_STARTUP_LOGS=0` or in the `Datadog.configure` block:
230
215
 
231
216
  ```ruby
232
217
  Datadog.configure { |c| c.diagnostics.startup_logs.enabled = false }
@@ -236,7 +221,7 @@ Datadog.configure { |c| c.diagnostics.startup_logs.enabled = false }
236
221
 
237
222
  Switching the library into debug mode will produce verbose, detailed logs about tracing activity, including any suppressed errors. This output can be helpful in identifying errors, confirming trace output, or catching HTTP transport issues.
238
223
 
239
- You can enable this via `diagnostics.debug = true` or `DD_TRACE_DEBUG=1`.
224
+ You can enable this via `DD_TRACE_DEBUG=1` or in the `Datadog.configure` block:
240
225
 
241
226
  ```ruby
242
227
  Datadog.configure { |c| c.diagnostics.debug = true }
@@ -0,0 +1,192 @@
1
+ #include <ruby.h>
2
+ #include <ruby/debug.h>
3
+
4
+ // constants
5
+ #define DD_COV_TARGET_FILES 1
6
+ #define DD_COV_TARGET_LINES 2
7
+
8
+ // Data structure
9
+ struct dd_cov_data
10
+ {
11
+ VALUE root;
12
+ int mode;
13
+ VALUE coverage;
14
+ };
15
+
16
+ static void dd_cov_mark(void *ptr)
17
+ {
18
+ struct dd_cov_data *dd_cov_data = ptr;
19
+ rb_gc_mark_movable(dd_cov_data->coverage);
20
+ rb_gc_mark_movable(dd_cov_data->root);
21
+ }
22
+
23
+ static void dd_cov_free(void *ptr)
24
+ {
25
+ struct dd_cov_data *dd_cov_data = ptr;
26
+
27
+ xfree(dd_cov_data);
28
+ }
29
+
30
+ static void dd_cov_compact(void *ptr)
31
+ {
32
+ struct dd_cov_data *dd_cov_data = ptr;
33
+ dd_cov_data->coverage = rb_gc_location(dd_cov_data->coverage);
34
+ dd_cov_data->root = rb_gc_location(dd_cov_data->root);
35
+ }
36
+
37
+ const rb_data_type_t dd_cov_data_type = {
38
+ .wrap_struct_name = "dd_cov",
39
+ .function = {
40
+ .dmark = dd_cov_mark,
41
+ .dfree = dd_cov_free,
42
+ .dsize = NULL,
43
+ .dcompact = dd_cov_compact},
44
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY};
45
+
46
+ static VALUE dd_cov_allocate(VALUE klass)
47
+ {
48
+ struct dd_cov_data *dd_cov_data;
49
+ VALUE obj = TypedData_Make_Struct(klass, struct dd_cov_data, &dd_cov_data_type, dd_cov_data);
50
+ dd_cov_data->coverage = rb_hash_new();
51
+ dd_cov_data->root = Qnil;
52
+ dd_cov_data->mode = DD_COV_TARGET_FILES;
53
+ return obj;
54
+ }
55
+
56
+ // DDCov methods
57
+ static VALUE dd_cov_initialize(int argc, VALUE *argv, VALUE self)
58
+ {
59
+ VALUE opt;
60
+ int mode;
61
+
62
+ rb_scan_args(argc, argv, "10", &opt);
63
+ VALUE rb_root = rb_hash_lookup(opt, ID2SYM(rb_intern("root")));
64
+ if (!RTEST(rb_root))
65
+ {
66
+ rb_raise(rb_eArgError, "root is required");
67
+ }
68
+
69
+ VALUE rb_mode = rb_hash_lookup(opt, ID2SYM(rb_intern("mode")));
70
+ if (!RTEST(rb_mode) || rb_mode == ID2SYM(rb_intern("files")))
71
+ {
72
+ mode = DD_COV_TARGET_FILES;
73
+ }
74
+ else if (rb_mode == ID2SYM(rb_intern("lines")))
75
+ {
76
+ mode = DD_COV_TARGET_LINES;
77
+ }
78
+ else
79
+ {
80
+ rb_raise(rb_eArgError, "mode is invalid");
81
+ }
82
+
83
+ struct dd_cov_data *dd_cov_data;
84
+ TypedData_Get_Struct(self, struct dd_cov_data, &dd_cov_data_type, dd_cov_data);
85
+
86
+ dd_cov_data->root = rb_root;
87
+ dd_cov_data->mode = mode;
88
+
89
+ return Qnil;
90
+ }
91
+
92
+ static void dd_cov_update_line_coverage(rb_event_flag_t event, VALUE data, VALUE self, ID id, VALUE klass)
93
+ {
94
+ struct dd_cov_data *dd_cov_data;
95
+ TypedData_Get_Struct(data, struct dd_cov_data, &dd_cov_data_type, dd_cov_data);
96
+
97
+ const char *filename = rb_sourcefile();
98
+ if (filename == NULL)
99
+ {
100
+ return;
101
+ }
102
+
103
+ if (dd_cov_data->root == Qnil)
104
+ {
105
+ return;
106
+ }
107
+
108
+ char *c_root = RSTRING_PTR(dd_cov_data->root);
109
+ if (c_root == NULL)
110
+ {
111
+ return;
112
+ }
113
+ long root_len = RSTRING_LEN(dd_cov_data->root);
114
+ // check that root is a prefix of the filename
115
+ // so this file is located under the given root
116
+ if (strncmp(c_root, filename, root_len) != 0)
117
+ {
118
+ return;
119
+ }
120
+
121
+ VALUE rb_str_source_file = rb_str_new2(filename);
122
+
123
+ if (dd_cov_data->mode == DD_COV_TARGET_FILES)
124
+ {
125
+ rb_hash_aset(dd_cov_data->coverage, rb_str_source_file, Qtrue);
126
+ return;
127
+ }
128
+
129
+ // this isn't optimized yet, this is a POC to show that lines coverage is possible
130
+ // ITR beta is going to use files coverage, we'll get back to this part when
131
+ // we need to implement lines coverage
132
+ if (dd_cov_data->mode == DD_COV_TARGET_LINES)
133
+ {
134
+ int line_number = rb_sourceline();
135
+ if (line_number <= 0)
136
+ {
137
+ return;
138
+ }
139
+
140
+ VALUE rb_lines = rb_hash_aref(dd_cov_data->coverage, rb_str_source_file);
141
+ if (rb_lines == Qnil)
142
+ {
143
+ rb_lines = rb_hash_new();
144
+ rb_hash_aset(dd_cov_data->coverage, rb_str_source_file, rb_lines);
145
+ }
146
+
147
+ rb_hash_aset(rb_lines, INT2FIX(line_number), Qtrue);
148
+ }
149
+ }
150
+
151
+ static VALUE dd_cov_start(VALUE self)
152
+ {
153
+ // get current thread
154
+ VALUE thval = rb_thread_current();
155
+
156
+ // add event hook
157
+ rb_thread_add_event_hook(thval, dd_cov_update_line_coverage, RUBY_EVENT_LINE, self);
158
+
159
+ return self;
160
+ }
161
+
162
+ static VALUE dd_cov_stop(VALUE self)
163
+ {
164
+ // get current thread
165
+ VALUE thval = rb_thread_current();
166
+ // remove event hook for the current thread
167
+ rb_thread_remove_event_hook(thval, dd_cov_update_line_coverage);
168
+
169
+ struct dd_cov_data *dd_cov_data;
170
+ TypedData_Get_Struct(self, struct dd_cov_data, &dd_cov_data_type, dd_cov_data);
171
+
172
+ VALUE cov = dd_cov_data->coverage;
173
+
174
+ dd_cov_data->coverage = rb_hash_new();
175
+
176
+ return cov;
177
+ }
178
+
179
+ void Init_datadog_cov(void)
180
+ {
181
+ VALUE mDatadog = rb_define_module("Datadog");
182
+ VALUE mCI = rb_define_module_under(mDatadog, "CI");
183
+ VALUE mITR = rb_define_module_under(mCI, "ITR");
184
+ VALUE mCoverage = rb_define_module_under(mITR, "Coverage");
185
+ VALUE cDatadogCov = rb_define_class_under(mCoverage, "DDCov", rb_cObject);
186
+
187
+ rb_define_alloc_func(cDatadogCov, dd_cov_allocate);
188
+
189
+ rb_define_method(cDatadogCov, "initialize", dd_cov_initialize, -1);
190
+ rb_define_method(cDatadogCov, "start", dd_cov_start, 0);
191
+ rb_define_method(cDatadogCov, "stop", dd_cov_stop, 0);
192
+ }
@@ -0,0 +1,18 @@
1
+ if RUBY_ENGINE != "ruby" || Gem.win_platform?
2
+ warn(
3
+ "WARN: Skipping build of code coverage native extension because of unsupported platform."
4
+ )
5
+
6
+ File.write("Makefile", "all install clean: # dummy makefile that does nothing")
7
+ exit
8
+ end
9
+
10
+ require "mkmf"
11
+
12
+ # Tag the native extension library with the Ruby version and Ruby platform.
13
+ # This makes it easier for development (avoids "oops I forgot to rebuild when I switched my Ruby") and ensures that
14
+ # the wrong library is never loaded.
15
+ # When requiring, we need to use the exact same string, including the version and the platform.
16
+ EXTENSION_NAME = "datadog_cov.#{RUBY_VERSION}_#{RUBY_PLATFORM}".freeze
17
+
18
+ create_makefile(EXTENSION_NAME)
@@ -1,7 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative "../ext/settings"
4
+ require_relative "../git/tree_uploader"
4
5
  require_relative "../itr/runner"
6
+ require_relative "../itr/coverage/transport"
7
+ require_relative "../itr/coverage/writer"
5
8
  require_relative "../test_visibility/flush"
6
9
  require_relative "../test_visibility/recorder"
7
10
  require_relative "../test_visibility/null_recorder"
@@ -10,25 +13,34 @@ require_relative "../test_visibility/serializers/factories/test_suite_level"
10
13
  require_relative "../test_visibility/transport"
11
14
  require_relative "../transport/api/builder"
12
15
  require_relative "../transport/remote_settings_api"
16
+ require_relative "../worker"
13
17
 
14
18
  module Datadog
15
19
  module CI
16
20
  module Configuration
17
21
  # Adds CI behavior to Datadog trace components
18
22
  module Components
19
- attr_reader :ci_recorder
23
+ attr_reader :ci_recorder, :itr
20
24
 
21
25
  def initialize(settings)
22
26
  # Activate CI mode if enabled
23
27
  if settings.ci.enabled
24
28
  activate_ci!(settings)
25
29
  else
30
+ @itr = nil
26
31
  @ci_recorder = TestVisibility::NullRecorder.new
27
32
  end
28
33
 
29
34
  super
30
35
  end
31
36
 
37
+ def shutdown!(replacement = nil)
38
+ super
39
+
40
+ @ci_recorder&.shutdown!
41
+ @itr&.shutdown!
42
+ end
43
+
32
44
  def activate_ci!(settings)
33
45
  # Configure ddtrace library for CI visibility mode
34
46
  # Deactivate telemetry
@@ -49,10 +61,17 @@ module Datadog
49
61
 
50
62
  # transport creation
51
63
  writer_options = settings.ci.writer_options
64
+ coverage_writer = nil
52
65
  test_visibility_api = build_test_visibility_api(settings)
53
66
 
54
67
  if test_visibility_api
55
- writer_options[:transport] = Datadog::CI::TestVisibility::Transport.new(
68
+ # setup writer for code coverage payloads
69
+ coverage_writer = ITR::Coverage::Writer.new(
70
+ transport: ITR::Coverage::Transport.new(api: test_visibility_api)
71
+ )
72
+
73
+ # configure tracing writer to send traces to CI visibility backend
74
+ writer_options[:transport] = TestVisibility::Transport.new(
56
75
  api: test_visibility_api,
57
76
  serializers_factory: serializers_factory(settings),
58
77
  dd_env: settings.env
@@ -71,21 +90,36 @@ module Datadog
71
90
 
72
91
  settings.tracing.test_mode.writer_options = writer_options
73
92
 
74
- itr = Datadog::CI::ITR::Runner.new(
75
- enabled: settings.ci.enabled && settings.ci.itr_enabled
76
- )
77
-
78
93
  remote_settings_api = Transport::RemoteSettingsApi.new(
79
94
  api: test_visibility_api,
80
95
  dd_env: settings.env
81
96
  )
82
97
 
98
+ itr = ITR::Runner.new(
99
+ api: test_visibility_api,
100
+ dd_env: settings.env,
101
+ coverage_writer: coverage_writer,
102
+ enabled: settings.ci.enabled && settings.ci.itr_enabled
103
+ )
104
+
105
+ git_tree_uploader = Git::TreeUploader.new(api: test_visibility_api)
106
+ git_tree_upload_worker = if settings.ci.git_metadata_upload_enabled
107
+ Worker.new do |repository_url|
108
+ git_tree_uploader.call(repository_url)
109
+ end
110
+ else
111
+ DummyWorker.new
112
+ end
113
+
83
114
  # CI visibility recorder global instance
84
115
  @ci_recorder = TestVisibility::Recorder.new(
85
116
  test_suite_level_visibility_enabled: !settings.ci.force_test_level_visibility,
86
117
  itr: itr,
87
- remote_settings_api: remote_settings_api
118
+ remote_settings_api: remote_settings_api,
119
+ git_tree_upload_worker: git_tree_upload_worker
88
120
  )
121
+
122
+ @itr = itr
89
123
  end
90
124
 
91
125
  def build_test_visibility_api(settings)
@@ -122,9 +156,9 @@ module Datadog
122
156
 
123
157
  def serializers_factory(settings)
124
158
  if settings.ci.force_test_level_visibility
125
- Datadog::CI::TestVisibility::Serializers::Factories::TestLevel
159
+ TestVisibility::Serializers::Factories::TestLevel
126
160
  else
127
- Datadog::CI::TestVisibility::Serializers::Factories::TestSuiteLevel
161
+ TestVisibility::Serializers::Factories::TestSuiteLevel
128
162
  end
129
163
  end
130
164
 
@@ -47,7 +47,7 @@ module Datadog
47
47
  o.after_set do |value|
48
48
  if value
49
49
  Datadog::Core.log_deprecation do
50
- "The experimental_test_suite_level_visibility_enabled setting has no effect and will be removed in 1.0. " \
50
+ "The experimental_test_suite_level_visibility_enabled setting has no effect and will be removed in 2.0. " \
51
51
  "Test suite level visibility is now enabled by default. " \
52
52
  "If you want to disable test suite level visibility set configuration.ci.force_test_level_visibility = true."
53
53
  end
@@ -61,6 +61,12 @@ module Datadog
61
61
  o.default false
62
62
  end
63
63
 
64
+ option :git_metadata_upload_enabled do |o|
65
+ o.type :bool
66
+ o.env CI::Ext::Settings::ENV_GIT_METADATA_UPLOAD_ENABLED
67
+ o.default true
68
+ end
69
+
64
70
  define_method(:instrument) do |integration_name, options = {}, &block|
65
71
  return unless enabled
66
72
 
@@ -26,21 +26,6 @@ module Datadog
26
26
  Utils::Configuration.fetch_service_name(Ext::DEFAULT_SERVICE_NAME)
27
27
  end
28
28
  end
29
-
30
- # @deprecated Will be removed in 1.0
31
- option :operation_name do |o|
32
- o.type :string
33
- o.env Ext::ENV_OPERATION_NAME
34
- o.default Ext::OPERATION_NAME
35
-
36
- o.after_set do |value|
37
- if value && value != Ext::OPERATION_NAME
38
- Datadog::Core.log_deprecation do
39
- "The operation_name setting has no effect and will be removed in 1.0"
40
- end
41
- end
42
- end
43
- end
44
29
  end
45
30
  end
46
31
  end
@@ -5,7 +5,7 @@ module Datadog
5
5
  module Contrib
6
6
  module Cucumber
7
7
  # Cucumber integration constants
8
- # TODO: mark as `@public_api` when GA, to protect from resource and tag name changes.
8
+ # @public_api
9
9
  module Ext
10
10
  ENV_ENABLED = "DD_TRACE_CUCUMBER_ENABLED"
11
11
  DEFAULT_SERVICE_NAME = "cucumber"
@@ -13,10 +13,6 @@ module Datadog
13
13
  FRAMEWORK = "cucumber"
14
14
 
15
15
  STEP_SPAN_TYPE = "step"
16
-
17
- # TODO: remove in 1.0
18
- ENV_OPERATION_NAME = "DD_TRACE_CUCUMBER_OPERATION_NAME"
19
- OPERATION_NAME = "cucumber.test"
20
16
  end
21
17
  end
22
18
  end