From 16b04ed5a24772130f9bc6be5732d9473c3ed654 Mon Sep 17 00:00:00 2001 From: Andrey Date: Tue, 7 May 2024 16:41:03 +0200 Subject: [PATCH 1/6] add settings option to ignore code coverage for certain paths --- lib/datadog/ci/configuration/settings.rb | 15 +++++++++++++++ lib/datadog/ci/ext/environment.rb | 7 +++++++ lib/datadog/ci/ext/settings.rb | 1 + lib/datadog/ci/utils/bundle.rb | 20 ++++++++++++++++++++ sig/datadog/ci/ext/environment.rbs | 2 ++ sig/datadog/ci/ext/settings.rbs | 1 + sig/datadog/ci/utils/bundle.rbs | 9 +++++++++ 7 files changed, 55 insertions(+) create mode 100644 lib/datadog/ci/utils/bundle.rb create mode 100644 sig/datadog/ci/utils/bundle.rbs diff --git a/lib/datadog/ci/configuration/settings.rb b/lib/datadog/ci/configuration/settings.rb index 856149f8..36d6fff2 100644 --- a/lib/datadog/ci/configuration/settings.rb +++ b/lib/datadog/ci/configuration/settings.rb @@ -1,6 +1,7 @@ # frozen_string_literal: true require_relative "../ext/settings" +require_relative "../utils/bundle" module Datadog module CI @@ -67,6 +68,20 @@ def self.add_settings!(base) o.default true end + option :itr_code_coverage_excluded_paths do |o| + o.type :array + o.env CI::Ext::Settings::ENV_ITR_CODE_COVERAGE_EXCLUDED_PATHS + o.after_set do |paths| + if paths.nil? && (bundle_path = Datadog::CI::Utils::Bundle.location) + paths = [bundle_path] + end + + paths.map do |path| + File.expand_path(path) + end + end + end + define_method(:instrument) do |integration_name, options = {}, &block| return unless enabled diff --git a/lib/datadog/ci/ext/environment.rb b/lib/datadog/ci/ext/environment.rb index 5e3c0034..9a326b6e 100644 --- a/lib/datadog/ci/ext/environment.rb +++ b/lib/datadog/ci/ext/environment.rb @@ -23,6 +23,13 @@ module Environment TAG_NODE_NAME = "ci.node.name" TAG_CI_ENV_VARS = "_dd.ci.env_vars" + POSSIBLE_BUNDLE_LOCATIONS = [ + ".bundle", + "vendor/bundle", + "vendor/cache", + "vendor/gems" + ].freeze + module_function def tags(env) diff --git a/lib/datadog/ci/ext/settings.rb b/lib/datadog/ci/ext/settings.rb index 9e2bfaf4..a2d66d5d 100644 --- a/lib/datadog/ci/ext/settings.rb +++ b/lib/datadog/ci/ext/settings.rb @@ -12,6 +12,7 @@ module Settings ENV_FORCE_TEST_LEVEL_VISIBILITY = "DD_CIVISIBILITY_FORCE_TEST_LEVEL_VISIBILITY" ENV_ITR_ENABLED = "DD_CIVISIBILITY_ITR_ENABLED" ENV_GIT_METADATA_UPLOAD_ENABLED = "DD_CIVISIBILITY_GIT_METADATA_UPLOAD_ENABLED" + ENV_ITR_CODE_COVERAGE_EXCLUDED_PATHS = "DD_CIVISIBILITY_ITR_CODE_COVERAGE_EXCLUDED_PATHS" # Source: https://docs.datadoghq.com/getting_started/site/ DD_SITE_ALLOWLIST = [ diff --git a/lib/datadog/ci/utils/bundle.rb b/lib/datadog/ci/utils/bundle.rb new file mode 100644 index 00000000..d890945a --- /dev/null +++ b/lib/datadog/ci/utils/bundle.rb @@ -0,0 +1,20 @@ +# frozen_string_literal: true + +require_relative "../ext/environment" +require_relative "../git/local_repository" + +module Datadog + module CI + module Utils + module Bundle + def self.location + Ext::Environment::POSSIBLE_BUNDLE_LOCATIONS.each do |location| + path = File.join(Datadog::CI::Git::LocalRepository.root, location) + return path if File.directory?(path) + end + nil + end + end + end + end +end diff --git a/sig/datadog/ci/ext/environment.rbs b/sig/datadog/ci/ext/environment.rbs index 9e875937..04e04368 100644 --- a/sig/datadog/ci/ext/environment.rbs +++ b/sig/datadog/ci/ext/environment.rbs @@ -27,6 +27,8 @@ module Datadog TAG_CI_ENV_VARS: String + POSSIBLE_BUNDLE_LOCATIONS: Array[String] + PROVIDERS: ::Array[Array[String | Symbol]] def self?.tags: (untyped env) -> Hash[String, String] diff --git a/sig/datadog/ci/ext/settings.rbs b/sig/datadog/ci/ext/settings.rbs index c8847c6c..656774ca 100644 --- a/sig/datadog/ci/ext/settings.rbs +++ b/sig/datadog/ci/ext/settings.rbs @@ -9,6 +9,7 @@ module Datadog ENV_FORCE_TEST_LEVEL_VISIBILITY: String ENV_ITR_ENABLED: String ENV_GIT_METADATA_UPLOAD_ENABLED: String + ENV_ITR_CODE_COVERAGE_EXCLUDED_PATHS: String DD_SITE_ALLOWLIST: Array[String] end diff --git a/sig/datadog/ci/utils/bundle.rbs b/sig/datadog/ci/utils/bundle.rbs new file mode 100644 index 00000000..62696c5f --- /dev/null +++ b/sig/datadog/ci/utils/bundle.rbs @@ -0,0 +1,9 @@ +module Datadog + module CI + module Utils + module Bundle + def self.location: () -> String? + end + end + end +end From 21f535200c302022f923ecd72402eeb98df6cabd Mon Sep 17 00:00:00 2001 From: Andrey Date: Wed, 8 May 2024 13:03:48 +0200 Subject: [PATCH 2/6] use bundler to determine bundle location, rename setting option to a single itr_code_coverage_excluded_bundle_path --- Steepfile | 1 + lib/datadog/ci/configuration/settings.rb | 19 +++++----- lib/datadog/ci/ext/environment.rb | 4 +-- lib/datadog/ci/ext/settings.rb | 2 +- lib/datadog/ci/utils/bundle.rb | 6 ++++ sig/datadog/ci/ext/settings.rbs | 2 +- spec/datadog/ci/utils/bundle_spec.rb | 46 ++++++++++++++++++++++++ vendor/rbs/bundler/0/bundler.rbs | 3 ++ 8 files changed, 68 insertions(+), 15 deletions(-) create mode 100644 spec/datadog/ci/utils/bundle_spec.rb create mode 100644 vendor/rbs/bundler/0/bundler.rbs diff --git a/Steepfile b/Steepfile index dafdd2bd..185b46ff 100644 --- a/Steepfile +++ b/Steepfile @@ -26,4 +26,5 @@ target :lib do library "msgpack" library "ci_queue" library "knapsack_pro" + library "bundler" end diff --git a/lib/datadog/ci/configuration/settings.rb b/lib/datadog/ci/configuration/settings.rb index 36d6fff2..d3b4edf4 100644 --- a/lib/datadog/ci/configuration/settings.rb +++ b/lib/datadog/ci/configuration/settings.rb @@ -68,17 +68,13 @@ def self.add_settings!(base) o.default true end - option :itr_code_coverage_excluded_paths do |o| - o.type :array - o.env CI::Ext::Settings::ENV_ITR_CODE_COVERAGE_EXCLUDED_PATHS - o.after_set do |paths| - if paths.nil? && (bundle_path = Datadog::CI::Utils::Bundle.location) - paths = [bundle_path] - end + option :itr_code_coverage_excluded_bundle_path do |o| + o.type :string, nilable: true + o.env CI::Ext::Settings::ENV_ITR_CODE_COVERAGE_EXCLUDED_BUNDLE_PATH + o.after_set do |path| + path ||= Datadog::CI::Utils::Bundle.location - paths.map do |path| - File.expand_path(path) - end + File.expand_path(path) if path end end @@ -104,6 +100,9 @@ def self.add_settings!(base) fetch_integration(integration_name).configuration end + # @deprecated Will be removed on datadog-ci-rb 1.0. + alias_method :use, :instrument + option :trace_flush option :writer_options do |o| diff --git a/lib/datadog/ci/ext/environment.rb b/lib/datadog/ci/ext/environment.rb index 9a326b6e..e2fa1b8e 100644 --- a/lib/datadog/ci/ext/environment.rb +++ b/lib/datadog/ci/ext/environment.rb @@ -24,10 +24,8 @@ module Environment TAG_CI_ENV_VARS = "_dd.ci.env_vars" POSSIBLE_BUNDLE_LOCATIONS = [ - ".bundle", "vendor/bundle", - "vendor/cache", - "vendor/gems" + ".bundle" ].freeze module_function diff --git a/lib/datadog/ci/ext/settings.rb b/lib/datadog/ci/ext/settings.rb index a2d66d5d..a1921f6e 100644 --- a/lib/datadog/ci/ext/settings.rb +++ b/lib/datadog/ci/ext/settings.rb @@ -12,7 +12,7 @@ module Settings ENV_FORCE_TEST_LEVEL_VISIBILITY = "DD_CIVISIBILITY_FORCE_TEST_LEVEL_VISIBILITY" ENV_ITR_ENABLED = "DD_CIVISIBILITY_ITR_ENABLED" ENV_GIT_METADATA_UPLOAD_ENABLED = "DD_CIVISIBILITY_GIT_METADATA_UPLOAD_ENABLED" - ENV_ITR_CODE_COVERAGE_EXCLUDED_PATHS = "DD_CIVISIBILITY_ITR_CODE_COVERAGE_EXCLUDED_PATHS" + ENV_ITR_CODE_COVERAGE_EXCLUDED_BUNDLE_PATH = "DD_CIVISIBILITY_ITR_CODE_COVERAGE_EXCLUDED_BUNDLE_PATH" # Source: https://docs.datadoghq.com/getting_started/site/ DD_SITE_ALLOWLIST = [ diff --git a/lib/datadog/ci/utils/bundle.rb b/lib/datadog/ci/utils/bundle.rb index d890945a..add572f2 100644 --- a/lib/datadog/ci/utils/bundle.rb +++ b/lib/datadog/ci/utils/bundle.rb @@ -8,6 +8,12 @@ module CI module Utils module Bundle def self.location + require "bundler" + bundle_path = Bundler.bundle_path.to_s + bundle_path if bundle_path&.start_with?(Datadog::CI::Git::LocalRepository.root) + rescue => e + Datadog.logger.warn("Failed to find bundled gems location: #{e}") + Ext::Environment::POSSIBLE_BUNDLE_LOCATIONS.each do |location| path = File.join(Datadog::CI::Git::LocalRepository.root, location) return path if File.directory?(path) diff --git a/sig/datadog/ci/ext/settings.rbs b/sig/datadog/ci/ext/settings.rbs index 656774ca..83ed4fad 100644 --- a/sig/datadog/ci/ext/settings.rbs +++ b/sig/datadog/ci/ext/settings.rbs @@ -9,7 +9,7 @@ module Datadog ENV_FORCE_TEST_LEVEL_VISIBILITY: String ENV_ITR_ENABLED: String ENV_GIT_METADATA_UPLOAD_ENABLED: String - ENV_ITR_CODE_COVERAGE_EXCLUDED_PATHS: String + ENV_ITR_CODE_COVERAGE_EXCLUDED_BUNDLE_PATH: String DD_SITE_ALLOWLIST: Array[String] end diff --git a/spec/datadog/ci/utils/bundle_spec.rb b/spec/datadog/ci/utils/bundle_spec.rb new file mode 100644 index 00000000..c763392d --- /dev/null +++ b/spec/datadog/ci/utils/bundle_spec.rb @@ -0,0 +1,46 @@ +require_relative "../../../../lib/datadog/ci/utils/bundle" + +RSpec.describe Datadog::CI::Utils::Bundle do + describe ".location" do + subject { described_class.location } + let(:bundle_path) { "/path/to/repo/vendor/bundle" } + let(:git_root) { "/path/to/repo" } + + before do + allow(Bundler).to receive(:bundle_path).and_return(bundle_path) + allow(Datadog::CI::Git::LocalRepository).to receive(:root).and_return(git_root) + end + + context "when Bundler.bundle_path is located under the git root" do + it { is_expected.to eq(bundle_path) } + end + + context "when Bundler.bundle_path is not located under the git root" do + let(:git_root) { "/path/to/different/repo" } + + it { is_expected.to be_nil } + end + + context "when an exception is raised" do + before do + allow(Bundler).to receive(:bundle_path).and_raise(StandardError.new("Failed to find bundle path")) + allow(Datadog.logger).to receive(:warn) + allow(File).to receive(:directory?).and_return(false) + end + + it "logs a warning and tries other possible bundle locations" do + expect(Datadog.logger).to receive(:warn).with(/Failed to find bundled gems location/) + + expect(Datadog::CI::Utils::Bundle.location).to be_nil + end + + context "when one of the possible bundle locations exists" do + it "returns the existing bundle location" do + allow(File).to receive(:directory?).with(File.join(git_root, "vendor/bundle")).and_return(true) + + expect(Datadog::CI::Utils::Bundle.location).to eq("/path/to/repo/vendor/bundle") + end + end + end + end +end diff --git a/vendor/rbs/bundler/0/bundler.rbs b/vendor/rbs/bundler/0/bundler.rbs new file mode 100644 index 00000000..17687741 --- /dev/null +++ b/vendor/rbs/bundler/0/bundler.rbs @@ -0,0 +1,3 @@ +module Bundler + def self.bundle_path: () -> Pathname +end From dee1becd2653662811da7ef541282d7b44d04109 Mon Sep 17 00:00:00 2001 From: Andrey Date: Wed, 8 May 2024 13:33:12 +0200 Subject: [PATCH 3/6] simplify and test itr_code_coverage_excluded_bundle_path setting --- lib/datadog/ci/configuration/settings.rb | 6 +-- .../datadog/ci/configuration/settings_spec.rb | 48 +++++++++++++++++++ 2 files changed, 50 insertions(+), 4 deletions(-) diff --git a/lib/datadog/ci/configuration/settings.rb b/lib/datadog/ci/configuration/settings.rb index d3b4edf4..d54f9c62 100644 --- a/lib/datadog/ci/configuration/settings.rb +++ b/lib/datadog/ci/configuration/settings.rb @@ -71,10 +71,8 @@ def self.add_settings!(base) option :itr_code_coverage_excluded_bundle_path do |o| o.type :string, nilable: true o.env CI::Ext::Settings::ENV_ITR_CODE_COVERAGE_EXCLUDED_BUNDLE_PATH - o.after_set do |path| - path ||= Datadog::CI::Utils::Bundle.location - - File.expand_path(path) if path + o.default do + Datadog::CI::Utils::Bundle.location end end diff --git a/spec/datadog/ci/configuration/settings_spec.rb b/spec/datadog/ci/configuration/settings_spec.rb index 5cea8e5a..8716cf35 100644 --- a/spec/datadog/ci/configuration/settings_spec.rb +++ b/spec/datadog/ci/configuration/settings_spec.rb @@ -301,6 +301,54 @@ def patcher end end + describe "#itr_code_coverage_excluded_bundle_path" do + subject(:itr_code_coverage_excluded_bundle_path) do + settings.ci.itr_code_coverage_excluded_bundle_path + end + + it { is_expected.to be nil } + + context "when #{Datadog::CI::Ext::Settings::ENV_ITR_CODE_COVERAGE_EXCLUDED_BUNDLE_PATH}" do + around do |example| + ClimateControl.modify( + Datadog::CI::Ext::Settings::ENV_ITR_CODE_COVERAGE_EXCLUDED_BUNDLE_PATH => path + ) do + example.run + end + end + + context "is not defined" do + let(:path) { nil } + + it { is_expected.to be nil } + + context "and when bundle location is found in project folder" do + let(:bundle_location) { "/path/to/repo/vendor/bundle" } + before do + allow(Datadog::CI::Utils::Bundle).to receive(:location).and_return(bundle_location) + end + + it { is_expected.to eq bundle_location } + end + end + + context "is set to some value" do + let(:path) { "/path/to/excluded" } + + it { is_expected.to eq path } + end + end + end + + describe "#itr_code_coverage_excluded_bundle_path=" do + it "updates the #enabled setting" do + expect { settings.ci.itr_code_coverage_excluded_bundle_path = "/path/to/excluded" } + .to change { settings.ci.itr_code_coverage_excluded_bundle_path } + .from(nil) + .to("/path/to/excluded") + end + end + describe "#instrument" do let(:integration_name) { :fake } From a16f200f1262d35f21fe8e129b2ac9531d013dbc Mon Sep 17 00:00:00 2001 From: Andrey Date: Wed, 8 May 2024 14:36:33 +0200 Subject: [PATCH 4/6] send itr_code_coverage_excluded_bundle_path from settings all the way to DDCov tool --- lib/datadog/ci/configuration/components.rb | 3 ++- lib/datadog/ci/itr/runner.rb | 11 ++++++++--- sig/datadog/ci/itr/coverage/ddcov.rbs | 2 +- sig/datadog/ci/itr/runner.rbs | 3 ++- spec/ddcov/ddcov_spec.rb | 3 ++- spec/support/contexts/ci_mode.rb | 2 ++ 6 files changed, 17 insertions(+), 7 deletions(-) diff --git a/lib/datadog/ci/configuration/components.rb b/lib/datadog/ci/configuration/components.rb index 0e7cb4c4..a729fc39 100644 --- a/lib/datadog/ci/configuration/components.rb +++ b/lib/datadog/ci/configuration/components.rb @@ -107,7 +107,8 @@ def activate_ci!(settings) dd_env: settings.env, config_tags: custom_configuration_tags, coverage_writer: coverage_writer, - enabled: settings.ci.enabled && settings.ci.itr_enabled + enabled: settings.ci.enabled && settings.ci.itr_enabled, + bundle_location: settings.ci.itr_code_coverage_excluded_bundle_path ) git_tree_uploader = Git::TreeUploader.new(api: test_visibility_api) diff --git a/lib/datadog/ci/itr/runner.rb b/lib/datadog/ci/itr/runner.rb index 44a7c8a8..76f0bc62 100644 --- a/lib/datadog/ci/itr/runner.rb +++ b/lib/datadog/ci/itr/runner.rb @@ -30,12 +30,14 @@ def initialize( config_tags: {}, api: nil, coverage_writer: nil, - enabled: false + enabled: false, + bundle_location: nil ) @enabled = enabled @api = api @dd_env = dd_env @config_tags = config_tags || {} + @bundle_location = bundle_location @test_skipping_enabled = false @code_coverage_enabled = false @@ -43,7 +45,7 @@ def initialize( @coverage_writer = coverage_writer @correlation_id = nil - @skippable_tests = [] + @skippable_tests = Set.new @skipped_tests_count = 0 @mutex = Mutex.new @@ -177,7 +179,10 @@ def write(event) end def coverage_collector - Thread.current[:dd_coverage_collector] ||= Coverage::DDCov.new(root: Git::LocalRepository.root) + Thread.current[:dd_coverage_collector] ||= Coverage::DDCov.new( + root: Git::LocalRepository.root, + ignored_path: @bundle_location + ) end def load_datadog_cov! diff --git a/sig/datadog/ci/itr/coverage/ddcov.rbs b/sig/datadog/ci/itr/coverage/ddcov.rbs index 89426c10..a1d06365 100644 --- a/sig/datadog/ci/itr/coverage/ddcov.rbs +++ b/sig/datadog/ci/itr/coverage/ddcov.rbs @@ -4,7 +4,7 @@ module Datadog module Coverage class DDCov - def initialize: (root: String, ?mode: Symbol) -> void + def initialize: (root: String, ?mode: Symbol, ignored_path: String?) -> void def start: () -> void diff --git a/sig/datadog/ci/itr/runner.rbs b/sig/datadog/ci/itr/runner.rbs index f76a308d..1ce20b44 100644 --- a/sig/datadog/ci/itr/runner.rbs +++ b/sig/datadog/ci/itr/runner.rbs @@ -14,6 +14,7 @@ module Datadog @api: Datadog::CI::Transport::Api::Base? @dd_env: String? @config_tags: Hash[String, String] + @bundle_location: String? @skipped_tests_count: Integer @mutex: Thread::Mutex @@ -22,7 +23,7 @@ module Datadog attr_reader skipped_tests_count: Integer attr_reader correlation_id: String? - def initialize: (dd_env: String?, ?enabled: bool, coverage_writer: Datadog::CI::ITR::Coverage::Writer?, api: Datadog::CI::Transport::Api::Base?, ?config_tags: Hash[String, String]?) -> void + def initialize: (dd_env: String?, ?enabled: bool, ?coverage_writer: Datadog::CI::ITR::Coverage::Writer?, ?api: Datadog::CI::Transport::Api::Base?, ?config_tags: Hash[String, String]?, ?bundle_location: String?) -> void def configure: (Hash[String, untyped] remote_configuration, test_session: Datadog::CI::TestSession, git_tree_upload_worker: Datadog::CI::Worker) -> void diff --git a/spec/ddcov/ddcov_spec.rb b/spec/ddcov/ddcov_spec.rb index 8e4f50ca..c78fb7c6 100644 --- a/spec/ddcov/ddcov_spec.rb +++ b/spec/ddcov/ddcov_spec.rb @@ -10,7 +10,8 @@ def absolute_path(path) File.expand_path(File.join(__dir__, path)) end - subject { described_class.new(root: root, mode: mode) } + let(:ignored_path) { nil } + subject { described_class.new(root: root, mode: mode, ignored_path: ignored_path) } describe "code coverage collection" do let!(:calculator) { Calculator.new } diff --git a/spec/support/contexts/ci_mode.rb b/spec/support/contexts/ci_mode.rb index 54b02054..2b7c59d0 100644 --- a/spec/support/contexts/ci_mode.rb +++ b/spec/support/contexts/ci_mode.rb @@ -22,6 +22,7 @@ let(:tests_skipping_enabled) { false } let(:git_metadata_upload_enabled) { false } let(:require_git) { false } + let(:bundle_path) { nil } let(:itr_correlation_id) { "itr_correlation_id" } let(:itr_skippable_tests) { [] } @@ -75,6 +76,7 @@ c.ci.force_test_level_visibility = force_test_level_visibility c.ci.itr_enabled = itr_enabled c.ci.git_metadata_upload_enabled = git_metadata_upload_enabled + c.ci.itr_code_coverage_excluded_bundle_path = bundle_path unless integration_name == :no_instrument c.ci.instrument integration_name, integration_options end From e097e1e59d3591820fa61d325301b888bbc5ee0d Mon Sep 17 00:00:00 2001 From: Andrey Date: Wed, 8 May 2024 15:31:21 +0200 Subject: [PATCH 5/6] ignore bundled gems location when running per test code coverage --- ext/datadog_cov/datadog_cov.c | 46 +++++++++++++++---- lib/datadog/ci/itr/runner.rb | 7 ++- .../step_definitions/helpers/helper.rb | 5 ++ .../features/step_definitions/steps.rb | 4 +- .../contrib/cucumber/instrumentation_spec.rb | 3 +- spec/ddcov/ddcov_spec.rb | 18 +++++++- 6 files changed, 69 insertions(+), 14 deletions(-) create mode 100644 spec/datadog/ci/contrib/cucumber/features/step_definitions/helpers/helper.rb diff --git a/ext/datadog_cov/datadog_cov.c b/ext/datadog_cov/datadog_cov.c index d35cf4a8..61af4d8d 100644 --- a/ext/datadog_cov/datadog_cov.c +++ b/ext/datadog_cov/datadog_cov.c @@ -5,10 +5,35 @@ #define DD_COV_TARGET_FILES 1 #define DD_COV_TARGET_LINES 2 +static int is_prefix(VALUE prefix, const char *str) +{ + if (prefix == Qnil) + { + return 0; + } + + const char *c_prefix = RSTRING_PTR(prefix); + if (c_prefix == NULL) + { + return 0; + } + + long prefix_len = RSTRING_LEN(prefix); + if (strncmp(c_prefix, str, prefix_len) == 0) + { + return 1; + } + else + { + return 0; + } +} + // Data structure struct dd_cov_data { VALUE root; + VALUE ignored_path; int mode; VALUE coverage; }; @@ -18,6 +43,7 @@ static void dd_cov_mark(void *ptr) struct dd_cov_data *dd_cov_data = ptr; rb_gc_mark_movable(dd_cov_data->coverage); rb_gc_mark_movable(dd_cov_data->root); + rb_gc_mark_movable(dd_cov_data->ignored_path); } static void dd_cov_free(void *ptr) @@ -32,6 +58,7 @@ static void dd_cov_compact(void *ptr) struct dd_cov_data *dd_cov_data = ptr; dd_cov_data->coverage = rb_gc_location(dd_cov_data->coverage); dd_cov_data->root = rb_gc_location(dd_cov_data->root); + dd_cov_data->ignored_path = rb_gc_location(dd_cov_data->ignored_path); } const rb_data_type_t dd_cov_data_type = { @@ -49,6 +76,7 @@ static VALUE dd_cov_allocate(VALUE klass) VALUE obj = TypedData_Make_Struct(klass, struct dd_cov_data, &dd_cov_data_type, dd_cov_data); dd_cov_data->coverage = rb_hash_new(); dd_cov_data->root = Qnil; + dd_cov_data->ignored_path = Qnil; dd_cov_data->mode = DD_COV_TARGET_FILES; return obj; } @@ -66,6 +94,8 @@ static VALUE dd_cov_initialize(int argc, VALUE *argv, VALUE self) rb_raise(rb_eArgError, "root is required"); } + VALUE rb_ignored_path = rb_hash_lookup(opt, ID2SYM(rb_intern("ignored_path"))); + VALUE rb_mode = rb_hash_lookup(opt, ID2SYM(rb_intern("mode"))); if (!RTEST(rb_mode) || rb_mode == ID2SYM(rb_intern("files"))) { @@ -84,6 +114,7 @@ static VALUE dd_cov_initialize(int argc, VALUE *argv, VALUE self) TypedData_Get_Struct(self, struct dd_cov_data, &dd_cov_data_type, dd_cov_data); dd_cov_data->root = rb_root; + dd_cov_data->ignored_path = rb_ignored_path; dd_cov_data->mode = mode; return Qnil; @@ -100,20 +131,15 @@ static void dd_cov_update_line_coverage(rb_event_flag_t event, VALUE data, VALUE return; } - if (dd_cov_data->root == Qnil) + // if given filename is not located under the root, we skip it + if (is_prefix(dd_cov_data->root, filename) == 0) { return; } - char *c_root = RSTRING_PTR(dd_cov_data->root); - if (c_root == NULL) - { - return; - } - long root_len = RSTRING_LEN(dd_cov_data->root); - // check that root is a prefix of the filename - // so this file is located under the given root - if (strncmp(c_root, filename, root_len) != 0) + // if ignored_path is provided and given filename is located under the ignored_path, we skip it too + // this is useful for ignoring bundled gems location + if (RTEST(dd_cov_data->ignored_path) && is_prefix(dd_cov_data->ignored_path, filename) == 1) { return; } diff --git a/lib/datadog/ci/itr/runner.rb b/lib/datadog/ci/itr/runner.rb index 76f0bc62..e35c857d 100644 --- a/lib/datadog/ci/itr/runner.rb +++ b/lib/datadog/ci/itr/runner.rb @@ -37,7 +37,12 @@ def initialize( @api = api @dd_env = dd_env @config_tags = config_tags || {} - @bundle_location = bundle_location + + @bundle_location = if bundle_location && !File.absolute_path?(bundle_location) + File.join(Git::LocalRepository.root, bundle_location) + else + bundle_location + end @test_skipping_enabled = false @code_coverage_enabled = false diff --git a/spec/datadog/ci/contrib/cucumber/features/step_definitions/helpers/helper.rb b/spec/datadog/ci/contrib/cucumber/features/step_definitions/helpers/helper.rb new file mode 100644 index 00000000..7a5019a7 --- /dev/null +++ b/spec/datadog/ci/contrib/cucumber/features/step_definitions/helpers/helper.rb @@ -0,0 +1,5 @@ +module Helper + def self.help? + true + end +end diff --git a/spec/datadog/ci/contrib/cucumber/features/step_definitions/steps.rb b/spec/datadog/ci/contrib/cucumber/features/step_definitions/steps.rb index 095fb0ca..93541356 100644 --- a/spec/datadog/ci/contrib/cucumber/features/step_definitions/steps.rb +++ b/spec/datadog/ci/contrib/cucumber/features/step_definitions/steps.rb @@ -1,5 +1,7 @@ +require_relative "helpers/helper" + Then "datadog" do - true + Helper.help? end Then "failure" do diff --git a/spec/datadog/ci/contrib/cucumber/instrumentation_spec.rb b/spec/datadog/ci/contrib/cucumber/instrumentation_spec.rb index ec9a6596..3b23acdc 100644 --- a/spec/datadog/ci/contrib/cucumber/instrumentation_spec.rb +++ b/spec/datadog/ci/contrib/cucumber/instrumentation_spec.rb @@ -16,6 +16,7 @@ let(:itr_enabled) { true } let(:code_coverage_enabled) { true } let(:tests_skipping_enabled) { true } + let(:bundle_path) { "step_definitions/helpers" } end let(:cucumber_8_or_above) { Gem::Version.new("8.0.0") <= Datadog::CI::Contrib::Cucumber::Integration.version } @@ -196,7 +197,7 @@ context "collecting coverage with features dir as root" do before { skip if PlatformHelpers.jruby? } - it "creates coverage events for each non-skipped test" do + it "creates coverage events for each non-skipped test ignoring bundle_path" do expect(coverage_events).to have(1).item expect_coverage_events_belong_to_session(test_session_span) diff --git a/spec/ddcov/ddcov_spec.rb b/spec/ddcov/ddcov_spec.rb index c78fb7c6..dbc48f22 100644 --- a/spec/ddcov/ddcov_spec.rb +++ b/spec/ddcov/ddcov_spec.rb @@ -19,7 +19,7 @@ def absolute_path(path) context "in files mode" do let(:mode) { :files } - context "when allocating and starting coverage without a root" do + context "when allocating and starting coverage without root" do it "does not fail" do cov = described_class.allocate cov.start @@ -57,6 +57,22 @@ def absolute_path(path) # this string will have a bunch of UTF-8 codepoints in it expect(coverage.keys.first).to include("calculator/code_with_") end + + context "when ignored_path is set" do + let(:ignored_path) { absolute_path("calculator/operations") } + + it "collects code coverage excluding ignored_path" do + subject.start + + expect(calculator.add(1, 2)).to eq(3) + expect(calculator.subtract(1, 2)).to eq(-1) + + coverage = subject.stop + + expect(coverage.size).to eq(1) + expect(coverage.keys).to include(absolute_path("calculator/calculator.rb")) + end + end end context "when root is in deeply nested dir" do From 6eddb658f4a60880a1e12b92eab0d68bf53dfecb Mon Sep 17 00:00:00 2001 From: Andrey Date: Mon, 13 May 2024 09:55:28 +0200 Subject: [PATCH 6/6] remove merge conflict artifacts --- lib/datadog/ci/configuration/settings.rb | 3 --- 1 file changed, 3 deletions(-) diff --git a/lib/datadog/ci/configuration/settings.rb b/lib/datadog/ci/configuration/settings.rb index d54f9c62..27be078b 100644 --- a/lib/datadog/ci/configuration/settings.rb +++ b/lib/datadog/ci/configuration/settings.rb @@ -98,9 +98,6 @@ def self.add_settings!(base) fetch_integration(integration_name).configuration end - # @deprecated Will be removed on datadog-ci-rb 1.0. - alias_method :use, :instrument - option :trace_flush option :writer_options do |o|