From 1e42f8730eb3ac830c6bcf7e0d648f6c894c616b Mon Sep 17 00:00:00 2001 From: Marco Costa Date: Thu, 2 Jan 2025 15:45:20 -0800 Subject: [PATCH] Add support for Kicks gem --- Matrixfile | 3 +- appraisal/generate.rb | 14 ++++--- appraisal/jruby-9.2.rb | 2 + appraisal/jruby-9.3.rb | 2 + appraisal/jruby-9.4.rb | 2 + appraisal/ruby-2.5.rb | 2 + appraisal/ruby-2.6.rb | 2 + appraisal/ruby-2.7.rb | 2 + appraisal/ruby-3.0.rb | 2 + appraisal/ruby-3.1.rb | 2 + appraisal/ruby-3.2.rb | 2 + appraisal/ruby-3.3.rb | 3 +- appraisal/ruby-3.4.rb | 2 + lib/datadog/tracing/contrib/registerable.rb | 11 ++++++ .../tracing/contrib/sneakers/integration.rb | 20 ++++++++-- sig/datadog/tracing/contrib/registerable.rbs | 2 + .../tracing/contrib/registerable_spec.rb | 38 +++++++++++++++++++ .../contrib/sneakers/integration_spec.rb | 33 ++++++++++++---- 18 files changed, 125 insertions(+), 19 deletions(-) diff --git a/Matrixfile b/Matrixfile index 9d2e8529dab..edf3055e0d3 100644 --- a/Matrixfile +++ b/Matrixfile @@ -168,7 +168,8 @@ 'contrib' => '✅ 2.5 / ✅ 2.6 / ✅ 2.7 / ✅ 3.0 / ✅ 3.1 / ✅ 3.2 / ✅ 3.3 / ✅ 3.4 / ✅ jruby' }, 'sneakers' => { - 'contrib' => '✅ 2.5 / ✅ 2.6 / ✅ 2.7 / ✅ 3.0 / ✅ 3.1 / ✅ 3.2 / ✅ 3.3 / ✅ 3.4 / ✅ jruby' + 'kicks-3' => '✅ 2.5 / ✅ 2.6 / ✅ 2.7 / ✅ 3.0 / ✅ 3.1 / ✅ 3.2 / ✅ 3.3 / ✅ 3.4 / ✅ jruby', + 'sneakers-2' => '✅ 2.5 / ✅ 2.6 / ✅ 2.7 / ✅ 3.0 / ✅ 3.1 / ✅ 3.2 / ✅ 3.3 / ✅ 3.4 / ✅ jruby', }, 'stripe' => { 'stripe-latest' => '✅ 2.5 / ✅ 2.6 / ✅ 2.7 / ✅ 3.0 / ✅ 3.1 / ✅ 3.2 / ✅ 3.3 / ✅ 3.4 / ✅ jruby', diff --git a/appraisal/generate.rb b/appraisal/generate.rb index 934a408f01a..c6022f43b99 100644 --- a/appraisal/generate.rb +++ b/appraisal/generate.rb @@ -49,12 +49,14 @@ # Builds a matrix of versions to test for a given integration -# `range`: the range of versions to test -# `gem` : optional, gem name to test (gem name can be different from the integration name) -# `min` : optional, minimum version to test -# `meta` : optional, additional metadata (development dependencies, etc.) for the group -def build_coverage_matrix(integration, range, gem: nil, min: nil, meta: {}) - gem ||= integration +# @param [String] integration the name of the integration to test +# @param [Range, Integer] range the range of major versions to test, or a single major version to test +# @param [String] gem optional, gem name to test (gem name can be different from the integration name) +# @param [String] min optional, minimum version to test +# @param [Hash] meta optional, additional metadata (development dependencies, etc.) for the group +def build_coverage_matrix(integration, range, gem: integration, min: nil, meta: {}) + # Allow single version to be passed easily + range = range..range if range.is_a?(Integer) if min appraise "#{integration}-min" do diff --git a/appraisal/jruby-9.2.rb b/appraisal/jruby-9.2.rb index 5e4073d035f..d60087e5fa3 100644 --- a/appraisal/jruby-9.2.rb +++ b/appraisal/jruby-9.2.rb @@ -202,6 +202,8 @@ build_coverage_matrix('stripe', 7..12, min: '5.15.0') build_coverage_matrix('opensearch', 2..3, gem: 'opensearch-ruby') build_coverage_matrix('elasticsearch', 7..8) +build_coverage_matrix('kicks', 3) +build_coverage_matrix('sneakers', 2) appraise 'relational_db' do gem 'activerecord', '~> 5' diff --git a/appraisal/jruby-9.3.rb b/appraisal/jruby-9.3.rb index f51344a8562..950c8d22edd 100644 --- a/appraisal/jruby-9.3.rb +++ b/appraisal/jruby-9.3.rb @@ -175,6 +175,8 @@ build_coverage_matrix('stripe', 7..12, min: '5.15.0') build_coverage_matrix('opensearch', 2..3, gem: 'opensearch-ruby') build_coverage_matrix('elasticsearch', 7..8) +build_coverage_matrix('kicks', 3) +build_coverage_matrix('sneakers', 2) appraise 'relational_db' do gem 'activerecord', '~> 6.0.0' diff --git a/appraisal/jruby-9.4.rb b/appraisal/jruby-9.4.rb index 947d54885cb..fd7a2cdcc59 100644 --- a/appraisal/jruby-9.4.rb +++ b/appraisal/jruby-9.4.rb @@ -79,6 +79,8 @@ build_coverage_matrix('stripe', 7..12, min: '5.15.0') build_coverage_matrix('opensearch', 2..3, gem: 'opensearch-ruby') build_coverage_matrix('elasticsearch', 7..8) +build_coverage_matrix('kicks', 3) +build_coverage_matrix('sneakers', 2) appraise 'relational_db' do gem 'activerecord', '~> 6.1.0' diff --git a/appraisal/ruby-2.5.rb b/appraisal/ruby-2.5.rb index 502c998055d..a62022fb94b 100644 --- a/appraisal/ruby-2.5.rb +++ b/appraisal/ruby-2.5.rb @@ -221,6 +221,8 @@ build_coverage_matrix('stripe', 7..12, min: '5.15.0') build_coverage_matrix('opensearch', 2..3, gem: 'opensearch-ruby') build_coverage_matrix('elasticsearch', 7..8) +build_coverage_matrix('kicks', 3) +build_coverage_matrix('sneakers', 2) appraise 'relational_db' do gem 'activerecord', '~> 5' diff --git a/appraisal/ruby-2.6.rb b/appraisal/ruby-2.6.rb index c89e19893c9..af0106ff975 100644 --- a/appraisal/ruby-2.6.rb +++ b/appraisal/ruby-2.6.rb @@ -174,6 +174,8 @@ build_coverage_matrix('stripe', 7..12, min: '5.15.0') build_coverage_matrix('opensearch', 2..3, gem: 'opensearch-ruby') build_coverage_matrix('elasticsearch', 7..8) +build_coverage_matrix('kicks', 3) +build_coverage_matrix('sneakers', 2) appraise 'relational_db' do gem 'activerecord', '~> 6.0.0' diff --git a/appraisal/ruby-2.7.rb b/appraisal/ruby-2.7.rb index 88b3b0f1e98..d00a8ce432b 100644 --- a/appraisal/ruby-2.7.rb +++ b/appraisal/ruby-2.7.rb @@ -174,6 +174,8 @@ build_coverage_matrix('stripe', 7..12, min: '5.15.0') build_coverage_matrix('opensearch', 2..3, gem: 'opensearch-ruby') build_coverage_matrix('elasticsearch', 7..8) +build_coverage_matrix('kicks', 3) +build_coverage_matrix('sneakers', 2) appraise 'relational_db' do gem 'activerecord', '~> 6.1.0' diff --git a/appraisal/ruby-3.0.rb b/appraisal/ruby-3.0.rb index ac024429e2f..80001e8bf2e 100644 --- a/appraisal/ruby-3.0.rb +++ b/appraisal/ruby-3.0.rb @@ -95,6 +95,8 @@ build_coverage_matrix('stripe', 7..12, min: '5.15.0') build_coverage_matrix('opensearch', 2..3, gem: 'opensearch-ruby') build_coverage_matrix('elasticsearch', 7..8) +build_coverage_matrix('kicks', 3) +build_coverage_matrix('sneakers', 2) appraise 'relational_db' do gem 'activerecord', '~> 7' diff --git a/appraisal/ruby-3.1.rb b/appraisal/ruby-3.1.rb index ac024429e2f..80001e8bf2e 100644 --- a/appraisal/ruby-3.1.rb +++ b/appraisal/ruby-3.1.rb @@ -95,6 +95,8 @@ build_coverage_matrix('stripe', 7..12, min: '5.15.0') build_coverage_matrix('opensearch', 2..3, gem: 'opensearch-ruby') build_coverage_matrix('elasticsearch', 7..8) +build_coverage_matrix('kicks', 3) +build_coverage_matrix('sneakers', 2) appraise 'relational_db' do gem 'activerecord', '~> 7' diff --git a/appraisal/ruby-3.2.rb b/appraisal/ruby-3.2.rb index ac024429e2f..80001e8bf2e 100644 --- a/appraisal/ruby-3.2.rb +++ b/appraisal/ruby-3.2.rb @@ -95,6 +95,8 @@ build_coverage_matrix('stripe', 7..12, min: '5.15.0') build_coverage_matrix('opensearch', 2..3, gem: 'opensearch-ruby') build_coverage_matrix('elasticsearch', 7..8) +build_coverage_matrix('kicks', 3) +build_coverage_matrix('sneakers', 2) appraise 'relational_db' do gem 'activerecord', '~> 7' diff --git a/appraisal/ruby-3.3.rb b/appraisal/ruby-3.3.rb index d361fcd68a7..62e3276fd1f 100644 --- a/appraisal/ruby-3.3.rb +++ b/appraisal/ruby-3.3.rb @@ -95,6 +95,8 @@ build_coverage_matrix('stripe', 7..12, min: '5.15.0') build_coverage_matrix('opensearch', 2..3, gem: 'opensearch-ruby') build_coverage_matrix('elasticsearch', 7..8) +build_coverage_matrix('kicks', 3) +build_coverage_matrix('sneakers', 2) appraise 'relational_db' do gem 'activerecord', '~> 7' @@ -131,7 +133,6 @@ gem 'roda', '>= 2.0.0' gem 'semantic_logger', '~> 4.0' gem 'sidekiq', '~> 7' - gem 'sneakers', '>= 2.12.0' gem 'sucker_punch' gem 'que', '>= 1.0.0' end diff --git a/appraisal/ruby-3.4.rb b/appraisal/ruby-3.4.rb index e83945820bc..22b38e8e050 100644 --- a/appraisal/ruby-3.4.rb +++ b/appraisal/ruby-3.4.rb @@ -95,6 +95,8 @@ build_coverage_matrix('stripe', 7..12, min: '5.15.0') build_coverage_matrix('opensearch', 2..3, gem: 'opensearch-ruby') build_coverage_matrix('elasticsearch', 7..8) +build_coverage_matrix('kicks', 3) +build_coverage_matrix('sneakers', 2) appraise 'relational_db' do # ActiveRecord locked because tests are failing with 7.1, which was attempted as a part of Ruby 3.4 testing in CI. diff --git a/lib/datadog/tracing/contrib/registerable.rb b/lib/datadog/tracing/contrib/registerable.rb index b9f4f936d66..997b1923a88 100644 --- a/lib/datadog/tracing/contrib/registerable.rb +++ b/lib/datadog/tracing/contrib/registerable.rb @@ -33,6 +33,17 @@ module ClassMethods def register_as(name, registry: Contrib::REGISTRY, auto_patch: false, **options) registry.add(name, new(name, **options), auto_patch) end + + # Registers this `alias_name` in the global tracer registry as an alias of `original_name`. + # Using `alias_name` or `original_name` become interchangeable. + # The configuration object is shared between the two names. + # The patcher will only run once if both are activated. + def register_as_alias(original_name, alias_name, registry: Contrib::REGISTRY) + original = registry[original_name] + raise ArgumentError, "integration '#{original_name}' not registered" unless original + + registry.add(alias_name, original, false) + end end # Instance methods for registerable behavior diff --git a/lib/datadog/tracing/contrib/sneakers/integration.rb b/lib/datadog/tracing/contrib/sneakers/integration.rb index 1b3b8f71a5e..fd12abda1e1 100644 --- a/lib/datadog/tracing/contrib/sneakers/integration.rb +++ b/lib/datadog/tracing/contrib/sneakers/integration.rb @@ -13,13 +13,25 @@ module Sneakers class Integration include Contrib::Integration - MINIMUM_VERSION = Gem::Version.new('2.12.0') + MINIMUM_SNEAKERS_VERSION = Gem::Version.new('2.12.0') + # All versions are supported. Kicks first version is 3.0.0. + MINIMUM_KICKS_VERSION = Gem::Version.new('3.0.0') # @public_api Changing the integration name or integration options can cause breaking changes register_as :sneakers, auto_patch: true - + register_as_alias :sneakers, :kicks + + # Sneakers development continues in the Kicks gem. + # The **only** thing that has changed is the gem name, + # even the file naming and module namespacing are the same (require 'sneakers', `::Sneakers`). + # + # The last version of Sneakers is 2.12.0. + # The first version of Kicks is 3.0.0. We currently support all versions of Kicks. + # + # @see https://github.com/jondot/sneakers/commit/9780692624c666b6db8266d2d5710f709cb0f2e2 def self.version - Gem.loaded_specs['sneakers'] && Gem.loaded_specs['sneakers'].version + Gem.loaded_specs['sneakers'] && Gem.loaded_specs['sneakers'].version || \ + Gem.loaded_specs['kicks'] && Gem.loaded_specs['kicks'].version end def self.loaded? @@ -27,7 +39,7 @@ def self.loaded? end def self.compatible? - super && version >= MINIMUM_VERSION + super && version >= MINIMUM_SNEAKERS_VERSION end def new_configuration diff --git a/sig/datadog/tracing/contrib/registerable.rbs b/sig/datadog/tracing/contrib/registerable.rbs index f08abbfd1e5..78201994c6d 100644 --- a/sig/datadog/tracing/contrib/registerable.rbs +++ b/sig/datadog/tracing/contrib/registerable.rbs @@ -5,6 +5,8 @@ module Datadog def self.included: (untyped base) -> untyped module ClassMethods def register_as: (untyped name, ?registry: untyped, ?auto_patch: bool, **untyped options) -> untyped + + def register_as_alias: (Symbol original_name, Symbol alias_name, registry: Registry) -> void end module InstanceMethods attr_reader name: untyped diff --git a/spec/datadog/tracing/contrib/registerable_spec.rb b/spec/datadog/tracing/contrib/registerable_spec.rb index a3d5ef7a1ae..5a0cf6ff057 100644 --- a/spec/datadog/tracing/contrib/registerable_spec.rb +++ b/spec/datadog/tracing/contrib/registerable_spec.rb @@ -58,6 +58,44 @@ end end end + + describe '#register_as_alias' do + subject(:register_as_alias) { registerable_class.register_as_alias(:original, :alias, **options) } + + context 'when a registry' do + context 'is provided' do + let(:options) { { registry: registry } } + let(:registry) { Datadog::Tracing::Contrib::Registry.new } + + context 'with the original integration not registered' do + it { expect { register_as_alias }.to raise_error(ArgumentError) } + end + + context 'with the original integration registered' do + before { registerable_class.register_as(:original, registry: registry) } + + it 'creates an alias to the original integration object' do + register_as_alias + expect(registry[:alias]).to be(registry[:original]) + end + end + end + + context 'is not provided' do + let(:options) { {} } + let(:registry) { Datadog::Tracing::Contrib::Registry.new } + + before { registerable_class.register_as(:original, registry: registry) } + + it 'invokes the global Datadog.registry' do + stub_const('Datadog::Tracing::Contrib::REGISTRY', registry) + + register_as_alias + expect(registry[:alias]).to be(registry[:original]) + end + end + end + end end describe 'instance behavior' do diff --git a/spec/datadog/tracing/contrib/sneakers/integration_spec.rb b/spec/datadog/tracing/contrib/sneakers/integration_spec.rb index 3a553a48c42..169dbbdcc8c 100644 --- a/spec/datadog/tracing/contrib/sneakers/integration_spec.rb +++ b/spec/datadog/tracing/contrib/sneakers/integration_spec.rb @@ -9,12 +9,17 @@ subject(:version) { described_class.version } context 'when the "sneakers" gem is loaded' do - include_context 'loaded gems', sneakers: described_class::MINIMUM_VERSION + include_context 'loaded gems', sneakers: described_class::MINIMUM_SNEAKERS_VERSION it { is_expected.to be_a_kind_of(Gem::Version) } end - context 'when "sneakers" gem is not loaded' do - include_context 'loaded gems', sneakers: nil + context 'when the "kicks" gem is loaded' do + include_context 'loaded gems', kicks: described_class::MINIMUM_KICKS_VERSION + it { is_expected.to be_a_kind_of(Gem::Version) } + end + + context 'when neither gem is not loaded' do + include_context 'loaded gems', sneakers: nil, kicks: nil it { is_expected.to be nil } end end @@ -40,18 +45,32 @@ context 'when "sneakers" gem is loaded with a version' do context 'that is less than the minimum' do - include_context 'loaded gems', sneakers: decrement_gem_version(described_class::MINIMUM_VERSION) + include_context 'loaded gems', + sneakers: decrement_gem_version(described_class::MINIMUM_SNEAKERS_VERSION), + kicks: nil + it { is_expected.to be false } + end + + context 'that meets the minimum version' do + include_context 'loaded gems', sneakers: described_class::MINIMUM_SNEAKERS_VERSION, kicks: nil + it { is_expected.to be true } + end + end + + context 'when "kicks" gem is loaded with a version' do + context 'that is less than the minimum' do + include_context 'loaded gems', sneakers: nil, kicks: decrement_gem_version(described_class::MINIMUM_KICKS_VERSION) it { is_expected.to be false } end context 'that meets the minimum version' do - include_context 'loaded gems', sneakers: described_class::MINIMUM_VERSION + include_context 'loaded gems', sneakers: nil, kicks: described_class::MINIMUM_KICKS_VERSION it { is_expected.to be true } end end - context 'when gem is not loaded' do - include_context 'loaded gems', sneakers: nil + context 'when neither gem is not loaded' do + include_context 'loaded gems', sneakers: nil, kicks: nil it { is_expected.to be false } end end