summaryrefslogtreecommitdiff
path: root/spec/deprecation_toolkit_env.rb
blob: a3f1bd0a26940c64f6df8b6b8afed18158174bdd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
# frozen_string_literal: true

require 'deprecation_toolkit'
require 'deprecation_toolkit/rspec'

module DeprecationToolkitEnv
  module DeprecationBehaviors
    class SelectiveRaise
      attr_reader :disallowed_deprecations_proc

      class RaiseDisallowedDeprecation < StandardError
        def initialize(test, current_deprecations)
          message = <<~EOF
            Disallowed deprecations detected while running test #{test}:

            #{current_deprecations.deprecations.join("\n")}
          EOF

          super(message)
        end
      end

      def initialize(disallowed_deprecations_proc)
        @disallowed_deprecations_proc = disallowed_deprecations_proc
      end

      # Note: trigger does not get called if the current_deprecations matches recorded_deprecations
      # See https://github.com/Shopify/deprecation_toolkit/blob/2398f38acb62220fb79a6cd720f61d9cea26bc06/lib/deprecation_toolkit/test_triggerer.rb#L8-L11
      def trigger(test, current_deprecations, recorded_deprecations)
        if selected_for_raise?(current_deprecations)
          raise RaiseDisallowedDeprecation.new(test, current_deprecations)
        elsif ENV['RECORD_DEPRECATIONS']
          record(test, current_deprecations, recorded_deprecations)
        end
      end

      private

      def selected_for_raise?(current_deprecations)
        disallowed_deprecations_proc.call(current_deprecations.deprecations_without_stacktrace)
      end

      def record(test, current_deprecations, recorded_deprecations)
        ::DeprecationToolkit::Behaviors::Record.trigger(test, current_deprecations, recorded_deprecations)
      end
    end
  end

  # Taken from https://github.com/jeremyevans/ruby-warning/blob/1.1.0/lib/warning.rb#L18
  def self.kwargs_warning
    %r{warning: (?:Using the last argument (?:for `.+' )?as keyword parameters is deprecated; maybe \*\* should be added to the call|Passing the keyword argument (?:for `.+' )?as the last hash parameter is deprecated|Splitting the last argument (?:for `.+' )?into positional and keyword parameters is deprecated|The called method (?:`.+' )?is defined here)\n\z}
  end

  # Allow these Gem paths to trigger keyword warnings as we upgrade these gems
  # one by one
  def self.allowed_kwarg_warning_paths
    %w[
      ee/lib/ee/gitlab/usage_data.rb
      spec/lib/gitlab/utils/usage_data_spec.rb
      spec/support/gitlab_experiment.rb
      spec/support/helpers/next_instance_of.rb
      rspec-mocks-3.10.0/lib/rspec/mocks/message_expectation.rb
      activerecord-6.0.3.4/lib/active_record/migration.rb
      devise-4.7.3/lib/devise/test/controller_helpers.rb
      attr_encrypted-3.1.0/lib/attr_encrypted/adapters/active_record.rb
      rspec-mocks-3.10.0/lib/rspec/mocks/message_expectation.rb
      rspec-expectations-3.10.0/lib/rspec/matchers/built_in/has.rb
      grape-1.5.1/lib/grape/middleware/stack.rb
      grape-1.5.1/lib/grape/validations/validators/coerce.rb
      grape_logging-1.8.3/lib/grape_logging/middleware/request_logger.rb
      activesupport-6.0.3.4/lib/active_support/cache.rb
      factory_bot-6.1.0/lib/factory_bot/decorator.rb
      doorkeeper-5.4.0/lib/doorkeeper/models/access_token_mixin.rb
      rouge-3.26.0/lib/rouge/formatter.rb
      batch-loader-1.4.0/lib/batch_loader/graphql.rb
      carrierwave-1.3.1/lib/carrierwave/sanitized_file.rb
      activerecord-6.0.3.4/lib/active_record/relation.rb
    ]
  end

  def self.configure!
    # Enable ruby deprecations for keywords, it's suppressed by default in Ruby 2.7.2
    Warning[:deprecated] = true

    DeprecationToolkit::Configuration.test_runner = :rspec
    DeprecationToolkit::Configuration.deprecation_path = 'deprecations'
    DeprecationToolkit::Configuration.warnings_treated_as_deprecation = [kwargs_warning]

    disallowed_deprecations = -> (deprecations) do
      deprecations.any? do |deprecation|
        kwargs_warning.match?(deprecation) &&
          allowed_kwarg_warning_paths.none? { |path| deprecation.include?(path) }
      end
    end

    DeprecationToolkit::Configuration.behavior = DeprecationBehaviors::SelectiveRaise.new(disallowed_deprecations)
  end
end