datadog-ci 1.0.0 → 1.1.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 +18 -2
- data/ext/datadog_cov/datadog_cov.c +115 -85
- data/lib/datadog/ci/configuration/components.rb +3 -2
- 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/itr/coverage/writer.rb +3 -1
- data/lib/datadog/ci/itr/runner.rb +11 -2
- 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 +3 -3
- metadata +4 -3
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 61f6379b9a5ac0c29ff9ee6b1687c1c2add77d6a5031dfd5758eb34a66cc6235
         | 
| 4 | 
            +
              data.tar.gz: a795d8d69513925ee5ea6cf113cb54cec3711fe65ae5e928fcdeb8e1454323af
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 3ea51d0baa70ecb4e66fb49712f4f291582ecb04455b2d32ec1328bb8ea3c112c4c25d80e450db542ee4f29408786b09a82b5f94fb1c7ef8c96b98d301e61e9b
         | 
| 7 | 
            +
              data.tar.gz: 4f066970c2d9ed93001f35f9096cefcf2a4447a86cf7c1d89435853b1da00389c587924304c7a213e56f58f64b191523d202e34f86da535ded271583881411ac
         | 
    
        data/CHANGELOG.md
    CHANGED
    
    | @@ -1,5 +1,16 @@ | |
| 1 1 | 
             
            ## [Unreleased]
         | 
| 2 2 |  | 
| 3 | 
            +
            ## [1.1.0] - 2024-07-01
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            ### Added
         | 
| 6 | 
            +
            * Ignore Webmock automatically when making HTTP calls ([#193][])
         | 
| 7 | 
            +
             | 
| 8 | 
            +
            ## [1.0.1] - 2024-06-11
         | 
| 9 | 
            +
             | 
| 10 | 
            +
            ### Fixed
         | 
| 11 | 
            +
            * multi threaded code coverage support for datadog_cov ([#189][])
         | 
| 12 | 
            +
            * code coverage extension fixes and improvements ([#171][])
         | 
| 13 | 
            +
             | 
| 3 14 | 
             
            ## [1.0.0] - 2024-06-06
         | 
| 4 15 |  | 
| 5 16 |  | 
| @@ -261,7 +272,9 @@ Currently test suite level visibility is not used by our instrumentation: it wil | |
| 261 272 |  | 
| 262 273 | 
             
            - Ruby versions < 2.7 no longer supported ([#8][])
         | 
| 263 274 |  | 
| 264 | 
            -
            [Unreleased]: https://github.com/DataDog/datadog-ci-rb/compare/v1. | 
| 275 | 
            +
            [Unreleased]: https://github.com/DataDog/datadog-ci-rb/compare/v1.1.0...main
         | 
| 276 | 
            +
            [1.1.0]: https://github.com/DataDog/datadog-ci-rb/compare/v1.0.1...v1.1.0
         | 
| 277 | 
            +
            [1.0.1]: https://github.com/DataDog/datadog-ci-rb/compare/v1.0.0...v1.0.1
         | 
| 265 278 | 
             
            [1.0.0]: https://github.com/DataDog/datadog-ci-rb/compare/v1.0.0.beta6...v1.0.0
         | 
| 266 279 | 
             
            [1.0.0.beta6]: https://github.com/DataDog/datadog-ci-rb/compare/v1.0.0.beta5...v1.0.0.beta6
         | 
| 267 280 | 
             
            [1.0.0.beta5]: https://github.com/DataDog/datadog-ci-rb/compare/v1.0.0.beta4...v1.0.0.beta5
         | 
| @@ -361,6 +374,7 @@ Currently test suite level visibility is not used by our instrumentation: it wil | |
| 361 374 | 
             
            [#167]: https://github.com/DataDog/datadog-ci-rb/issues/167
         | 
| 362 375 | 
             
            [#168]: https://github.com/DataDog/datadog-ci-rb/issues/168
         | 
| 363 376 | 
             
            [#170]: https://github.com/DataDog/datadog-ci-rb/issues/170
         | 
| 377 | 
            +
            [#171]: https://github.com/DataDog/datadog-ci-rb/issues/171
         | 
| 364 378 | 
             
            [#172]: https://github.com/DataDog/datadog-ci-rb/issues/172
         | 
| 365 379 | 
             
            [#173]: https://github.com/DataDog/datadog-ci-rb/issues/173
         | 
| 366 380 | 
             
            [#174]: https://github.com/DataDog/datadog-ci-rb/issues/174
         | 
| @@ -368,4 +382,6 @@ Currently test suite level visibility is not used by our instrumentation: it wil | |
| 368 382 | 
             
            [#180]: https://github.com/DataDog/datadog-ci-rb/issues/180
         | 
| 369 383 | 
             
            [#183]: https://github.com/DataDog/datadog-ci-rb/issues/183
         | 
| 370 384 | 
             
            [#185]: https://github.com/DataDog/datadog-ci-rb/issues/185
         | 
| 371 | 
            -
            [# | 
| 385 | 
            +
            [#189]: https://github.com/DataDog/datadog-ci-rb/issues/189
         | 
| 386 | 
            +
            [#190]: https://github.com/DataDog/datadog-ci-rb/issues/190
         | 
| 387 | 
            +
            [#193]: https://github.com/DataDog/datadog-ci-rb/issues/193
         | 
| @@ -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)
         | 
| @@ -204,7 +205,7 @@ module Datadog | |
| 204 205 | 
             
                    end
         | 
| 205 206 |  | 
| 206 207 | 
             
                    def timecop?
         | 
| 207 | 
            -
                      Gem.loaded_specs.key?("timecop") || defined?(Timecop)
         | 
| 208 | 
            +
                      Gem.loaded_specs.key?("timecop") || !!defined?(Timecop)
         | 
| 208 209 | 
             
                    end
         | 
| 209 210 | 
             
                  end
         | 
| 210 211 | 
             
                end
         | 
| @@ -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 |  | 
| @@ -42,15 +42,15 @@ module Datadog | |
| 42 42 | 
             
                      end
         | 
| 43 43 |  | 
| 44 44 | 
             
                      def ci_queue?
         | 
| 45 | 
            -
                        defined?(::RSpec::Queue::Runner)
         | 
| 45 | 
            +
                        !!defined?(::RSpec::Queue::Runner)
         | 
| 46 46 | 
             
                      end
         | 
| 47 47 |  | 
| 48 48 | 
             
                      def knapsack_pro?
         | 
| 49 49 | 
             
                        knapsack_version = Gem.loaded_specs["knapsack_pro"]&.version
         | 
| 50 50 |  | 
| 51 51 | 
             
                        # additional instrumentation is needed for KnapsackPro version 7 and later
         | 
| 52 | 
            -
                        defined?(::KnapsackPro) &&
         | 
| 53 | 
            -
                          knapsack_version && knapsack_version >= Gem::Version.new("7")
         | 
| 52 | 
            +
                        !!defined?(::KnapsackPro) &&
         | 
| 53 | 
            +
                          !knapsack_version.nil? && knapsack_version >= Gem::Version.new("7")
         | 
| 54 54 | 
             
                      end
         | 
| 55 55 | 
             
                    end
         | 
| 56 56 | 
             
                  end
         | 
| @@ -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
         | 
| @@ -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
    
    
    
        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. | 
| 4 | 
            +
              version: 1.1.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-01 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: datadog
         | 
| @@ -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
         |