From 074cf3c28e5b08c8352fffdca09e8bb750abe0c2 Mon Sep 17 00:00:00 2001 From: Kyrylo Silin Date: Tue, 8 Jun 2021 19:23:23 +0300 Subject: [PATCH 01/50] gemspec: remove ethon dependency lock We no longer need this lock since the build passes fine without it. --- airbrake.gemspec | 4 ---- 1 file changed, 4 deletions(-) diff --git a/airbrake.gemspec b/airbrake.gemspec index f5f7abd0..b9fbd58b 100644 --- a/airbrake.gemspec +++ b/airbrake.gemspec @@ -50,10 +50,6 @@ DESC s.add_development_dependency 'httpclient', '~> 2.8' s.add_development_dependency 'typhoeus', '~> 1.3' - # Fixes build failure with ethon v0.13.0 - # https://app.circleci.com/pipelines/github/airbrake/airbrake/158/workflows/f22d902f-f0bb-449b-8b95-2a0ac76047f2 - s.add_development_dependency 'ethon', '= 0.12.0' - # Fixes build failure with public_suffix v3 # https://circleci.com/gh/airbrake/airbrake-ruby/889 s.add_development_dependency 'public_suffix', '~> 4.0', '< 5.0' From aa374af4c3999d20e1f26d93d7e897d5b8f4fb7f Mon Sep 17 00:00:00 2001 From: Kyrylo Silin Date: Mon, 20 Sep 2021 16:19:36 +0300 Subject: [PATCH 02/50] Bump Rubocop to '= 0.81' --- gemfiles/rack.gemfile | 2 +- gemfiles/rails_5.0.gemfile | 2 +- gemfiles/rails_5.1.gemfile | 2 +- gemfiles/rails_5.2.gemfile | 2 +- gemfiles/rails_6.0.gemfile | 2 +- gemfiles/sinatra.gemfile | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/gemfiles/rack.gemfile b/gemfiles/rack.gemfile index b30d6525..899701a4 100644 --- a/gemfiles/rack.gemfile +++ b/gemfiles/rack.gemfile @@ -2,7 +2,7 @@ source "https://rubygems.org" -gem "rubocop", "= 0.55", require: false +gem "rubocop", "= 0.81", require: false gem "warden", "~> 1.2.6" gemspec path: "../" diff --git a/gemfiles/rails_5.0.gemfile b/gemfiles/rails_5.0.gemfile index 1869db61..92ec038b 100644 --- a/gemfiles/rails_5.0.gemfile +++ b/gemfiles/rails_5.0.gemfile @@ -2,7 +2,7 @@ source "https://rubygems.org" -gem "rubocop", "= 0.55", require: false +gem "rubocop", "= 0.81", require: false gem "rails", "~> 5.0.7" gem "warden", "~> 1.2.3" gem "activerecord-jdbcsqlite3-adapter", "~> 1.3.18", platforms: :jruby diff --git a/gemfiles/rails_5.1.gemfile b/gemfiles/rails_5.1.gemfile index 3dd5ffd3..30219e7a 100644 --- a/gemfiles/rails_5.1.gemfile +++ b/gemfiles/rails_5.1.gemfile @@ -2,7 +2,7 @@ source "https://rubygems.org" -gem "rubocop", "= 0.55", require: false +gem "rubocop", "= 0.81", require: false gem "rails", "~> 5.1.4" gem "warden", "~> 1.2.6" gem "activerecord-jdbcsqlite3-adapter", "~> 51.0", platforms: :jruby diff --git a/gemfiles/rails_5.2.gemfile b/gemfiles/rails_5.2.gemfile index 1da3cd83..99275e45 100644 --- a/gemfiles/rails_5.2.gemfile +++ b/gemfiles/rails_5.2.gemfile @@ -2,7 +2,7 @@ source "https://rubygems.org" -gem "rubocop", "= 0.55", require: false +gem "rubocop", "= 0.81", require: false gem "rails", "~> 5.2.0" gem "warden", "~> 1.2.6" gem "rack", "~> 2.0" diff --git a/gemfiles/rails_6.0.gemfile b/gemfiles/rails_6.0.gemfile index 7e241d21..b46ad973 100644 --- a/gemfiles/rails_6.0.gemfile +++ b/gemfiles/rails_6.0.gemfile @@ -2,7 +2,7 @@ source "https://rubygems.org" -gem "rubocop", "= 0.55", require: false +gem "rubocop", "= 0.81", require: false gem "rails", "~> 6.0.2" gem "warden", "~> 1.2.6" gem "rack", "~> 2.0" diff --git a/gemfiles/sinatra.gemfile b/gemfiles/sinatra.gemfile index a87e20a1..592990d6 100644 --- a/gemfiles/sinatra.gemfile +++ b/gemfiles/sinatra.gemfile @@ -2,7 +2,7 @@ source "https://rubygems.org" -gem "rubocop", "= 0.55", require: false +gem "rubocop", "= 0.81", require: false gem "sinatra", "~> 2" gem "warden", "~> 1.2.6" From 017c1efd3b8b8c879e57da55d2d08e8a3f9eb5a5 Mon Sep 17 00:00:00 2001 From: Kyrylo Silin Date: Tue, 21 Sep 2021 12:07:31 +0300 Subject: [PATCH 03/50] spec/integration/rails: skip Typhoeus test on JRuby This spec segfaults on latest JRuby 9.2.19.0 in JVM. https://app.circleci.com/pipelines/github/airbrake/airbrake/227/workflows/3db05cae-87d8-4599-9da2-a37c4c76bf4f/jobs/9670 During an extensive debugging session I haven't been able to identify the root cause. I found an identical report from 2012 but it had no resolution: https://github.com/typhoeus/typhoeus/issues/202 I also found related links: * https://github.com/jruby/jruby/issues/231 * https://github.com/jruby/jruby/issues/752 --- spec/integration/rails/rails_spec.rb | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/spec/integration/rails/rails_spec.rb b/spec/integration/rails/rails_spec.rb index 762081dc..5797fbe3 100644 --- a/spec/integration/rails/rails_spec.rb +++ b/spec/integration/rails/rails_spec.rb @@ -478,6 +478,13 @@ def force_http_libs_prepend stub_request(:get, 'http://example.com').to_return(body: '') end + before do + # On JRuby 9.2.19.0 this fails with a SIGSEGV in JVM: + # https://bit.ly/3Everoa + # This is somehow related to libcurl.so. + skip('SIGSEGV on JRuby 9.2.19.0') if Airbrake::JRUBY + end + it "includes the http breakdown" do expect(Airbrake).to receive(:notify_performance_breakdown).with( hash_including(groups: { http: be > 0 }), From 692a3464074f7b7ac977b90ea0badffb8093a424 Mon Sep 17 00:00:00 2001 From: Kyrylo Silin Date: Mon, 20 Sep 2021 13:56:05 +0300 Subject: [PATCH 04/50] Dropped support for Ruby 2.3 & 2.4 Airbrake Ruby no longer supports these versions as of https://github.com/airbrake/airbrake-ruby/pull/663. --- .circleci/config.yml | 43 ------------------- .rubocop.yml | 2 +- CHANGELOG.md | 7 ++++ airbrake.gemspec | 2 +- lib/airbrake/delayed_job.rb | 58 +++++++++++++------------- lib/airbrake/sneakers.rb | 32 +++++++------- spec/support/matchers/a_notice_with.rb | 18 +------- 7 files changed, 53 insertions(+), 109 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 17b27aa9..1c5c7081 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -72,43 +72,6 @@ jobs: name: Verify all @since tag versions start with letter 'v' command: | ! egrep -r "# @since [0-9]" lib - "ruby-2.3": - docker: - - image: circleci/ruby:2.3 - auth: - username: $DOCKERHUB_USER - password: $DOCKERHUB_PASSWORD - working_directory: ~/airbrake - steps: - - <<: *repo_restore_cache - - <<: *bundle_install - - <<: *appraisal_install - - <<: *unit - - <<: *rails41 - - <<: *rails42 - - <<: *rails50 - - <<: *rails51 - - <<: *rails52 - - <<: *sinatra - - <<: *rack - "ruby-2.4": - docker: - - image: circleci/ruby:2.4 - auth: - username: $DOCKERHUB_USER - password: $DOCKERHUB_PASSWORD - working_directory: ~/airbrake - steps: - - <<: *repo_restore_cache - - <<: *bundle_install - - <<: *appraisal_install - - <<: *unit - - <<: *rails42 - - <<: *rails50 - - <<: *rails51 - - <<: *rails52 - - <<: *sinatra - - <<: *rack "ruby-2.5": docker: - image: circleci/ruby:2.5 @@ -187,12 +150,6 @@ workflows: build: jobs: - lint - - "ruby-2.3": - requires: - - lint - - "ruby-2.4": - requires: - - lint - "ruby-2.5": requires: - lint diff --git a/.rubocop.yml b/.rubocop.yml index 560391fc..786d52ed 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,7 +1,7 @@ # Explanations of all possible options: # https://github.com/bbatsov/rubocop/blob/master/config/default.yml AllCops: - TargetRubyVersion: 2.3 + TargetRubyVersion: 2.5 DisplayCopNames: true DisplayStyleGuide: true diff --git a/CHANGELOG.md b/CHANGELOG.md index a4f504c7..d73c55b6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,13 @@ Airbrake Changelog ### master +Breaking changes: + +* Dropped support for Ruby 2.3 + ([#1180](https://github.com/airbrake/airbrake/issues/1180)) +* Dropped support for Ruby 2.4 + ([#1180](https://github.com/airbrake/airbrake/issues/1180)) + ### [v11.0.3][v11.0.3] (May 13, 2021) * Fixed `Sneakers` integration when 3rd party code monkey-patches diff --git a/airbrake.gemspec b/airbrake.gemspec index b9fbd58b..c04ab7c1 100644 --- a/airbrake.gemspec +++ b/airbrake.gemspec @@ -28,7 +28,7 @@ DESC s.require_path = 'lib' s.files = ['lib/airbrake.rb', *Dir.glob('lib/**/*')] - s.required_ruby_version = '>= 2.3' + s.required_ruby_version = '>= 2.5' s.add_dependency 'airbrake-ruby', '~> 5.1' diff --git a/lib/airbrake/delayed_job.rb b/lib/airbrake/delayed_job.rb index 31fa47cb..76d07afe 100644 --- a/lib/airbrake/delayed_job.rb +++ b/lib/airbrake/delayed_job.rb @@ -7,41 +7,39 @@ module Plugins class Airbrake < ::Delayed::Plugin callbacks do |lifecycle| lifecycle.around(:invoke_job) do |job, *args, &block| - begin - timing = ::Airbrake::Benchmark.measure do - # Forward the call to the next callback in the callback chain - block.call(job, *args) - end - rescue Exception => exception # rubocop:disable Lint/RescueException - params = job.as_json + timing = ::Airbrake::Benchmark.measure do + # Forward the call to the next callback in the callback chain + block.call(job, *args) + end + rescue Exception => exception # rubocop:disable Lint/RescueException + params = job.as_json - # If DelayedJob is used through ActiveJob, it contains extra info. - if job.payload_object.respond_to?(:job_data) - params[:active_job] = job.payload_object.job_data - job_class = job.payload_object.job_data['job_class'] - end + # If DelayedJob is used through ActiveJob, it contains extra info. + if job.payload_object.respond_to?(:job_data) + params[:active_job] = job.payload_object.job_data + job_class = job.payload_object.job_data['job_class'] + end - action = job_class || job.payload_object.class.name + action = job_class || job.payload_object.class.name - ::Airbrake.notify(exception, params) do |notice| - notice[:context][:component] = 'delayed_job' - notice[:context][:action] = action - end + ::Airbrake.notify(exception, params) do |notice| + notice[:context][:component] = 'delayed_job' + notice[:context][:action] = action + end - ::Airbrake.notify_queue( - queue: action, - error_count: 1, - timing: 0.01, - ) + ::Airbrake.notify_queue( + queue: action, + error_count: 1, + timing: 0.01, + ) - raise exception - else - ::Airbrake.notify_queue( - queue: job_class || job.payload_object.class.name, - error_count: 0, - timing: timing, - ) - end + raise exception + else + ::Airbrake.notify_queue( + queue: job_class || job.payload_object.class.name, + error_count: 0, + timing: timing, + ) end end end diff --git a/lib/airbrake/sneakers.rb b/lib/airbrake/sneakers.rb index 035b7a72..7d4e22ba 100644 --- a/lib/airbrake/sneakers.rb +++ b/lib/airbrake/sneakers.rb @@ -48,24 +48,22 @@ module Worker define_method( ::Sneakers::Worker.method_defined?(:process_work) ? :process_work : :do_work, ) do |delivery_info, metadata, msg, handler| - begin - timing = Airbrake::Benchmark.measure do - super(delivery_info, metadata, msg, handler) - end - rescue Exception => exception # rubocop:disable Lint/RescueException - Airbrake.notify_queue( - queue: self.class.to_s, - error_count: 1, - timing: 0.01, - ) - raise exception - else - Airbrake.notify_queue( - queue: self.class.to_s, - error_count: 0, - timing: timing, - ) + timing = Airbrake::Benchmark.measure do + super(delivery_info, metadata, msg, handler) end + rescue Exception => exception # rubocop:disable Lint/RescueException + Airbrake.notify_queue( + queue: self.class.to_s, + error_count: 1, + timing: 0.01, + ) + raise exception + else + Airbrake.notify_queue( + queue: self.class.to_s, + error_count: 0, + timing: timing, + ) end end end diff --git a/spec/support/matchers/a_notice_with.rb b/spec/support/matchers/a_notice_with.rb index 518c2869..fb401d64 100644 --- a/spec/support/matchers/a_notice_with.rb +++ b/spec/support/matchers/a_notice_with.rb @@ -5,12 +5,7 @@ payload = notice[access_keys.shift] break(false) unless payload - actual_val = - if payload.respond_to?(:dig) - payload.dig(*access_keys) - else - dig_pre_23(payload, *access_keys) - end + actual_val = payload.dig(*access_keys) if expected_val.is_a?(Regexp) actual_val =~ expected_val @@ -18,15 +13,4 @@ actual_val == expected_val end end - - # TODO: Use the normal "dig" version once we support Ruby 2.3 and above. - def dig_pre_23(hash, *keys) - v = hash[keys.shift] - while keys.any? - return unless v.is_a?(Hash) - - v = v[keys.shift] - end - v - end end From 15a39ba7e9f107f1f54a4e84da9b8ac80acca6e1 Mon Sep 17 00:00:00 2001 From: Kyrylo Silin Date: Mon, 20 Sep 2021 12:32:32 +0300 Subject: [PATCH 05/50] gemspec: bump airbrake-ruby to `~> 6.0` --- CHANGELOG.md | 5 +++++ airbrake.gemspec | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d73c55b6..3a95a8b5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,11 @@ Breaking changes: * Dropped support for Ruby 2.4 ([#1180](https://github.com/airbrake/airbrake/issues/1180)) +Maintenance: + +* Bumped `airbrake-ruby` requirement to `~> 6.0` + ([#1181](https://github.com/airbrake/airbrake/issues/1181)) + ### [v11.0.3][v11.0.3] (May 13, 2021) * Fixed `Sneakers` integration when 3rd party code monkey-patches diff --git a/airbrake.gemspec b/airbrake.gemspec index c04ab7c1..37a797ad 100644 --- a/airbrake.gemspec +++ b/airbrake.gemspec @@ -30,7 +30,7 @@ DESC s.required_ruby_version = '>= 2.5' - s.add_dependency 'airbrake-ruby', '~> 5.1' + s.add_dependency 'airbrake-ruby', '~> 6.0' s.add_development_dependency 'rspec', '~> 3' s.add_development_dependency 'rspec-wait', '~> 0' From 0efd7163564bf5f37926a2934e7f30a88c73d99a Mon Sep 17 00:00:00 2001 From: Kyrylo Silin Date: Mon, 20 Sep 2021 10:16:10 +0300 Subject: [PATCH 06/50] generators: do not embed creds into the config file This is bad engineering practice as it violates [the twelve-factor app principles](https://12factor.net) (factor 3). --- README.md | 18 +-- lib/generators/airbrake_generator.rb | 9 +- lib/generators/airbrake_initializer.rb.erb | 130 ++++++++++----------- 3 files changed, 79 insertions(+), 78 deletions(-) diff --git a/README.md b/README.md index 4b56b073..29b1ba98 100644 --- a/README.md +++ b/README.md @@ -94,17 +94,21 @@ Configuration #### Integration -To integrate Airbrake with your Rails application, you need to know -your [project id and project key][project-idkey]. Invoke the following command -and replace `PROJECT_ID` and `PROJECT_KEY` with your values: +To integrate Airbrake with your Rails application, you need to know your +[project id and project key][project-idkey]. Set `AIRBRAKE_PROJECT_ID` & +`AIRBRAKE_PROJECT_KEY` environment variables with your project's values and +generate the Airbrake config: ```bash -rails g airbrake PROJECT_ID PROJECT_KEY +export AIRBRAKE_PROJECT_ID= +export AIRBRAKE_PROJECT_KEY= + +rails g airbrake ``` -[Heroku add-on][heroku-addon] users can omit specifying the key and the id and -invoke the command without arguments (Heroku add-on's environment variables will -be used) ([Heroku add-on docs][heroku-docs]): +[Heroku add-on][heroku-addon] users can omit specifying the key and the +id. Heroku add-on's environment variables will be used ([Heroku add-on +docs][heroku-docs]): ```bash rails g airbrake diff --git a/lib/generators/airbrake_generator.rb b/lib/generators/airbrake_generator.rb index afb3f5b3..1b1e252f 100644 --- a/lib/generators/airbrake_generator.rb +++ b/lib/generators/airbrake_generator.rb @@ -3,22 +3,19 @@ # Creates the Airbrake initializer file for Rails apps. # # @example Invokation from terminal -# rails generate airbrake PROJECT_KEY PROJECT_ID [NAME] +# rails generate airbrake [NAME] # class AirbrakeGenerator < Rails::Generators::Base # Adds current directory to source paths, so we can find the template file. source_root File.expand_path(__dir__) - argument :project_id, required: false - argument :project_key, required: false - # Makes the NAME option optional, which allows to subclass from Base, so we # can pass arguments to the ERB template. # - # @see http://asciicasts.com/episodes/218-making-generators-in-rails-3 + # @see https://asciicasts.com/episodes/218-making-generators-in-rails-3.html argument :name, type: :string, default: 'application' - desc 'Configures the Airbrake notifier with your project id and project key' + desc 'Configures the Airbrake notifier' def generate_layout template 'airbrake_initializer.rb.erb', 'config/initializers/airbrake.rb' end diff --git a/lib/generators/airbrake_initializer.rb.erb b/lib/generators/airbrake_initializer.rb.erb index 3f43d32f..23c83eaf 100644 --- a/lib/generators/airbrake_initializer.rb.erb +++ b/lib/generators/airbrake_initializer.rb.erb @@ -1,80 +1,80 @@ # frozen_string_literal: true -# Airbrake is an online tool that provides robust exception tracking in your Rails -# applications. In doing so, it allows you to easily review errors, tie an error -# to an individual piece of code, and trace the cause back to recent -# changes. Airbrake enables for easy categorization, searching, and prioritization -# of exceptions so that when errors occur, your team can quickly determine the -# root cause. +# Airbrake is an online tool that provides robust exception tracking in your +# Rails applications. In doing so, it allows you to easily review errors, tie an +# error to an individual piece of code, and trace the cause back to recent +# changes. Airbrake enables for easy categorization, searching, and +# prioritization of exceptions so that when errors occur, your team can quickly +# determine the root cause. # # Configuration details: # https://github.com/airbrake/airbrake-ruby#configuration -Airbrake.configure do |c| - # You must set both project_id & project_key. To find your project_id and - # project_key navigate to your project's General Settings and copy the values - # from the right sidebar. - # https://github.com/airbrake/airbrake-ruby#project_id--project_key -<% if project_id -%> - c.project_id = <%= project_id %> -<% else -%> - c.project_id = ENV['AIRBRAKE_PROJECT_ID'] -<% end -%> -<% if project_key -%> - c.project_key = '<%= project_key %>' -<% else -%> - c.project_key = ENV['AIRBRAKE_API_KEY'] -<% end -%> +if (project_id = ENV['AIRBRAKE_PROJECT_ID']) && + project_key = (ENV['AIRBRAKE_PROJECT_KEY'] || ENV['AIRBRAKE_API_KEY']) + Airbrake.configure do |c| + # You must set both project_id & project_key. To find your project_id and + # project_key navigate to your project's General Settings and copy the + # values from the right sidebar. + # https://github.com/airbrake/airbrake-ruby#project_id--project_key + c.project_id = project_id + c.project_key = project_key - # Configures the root directory of your project. Expects a String or a - # Pathname, which represents the path to your project. Providing this option - # helps us to filter out repetitive data from backtrace frames and link to - # GitHub files from our dashboard. - # https://github.com/airbrake/airbrake-ruby#root_directory - c.root_directory = Rails.root + # Configures the root directory of your project. Expects a String or a + # Pathname, which represents the path to your project. Providing this option + # helps us to filter out repetitive data from backtrace frames and link to + # GitHub files from our dashboard. + # https://github.com/airbrake/airbrake-ruby#root_directory + c.root_directory = Rails.root - # By default, Airbrake Ruby outputs to STDOUT. In Rails apps it makes sense to - # use the Rails' logger. - # https://github.com/airbrake/airbrake-ruby#logger - c.logger = Airbrake::Rails.logger + # By default, Airbrake Ruby outputs to STDOUT. In Rails apps it makes sense + # to use the Rails' logger. + # https://github.com/airbrake/airbrake-ruby#logger + c.logger = Airbrake::Rails.logger - # Configures the environment the application is running in. Helps the Airbrake - # dashboard to distinguish between exceptions occurring in different - # environments. - # NOTE: This option must be set in order to make the 'ignore_environments' - # option work. - # https://github.com/airbrake/airbrake-ruby#environment - c.environment = Rails.env + # Configures the environment the application is running in. Helps the + # Airbrake dashboard to distinguish between exceptions occurring in + # different environments. + # NOTE: This option must be set in order to make the 'ignore_environments' + # option work. + # https://github.com/airbrake/airbrake-ruby#environment + c.environment = Rails.env - # Setting this option allows Airbrake to filter exceptions occurring in - # unwanted environments such as :test. - # NOTE: This option *does not* work if you don't set the 'environment' option. - # https://github.com/airbrake/airbrake-ruby#ignore_environments - c.ignore_environments = %w[test] + # Setting this option allows Airbrake to filter exceptions occurring in + # unwanted environments such as :test. NOTE: This option *does not* work if + # you don't set the 'environment' option. + # https://github.com/airbrake/airbrake-ruby#ignore_environments + c.ignore_environments = %w[test] - # A list of parameters that should be filtered out of what is sent to - # Airbrake. By default, all "password" attributes will have their contents - # replaced. - # https://github.com/airbrake/airbrake-ruby#blocklist_keys - c.blocklist_keys = [/password/i, /authorization/i] + # A list of parameters that should be filtered out of what is sent to + # Airbrake. By default, all "password" attributes will have their contents + # replaced. + # https://github.com/airbrake/airbrake-ruby#blocklist_keys + c.blocklist_keys = [/password/i, /authorization/i] - # Alternatively, you can integrate with Rails' filter_parameters. - # Read more: https://goo.gl/gqQ1xS - # c.blocklist_keys = Rails.application.config.filter_parameters -end + # Alternatively, you can integrate with Rails' filter_parameters. + # Read more: https://goo.gl/gqQ1xS + # c.blocklist_keys = Rails.application.config.filter_parameters + end -# A filter that collects request body information. Enable it if you are sure you -# don't send sensitive information to Airbrake in your body (such as passwords). -# https://github.com/airbrake/airbrake#requestbodyfilter -# Airbrake.add_filter(Airbrake::Rack::RequestBodyFilter.new) + # A filter that collects request body information. Enable it if you are sure you + # don't send sensitive information to Airbrake in your body (such as passwords). + # https://github.com/airbrake/airbrake#requestbodyfilter + # Airbrake.add_filter(Airbrake::Rack::RequestBodyFilter.new) -# Attaches thread & fiber local variables along with general thread information. -# Airbrake.add_filter(Airbrake::Filters::ThreadFilter.new) + # Attaches thread & fiber local variables along with general thread information. + # Airbrake.add_filter(Airbrake::Filters::ThreadFilter.new) -# Attaches loaded dependencies to the notice object -# (under context/versions/dependencies). -# Airbrake.add_filter(Airbrake::Filters::DependencyFilter.new) + # Attaches loaded dependencies to the notice object + # (under context/versions/dependencies). + # Airbrake.add_filter(Airbrake::Filters::DependencyFilter.new) -# If you want to convert your log messages to Airbrake errors, we offer an -# integration with the Logger class from stdlib. -# https://github.com/airbrake/airbrake#logger -# Rails.logger = Airbrake::AirbrakeLogger.new(Rails.logger) + # If you want to convert your log messages to Airbrake errors, we offer an + # integration with the Logger class from stdlib. + # https://github.com/airbrake/airbrake#logger + # Rails.logger = Airbrake::AirbrakeLogger.new(Rails.logger) +else + Rails.logger.warn( + "#{__FILE__}: Airbrake project id or project key is not set. " \ + "Skipping Airbrake configuration" + ) +end From 19ff298f20341b7169c9880cf2361cf5e710eaeb Mon Sep 17 00:00:00 2001 From: Kyrylo Silin Date: Tue, 21 Sep 2021 18:12:06 +0300 Subject: [PATCH 07/50] Stop testing against old Rails versions (4.1, 4.2, 5.0, 5.1) The build fails on JRuby due to different reasons and debugging becomes a real pain. Running the build takes a long time as well. --- .circleci/config.yml | 24 ----------- Appraisals | 88 ++++---------------------------------- gemfiles/rails_4.0.gemfile | 15 ------- gemfiles/rails_4.1.gemfile | 17 -------- gemfiles/rails_4.2.gemfile | 17 -------- gemfiles/rails_5.0.gemfile | 16 ------- gemfiles/rails_5.1.gemfile | 17 -------- 7 files changed, 8 insertions(+), 186 deletions(-) delete mode 100644 gemfiles/rails_4.0.gemfile delete mode 100644 gemfiles/rails_4.1.gemfile delete mode 100644 gemfiles/rails_4.2.gemfile delete mode 100644 gemfiles/rails_5.0.gemfile delete mode 100644 gemfiles/rails_5.1.gemfile diff --git a/.circleci/config.yml b/.circleci/config.yml index 1c5c7081..7c37e821 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -21,22 +21,6 @@ references: run: name: Run unit tests command: bundle exec rake spec:unit - rails41: &rails41 - run: - name: Test Rails 4.1 - command: bundle exec appraisal rails-4.1 rake spec:integration:rails - rails42: &rails42 - run: - name: Test Rails 4.2 - command: bundle exec appraisal rails-4.2 rake spec:integration:rails - rails50: &rails50 - run: - name: Test Rails 5.0 - command: bundle exec appraisal rails-5.0 rake spec:integration:rails - rails51: &rails51 - run: - name: Test Rails 5.1 - command: bundle exec appraisal rails-5.1 rake spec:integration:rails rails52: &rails52 run: name: Test Rails 5.2 @@ -84,8 +68,6 @@ jobs: - <<: *bundle_install - <<: *appraisal_install - <<: *unit - - <<: *rails42 - - <<: *rails51 - <<: *rails52 - <<: *rails60 - <<: *sinatra @@ -102,9 +84,6 @@ jobs: - <<: *bundle_install - <<: *appraisal_install - <<: *unit - - <<: *rails42 - - <<: *rails50 - - <<: *rails51 - <<: *rails52 - <<: *rails60 - <<: *sinatra @@ -121,8 +100,6 @@ jobs: - <<: *bundle_install - <<: *appraisal_install - <<: *unit - - <<: *rails50 - - <<: *rails51 - <<: *rails52 - <<: *rails60 - <<: *sinatra @@ -139,7 +116,6 @@ jobs: - <<: *bundle_install - <<: *appraisal_install - <<: *unit - - <<: *rails51 - <<: *rails52 - <<: *rails60 - <<: *sinatra diff --git a/Appraisals b/Appraisals index 8d41fc41..c47554c7 100644 --- a/Appraisals +++ b/Appraisals @@ -1,62 +1,11 @@ # frozen_string_literal: true -if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.7.0') && RUBY_ENGINE != 'jruby' - appraise 'rails-4.1' do - gem 'rails', '~> 4.1.16' - gem 'warden', '~> 1.2.3' - - gem 'activerecord-jdbcsqlite3-adapter', '~> 1.3.18', platforms: :jruby - gem 'sqlite3', '~> 1.3.11', platforms: %i[mri rbx] - - gem 'resque', '~> 1.25.2' - gem 'resque_spec', github: 'airbrake/resque_spec' - - gem 'delayed_job_active_record', '~> 4.1.0' - - gem 'mime-types', '~> 3.1' - gem 'sprockets', '~> 3.7' - gem 'rack', '~> 1' - end - - appraise 'rails-4.2' do - gem 'rails', '~> 4.2.10' - gem 'warden', '~> 1.2.3' - - gem 'activerecord-jdbcsqlite3-adapter', '~> 1.3.18', platforms: :jruby - gem 'sqlite3', '~> 1.3.11', platforms: %i[mri rbx] - - gem 'resque', '~> 1.25.2' - gem 'resque_spec', github: 'airbrake/resque_spec' - - gem 'delayed_job_active_record', '~> 4.1.0' - - gem 'mime-types', '~> 3.1' - gem 'sprockets', '~> 3.7' - gem 'rack', '~> 1' - end -end - -appraise 'rails-5.0' do - gem 'rails', '~> 5.0.7' - gem 'warden', '~> 1.2.3' - - gem 'activerecord-jdbcsqlite3-adapter', '~> 1.3.18', platforms: :jruby - gem 'sqlite3', '~> 1.3.11', platforms: %i[mri rbx] - - gem 'resque', '~> 1.25.2' - gem 'resque_spec', github: 'airbrake/resque_spec' - - gem 'delayed_job_active_record', '~> 4.1.0' - - gem 'mime-types', '~> 3.1' - gem 'sprockets', '~> 3.7' -end - -appraise 'rails-5.1' do - gem 'rails', '~> 5.1.4' +appraise 'rails-5.2' do + gem 'rails', '~> 5.2.0' gem 'warden', '~> 1.2.6' + gem 'rack', '~> 2.0' - gem 'activerecord-jdbcsqlite3-adapter', '~> 51.0', platforms: :jruby + gem 'activerecord-jdbcsqlite3-adapter', '~> 52.0', platforms: :jruby gem 'sqlite3', '~> 1.3.11', platforms: %i[mri rbx] gem 'resque', '~> 1.26' @@ -66,16 +15,15 @@ appraise 'rails-5.1' do gem 'delayed_job_active_record', '~> 4.1' gem 'mime-types', '~> 3.1' - gem 'sprockets', '~> 3.7' end -appraise 'rails-5.2' do - gem 'rails', '~> 5.2.0' +appraise 'rails-6.0' do + gem 'rails', '~> 6.0.2' gem 'warden', '~> 1.2.6' gem 'rack', '~> 2.0' - gem 'activerecord-jdbcsqlite3-adapter', '~> 52.0', platforms: :jruby - gem 'sqlite3', '~> 1.3.11', platforms: %i[mri rbx] + gem 'activerecord-jdbcsqlite3-adapter', '~> 60.1', platforms: :jruby + gem 'sqlite3', '~> 1.4', platforms: %i[mri rbx] gem 'resque', '~> 1.26' gem 'resque_spec', github: 'airbrake/resque_spec' @@ -86,26 +34,6 @@ appraise 'rails-5.2' do gem 'mime-types', '~> 3.1' end -# Rails 6.0+ supports only modern Rubies (2.5+) -if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('2.5') - appraise 'rails-6.0' do - gem 'rails', '~> 6.0.2' - gem 'warden', '~> 1.2.6' - gem 'rack', '~> 2.0' - - gem 'activerecord-jdbcsqlite3-adapter', '~> 60.1', platforms: :jruby - gem 'sqlite3', '~> 1.4', platforms: %i[mri rbx] - - gem 'resque', '~> 1.26' - gem 'resque_spec', github: 'airbrake/resque_spec' - - gem 'delayed_job', github: 'collectiveidea/delayed_job' - gem 'delayed_job_active_record', '~> 4.1' - - gem 'mime-types', '~> 3.1' - end -end - appraise 'sinatra' do gem 'sinatra', '~> 2' gem 'warden', '~> 1.2.6' diff --git a/gemfiles/rails_4.0.gemfile b/gemfiles/rails_4.0.gemfile deleted file mode 100644 index b2b99eee..00000000 --- a/gemfiles/rails_4.0.gemfile +++ /dev/null @@ -1,15 +0,0 @@ -# This file was generated by Appraisal - -source "https://rubygems.org" - -gem "rubocop", "= 0.51", require: false -gem "rails", "~> 4.0.13" -gem "warden", "~> 1.2.3" -gem "activerecord-jdbcsqlite3-adapter", "~> 1.3.18", platforms: :jruby -gem "sqlite3", "~> 1.3.11", platforms: [:mri, :rbx] -gem "resque", "~> 1.25.2" -gem "resque_spec", github: "airbrake/resque_spec" -gem "delayed_job_active_record", "~> 4.1.0" -gem "mime-types", "~> 3.1" - -gemspec path: "../" diff --git a/gemfiles/rails_4.1.gemfile b/gemfiles/rails_4.1.gemfile deleted file mode 100644 index 0cab4cba..00000000 --- a/gemfiles/rails_4.1.gemfile +++ /dev/null @@ -1,17 +0,0 @@ -# This file was generated by Appraisal - -source "https://rubygems.org" - -gem "rubocop", "= 0.55", require: false -gem "rails", "~> 4.1.16" -gem "warden", "~> 1.2.3" -gem "activerecord-jdbcsqlite3-adapter", "~> 1.3.18", platforms: :jruby -gem "sqlite3", "~> 1.3.11", platforms: [:mri, :rbx] -gem "resque", "~> 1.25.2" -gem "resque_spec", github: "airbrake/resque_spec" -gem "delayed_job_active_record", "~> 4.1.0" -gem "mime-types", "~> 3.1" -gem "sprockets", "~> 3.7" -gem "rack", "~> 1" - -gemspec path: "../" diff --git a/gemfiles/rails_4.2.gemfile b/gemfiles/rails_4.2.gemfile deleted file mode 100644 index 5776db59..00000000 --- a/gemfiles/rails_4.2.gemfile +++ /dev/null @@ -1,17 +0,0 @@ -# This file was generated by Appraisal - -source "https://rubygems.org" - -gem "rubocop", "= 0.55", require: false -gem "rails", "~> 4.2.10" -gem "warden", "~> 1.2.3" -gem "activerecord-jdbcsqlite3-adapter", "~> 1.3.18", platforms: :jruby -gem "sqlite3", "~> 1.3.11", platforms: [:mri, :rbx] -gem "resque", "~> 1.25.2" -gem "resque_spec", github: "airbrake/resque_spec" -gem "delayed_job_active_record", "~> 4.1.0" -gem "mime-types", "~> 3.1" -gem "sprockets", "~> 3.7" -gem "rack", "~> 1" - -gemspec path: "../" diff --git a/gemfiles/rails_5.0.gemfile b/gemfiles/rails_5.0.gemfile deleted file mode 100644 index 92ec038b..00000000 --- a/gemfiles/rails_5.0.gemfile +++ /dev/null @@ -1,16 +0,0 @@ -# This file was generated by Appraisal - -source "https://rubygems.org" - -gem "rubocop", "= 0.81", require: false -gem "rails", "~> 5.0.7" -gem "warden", "~> 1.2.3" -gem "activerecord-jdbcsqlite3-adapter", "~> 1.3.18", platforms: :jruby -gem "sqlite3", "~> 1.3.11", platforms: [:mri, :rbx] -gem "resque", "~> 1.25.2" -gem "resque_spec", github: "airbrake/resque_spec" -gem "delayed_job_active_record", "~> 4.1.0" -gem "mime-types", "~> 3.1" -gem "sprockets", "~> 3.7" - -gemspec path: "../" diff --git a/gemfiles/rails_5.1.gemfile b/gemfiles/rails_5.1.gemfile deleted file mode 100644 index 30219e7a..00000000 --- a/gemfiles/rails_5.1.gemfile +++ /dev/null @@ -1,17 +0,0 @@ -# This file was generated by Appraisal - -source "https://rubygems.org" - -gem "rubocop", "= 0.81", require: false -gem "rails", "~> 5.1.4" -gem "warden", "~> 1.2.6" -gem "activerecord-jdbcsqlite3-adapter", "~> 51.0", platforms: :jruby -gem "sqlite3", "~> 1.3.11", platforms: [:mri, :rbx] -gem "resque", "~> 1.26" -gem "resque_spec", github: "airbrake/resque_spec" -gem "delayed_job", github: "collectiveidea/delayed_job" -gem "delayed_job_active_record", "~> 4.1" -gem "mime-types", "~> 3.1" -gem "sprockets", "~> 3.7" - -gemspec path: "../" From d1cb978c0eed317ec029afc8f067d8b477d043a9 Mon Sep 17 00:00:00 2001 From: Kyrylo Silin Date: Tue, 21 Sep 2021 13:38:06 +0300 Subject: [PATCH 08/50] Replace CircleCI with GitHub Actions --- .circleci/config.yml | 140 ------------------------------------- .github/workflows/test.yml | 53 ++++++++++++++ 2 files changed, 53 insertions(+), 140 deletions(-) delete mode 100644 .circleci/config.yml create mode 100644 .github/workflows/test.yml diff --git a/.circleci/config.yml b/.circleci/config.yml deleted file mode 100644 index 7c37e821..00000000 --- a/.circleci/config.yml +++ /dev/null @@ -1,140 +0,0 @@ -version: 2 -references: - repo_restore_cache: &repo_restore_cache - restore_cache: - keys: - - repo-{{ .Environment.CIRCLE_SHA1 }} - repo_save_cache: &repo_save_cache - save_cache: - key: repo-{{ .Environment.CIRCLE_SHA1 }}-{{ epoch }} - paths: - - ~/airbrake - bundle_install: &bundle_install - run: - name: Install Bundler dependencies - command: bundle install --path ~/airbrake/vendor/bundle --jobs 15 - appraisal_install: &appraisal_install - run: - name: Install Appraisal dependencies - command: bundle exec appraisal install --jobs 15 - unit: &unit - run: - name: Run unit tests - command: bundle exec rake spec:unit - rails52: &rails52 - run: - name: Test Rails 5.2 - command: bundle exec appraisal rails-5.2 rake spec:integration:rails - rails60: &rails60 - run: - name: Test Rails 6.0 - command: bundle exec appraisal rails-6.0 rake spec:integration:rails - sinatra: &sinatra - run: - name: Test Sinatra - command: bundle exec appraisal sinatra rake spec:integration:sinatra - rack: &rack - run: - name: Test Rack - command: bundle exec appraisal rack rake spec:integration:rack -jobs: - lint: - docker: - - image: circleci/ruby:2.7 - auth: - username: $DOCKERHUB_USER - password: $DOCKERHUB_PASSWORD - working_directory: ~/airbrake - steps: - - checkout - - <<: *repo_save_cache - - <<: *bundle_install - - run: - name: Run RuboCop linting - command: bundle exec rubocop --parallel - - run: - name: Verify all @since tag versions start with letter 'v' - command: | - ! egrep -r "# @since [0-9]" lib - "ruby-2.5": - docker: - - image: circleci/ruby:2.5 - auth: - username: $DOCKERHUB_USER - password: $DOCKERHUB_PASSWORD - working_directory: ~/airbrake - steps: - - <<: *repo_restore_cache - - <<: *bundle_install - - <<: *appraisal_install - - <<: *unit - - <<: *rails52 - - <<: *rails60 - - <<: *sinatra - - <<: *rack - "ruby-2.6": - docker: - - image: circleci/ruby:2.6 - auth: - username: $DOCKERHUB_USER - password: $DOCKERHUB_PASSWORD - working_directory: ~/airbrake - steps: - - <<: *repo_restore_cache - - <<: *bundle_install - - <<: *appraisal_install - - <<: *unit - - <<: *rails52 - - <<: *rails60 - - <<: *sinatra - - <<: *rack - "ruby-2.7": - docker: - - image: circleci/ruby:2.7 - auth: - username: $DOCKERHUB_USER - password: $DOCKERHUB_PASSWORD - working_directory: ~/airbrake - steps: - - <<: *repo_restore_cache - - <<: *bundle_install - - <<: *appraisal_install - - <<: *unit - - <<: *rails52 - - <<: *rails60 - - <<: *sinatra - - <<: *rack - "jruby-9.2": - docker: - - image: circleci/jruby:9.2 - auth: - username: $DOCKERHUB_USER - password: $DOCKERHUB_PASSWORD - working_directory: ~/airbrake - steps: - - <<: *repo_restore_cache - - <<: *bundle_install - - <<: *appraisal_install - - <<: *unit - - <<: *rails52 - - <<: *rails60 - - <<: *sinatra - - <<: *rack - -workflows: - version: 2 - build: - jobs: - - lint - - "ruby-2.5": - requires: - - lint - - "ruby-2.6": - requires: - - lint - - "ruby-2.7": - requires: - - lint - - "jruby-9.2": - requires: - - lint diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 00000000..57950a2b --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,53 @@ +name: airbrake + +on: [push] + +jobs: + test: + strategy: + matrix: + os: [ubuntu-latest] + ruby: [2.5, 2.6, 2.7, jruby] + + runs-on: ${{ matrix.os }} + + steps: + - uses: actions/checkout@v2 + + - name: Update package list + run: sudo apt-get update + + - name: Install cURL Headers + run: sudo apt-get install libcurl4 libcurl4-openssl-dev + + - uses: ruby/setup-ruby@v1 + with: + ruby-version: ${{ matrix.ruby }} + bundler-cache: true + + - name: Rubocop lint + run: bundle exec rubocop + + - name: Install Bundler dependencies + run: bundle install + + - name: Install Appraisal dependencies + run: bundle exec appraisal install + + - name: Display Ruby version + run: ruby -v + + - name: Unit tests + run: bundle exec rake spec:unit + + - name: Test Rails 5.2 + run: bundle exec appraisal rails-5.2 rake spec:integration:rails + + - name: Test Rails 6.0 + run: bundle exec appraisal rails-6.0 rake spec:integration:rails + + - name: Test Sinatra + run: bundle exec appraisal sinatra rake spec:integration:sinatra + + - name: Test Rack + run: bundle exec appraisal rack rake spec:integration:rack From 50b407399c7dcaeb657fcf4633759780ca53c871 Mon Sep 17 00:00:00 2001 From: Kyrylo Silin Date: Tue, 21 Sep 2021 19:06:45 +0300 Subject: [PATCH 09/50] Appraisals: bump sqlite3 dependency to v1.4 --- Appraisals | 2 +- gemfiles/rails_5.2.gemfile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Appraisals b/Appraisals index c47554c7..bc558e03 100644 --- a/Appraisals +++ b/Appraisals @@ -6,7 +6,7 @@ appraise 'rails-5.2' do gem 'rack', '~> 2.0' gem 'activerecord-jdbcsqlite3-adapter', '~> 52.0', platforms: :jruby - gem 'sqlite3', '~> 1.3.11', platforms: %i[mri rbx] + gem 'sqlite3', '~> 1.4', platforms: %i[mri rbx] gem 'resque', '~> 1.26' gem 'resque_spec', github: 'airbrake/resque_spec' diff --git a/gemfiles/rails_5.2.gemfile b/gemfiles/rails_5.2.gemfile index 99275e45..5a4012a6 100644 --- a/gemfiles/rails_5.2.gemfile +++ b/gemfiles/rails_5.2.gemfile @@ -7,7 +7,7 @@ gem "rails", "~> 5.2.0" gem "warden", "~> 1.2.6" gem "rack", "~> 2.0" gem "activerecord-jdbcsqlite3-adapter", "~> 52.0", platforms: :jruby -gem "sqlite3", "~> 1.3.11", platforms: [:mri, :rbx] +gem "sqlite3", "~> 1.4", platforms: [:mri, :rbx] gem "resque", "~> 1.26" gem "resque_spec", github: "airbrake/resque_spec" gem "delayed_job", github: "collectiveidea/delayed_job" From 5a78297820147999a33c0becd1df6b20d8e7621e Mon Sep 17 00:00:00 2001 From: Kyrylo Silin Date: Tue, 21 Sep 2021 19:12:47 +0300 Subject: [PATCH 10/50] spec/apps: fix warning about redefined constants DummyApp is defined by both Rack and Rails tests. Let's not shadow constants. --- spec/apps/rack/{dummy_app.rb => rack_app.rb} | 2 +- spec/integration/rack/rack_spec.rb | 2 +- spec/spec_helper.rb | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) rename spec/apps/rack/{dummy_app.rb => rack_app.rb} (91%) diff --git a/spec/apps/rack/dummy_app.rb b/spec/apps/rack/rack_app.rb similarity index 91% rename from spec/apps/rack/dummy_app.rb rename to spec/apps/rack/rack_app.rb index a3e6f260..4ee0f412 100644 --- a/spec/apps/rack/dummy_app.rb +++ b/spec/apps/rack/rack_app.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -DummyApp = Rack::Builder.new do +RackApp = Rack::Builder.new do use Rack::ShowExceptions use Airbrake::Rack::Middleware use Warden::Manager diff --git a/spec/integration/rack/rack_spec.rb b/spec/integration/rack/rack_spec.rb index 83a1107c..52a57c6b 100644 --- a/spec/integration/rack/rack_spec.rb +++ b/spec/integration/rack/rack_spec.rb @@ -3,7 +3,7 @@ require 'integration/shared_examples/rack_examples' RSpec.describe "Rack integration specs" do - let(:app) { DummyApp } + let(:app) { RackApp } include_examples 'rack examples' diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 6b3c274c..4fe35e7e 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -97,7 +97,7 @@ # Don't load the Rack app since we want to test Sinatra if it's loaded. raise LoadError if defined?(Sinatra) - require 'apps/rack/dummy_app' + require 'apps/rack/rack_app' rescue LoadError puts '** Skipped Rack specs' end From d48186501f1ae07858be891db431297737fba453 Mon Sep 17 00:00:00 2001 From: Kyrylo Silin Date: Tue, 21 Sep 2021 18:37:26 +0300 Subject: [PATCH 11/50] .github/workflows: test against Ruby 3.0 and Rails 6.0 --- .github/workflows/test.yml | 4 +++- Appraisals | 27 +++++++++++++++------------ gemfiles/rails_6.0.gemfile | 2 +- spec/apps/rails/dummy_app.rb | 23 ++++++++++------------- 4 files changed, 29 insertions(+), 27 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 57950a2b..4f13b45f 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -7,7 +7,8 @@ jobs: strategy: matrix: os: [ubuntu-latest] - ruby: [2.5, 2.6, 2.7, jruby] + # Due to https://github.com/actions/runner/issues/849, we have to use quotes for '3.0' + ruby: [2.5, 2.6, 2.7, '3.0', jruby] runs-on: ${{ matrix.os }} @@ -41,6 +42,7 @@ jobs: run: bundle exec rake spec:unit - name: Test Rails 5.2 + if: ${{ matrix.ruby != '3.0' }} run: bundle exec appraisal rails-5.2 rake spec:integration:rails - name: Test Rails 6.0 diff --git a/Appraisals b/Appraisals index bc558e03..577ea144 100644 --- a/Appraisals +++ b/Appraisals @@ -1,24 +1,27 @@ # frozen_string_literal: true -appraise 'rails-5.2' do - gem 'rails', '~> 5.2.0' - gem 'warden', '~> 1.2.6' - gem 'rack', '~> 2.0' +# Rails 5 doesn't work on Ruby 3+. +if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('3.0.0') + appraise 'rails-5.2' do + gem 'rails', '~> 5.2.0' + gem 'warden', '~> 1.2.6' + gem 'rack', '~> 2.0' - gem 'activerecord-jdbcsqlite3-adapter', '~> 52.0', platforms: :jruby - gem 'sqlite3', '~> 1.4', platforms: %i[mri rbx] + gem 'activerecord-jdbcsqlite3-adapter', '~> 52.0', platforms: :jruby + gem 'sqlite3', '~> 1.4', platforms: %i[mri rbx] - gem 'resque', '~> 1.26' - gem 'resque_spec', github: 'airbrake/resque_spec' + gem 'resque', '~> 1.26' + gem 'resque_spec', github: 'airbrake/resque_spec' - gem 'delayed_job', github: 'collectiveidea/delayed_job' - gem 'delayed_job_active_record', '~> 4.1' + gem 'delayed_job', github: 'collectiveidea/delayed_job' + gem 'delayed_job_active_record', '~> 4.1' - gem 'mime-types', '~> 3.1' + gem 'mime-types', '~> 3.1' + end end appraise 'rails-6.0' do - gem 'rails', '~> 6.0.2' + gem 'rails', '~> 6.0.4.1' gem 'warden', '~> 1.2.6' gem 'rack', '~> 2.0' diff --git a/gemfiles/rails_6.0.gemfile b/gemfiles/rails_6.0.gemfile index b46ad973..240d4b09 100644 --- a/gemfiles/rails_6.0.gemfile +++ b/gemfiles/rails_6.0.gemfile @@ -3,7 +3,7 @@ source "https://rubygems.org" gem "rubocop", "= 0.81", require: false -gem "rails", "~> 6.0.2" +gem "rails", "~> 6.0.4.1" gem "warden", "~> 1.2.6" gem "rack", "~> 2.0" gem "activerecord-jdbcsqlite3-adapter", "~> 60.1", platforms: :jruby diff --git a/spec/apps/rails/dummy_app.rb b/spec/apps/rails/dummy_app.rb index 53840824..260a3f53 100644 --- a/spec/apps/rails/dummy_app.rb +++ b/spec/apps/rails/dummy_app.rb @@ -73,22 +73,19 @@ def raise_error_after_rollback end end -# ActiveJob. -if Gem::Version.new(Rails.version) >= Gem::Version.new('4.2') - class BingoJob < ActiveJob::Base - queue_as :bingo - - class BingoWrapper - def initialize(bingo) - @bingo = bingo - end - end +class BingoJob < ActiveJob::Base + queue_as :bingo - def perform(*_args) - @wrapper = BingoWrapper.new(self) - raise AirbrakeTestError, 'active_job error' + class BingoWrapper + def initialize(bingo) + @bingo = bingo end end + + def perform(*_args) + @wrapper = BingoWrapper.new(self) + raise AirbrakeTestError, 'active_job error' + end end # Resque. From 60601bbf70d55c9420af5a671a3345e1573a7604 Mon Sep 17 00:00:00 2001 From: Kyrylo Silin Date: Wed, 22 Sep 2021 11:47:26 +0300 Subject: [PATCH 12/50] Test against Rails 6.1 and fix broken tests Rails 6.1 deprecates rendering actions with `.` in the name, which breaks some of our tests. We expect the `view` param in the breakdown to be present, but it's not anymore due to this warning. Fixing the warning fixes the tests. When I made this change, other routes started to include the `view` param as well, therefore I added it to make other tests pass. --- .github/workflows/test.yml | 3 +++ Appraisals | 17 +++++++++++++++++ gemfiles/rails_6.1.gemfile | 17 +++++++++++++++++ spec/apps/rails/dummy_app.rb | 18 +++++++++--------- spec/integration/rails/rails_spec.rb | 8 ++++---- 5 files changed, 50 insertions(+), 13 deletions(-) create mode 100644 gemfiles/rails_6.1.gemfile diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 4f13b45f..2394f37f 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -48,6 +48,9 @@ jobs: - name: Test Rails 6.0 run: bundle exec appraisal rails-6.0 rake spec:integration:rails + - name: Test Rails 6.1 + run: bundle exec appraisal rails-6.1 rake spec:integration:rails + - name: Test Sinatra run: bundle exec appraisal sinatra rake spec:integration:sinatra diff --git a/Appraisals b/Appraisals index 577ea144..a8d0de9e 100644 --- a/Appraisals +++ b/Appraisals @@ -37,6 +37,23 @@ appraise 'rails-6.0' do gem 'mime-types', '~> 3.1' end +appraise 'rails-6.1' do + gem 'rails', '~> 6.1.4.1' + gem 'warden', '~> 1.2.6' + gem 'rack', '~> 2.0' + + gem 'activerecord-jdbcsqlite3-adapter', '~> 60.1', platforms: :jruby + gem 'sqlite3', '~> 1.4', platforms: %i[mri rbx] + + gem 'resque', '~> 1.26' + gem 'resque_spec', github: 'airbrake/resque_spec' + + gem 'delayed_job', github: 'collectiveidea/delayed_job' + gem 'delayed_job_active_record', '~> 4.1' + + gem 'mime-types', '~> 3.1' +end + appraise 'sinatra' do gem 'sinatra', '~> 2' gem 'warden', '~> 1.2.6' diff --git a/gemfiles/rails_6.1.gemfile b/gemfiles/rails_6.1.gemfile new file mode 100644 index 00000000..6e8a087f --- /dev/null +++ b/gemfiles/rails_6.1.gemfile @@ -0,0 +1,17 @@ +# This file was generated by Appraisal + +source "https://rubygems.org" + +gem "rubocop", "= 0.81", require: false +gem "rails", "~> 6.1.4.1" +gem "warden", "~> 1.2.6" +gem "rack", "~> 2.0" +gem "activerecord-jdbcsqlite3-adapter", "~> 60.1", platforms: :jruby +gem "sqlite3", "~> 1.4", platforms: [:mri, :rbx] +gem "resque", "~> 1.26" +gem "resque_spec", github: "airbrake/resque_spec" +gem "delayed_job", github: "collectiveidea/delayed_job" +gem "delayed_job_active_record", "~> 4.1" +gem "mime-types", "~> 3.1" + +gemspec path: "../" diff --git a/spec/apps/rails/dummy_app.rb b/spec/apps/rails/dummy_app.rb index 260a3f53..428eacdb 100644 --- a/spec/apps/rails/dummy_app.rb +++ b/spec/apps/rails/dummy_app.rb @@ -144,47 +144,47 @@ def breakdown end def breakdown_view_only - render 'dummy/breakdown.html.erb' + render 'dummy/breakdown', format: [:erb] end def breakdown_http Net::HTTP.get('example.com', '/') - render 'dummy/breakdown_http.html.erb' + render 'dummy/breakdown_http', format: [:erb] end def breakdown_curl_http Curl.get('example.com') - render 'dummy/breakdown_curl_http.html.erb' + render 'dummy/breakdown_curl_http', format: [:erb] end def breakdown_curl_http_easy Curl::Easy.perform('example.com') - render 'dummy/breakdown_curl_http_easy.html.erb' + render 'dummy/breakdown_curl_http_easy', format: [:erb] end def breakdown_curl_http_multi Curl::Multi.get(['example.com']) - render 'dummy/breakdown_curl_http_multi.html.erb' + render 'dummy/breakdown_curl_http_multi', format: [:erb] end def breakdown_excon Excon.get('http://example.com') - render 'dummy/breakdown_excon.html.erb' + render 'dummy/breakdown_excon', format: [:erb] end def breakdown_http_rb HTTP.get('http://example.com') - render 'dummy/breakdown_http_rb.html.erb' + render 'dummy/breakdown_http_rb', format: [:erb] end def breakdown_http_client HTTPClient.new.get('http://example.com') - render 'dummy/breakdown_http_client.html.erb' + render 'dummy/breakdown_http_client', format: [:erb] end def breakdown_typhoeus Typhoeus.get('example.com') - render 'dummy/breakdown_typhoeus.html.erb' + render 'dummy/breakdown_typhoeus', format: [:erb] end def notify_airbrake_helper diff --git a/spec/integration/rails/rails_spec.rb b/spec/integration/rails/rails_spec.rb index 5797fbe3..5e914975 100644 --- a/spec/integration/rails/rails_spec.rb +++ b/spec/integration/rails/rails_spec.rb @@ -429,7 +429,7 @@ def force_http_libs_prepend it "includes the http breakdown" do expect(Airbrake).to receive(:notify_performance_breakdown).with( - hash_including(groups: { http: be > 0 }), + hash_including(groups: { view: be > 0, http: be > 0 }), an_instance_of(Hash), ) get '/breakdown_excon' @@ -444,7 +444,7 @@ def force_http_libs_prepend it "includes the http breakdown" do expect(Airbrake).to receive(:notify_performance_breakdown).with( - hash_including(groups: { http: be > 0 }), + hash_including(groups: { view: be > 0, http: be > 0 }), an_instance_of(Hash), ) get '/breakdown_http_rb' @@ -465,7 +465,7 @@ def force_http_libs_prepend it "includes the http breakdown" do expect(Airbrake).to receive(:notify_performance_breakdown).with( - hash_including(groups: { http: be > 0 }), + hash_including(groups: { view: be > 0, http: be > 0 }), an_instance_of(Hash), ) get '/breakdown_http_client' @@ -487,7 +487,7 @@ def force_http_libs_prepend it "includes the http breakdown" do expect(Airbrake).to receive(:notify_performance_breakdown).with( - hash_including(groups: { http: be > 0 }), + hash_including(groups: { view: be > 0, http: be > 0 }), an_instance_of(Hash), ) get '/breakdown_typhoeus' From 49ec4f4751ebd70fd0bd344279167b52f7baca91 Mon Sep 17 00:00:00 2001 From: Kyrylo Silin Date: Wed, 22 Sep 2021 13:25:07 +0300 Subject: [PATCH 13/50] Appraisals: depend on branch `61-stable` for JRuby sqlite3 This branch has compatibility fixes with Rails 6.1. --- Appraisals | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Appraisals b/Appraisals index a8d0de9e..27b83261 100644 --- a/Appraisals +++ b/Appraisals @@ -42,7 +42,10 @@ appraise 'rails-6.1' do gem 'warden', '~> 1.2.6' gem 'rack', '~> 2.0' - gem 'activerecord-jdbcsqlite3-adapter', '~> 60.1', platforms: :jruby + gem 'activerecord-jdbcsqlite3-adapter', + github: 'jruby/activerecord-jdbc-adapter', + branch: '61-stable', + platforms: :jruby gem 'sqlite3', '~> 1.4', platforms: %i[mri rbx] gem 'resque', '~> 1.26' From 51ae1920cfd1b952d82c709cf70d88b84675cde3 Mon Sep 17 00:00:00 2001 From: Kyrylo Silin Date: Wed, 22 Sep 2021 13:26:03 +0300 Subject: [PATCH 14/50] Depend on development version of sneakers We have to do that so that we can resolve the rake version problem (sneakers wants an older version of rake, other gems want newer). This was fixed on their `master`. Likely the issue to track: https://github.com/jondot/sneakers/issues/452 --- .rubocop.yml | 3 +++ Gemfile | 1 + airbrake.gemspec | 1 - gemfiles/rack.gemfile | 1 + gemfiles/rails_5.2.gemfile | 1 + gemfiles/rails_6.0.gemfile | 1 + gemfiles/rails_6.1.gemfile | 3 ++- gemfiles/sinatra.gemfile | 1 + 8 files changed, 10 insertions(+), 2 deletions(-) diff --git a/.rubocop.yml b/.rubocop.yml index 786d52ed..afac6ee3 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -4,6 +4,9 @@ AllCops: TargetRubyVersion: 2.5 DisplayCopNames: true DisplayStyleGuide: true + Exclude: + - 'gemfiles/*.gemfile' + - 'vendor/**/*' Metrics/MethodLength: Max: 25 diff --git a/Gemfile b/Gemfile index f3449189..51f12db2 100644 --- a/Gemfile +++ b/Gemfile @@ -2,3 +2,4 @@ source 'https://rubygems.org' gemspec gem 'rubocop', '= 0.81', require: false +gem 'sneakers', github: 'jondot/sneakers', ref: '31d0cb25dc5bbcfb0749567e9e0f80e6353fb66b' diff --git a/airbrake.gemspec b/airbrake.gemspec index 37a797ad..0291cb93 100644 --- a/airbrake.gemspec +++ b/airbrake.gemspec @@ -40,7 +40,6 @@ DESC s.add_development_dependency 'rack', '~> 2' s.add_development_dependency 'webmock', '~> 3' s.add_development_dependency 'amq-protocol' - s.add_development_dependency 'sneakers', '~> 2' s.add_development_dependency 'rack-test', '= 0.6.3' s.add_development_dependency 'redis', '= 4.1.4' s.add_development_dependency 'sidekiq', '~> 5' diff --git a/gemfiles/rack.gemfile b/gemfiles/rack.gemfile index 899701a4..6a901c41 100644 --- a/gemfiles/rack.gemfile +++ b/gemfiles/rack.gemfile @@ -3,6 +3,7 @@ source "https://rubygems.org" gem "rubocop", "= 0.81", require: false +gem "sneakers", github: "jondot/sneakers", ref: "31d0cb25dc5bbcfb0749567e9e0f80e6353fb66b" gem "warden", "~> 1.2.6" gemspec path: "../" diff --git a/gemfiles/rails_5.2.gemfile b/gemfiles/rails_5.2.gemfile index 5a4012a6..e4d07ee2 100644 --- a/gemfiles/rails_5.2.gemfile +++ b/gemfiles/rails_5.2.gemfile @@ -3,6 +3,7 @@ source "https://rubygems.org" gem "rubocop", "= 0.81", require: false +gem "sneakers", github: "jondot/sneakers", ref: "31d0cb25dc5bbcfb0749567e9e0f80e6353fb66b" gem "rails", "~> 5.2.0" gem "warden", "~> 1.2.6" gem "rack", "~> 2.0" diff --git a/gemfiles/rails_6.0.gemfile b/gemfiles/rails_6.0.gemfile index 240d4b09..bed8223a 100644 --- a/gemfiles/rails_6.0.gemfile +++ b/gemfiles/rails_6.0.gemfile @@ -3,6 +3,7 @@ source "https://rubygems.org" gem "rubocop", "= 0.81", require: false +gem "sneakers", github: "jondot/sneakers", ref: "31d0cb25dc5bbcfb0749567e9e0f80e6353fb66b" gem "rails", "~> 6.0.4.1" gem "warden", "~> 1.2.6" gem "rack", "~> 2.0" diff --git a/gemfiles/rails_6.1.gemfile b/gemfiles/rails_6.1.gemfile index 6e8a087f..2572ea44 100644 --- a/gemfiles/rails_6.1.gemfile +++ b/gemfiles/rails_6.1.gemfile @@ -3,10 +3,11 @@ source "https://rubygems.org" gem "rubocop", "= 0.81", require: false +gem "sneakers", github: "jondot/sneakers", ref: "31d0cb25dc5bbcfb0749567e9e0f80e6353fb66b" gem "rails", "~> 6.1.4.1" gem "warden", "~> 1.2.6" gem "rack", "~> 2.0" -gem "activerecord-jdbcsqlite3-adapter", "~> 60.1", platforms: :jruby +gem "activerecord-jdbcsqlite3-adapter", github: "jruby/activerecord-jdbc-adapter", branch: "61-stable", platforms: :jruby gem "sqlite3", "~> 1.4", platforms: [:mri, :rbx] gem "resque", "~> 1.26" gem "resque_spec", github: "airbrake/resque_spec" diff --git a/gemfiles/sinatra.gemfile b/gemfiles/sinatra.gemfile index 592990d6..ed757908 100644 --- a/gemfiles/sinatra.gemfile +++ b/gemfiles/sinatra.gemfile @@ -3,6 +3,7 @@ source "https://rubygems.org" gem "rubocop", "= 0.81", require: false +gem "sneakers", github: "jondot/sneakers", ref: "31d0cb25dc5bbcfb0749567e9e0f80e6353fb66b" gem "sinatra", "~> 2" gem "warden", "~> 1.2.6" From 4215fabccccad017bb85190d9a54b2b791ebe704 Mon Sep 17 00:00:00 2001 From: Kyrylo Silin Date: Wed, 22 Sep 2021 14:11:12 +0300 Subject: [PATCH 15/50] Bump rubocop to `~> 1.21` and fix cop offences --- .rubocop.yml | 1 + Gemfile | 2 +- README.md | 2 +- airbrake.gemspec | 1 - lib/airbrake/logger.rb | 4 +++- lib/airbrake/rack/context_filter.rb | 16 ++++++++++------ lib/airbrake/rack/instrumentable.rb | 4 ++++ lib/airbrake/rack/route_filter.rb | 2 +- lib/airbrake/rails.rb | 2 +- lib/airbrake/shoryuken.rb | 6 ++---- lib/airbrake/sidekiq.rb | 8 +++----- spec/apps/rails/dummy_app.rb | 2 +- spec/integration/rails/rake_spec.rb | 2 +- spec/integration/sinatra/sinatra_spec.rb | 2 +- spec/unit/rack/instrumentable_spec.rb | 18 +++++++++++++++--- spec/unit/rack/rack_spec.rb | 14 +++++++------- spec/unit/rake/tasks_spec.rb | 4 ++-- spec/unit/shoryuken_spec.rb | 2 +- 18 files changed, 55 insertions(+), 37 deletions(-) diff --git a/.rubocop.yml b/.rubocop.yml index afac6ee3..811096aa 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -4,6 +4,7 @@ AllCops: TargetRubyVersion: 2.5 DisplayCopNames: true DisplayStyleGuide: true + NewCops: enable Exclude: - 'gemfiles/*.gemfile' - 'vendor/**/*' diff --git a/Gemfile b/Gemfile index 51f12db2..144688c3 100644 --- a/Gemfile +++ b/Gemfile @@ -1,5 +1,5 @@ source 'https://rubygems.org' gemspec -gem 'rubocop', '= 0.81', require: false +gem 'rubocop', '~> 1.21', require: false gem 'sneakers', github: 'jondot/sneakers', ref: '31d0cb25dc5bbcfb0749567e9e0f80e6353fb66b' diff --git a/README.md b/README.md index 29b1ba98..50001543 100644 --- a/README.md +++ b/README.md @@ -492,7 +492,7 @@ wrap your logger in Airbrake's decorator class: require 'airbrake/logger' # Create a normal logger -logger = Logger.new(STDOUT) +logger = Logger.new($stdout) # Wrap it logger = Airbrake::AirbrakeLogger.new(logger) diff --git a/airbrake.gemspec b/airbrake.gemspec index 0291cb93..aa18e5e5 100644 --- a/airbrake.gemspec +++ b/airbrake.gemspec @@ -3,7 +3,6 @@ require './lib/airbrake/version' Gem::Specification.new do |s| s.name = 'airbrake' s.version = Airbrake::AIRBRAKE_VERSION.dup - s.date = Time.now.strftime('%Y-%m-%d') s.summary = < exception notify_airbrake(exception, worker, queue, body) Airbrake.notify_queue( diff --git a/lib/airbrake/sidekiq.rb b/lib/airbrake/sidekiq.rb index 05c1c96f..0f088a29 100644 --- a/lib/airbrake/sidekiq.rb +++ b/lib/airbrake/sidekiq.rb @@ -6,10 +6,8 @@ module Airbrake module Sidekiq # Provides integration with Sidekiq v2+. class ErrorHandler - def call(_worker, context, _queue) - timing = Airbrake::Benchmark.measure do - yield - end + def call(_worker, context, _queue, &block) + timing = Airbrake::Benchmark.measure(&block) rescue Exception => exception # rubocop:disable Lint/RescueException notify_airbrake(exception, context) Airbrake.notify_queue( @@ -38,7 +36,7 @@ def notify_airbrake(exception, context) # @return [String] job's name. When ActiveJob is present, retrieve # job_class. When used directly, use worker's name def action(context) - klass = context['class'] || context[:job] && context[:job]['class'] + klass = context['class'] || (context[:job] && context[:job]['class']) return klass unless context[:job] && context[:job]['args'].first.is_a?(Hash) return klass unless (job_class = context[:job]['args'].first['job_class']) diff --git a/spec/apps/rails/dummy_app.rb b/spec/apps/rails/dummy_app.rb index 428eacdb..d823d58b 100644 --- a/spec/apps/rails/dummy_app.rb +++ b/spec/apps/rails/dummy_app.rb @@ -10,7 +10,7 @@ class DummyApp < Rails::Application config.secret_key_base = '62773890cad9d9d584b57320f8612f8f7378a90aadcabc6ee' # Configure a logger, without it the tests can't run. - vsn = Rails.version.split('').values_at(0, 2).join('') + vsn = Rails.version.chars.values_at(0, 2).join log_path = File.join(File.dirname(__FILE__), 'logs', "#{vsn}.log") config.logger = Logger.new(log_path) Rails.logger = config.logger diff --git a/spec/integration/rails/rake_spec.rb b/spec/integration/rails/rake_spec.rb index 85ef3578..5bff5643 100644 --- a/spec/integration/rails/rake_spec.rb +++ b/spec/integration/rails/rake_spec.rb @@ -41,7 +41,7 @@ it "includes a timestamp" do expected_notice = a_notice_with( - %i[params rake_task timestamp], /20\d\d\-\d\d-\d\d.+/ + %i[params rake_task timestamp], /20\d\d-\d\d-\d\d.+/ ) expect(Airbrake).to receive(:notify_sync).with(expected_notice) end diff --git a/spec/integration/sinatra/sinatra_spec.rb b/spec/integration/sinatra/sinatra_spec.rb index 632770a0..2fbc5e3e 100644 --- a/spec/integration/sinatra/sinatra_spec.rb +++ b/spec/integration/sinatra/sinatra_spec.rb @@ -25,7 +25,7 @@ get '/crash' sleep 2 - body = %r("context":{.*"route":"\/crash".*}) + body = %r("context":{.*"route":"/crash".*}) expect(a_request(:post, endpoint).with(body: body)).to have_been_made end end diff --git a/spec/unit/rack/instrumentable_spec.rb b/spec/unit/rack/instrumentable_spec.rb index bc09f228..ddaacd11 100644 --- a/spec/unit/rack/instrumentable_spec.rb +++ b/spec/unit/rack/instrumentable_spec.rb @@ -36,12 +36,16 @@ def method_with!(val); end def method_with?(val); end airbrake_capture_timing :method_with? + # rubocop:disable Layout/EmptyLinesAroundAttributeAccessor attr_writer :method_with airbrake_capture_timing :method_with= + # rubocop:enable Layout/EmptyLinesAroundAttributeAccessor + # rubocop:disable Lint/UselessMethodDefinition def ==(other) super end + # rubocop:enable Lint/UselessMethodDefinition airbrake_capture_timing :== def method_with_block @@ -65,25 +69,33 @@ def writer_with_everything=(a, b = nil, *args, foo:, bar: nil) prepend( Module.new do + # rubocop:disable Lint/UselessMethodDefinition def prepended_method!(*args, **kw_args) super end + # rubocop:enable Lint/UselessMethodDefinition + # rubocop:disable Lint/UselessMethodDefinition def prepended_writer=(*args, **kw_args) super end + # rubocop:enable Lint/UselessMethodDefinition protected + # rubocop:disable Lint/UselessMethodDefinition def a_prepended_protected_method super end + # rubocop:enable Lint/UselessMethodDefinition private + # rubocop:disable Lint/UselessMethodDefinition def a_prepended_private_method super end + # rubocop:enable Lint/UselessMethodDefinition end, ) @@ -236,12 +248,12 @@ def a_prepended_private_method; end end it "attaches timing for a method with all arg types" do - klass.new.send('method_with_everything!', 1, 2, 3, foo: 4, bar: 5) {} + klass.new.send('method_with_everything!', 1, 2, 3, foo: 4, bar: 5) { 1 } expect(groups).to match('method_with_everything!' => be > 0) end it "attaches timing for a writer method with all arg types" do - klass.new.send('writer_with_everything=', 1, 2, 3, foo: 4, bar: 5) {} + klass.new.send('writer_with_everything=', 1, 2, 3, foo: 4, bar: 5) { 1 } expect(groups).to match('writer_with_everything=' => be > 0) end @@ -251,7 +263,7 @@ def a_prepended_private_method; end end it "attaches timing for a prepended writer method with all arg types" do - klass.new.send('prepended_writer=', 1, 2, 3, foo: 4, bar: 5) {} + klass.new.send('prepended_writer=', 1, 2, 3, foo: 4, bar: 5) { 1 } expect(groups).to match('prepended_writer=' => be > 0) end diff --git a/spec/unit/rack/rack_spec.rb b/spec/unit/rack/rack_spec.rb index c4880614..5549d3b6 100644 --- a/spec/unit/rack/rack_spec.rb +++ b/spec/unit/rack/rack_spec.rb @@ -8,7 +8,7 @@ context "when request store doesn't have any routes" do it "doesn't store timing" do - described_class.capture_timing('operation') {} + described_class.capture_timing('operation') { 1 } expect(Airbrake::Rack::RequestStore.store).to be_empty end @@ -39,9 +39,9 @@ end it "doesn't attach any timings" do - described_class.capture_timing('operation 1') {} - described_class.capture_timing('operation 2') {} - described_class.capture_timing('operation 3') {} + described_class.capture_timing('operation 1') { 1 } + described_class.capture_timing('operation 2') { 2 } + described_class.capture_timing('operation 3') { 3 } expect(routes['/about'][:groups]).to be_empty end @@ -54,9 +54,9 @@ end it "attaches all timings for different operations to the request store" do - described_class.capture_timing('operation 1') {} - described_class.capture_timing('operation 2') {} - described_class.capture_timing('operation 3') {} + described_class.capture_timing('operation 1') { 1 } + described_class.capture_timing('operation 2') { 2 } + described_class.capture_timing('operation 3') { 3 } expect(routes['/about'][:groups]).to match( 'operation 1' => be > 0, diff --git a/spec/unit/rake/tasks_spec.rb b/spec/unit/rake/tasks_spec.rb index 18251325..813bacf0 100644 --- a/spec/unit/rake/tasks_spec.rb +++ b/spec/unit/rake/tasks_spec.rb @@ -11,7 +11,7 @@ def wait_for_a_request_with_body(body) before do stub_request(:post, endpoint).to_return(status: 201, body: '{}') - allow(STDOUT).to receive(:puts).and_return(nil) + allow($stdout).to receive(:puts).and_return(nil) end describe "airbrake:deploy" do @@ -62,7 +62,7 @@ def wait_for_a_request_with_body(body) describe "parsing environment variables" do it "does not raise when an env variable value contains '='" do - heroku_config = airbrake_vars + "URL=https://airbrake.io/docs?key=11\n" + heroku_config = "#{airbrake_vars} URL=https://airbrake.io/docs?key=11\n" expect(Bundler).to receive(:with_clean_env).twice.and_return(heroku_config) task.invoke diff --git a/spec/unit/shoryuken_spec.rb b/spec/unit/shoryuken_spec.rb index e7bcaece..59bdb7b4 100644 --- a/spec/unit/shoryuken_spec.rb +++ b/spec/unit/shoryuken_spec.rb @@ -89,7 +89,7 @@ def wait_for_a_request_with_body(body) timing: an_instance_of(Float), ) - expect { subject.call(worker, queue, nil, body) {} }.not_to raise_error + expect { subject.call(worker, queue, nil, body) { 1 } }.not_to raise_error end end end From d0264da7073d7505b1852b120bc91ff35c1c5e11 Mon Sep 17 00:00:00 2001 From: Kyrylo Silin Date: Wed, 22 Sep 2021 15:10:54 +0300 Subject: [PATCH 16/50] gemspec: bump stale dependencies These dependencies couldn't be bumped before because they dropped Ruby <2.5 support. Now that our requirement is Ruby 2.5+, we can bump them as well. --- airbrake.gemspec | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/airbrake.gemspec b/airbrake.gemspec index aa18e5e5..4509dc1d 100644 --- a/airbrake.gemspec +++ b/airbrake.gemspec @@ -39,12 +39,12 @@ DESC s.add_development_dependency 'rack', '~> 2' s.add_development_dependency 'webmock', '~> 3' s.add_development_dependency 'amq-protocol' - s.add_development_dependency 'rack-test', '= 0.6.3' + s.add_development_dependency 'rack-test', '~> 1.1' s.add_development_dependency 'redis', '= 4.1.4' - s.add_development_dependency 'sidekiq', '~> 5' + s.add_development_dependency 'sidekiq', '~> 6' s.add_development_dependency 'curb', '~> 0.9' if RUBY_ENGINE == 'ruby' s.add_development_dependency 'excon', '~> 0.64' - s.add_development_dependency 'http', '~> 2.2' + s.add_development_dependency 'http', '~> 5.0' s.add_development_dependency 'httpclient', '~> 2.8' s.add_development_dependency 'typhoeus', '~> 1.3' @@ -52,6 +52,5 @@ DESC # https://circleci.com/gh/airbrake/airbrake-ruby/889 s.add_development_dependency 'public_suffix', '~> 4.0', '< 5.0' - # redis-namespace > 1.6.0 wants Ruby >= 2.4. - s.add_development_dependency 'redis-namespace', '= 1.6.0' + s.add_development_dependency 'redis-namespace', '~> 1.8' end From 28218a9bb5389f094fb4f9f496e69d74e2ba6b31 Mon Sep 17 00:00:00 2001 From: Kyrylo Silin Date: Wed, 22 Sep 2021 15:12:03 +0300 Subject: [PATCH 17/50] README: update Ruby version requirement information. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 50001543..e214be23 100644 --- a/README.md +++ b/README.md @@ -651,7 +651,7 @@ Then, invoke it like shown in the example for Rails. Supported Rubies ---------------- -* CRuby >= 2.3.0 +* CRuby >= 2.5.0 * JRuby >= 9k Contact From 3112a17f6c5984503b9ec03f80cc50e590a8e6c9 Mon Sep 17 00:00:00 2001 From: Kyrylo Silin Date: Wed, 22 Sep 2021 15:36:50 +0300 Subject: [PATCH 18/50] README: replace mentions of CircleCI with GitHub Actions --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index e214be23..ff8b83ad 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ Airbrake ======== -[![Circle Build Status](https://circleci.com/gh/airbrake/airbrake.png?style=shield)](https://circleci.com/gh/airbrake/airbrake) +[![Build Status](https://github.com/airbrake/airbrake/workflows/airbrake/badge.svg) [![Code Climate](https://codeclimate.com/github/airbrake/airbrake.svg)](https://codeclimate.com/github/airbrake/airbrake) [![Gem Version](https://badge.fury.io/rb/airbrake.svg)](http://badge.fury.io/rb/airbrake) [![Documentation Status](http://inch-ci.org/github/airbrake/airbrake.svg?branch=master)](http://inch-ci.org/github/airbrake/airbrake) @@ -702,8 +702,8 @@ bundle exec appraisal rails-4.2 rake spec:integration:rails bundle exec appraisal sinatra rake spec:integration:sinatra ``` -Pro tip: [CircleCI config](/.circleci/config.yml) has the list of all -integration tests and commands to invoke them. +Pro tip: [GitHub Actions config](/.github/workflows/test.yml) has the list of +all the integration tests and commands to invoke them. [airbrake.io]: https://airbrake.io [airbrake-ruby]: https://github.com/airbrake/airbrake-ruby From 6edd53967b1f3a95d8c03135e933c298006ead93 Mon Sep 17 00:00:00 2001 From: Kyrylo Silin Date: Wed, 22 Sep 2021 15:44:49 +0300 Subject: [PATCH 19/50] README: link to GitHub Actions --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ff8b83ad..21427543 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ Airbrake ======== -[![Build Status](https://github.com/airbrake/airbrake/workflows/airbrake/badge.svg) +[![Build Status](https://github.com/airbrake/airbrake/workflows/airbrake/badge.svg)](https://github.com/airbrake/airbrake/actions) [![Code Climate](https://codeclimate.com/github/airbrake/airbrake.svg)](https://codeclimate.com/github/airbrake/airbrake) [![Gem Version](https://badge.fury.io/rb/airbrake.svg)](http://badge.fury.io/rb/airbrake) [![Documentation Status](http://inch-ci.org/github/airbrake/airbrake.svg?branch=master)](http://inch-ci.org/github/airbrake/airbrake) From 512b4eb37f4be2fb221397da61975203f07c9c7b Mon Sep 17 00:00:00 2001 From: Kyrylo Silin Date: Wed, 22 Sep 2021 15:51:28 +0300 Subject: [PATCH 20/50] Release v12.0.0 --- CHANGELOG.md | 23 +++++++++++++++++++++++ lib/airbrake/version.rb | 2 +- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3a95a8b5..32abbd4e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,8 @@ Airbrake Changelog ### master +### [v12.0.0][v12.0.0] (September 22, 2021) + Breaking changes: * Dropped support for Ruby 2.3 @@ -15,6 +17,26 @@ Maintenance: * Bumped `airbrake-ruby` requirement to `~> 6.0` ([#1181](https://github.com/airbrake/airbrake/issues/1181)) +Other changes: + +* Rails generator no longer embeds project id & project key into the generated + initializer file. Set environment variables instead. + + Before: + + ```sh + % rails g airbrake PROJECT_ID PROJECT_KEY + ``` + + After: + + ```sh + export AIRBRAKE_PROJECT_ID= + export AIRBRAKE_PROJECT_KEY= + + rails g airbrake + ``` + ### [v11.0.3][v11.0.3] (May 13, 2021) * Fixed `Sneakers` integration when 3rd party code monkey-patches @@ -960,3 +982,4 @@ Features: [v11.0.1]: https://github.com/airbrake/airbrake/releases/tag/v11.0.1 [v11.0.2]: https://github.com/airbrake/airbrake/releases/tag/v11.0.2 [v11.0.3]: https://github.com/airbrake/airbrake/releases/tag/v11.0.3 +[v12.0.0]: https://github.com/airbrake/airbrake/releases/tag/v12.0.0 diff --git a/lib/airbrake/version.rb b/lib/airbrake/version.rb index 05796c8b..cecb64f0 100644 --- a/lib/airbrake/version.rb +++ b/lib/airbrake/version.rb @@ -3,5 +3,5 @@ # We use Semantic Versioning v2.0.0 # More information: http://semver.org/ module Airbrake - AIRBRAKE_VERSION = '11.0.3' + AIRBRAKE_VERSION = '12.0.0' end From 4740a562d62181103f4b8b6080117519ab1ff57b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 23 Sep 2021 00:01:19 +0000 Subject: [PATCH 21/50] build(deps-dev): update redis requirement from = 4.1.4 to = 4.4.0 Updates the requirements on [redis](https://github.com/redis/redis-rb) to permit the latest version. - [Release notes](https://github.com/redis/redis-rb/releases) - [Changelog](https://github.com/redis/redis-rb/blob/master/CHANGELOG.md) - [Commits](https://github.com/redis/redis-rb/compare/v4.1.4...v4.4.0) --- updated-dependencies: - dependency-name: redis dependency-type: direct:development ... Signed-off-by: dependabot[bot] --- airbrake.gemspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/airbrake.gemspec b/airbrake.gemspec index 4509dc1d..a736ff69 100644 --- a/airbrake.gemspec +++ b/airbrake.gemspec @@ -40,7 +40,7 @@ DESC s.add_development_dependency 'webmock', '~> 3' s.add_development_dependency 'amq-protocol' s.add_development_dependency 'rack-test', '~> 1.1' - s.add_development_dependency 'redis', '= 4.1.4' + s.add_development_dependency 'redis', '= 4.4.0' s.add_development_dependency 'sidekiq', '~> 6' s.add_development_dependency 'curb', '~> 0.9' if RUBY_ENGINE == 'ruby' s.add_development_dependency 'excon', '~> 0.64' From 2623afd98093935b58a9a6fdaf6c9da4f1d8694a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 16 Oct 2021 00:00:52 +0000 Subject: [PATCH 22/50] build(deps-dev): update redis requirement from = 4.4.0 to = 4.5.1 Updates the requirements on [redis](https://github.com/redis/redis-rb) to permit the latest version. - [Release notes](https://github.com/redis/redis-rb/releases) - [Changelog](https://github.com/redis/redis-rb/blob/master/CHANGELOG.md) - [Commits](https://github.com/redis/redis-rb/compare/v4.4.0...v4.5.1) --- updated-dependencies: - dependency-name: redis dependency-type: direct:development ... Signed-off-by: dependabot[bot] --- airbrake.gemspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/airbrake.gemspec b/airbrake.gemspec index a736ff69..4549fc73 100644 --- a/airbrake.gemspec +++ b/airbrake.gemspec @@ -40,7 +40,7 @@ DESC s.add_development_dependency 'webmock', '~> 3' s.add_development_dependency 'amq-protocol' s.add_development_dependency 'rack-test', '~> 1.1' - s.add_development_dependency 'redis', '= 4.4.0' + s.add_development_dependency 'redis', '= 4.5.1' s.add_development_dependency 'sidekiq', '~> 6' s.add_development_dependency 'curb', '~> 0.9' if RUBY_ENGINE == 'ruby' s.add_development_dependency 'excon', '~> 0.64' From 67fc65b1de45eba8dea38a424460198ac9516e07 Mon Sep 17 00:00:00 2001 From: Kyrylo Silin Date: Thu, 28 Oct 2021 12:29:03 +0300 Subject: [PATCH 23/50] README: spruce up key features --- README.md | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 21427543..72018770 100644 --- a/README.md +++ b/README.md @@ -47,26 +47,26 @@ The list of integrations that are available in this gem includes: * [Heroku support][heroku-docs] (as an [add-on][heroku-addon]) * Web frameworks - * Rails[[link](#rails)] - * Sinatra[[link](#sinatra)] - * Rack applications[[link](#rack)] + * [Rails](#rails) + * [Sinatra](#sinatra) + * [Rack applications](#rack) * Job processing libraries - * ActiveJob[[link](#activejob)] - * Resque[[link](#resque)] - * Sidekiq[[link](#sidekiq)] - * DelayedJob[[link](#delayedjob)] - * Shoryuken[[link](#shoryuken)] - * Sneakers[[link](#sneakers)] + * [ActiveJob](#activejob) + * [Resque](#resque) + * [Sidekiq](#sidekiq) + * [DelayedJob](#delayedjob) + * [Shoryuken](#shoryuken) + * [Sneakers](#sneakers) * Other libraries - * ActionCable[[link](#actioncable)] - * Rake[[link](#rake)] - * Logger[[link](#logger)] -* Plain Ruby scripts[[link](#plain-ruby-scripts)] + * [ActionCable](#actioncable) + * [Rake](#rake) + * [Logger](#logger) +* [Plain Ruby scripts](#plain-ruby-scripts) Deployment tracking: -* Using Capistrano[[link](#capistrano)] -* Using the Rake task[[link](#rake-task)] +* Using [Capistrano](#capistrano) +* Using the [Rake task](#rake-task) Installation ------------ From 4f7cf3e8d6f53cbf8ef958dc5dd53f374421f58b Mon Sep 17 00:00:00 2001 From: Kyrylo Silin Date: Tue, 2 Nov 2021 13:25:07 +0200 Subject: [PATCH 24/50] Change terminology: "resource" -> "metric" --- CHANGELOG.md | 6 +++--- ...tion_controller_performance_breakdown_subscriber_spec.rb | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 32abbd4e..2a8ddbe2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -292,12 +292,12 @@ Features: ### [v9.2.2][v9.2.2] (May 10, 2019) -* Rails: started attaching Rack request and User info to the resource object, +* Rails: started attaching Rack request and User info to the metric object, which is accessible through performance hooks: ```ruby - Airbrake.add_performance_filter do |resource| - if resource.stash.key?(:user) + Airbrake.add_performance_filter do |metric| + if metric.stash.key?(:user) # custom logic end end diff --git a/spec/unit/rails/action_controller_performance_breakdown_subscriber_spec.rb b/spec/unit/rails/action_controller_performance_breakdown_subscriber_spec.rb index fadfeef5..7f926485 100644 --- a/spec/unit/rails/action_controller_performance_breakdown_subscriber_spec.rb +++ b/spec/unit/rails/action_controller_performance_breakdown_subscriber_spec.rb @@ -95,7 +95,7 @@ } end - it "sends request info as resource stash" do + it "sends request info as metric stash" do expect(Airbrake).to receive(:notify_performance_breakdown).with( an_instance_of(Hash), hash_including(request: request), @@ -113,7 +113,7 @@ ) end - it "sends user info as resource stash" do + it "sends user info as metric stash" do expect(Airbrake).to receive(:notify_performance_breakdown).with( an_instance_of(Hash), hash_including(user: { 'id' => 1, 'name' => 'Arthur' }), From c2f9a9345cf16e275bf81a6e75f37980cb366c9e Mon Sep 17 00:00:00 2001 From: Takuya Noguchi Date: Sun, 14 Nov 2021 03:47:54 +0000 Subject: [PATCH 25/50] Fix up the PR number in PR 1179 Signed-off-by: Takuya Noguchi --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2a8ddbe2..4d02a354 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,7 +15,7 @@ Breaking changes: Maintenance: * Bumped `airbrake-ruby` requirement to `~> 6.0` - ([#1181](https://github.com/airbrake/airbrake/issues/1181)) + ([#1179](https://github.com/airbrake/airbrake/pull/1179)) Other changes: From 4b901d60f5fefc57d98e742c4c7baff3a5513509 Mon Sep 17 00:00:00 2001 From: Kyrylo Silin Date: Wed, 24 Nov 2021 13:04:36 +0200 Subject: [PATCH 26/50] gemspec: set `rubygems_mfa_required` to fix a Rubocop offence ...and to improve security --- airbrake.gemspec | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/airbrake.gemspec b/airbrake.gemspec index 4549fc73..f7593f85 100644 --- a/airbrake.gemspec +++ b/airbrake.gemspec @@ -29,6 +29,10 @@ DESC s.required_ruby_version = '>= 2.5' + s.metadata = { + 'rubygems_mfa_required' => 'true', + } + s.add_dependency 'airbrake-ruby', '~> 6.0' s.add_development_dependency 'rspec', '~> 3' From 6e5c3cec19b7eb494af68f19126ca0443c175114 Mon Sep 17 00:00:00 2001 From: Kyrylo Silin Date: Wed, 24 Nov 2021 13:16:32 +0200 Subject: [PATCH 27/50] spec: replace all instances of OpenStruct with Struct Suggested by Rubocop. --- spec/integration/rails/rails_spec.rb | 17 ++++++----------- .../shared_examples/rack_examples.rb | 9 ++------- spec/unit/rack/user_spec.rb | 11 +++-------- .../action_controller_route_subscriber_spec.rb | 1 - 4 files changed, 11 insertions(+), 27 deletions(-) diff --git a/spec/integration/rails/rails_spec.rb b/spec/integration/rails/rails_spec.rb index 5e914975..ee0cccdd 100644 --- a/spec/integration/rails/rails_spec.rb +++ b/spec/integration/rails/rails_spec.rb @@ -64,11 +64,8 @@ def force_http_libs_prepend shared_examples "context payload content" do |route| let(:user) do - OpenStruct.new( - id: 1, - email: 'qa@example.com', - username: 'qa-dept', - ) + stub_const('User', Struct.new(:id, :email, :username)) + User.new(1, 'qa@example.com', 'qa-dept') end before do @@ -223,11 +220,8 @@ def force_http_libs_prepend describe "user extraction" do context "when Warden is not available but 'current_user' is defined" do let(:user) do - OpenStruct.new( - id: 1, - email: 'qa@example.com', - username: 'qa-dept', - ) + stub_const('User', Struct.new(:id, :email, :username)) + User.new(1, 'qa@example.com', 'qa-dept') end before do @@ -497,7 +491,8 @@ def force_http_libs_prepend context "when current user is logged in" do let(:user) do - OpenStruct.new(id: 1, email: 'qa@example.com', username: 'qa-dept') + stub_const('User', Struct.new(:id, :email, :username)) + User.new(1, 'qa@example.com', 'qa-dept') end before do diff --git a/spec/integration/shared_examples/rack_examples.rb b/spec/integration/shared_examples/rack_examples.rb index 1925ef5b..670e17f3 100644 --- a/spec/integration/shared_examples/rack_examples.rb +++ b/spec/integration/shared_examples/rack_examples.rb @@ -40,13 +40,8 @@ describe "user payload" do let(:user) do - OpenStruct.new( - id: 1, - email: 'qa@example.com', - username: 'qa-dept', - first_name: 'John', - last_name: 'Doe', - ) + stub_const('User', Struct.new(:id, :email, :username, :first_name, :last_name)) + User.new(1, 'qa@example.com', 'qa-dept', 'John', 'Doe') end before { login_as(user) } diff --git a/spec/unit/rack/user_spec.rb b/spec/unit/rack/user_spec.rb index db05fc15..11f2d73f 100644 --- a/spec/unit/rack/user_spec.rb +++ b/spec/unit/rack/user_spec.rb @@ -4,13 +4,8 @@ let(:endpoint) { 'https://api.airbrake.io/api/v3/projects/113743/notices' } let(:user) do - OpenStruct.new( - id: 1, - email: 'qa@example.com', - username: 'qa-dept', - first_name: 'Bingo', - last_name: 'Bongo', - ) + stub_const('User', Struct.new(:id, :email, :username, :first_name, :last_name)) + User.new(1, 'qa@example.com', 'qa-dept', 'Bingo', 'Bongo') end def env_for(url, opts = {}) @@ -190,7 +185,7 @@ def current_user end context "when Rack user doesn't contain any of the expect fields" do - let(:user_data) { described_class.new(OpenStruct.new).as_json } + let(:user_data) { described_class.new({}).as_json } it "is empty" do expect(user_data).to be_empty diff --git a/spec/unit/rails/action_controller_route_subscriber_spec.rb b/spec/unit/rails/action_controller_route_subscriber_spec.rb index ec5432f7..d60b22ed 100644 --- a/spec/unit/rails/action_controller_route_subscriber_spec.rb +++ b/spec/unit/rails/action_controller_route_subscriber_spec.rb @@ -1,6 +1,5 @@ # frozen_string_literal: true -require 'ostruct' require 'airbrake/rails/action_controller_route_subscriber' RSpec.describe Airbrake::Rails::ActionControllerRouteSubscriber do From 00ba6d1ce893ae7f1e72fb7e6d9d690b20a9b835 Mon Sep 17 00:00:00 2001 From: Kyrylo Silin Date: Mon, 10 Jan 2022 17:52:33 +0200 Subject: [PATCH 28/50] gemspec: relax 'redis' dependency It was needed to support Ruby 2.2 and lower but since we don't care about them anymore, we can relax redis version. --- airbrake.gemspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/airbrake.gemspec b/airbrake.gemspec index f7593f85..5bb4525f 100644 --- a/airbrake.gemspec +++ b/airbrake.gemspec @@ -44,7 +44,7 @@ DESC s.add_development_dependency 'webmock', '~> 3' s.add_development_dependency 'amq-protocol' s.add_development_dependency 'rack-test', '~> 1.1' - s.add_development_dependency 'redis', '= 4.5.1' + s.add_development_dependency 'redis', '~> 4.5' s.add_development_dependency 'sidekiq', '~> 6' s.add_development_dependency 'curb', '~> 0.9' if RUBY_ENGINE == 'ruby' s.add_development_dependency 'excon', '~> 0.64' From 81f7dc566cd4f95e51679eec4e1cbd13b840962c Mon Sep 17 00:00:00 2001 From: Kyrylo Silin Date: Mon, 10 Jan 2022 18:47:04 +0200 Subject: [PATCH 29/50] Drop support for Ruby 2.5 Some of our test dependencies start requiring Ruby 2.6+. Ruby 2.5 was EOL on 31 Mar 2021, so it should be safe to move on. --- .github/workflows/test.yml | 3 +-- .rubocop.yml | 2 +- CHANGELOG.md | 5 +++++ README.md | 2 +- airbrake.gemspec | 2 +- 5 files changed, 9 insertions(+), 5 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 2394f37f..e6d9b958 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -7,8 +7,7 @@ jobs: strategy: matrix: os: [ubuntu-latest] - # Due to https://github.com/actions/runner/issues/849, we have to use quotes for '3.0' - ruby: [2.5, 2.6, 2.7, '3.0', jruby] + ruby: [2.6, 2.7, 3.0, jruby] runs-on: ${{ matrix.os }} diff --git a/.rubocop.yml b/.rubocop.yml index 811096aa..6a775176 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,7 +1,7 @@ # Explanations of all possible options: # https://github.com/bbatsov/rubocop/blob/master/config/default.yml AllCops: - TargetRubyVersion: 2.5 + TargetRubyVersion: 2.6 DisplayCopNames: true DisplayStyleGuide: true NewCops: enable diff --git a/CHANGELOG.md b/CHANGELOG.md index 4d02a354..0142d533 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,11 @@ Airbrake Changelog ### master +Breaking changes: + +* Dropped support for Ruby 2.5 + ([#1180](https://github.com/airbrake/airbrake/issues/1180)) + ### [v12.0.0][v12.0.0] (September 22, 2021) Breaking changes: diff --git a/README.md b/README.md index 72018770..3cbd213f 100644 --- a/README.md +++ b/README.md @@ -651,7 +651,7 @@ Then, invoke it like shown in the example for Rails. Supported Rubies ---------------- -* CRuby >= 2.5.0 +* CRuby >= 2.6.0 * JRuby >= 9k Contact diff --git a/airbrake.gemspec b/airbrake.gemspec index 5bb4525f..4a7dac67 100644 --- a/airbrake.gemspec +++ b/airbrake.gemspec @@ -27,7 +27,7 @@ DESC s.require_path = 'lib' s.files = ['lib/airbrake.rb', *Dir.glob('lib/**/*')] - s.required_ruby_version = '>= 2.5' + s.required_ruby_version = '>= 2.6' s.metadata = { 'rubygems_mfa_required' => 'true', From 3189451a4e55b4bda883d763e1c25cfe83a62f4f Mon Sep 17 00:00:00 2001 From: Kyrylo Silin Date: Mon, 10 Jan 2022 18:52:11 +0200 Subject: [PATCH 30/50] rubocop: fix Style/SlicingWithRange cop offences --- CHANGELOG.md | 2 +- spec/integration/rails/rails_spec.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0142d533..fc69e5a5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,7 @@ Airbrake Changelog Breaking changes: * Dropped support for Ruby 2.5 - ([#1180](https://github.com/airbrake/airbrake/issues/1180)) + ([#1208](https://github.com/airbrake/airbrake/issues/1208)) ### [v12.0.0][v12.0.0] (September 22, 2021) diff --git a/spec/integration/rails/rails_spec.rb b/spec/integration/rails/rails_spec.rb index ee0cccdd..7f83a8e7 100644 --- a/spec/integration/rails/rails_spec.rb +++ b/spec/integration/rails/rails_spec.rb @@ -105,7 +105,7 @@ def force_http_libs_prepend end it "includes params" do - action = route[1..-1] + action = route[1..] body = /"context":{.*"params":{.*"controller":"dummy","action":"#{action}".*}/ expect(a_request(:post, endpoint).with(body: body)).to have_been_made end From d8c23236cd0e921ae6fbf63fa93580b9418a4870 Mon Sep 17 00:00:00 2001 From: Kyrylo Silin Date: Mon, 10 Jan 2022 19:13:50 +0200 Subject: [PATCH 31/50] Bump rubocop dependency to `~> 1.21` --- gemfiles/rack.gemfile | 2 +- gemfiles/rails_6.0.gemfile | 2 +- gemfiles/rails_6.1.gemfile | 2 +- gemfiles/sinatra.gemfile | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/gemfiles/rack.gemfile b/gemfiles/rack.gemfile index 6a901c41..fb5db120 100644 --- a/gemfiles/rack.gemfile +++ b/gemfiles/rack.gemfile @@ -2,7 +2,7 @@ source "https://rubygems.org" -gem "rubocop", "= 0.81", require: false +gem "rubocop", "~> 1.21", require: false gem "sneakers", github: "jondot/sneakers", ref: "31d0cb25dc5bbcfb0749567e9e0f80e6353fb66b" gem "warden", "~> 1.2.6" diff --git a/gemfiles/rails_6.0.gemfile b/gemfiles/rails_6.0.gemfile index bed8223a..20a33d65 100644 --- a/gemfiles/rails_6.0.gemfile +++ b/gemfiles/rails_6.0.gemfile @@ -2,7 +2,7 @@ source "https://rubygems.org" -gem "rubocop", "= 0.81", require: false +gem "rubocop", "~> 1.21", require: false gem "sneakers", github: "jondot/sneakers", ref: "31d0cb25dc5bbcfb0749567e9e0f80e6353fb66b" gem "rails", "~> 6.0.4.1" gem "warden", "~> 1.2.6" diff --git a/gemfiles/rails_6.1.gemfile b/gemfiles/rails_6.1.gemfile index 2572ea44..5d570767 100644 --- a/gemfiles/rails_6.1.gemfile +++ b/gemfiles/rails_6.1.gemfile @@ -2,7 +2,7 @@ source "https://rubygems.org" -gem "rubocop", "= 0.81", require: false +gem "rubocop", "~> 1.21", require: false gem "sneakers", github: "jondot/sneakers", ref: "31d0cb25dc5bbcfb0749567e9e0f80e6353fb66b" gem "rails", "~> 6.1.4.1" gem "warden", "~> 1.2.6" diff --git a/gemfiles/sinatra.gemfile b/gemfiles/sinatra.gemfile index ed757908..df8d0686 100644 --- a/gemfiles/sinatra.gemfile +++ b/gemfiles/sinatra.gemfile @@ -2,7 +2,7 @@ source "https://rubygems.org" -gem "rubocop", "= 0.81", require: false +gem "rubocop", "~> 1.21", require: false gem "sneakers", github: "jondot/sneakers", ref: "31d0cb25dc5bbcfb0749567e9e0f80e6353fb66b" gem "sinatra", "~> 2" gem "warden", "~> 1.2.6" From aa865dc8efac5c41d0de87bdc44ad8a6f82efacc Mon Sep 17 00:00:00 2001 From: Kyrylo Silin Date: Mon, 10 Jan 2022 19:02:07 +0200 Subject: [PATCH 32/50] github/workflows/test: test against Ruby 3.1 --- .github/workflows/test.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index e6d9b958..684757a9 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -7,7 +7,7 @@ jobs: strategy: matrix: os: [ubuntu-latest] - ruby: [2.6, 2.7, 3.0, jruby] + ruby: [2.6, 2.7, 3.0, 3.1, jruby] runs-on: ${{ matrix.os }} @@ -41,7 +41,7 @@ jobs: run: bundle exec rake spec:unit - name: Test Rails 5.2 - if: ${{ matrix.ruby != '3.0' }} + if: ${{ matrix.ruby != '3.0' && matrix.ruby != '3.1' }} run: bundle exec appraisal rails-5.2 rake spec:integration:rails - name: Test Rails 6.0 From 2e0ec7ebdcb0c697574b786ac52558be221f0060 Mon Sep 17 00:00:00 2001 From: Kyrylo Silin Date: Mon, 10 Jan 2022 18:11:36 +0200 Subject: [PATCH 33/50] Appraisals: test against Rails 7.0 Also switch the delayed job library to https://github.com/Betterment/delayed, which was blocking us from testing against Rails 7.0. https://github.com/collectiveidea/delayed_job_active_record/issues/196 is still unresolved. --- .github/workflows/test.yml | 4 ++++ Appraisals | 30 ++++++++++++++++++++++------ gemfiles/rails_5.2.gemfile | 2 +- gemfiles/rails_6.0.gemfile | 3 +-- gemfiles/rails_6.1.gemfile | 3 +-- gemfiles/rails_7.0.gemfile | 17 ++++++++++++++++ spec/apps/rails/dummy_app.rb | 4 ++-- spec/integration/rails/rails_spec.rb | 2 +- 8 files changed, 51 insertions(+), 14 deletions(-) create mode 100644 gemfiles/rails_7.0.gemfile diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 684757a9..a127c6d8 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -50,6 +50,10 @@ jobs: - name: Test Rails 6.1 run: bundle exec appraisal rails-6.1 rake spec:integration:rails + - name: Test Rails 7.0 + if: ${{ matrix.ruby != '2.6' && matrix.ruby != 'jruby' }} + run: bundle exec appraisal rails-7.0 rake spec:integration:rails + - name: Test Sinatra run: bundle exec appraisal sinatra rake spec:integration:sinatra diff --git a/Appraisals b/Appraisals index 27b83261..3ffd8829 100644 --- a/Appraisals +++ b/Appraisals @@ -13,8 +13,7 @@ if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('3.0.0') gem 'resque', '~> 1.26' gem 'resque_spec', github: 'airbrake/resque_spec' - gem 'delayed_job', github: 'collectiveidea/delayed_job' - gem 'delayed_job_active_record', '~> 4.1' + gem 'delayed', '~> 0.4' gem 'mime-types', '~> 3.1' end @@ -31,8 +30,7 @@ appraise 'rails-6.0' do gem 'resque', '~> 1.26' gem 'resque_spec', github: 'airbrake/resque_spec' - gem 'delayed_job', github: 'collectiveidea/delayed_job' - gem 'delayed_job_active_record', '~> 4.1' + gem 'delayed', '~> 0.4' gem 'mime-types', '~> 3.1' end @@ -51,12 +49,32 @@ appraise 'rails-6.1' do gem 'resque', '~> 1.26' gem 'resque_spec', github: 'airbrake/resque_spec' - gem 'delayed_job', github: 'collectiveidea/delayed_job' - gem 'delayed_job_active_record', '~> 4.1' + gem 'delayed', '~> 0.4' gem 'mime-types', '~> 3.1' end +if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('2.7.0') + appraise 'rails-7.0' do + gem 'rails', '~> 7.0.1' + gem 'warden', '~> 1.2.6' + gem 'rack', '~> 2.0' + + gem 'activerecord-jdbcsqlite3-adapter', + github: 'jruby/activerecord-jdbc-adapter', + branch: '61-stable', + platforms: :jruby + gem 'sqlite3', '~> 1.4', platforms: %i[mri rbx] + + gem 'resque', '~> 1.26' + gem 'resque_spec', github: 'airbrake/resque_spec' + + gem 'delayed', '~> 0.4' + + gem 'mime-types', '~> 3.1' + end +end + appraise 'sinatra' do gem 'sinatra', '~> 2' gem 'warden', '~> 1.2.6' diff --git a/gemfiles/rails_5.2.gemfile b/gemfiles/rails_5.2.gemfile index e4d07ee2..efc49618 100644 --- a/gemfiles/rails_5.2.gemfile +++ b/gemfiles/rails_5.2.gemfile @@ -2,7 +2,7 @@ source "https://rubygems.org" -gem "rubocop", "= 0.81", require: false +gem "rubocop", "~> 1.21", require: false gem "sneakers", github: "jondot/sneakers", ref: "31d0cb25dc5bbcfb0749567e9e0f80e6353fb66b" gem "rails", "~> 5.2.0" gem "warden", "~> 1.2.6" diff --git a/gemfiles/rails_6.0.gemfile b/gemfiles/rails_6.0.gemfile index 20a33d65..1d23b215 100644 --- a/gemfiles/rails_6.0.gemfile +++ b/gemfiles/rails_6.0.gemfile @@ -11,8 +11,7 @@ gem "activerecord-jdbcsqlite3-adapter", "~> 60.1", platforms: :jruby gem "sqlite3", "~> 1.4", platforms: [:mri, :rbx] gem "resque", "~> 1.26" gem "resque_spec", github: "airbrake/resque_spec" -gem "delayed_job", github: "collectiveidea/delayed_job" -gem "delayed_job_active_record", "~> 4.1" +gem "delayed", "~> 0.4" gem "mime-types", "~> 3.1" gemspec path: "../" diff --git a/gemfiles/rails_6.1.gemfile b/gemfiles/rails_6.1.gemfile index 5d570767..a035e1e4 100644 --- a/gemfiles/rails_6.1.gemfile +++ b/gemfiles/rails_6.1.gemfile @@ -11,8 +11,7 @@ gem "activerecord-jdbcsqlite3-adapter", github: "jruby/activerecord-jdbc-adapter gem "sqlite3", "~> 1.4", platforms: [:mri, :rbx] gem "resque", "~> 1.26" gem "resque_spec", github: "airbrake/resque_spec" -gem "delayed_job", github: "collectiveidea/delayed_job" -gem "delayed_job_active_record", "~> 4.1" +gem "delayed", "~> 0.4" gem "mime-types", "~> 3.1" gemspec path: "../" diff --git a/gemfiles/rails_7.0.gemfile b/gemfiles/rails_7.0.gemfile new file mode 100644 index 00000000..82e44a3f --- /dev/null +++ b/gemfiles/rails_7.0.gemfile @@ -0,0 +1,17 @@ +# This file was generated by Appraisal + +source "https://rubygems.org" + +gem "rubocop", "~> 1.21", require: false +gem "sneakers", github: "jondot/sneakers", ref: "31d0cb25dc5bbcfb0749567e9e0f80e6353fb66b" +gem "rails", "~> 7.0.1" +gem "warden", "~> 1.2.6" +gem "rack", "~> 2.0" +gem "activerecord-jdbcsqlite3-adapter", github: "jruby/activerecord-jdbc-adapter", branch: "61-stable", platforms: :jruby +gem "sqlite3", "~> 1.4", platforms: [:mri, :rbx] +gem "resque", "~> 1.26" +gem "resque_spec", github: "airbrake/resque_spec" +gem "delayed", "~> 0.4" +gem "mime-types", "~> 3.1" + +gemspec path: "../" diff --git a/spec/apps/rails/dummy_app.rb b/spec/apps/rails/dummy_app.rb index d823d58b..36e396e2 100644 --- a/spec/apps/rails/dummy_app.rb +++ b/spec/apps/rails/dummy_app.rb @@ -231,8 +231,8 @@ def delayed_job # Modified version of: https://goo.gl/q8uCJq migration_template = File.open( File.join( - $LOAD_PATH.grep(/delayed_job/)[0], - 'generators/delayed_job/templates/migration.rb', + $LOAD_PATH.grep(/delayed/)[0], + 'generators/delayed/templates/migration.rb', ), ) diff --git a/spec/integration/rails/rails_spec.rb b/spec/integration/rails/rails_spec.rb index 7f83a8e7..1c8f7b68 100644 --- a/spec/integration/rails/rails_spec.rb +++ b/spec/integration/rails/rails_spec.rb @@ -261,7 +261,7 @@ def force_http_libs_prepend it "defaults to 500 when status code for exception returns 0" do allow(ActionDispatch::ExceptionWrapper) - .to receive(:status_code_for_exception).and_return(0) + .to receive(:status_code).and_return(0) expect(Airbrake).to receive(:notify_request).with( hash_including( From 7e03129eef591c46cce1c465533c3efcab03d09e Mon Sep 17 00:00:00 2001 From: Kyrylo Silin Date: Mon, 17 Jan 2022 18:01:53 +0200 Subject: [PATCH 34/50] rails/app: check for `Nodes::Star` instead of using `glob?` Fixes https://github.com/airbrake/airbrake/issues/1177 (airbrake gem don't work with 7.0.0.alpha2 release) Alternative to https://github.com/airbrake/airbrake/pull/1206 `glob?` on Rails 7+ raises error because Rails 7+ doesn't keep the route AST in memory anymore. A Rails contributor who worked on the related code [suggested][1] to use `Nodes::Star` instead, since that used to be the previous implementation of the `glob?` method. [1]: https://github.com/rails/rails/pull/43006#discussion_r783840849 --- CHANGELOG.md | 6 ++++++ lib/airbrake/rails/app.rb | 10 +++++----- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fc69e5a5..790476cb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,12 @@ Breaking changes: * Dropped support for Ruby 2.5 ([#1208](https://github.com/airbrake/airbrake/issues/1208)) +Bug fixes: + +* Fixed APM not working on Rails 7 due to ``NoMethodError (undefined method + `glob?' for nil:NilClass)`` + ([#1211](https://github.com/airbrake/airbrake/issues/1211)) + ### [v12.0.0][v12.0.0] (September 22, 2021) Breaking changes: diff --git a/lib/airbrake/rails/app.rb b/lib/airbrake/rails/app.rb index 89cfb1e3..2bbec863 100644 --- a/lib/airbrake/rails/app.rb +++ b/lib/airbrake/rails/app.rb @@ -40,12 +40,12 @@ def self.recognize_route(request) # Skip "catch-all" routes such as: # get '*path => 'pages#about' # - # @todo The `glob?` method was added in Rails v4.2.0.beta1. We - # should remove the `respond_to?` check once we drop old Rails - # versions support. + # Ideally, we should be using `route.glob?` but in Rails 7+ this + # call would fail with a `NoMethodError`. This is because in + # Rails 7+ the AST for the route is not kept in memory anymore. # - # https://github.com/rails/rails/commit/5460591f0226a9d248b7b4f89186bd5553e7768f - next if route.respond_to?(:glob?) && route.glob? + # See: https://github.com/rails/rails/pull/43006#discussion_r783895766 + next if route.path.spec.any?(ActionDispatch::Journey::Nodes::Star) path = if engine == ::Rails.application From 228e7649d1e1dfd8fe9f23a913ccf14336ad7bc6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 18 Jan 2022 01:01:12 +0000 Subject: [PATCH 35/50] build(deps-dev): update curb requirement from ~> 0.9 to ~> 1.0 Updates the requirements on [curb](https://github.com/taf2/curb) to permit the latest version. - [Release notes](https://github.com/taf2/curb/releases) - [Changelog](https://github.com/taf2/curb/blob/master/ChangeLog.md) - [Commits](https://github.com/taf2/curb/commits) --- updated-dependencies: - dependency-name: curb dependency-type: direct:development ... Signed-off-by: dependabot[bot] --- airbrake.gemspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/airbrake.gemspec b/airbrake.gemspec index 4a7dac67..64e117d4 100644 --- a/airbrake.gemspec +++ b/airbrake.gemspec @@ -46,7 +46,7 @@ DESC s.add_development_dependency 'rack-test', '~> 1.1' s.add_development_dependency 'redis', '~> 4.5' s.add_development_dependency 'sidekiq', '~> 6' - s.add_development_dependency 'curb', '~> 0.9' if RUBY_ENGINE == 'ruby' + s.add_development_dependency 'curb', '~> 1.0' if RUBY_ENGINE == 'ruby' s.add_development_dependency 'excon', '~> 0.64' s.add_development_dependency 'http', '~> 5.0' s.add_development_dependency 'httpclient', '~> 2.8' From a8a0f74fa9a9cbb668fc49f39f0a11d88d336da9 Mon Sep 17 00:00:00 2001 From: Kyrylo Silin Date: Tue, 18 Jan 2022 11:50:25 +0200 Subject: [PATCH 36/50] Release v13.0.0 --- CHANGELOG.md | 3 +++ lib/airbrake/version.rb | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 790476cb..eea5fc60 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,8 @@ Airbrake Changelog ### master +### [v13.0.0][v13.0.0] (January 18, 2022) + Breaking changes: * Dropped support for Ruby 2.5 @@ -994,3 +996,4 @@ Features: [v11.0.2]: https://github.com/airbrake/airbrake/releases/tag/v11.0.2 [v11.0.3]: https://github.com/airbrake/airbrake/releases/tag/v11.0.3 [v12.0.0]: https://github.com/airbrake/airbrake/releases/tag/v12.0.0 +[v13.0.0]: https://github.com/airbrake/airbrake/releases/tag/v13.0.0 diff --git a/lib/airbrake/version.rb b/lib/airbrake/version.rb index cecb64f0..506e6a2f 100644 --- a/lib/airbrake/version.rb +++ b/lib/airbrake/version.rb @@ -3,5 +3,5 @@ # We use Semantic Versioning v2.0.0 # More information: http://semver.org/ module Airbrake - AIRBRAKE_VERSION = '12.0.0' + AIRBRAKE_VERSION = '13.0.0' end From 97fd18aaedee2c1a707d964b45149f3f2afad46f Mon Sep 17 00:00:00 2001 From: naveensrinivasan <172697+naveensrinivasan@users.noreply.github.com> Date: Wed, 6 Apr 2022 18:13:30 +0000 Subject: [PATCH 37/50] Set permissions for GitHub actions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Included permissions for the action. https://github.com/ossf/scorecard/blob/main/docs/checks.md#token-permissions https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#permissions https://docs.github.com/en/actions/using-jobs/assigning-permissions-to-jobs [Keeping your GitHub Actions and workflows secure Part 1: Preventing pwn requests](https://securitylab.github.com/research/github-actions-preventing-pwn-requests/) > Restrict the GitHub token permissions only to the required ones; this way, even if the attackers will succeed in compromising your workflow, they won’t be able to do much. https://www.legitsecurity.com/blog/github-privilege-escalation-vulnerability Signed-off-by: naveensrinivasan <172697+naveensrinivasan@users.noreply.github.com> --- .github/workflows/test.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index a127c6d8..0e5e340b 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -2,6 +2,9 @@ name: airbrake on: [push] +permissions: + contents: read + jobs: test: strategy: From aa5919983c2b925ac21548b890e615ce7168ebf1 Mon Sep 17 00:00:00 2001 From: nathannaveen <42319948+nathannaveen@users.noreply.github.com> Date: Thu, 28 Apr 2022 19:44:49 -0500 Subject: [PATCH 38/50] chore: Included githubactions in the dependabot config This should help with keeping the GitHub actions updated on new releases. This will also help with keeping it secure. Dependabot helps in keeping the supply chain secure https://docs.github.com/en/code-security/dependabot GitHub actions up to date https://docs.github.com/en/code-security/dependabot/working-with-dependabot/keeping-your-actions-up-to-date-with-dependabot https://github.com/ossf/scorecard/blob/main/docs/checks.md#dependency-update-tool Signed-off-by: nathannaveen <42319948+nathannaveen@users.noreply.github.com> --- .github/dependabot.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 525316af..ec31adca 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -10,3 +10,9 @@ updates: - dependency-name: ethon versions: - 0.13.0 +- package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: daily + time: "19:00" + timezone: US/Central From e9f397357eea8c13ba24b2b30ce60fdaed2c9a25 Mon Sep 17 00:00:00 2001 From: Kyrylo Silin Date: Fri, 29 Apr 2022 15:33:44 +0300 Subject: [PATCH 39/50] rubocop: fix offences of the Style/FetchEnvVar cop --- lib/airbrake/capistrano/capistrano2.rb | 2 +- lib/airbrake/rake/tasks.rb | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/lib/airbrake/capistrano/capistrano2.rb b/lib/airbrake/capistrano/capistrano2.rb index 01cca28e..d242eaaf 100644 --- a/lib/airbrake/capistrano/capistrano2.rb +++ b/lib/airbrake/capistrano/capistrano2.rb @@ -21,7 +21,7 @@ def self.load_into(config) RAILS_ENV=#{fetch(:rails_env, nil)} \ bundle exec rake airbrake:deploy \ - USERNAME=#{Shellwords.shellescape(ENV['USER'] || ENV['USERNAME'])} \ + USERNAME=#{Shellwords.shellescape(ENV.fetch('USER', nil) || ENV.fetch('USERNAME', nil))} \ ENVIRONMENT=#{fetch(:airbrake_env, fetch(:rails_env, 'production'))} \ REVISION=#{current_revision.strip} \ REPOSITORY=#{repository} \ diff --git a/lib/airbrake/rake/tasks.rb b/lib/airbrake/rake/tasks.rb index 0de50541..b4eef44e 100644 --- a/lib/airbrake/rake/tasks.rb +++ b/lib/airbrake/rake/tasks.rb @@ -53,11 +53,11 @@ raise Airbrake::Error, 'airbrake-ruby is not configured' unless Airbrake.configured? deploy_params = { - environment: ENV['ENVIRONMENT'], - username: ENV['USERNAME'], - revision: ENV['REVISION'], - repository: ENV['REPOSITORY'], - version: ENV['VERSION'], + environment: ENV.fetch('ENVIRONMENT', nil), + username: ENV.fetch('USERNAME', nil), + revision: ENV.fetch('REVISION', nil), + repository: ENV.fetch('REPOSITORY', nil), + version: ENV.fetch('VERSION', nil), } promise = Airbrake.notify_deploy(deploy_params) promise.then do @@ -68,7 +68,7 @@ desc 'Install a Heroku deploy hook to notify Airbrake of deploys' task :install_heroku_deploy_hook do - app = ENV['HEROKU_APP'] + app = ENV.fetch('HEROKU_APP', nil) config = Bundler.with_clean_env do `heroku config --shell#{" --app #{app}" if app}` @@ -89,7 +89,7 @@ " environment will be used." end - unless (repo = ENV['REPOSITORY_URL']) + unless (repo = ENV.fetch('REPOSITORY_URL', nil)) repo = `git remote get-url origin 2>/dev/null`.chomp if repo.empty? puts "Airbrake couldn't identify your app's repository." From a963db00020cfbfc668b713f45444147adf9e75f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 29 Apr 2022 12:46:33 +0000 Subject: [PATCH 40/50] build(deps): bump actions/checkout from 2 to 3 Bumps [actions/checkout](https://github.com/actions/checkout) from 2 to 3. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v2...v3) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 0e5e340b..fe076605 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -15,7 +15,7 @@ jobs: runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Update package list run: sudo apt-get update From 36cf68df1510b64f46e5e25eb3ad5037a37a3753 Mon Sep 17 00:00:00 2001 From: Kyrylo Silin Date: Wed, 11 May 2022 20:00:38 +0300 Subject: [PATCH 41/50] rubocop: ignore context & describe when running Metrics/BlockLength The default is not enough for RSpec. --- .rubocop.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.rubocop.yml b/.rubocop.yml index 6a775176..94f7bd47 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -45,6 +45,9 @@ Style/FrozenStringLiteralComment: Metrics/BlockLength: CountComments: false Max: 25 + IgnoredMethods: + - describe + - context Exclude: - 'Rakefile' - '**/*.rake' From e752fec3ba2d42fb187039ca17dc2b327989f551 Mon Sep 17 00:00:00 2001 From: Kyrylo Silin Date: Wed, 11 May 2022 20:01:33 +0300 Subject: [PATCH 42/50] spec/action_controller_notify_subscriber: use have_received This form is nicer because we run expectations after the main code, not before. --- ...ction_controller_notify_subscriber_spec.rb | 24 ++++++++++++------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/spec/unit/rails/action_controller_notify_subscriber_spec.rb b/spec/unit/rails/action_controller_notify_subscriber_spec.rb index 16b4509c..ee74d149 100644 --- a/spec/unit/rails/action_controller_notify_subscriber_spec.rb +++ b/spec/unit/rails/action_controller_notify_subscriber_spec.rb @@ -10,12 +10,13 @@ before do allow(Airbrake::Rails::Event).to receive(:new).and_return(event) + allow(Airbrake).to receive(:notify_request) end context "when there are no routes in the request store" do it "doesn't notify requests" do - expect(Airbrake).not_to receive(:notify_request) subject.call([]) + expect(Airbrake).not_to have_received(:notify_request) end end @@ -38,8 +39,8 @@ end it "doesn't notify requests" do - expect(Airbrake).not_to receive(:notify_request) subject.call([]) + expect(Airbrake).not_to have_received(:notify_request) end end @@ -47,22 +48,27 @@ before do allow(Airbrake::Config.instance) .to receive(:performance_stats).and_return(true) + + allow(event).to receive(:method).and_return('GET') + allow(event).to receive(:status_code).and_return(200) + allow(event).to receive(:time).and_return(Time.now) + allow(event).to receive(:duration).and_return(1.234) end it "sends request info to Airbrake" do - expect(Airbrake).to receive(:notify_request).with( + subject.call([]) + + expect(Airbrake).to have_received(:notify_request).with( hash_including( method: 'GET', route: '/test-route', status_code: 200, ), ) - expect(event).to receive(:method).and_return('GET') - expect(event).to receive(:status_code).and_return(200) - expect(event).to receive(:time).and_return(Time.now) - expect(event).to receive(:duration).and_return(1.234) - - subject.call([]) + expect(event).to have_received(:method) + expect(event).to have_received(:status_code) + expect(event).to have_received(:time) + expect(event).to have_received(:duration) end end end From 852ffd6219e3a6c3dba642c23fa8995279c06975 Mon Sep 17 00:00:00 2001 From: Kyrylo Silin Date: Wed, 11 May 2022 20:02:29 +0300 Subject: [PATCH 43/50] action_controller_notify_subscriber: use seconds as time on Rails 7+ Fixes bugged route stat reporting on Rails 7+ due to the fact that `@event.time` returns milliseconds (but we want seconds). Therefore the time that we pass is ahead by centuries, and our backend rejects such routes. --- CHANGELOG.md | 4 ++ .../action_controller_notify_subscriber.rb | 15 +++++- lib/airbrake/rails/railtie.rb | 2 +- ...ction_controller_notify_subscriber_spec.rb | 49 ++++++++++++++----- 4 files changed, 55 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index eea5fc60..f5ddde08 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,10 @@ Airbrake Changelog ### master +* Fixed support of APM on Rails 7+, where the reported time of a route was + malformed, resulting in the complete rejection of the route stats by the + backend ([#1223](https://github.com/airbrake/airbrake/issues/1223)) + ### [v13.0.0][v13.0.0] (January 18, 2022) Breaking changes: diff --git a/lib/airbrake/rails/action_controller_notify_subscriber.rb b/lib/airbrake/rails/action_controller_notify_subscriber.rb index f8fd94f7..7fb4e8c4 100644 --- a/lib/airbrake/rails/action_controller_notify_subscriber.rb +++ b/lib/airbrake/rails/action_controller_notify_subscriber.rb @@ -9,6 +9,10 @@ module Rails # # @since v8.0.0 class ActionControllerNotifySubscriber + def initialize(rails_vsn) + @rails_7_or_above = rails_vsn.to_i >= 7 + end + def call(*args) return unless Airbrake::Config.instance.performance_stats @@ -23,7 +27,16 @@ def call(*args) route: route, status_code: event.status_code, timing: event.duration, - time: event.time, + + # On Rails 7+ `ActiveSupport::Notifications::Event#time` returns an + # instance of Float. It represents monotonic time in milliseconds. + # Airbrake Ruby expects that the provided time is in seconds. Hence, + # we need to convert it from milliseconds to seconds. In the + # versions below Rails 7, time is an instance of Time. + # + # Relevant commit: + # https://github.com/rails/rails/commit/81d0dc90becfe0b8e7f7f26beb66c25d84b8ec7f + time: @rails_7_or_above ? event.time / 1000 : event.time, ) end end diff --git a/lib/airbrake/rails/railtie.rb b/lib/airbrake/rails/railtie.rb index d3feb7a0..d142fb00 100644 --- a/lib/airbrake/rails/railtie.rb +++ b/lib/airbrake/rails/railtie.rb @@ -64,7 +64,7 @@ class Railtie < ::Rails::Railtie require 'airbrake/rails/action_controller_notify_subscriber' ActiveSupport::Notifications.subscribe( 'process_action.action_controller', - Airbrake::Rails::ActionControllerNotifySubscriber.new, + Airbrake::Rails::ActionControllerNotifySubscriber.new(::Rails.version), ) # Send performance breakdown: where a request spends its time. diff --git a/spec/unit/rails/action_controller_notify_subscriber_spec.rb b/spec/unit/rails/action_controller_notify_subscriber_spec.rb index ee74d149..33dc4058 100644 --- a/spec/unit/rails/action_controller_notify_subscriber_spec.rb +++ b/spec/unit/rails/action_controller_notify_subscriber_spec.rb @@ -3,6 +3,8 @@ require 'airbrake/rails/action_controller_notify_subscriber' RSpec.describe Airbrake::Rails::ActionControllerNotifySubscriber do + subject(:subscriber) { described_class.new('1.0.0') } + after { Airbrake::Rack::RequestStore.clear } describe "#call" do @@ -15,7 +17,7 @@ context "when there are no routes in the request store" do it "doesn't notify requests" do - subject.call([]) + subscriber.call([]) expect(Airbrake).not_to have_received(:notify_request) end end @@ -39,7 +41,7 @@ end it "doesn't notify requests" do - subject.call([]) + subscriber.call([]) expect(Airbrake).not_to have_received(:notify_request) end end @@ -51,24 +53,45 @@ allow(event).to receive(:method).and_return('GET') allow(event).to receive(:status_code).and_return(200) - allow(event).to receive(:time).and_return(Time.now) allow(event).to receive(:duration).and_return(1.234) end - it "sends request info to Airbrake" do - subject.call([]) + context "and also when the passed Rails version is below 7" do + let(:time) { Time.new } + + subject(:subscriber) { described_class.new('6.0.0') } + + before { allow(event).to receive(:time).and_return(time) } + + it "sends request info to Airbrake" do + subscriber.call([]) + expect(Airbrake).to have_received(:notify_request).with( + method: 'GET', + route: '/test-route', + status_code: 200, + timing: 1.234, + time: time, + ) + end + end + + context "and also when the passed Rails version is 7+" do + let(:milliseconds) { 1652280862048.6873 } + + subject(:subscriber) { described_class.new('7.0.0') } + + before { allow(event).to receive(:time).and_return(milliseconds) } - expect(Airbrake).to have_received(:notify_request).with( - hash_including( + it "sends request info to Airbrake with time in seconds" do + subscriber.call([]) + expect(Airbrake).to have_received(:notify_request).with( method: 'GET', route: '/test-route', status_code: 200, - ), - ) - expect(event).to have_received(:method) - expect(event).to have_received(:status_code) - expect(event).to have_received(:time) - expect(event).to have_received(:duration) + timing: 1.234, + time: 1652280862.0486872, + ) + end end end end From c4521bf4d93d6787e74d6a6989c6e493e43b0caf Mon Sep 17 00:00:00 2001 From: Kyrylo Silin Date: Thu, 12 May 2022 17:22:22 +0300 Subject: [PATCH 44/50] rails: factor out airbrake.middleware 'tie' code into a class --- lib/airbrake/rails/railtie.rb | 29 +-------- lib/airbrake/rails/railties/middleware_tie.rb | 62 +++++++++++++++++++ 2 files changed, 64 insertions(+), 27 deletions(-) create mode 100644 lib/airbrake/rails/railties/middleware_tie.rb diff --git a/lib/airbrake/rails/railtie.rb b/lib/airbrake/rails/railtie.rb index d142fb00..76da67ba 100644 --- a/lib/airbrake/rails/railtie.rb +++ b/lib/airbrake/rails/railtie.rb @@ -9,33 +9,8 @@ module Rails # rubocop:disable Metrics/BlockLength class Railtie < ::Rails::Railtie initializer('airbrake.middleware') do |app| - # Since Rails 3.2 the ActionDispatch::DebugExceptions middleware is - # responsible for logging exceptions and showing a debugging page in - # case the request is local. We want to insert our middleware after - # DebugExceptions, so we don't notify Airbrake about local requests. - - if ::Rails.version.to_i >= 5 - # Avoid the warning about deprecated strings. - # Insert after DebugExceptions, since ConnectionManagement doesn't - # exist in Rails 5 anymore. - app.config.middleware.insert_after( - ActionDispatch::DebugExceptions, - Airbrake::Rack::Middleware, - ) - elsif defined?(::ActiveRecord::ConnectionAdapters::ConnectionManagement) - # Insert after ConnectionManagement to avoid DB connection leakage: - # https://github.com/airbrake/airbrake/pull/568 - app.config.middleware.insert_after( - ::ActiveRecord::ConnectionAdapters::ConnectionManagement, - 'Airbrake::Rack::Middleware', - ) - else - # Insert after DebugExceptions for apps without ActiveRecord. - app.config.middleware.insert_after( - ActionDispatch::DebugExceptions, - 'Airbrake::Rack::Middleware', - ) - end + require 'airbrake/rails/railties/middleware_tie' + Railties::MiddlewareTie.new(app).call end rake_tasks do diff --git a/lib/airbrake/rails/railties/middleware_tie.rb b/lib/airbrake/rails/railties/middleware_tie.rb new file mode 100644 index 00000000..3c5bee8d --- /dev/null +++ b/lib/airbrake/rails/railties/middleware_tie.rb @@ -0,0 +1,62 @@ +# frozen_string_literal: true + +module Airbrake + module Rails + module Railties + # Ties Airbrake Rails Middleware with Rails (error sending). + # + # Since Rails 3.2 the ActionDispatch::DebugExceptions middleware is + # responsible for logging exceptions and showing a debugging page in case + # the request is local. We want to insert our middleware after + # DebugExceptions, so we don't notify Airbrake about local requests. + # + # @api private + # @since v13.0.1 + class MiddlewareTie + def initialize(app) + @app = app + @middleware = app.config.middleware + end + + def call + return tie_rails_5_or_above if ::Rails.version.to_i >= 5 + + if defined?(::ActiveRecord::ConnectionAdapters::ConnectionManagement) + return tie_rails_4_or_below_with_active_record + end + + tie_rails_4_or_below_with_active_record + end + + private + + # Avoid the warning about deprecated strings. + # Insert after DebugExceptions, since ConnectionManagement doesn't + # exist in Rails 5 anymore. + def tie_rails_5_or_above + @middleware.insert_after( + ActionDispatch::DebugExceptions, + Airbrake::Rack::Middleware, + ) + end + + # Insert after ConnectionManagement to avoid DB connection leakage: + # https://github.com/airbrake/airbrake/pull/568 + def tie_rails_4_or_below_with_active_record + @middleware.insert_after( + ::ActiveRecord::ConnectionAdapters::ConnectionManagement, + 'Airbrake::Rack::Middleware', + ) + end + + # Insert after DebugExceptions for apps without ActiveRecord. + def tie_rails_4_or_below_without_active_record + @middleware.insert_after( + ActionDispatch::DebugExceptions, + 'Airbrake::Rack::Middleware', + ) + end + end + end + end +end From a0bca59211243c0ccde6d686c0da64c8da5f9bbf Mon Sep 17 00:00:00 2001 From: Kyrylo Silin Date: Thu, 12 May 2022 18:48:55 +0300 Subject: [PATCH 45/50] rails: factor out airbrake.action_controller 'tie' code into a class --- lib/airbrake/rails/railtie.rb | 41 +-------- .../rails/railties/action_controller_tie.rb | 92 +++++++++++++++++++ 2 files changed, 94 insertions(+), 39 deletions(-) create mode 100644 lib/airbrake/rails/railties/action_controller_tie.rb diff --git a/lib/airbrake/rails/railtie.rb b/lib/airbrake/rails/railtie.rb index 76da67ba..264cbd53 100644 --- a/lib/airbrake/rails/railtie.rb +++ b/lib/airbrake/rails/railtie.rb @@ -22,45 +22,8 @@ class Railtie < ::Rails::Railtie end initializer('airbrake.action_controller') do - ActiveSupport.on_load(:action_controller, run_once: true) do - # Patches ActionController with methods that allow us to retrieve - # interesting request data. Appends that information to notices. - require 'airbrake/rails/action_controller' - include Airbrake::Rails::ActionController - - # Cache route information for the duration of the request. - require 'airbrake/rails/action_controller_route_subscriber' - ActiveSupport::Notifications.subscribe( - 'start_processing.action_controller', - Airbrake::Rails::ActionControllerRouteSubscriber.new, - ) - - # Send route stats. - require 'airbrake/rails/action_controller_notify_subscriber' - ActiveSupport::Notifications.subscribe( - 'process_action.action_controller', - Airbrake::Rails::ActionControllerNotifySubscriber.new(::Rails.version), - ) - - # Send performance breakdown: where a request spends its time. - require 'airbrake/rails/action_controller_performance_breakdown_subscriber' - ActiveSupport::Notifications.subscribe( - 'process_action.action_controller', - Airbrake::Rails::ActionControllerPerformanceBreakdownSubscriber.new, - ) - - require 'airbrake/rails/net_http' if defined?(Net) && defined?(Net::HTTP) - require 'airbrake/rails/curb' if defined?(Curl) && defined?(Curl::CURB_VERSION) - require 'airbrake/rails/http' if defined?(HTTP) && defined?(HTTP::Client) - require 'airbrake/rails/http_client' if defined?(HTTPClient) - require 'airbrake/rails/typhoeus' if defined?(Typhoeus) - - if defined?(Excon) - require 'airbrake/rails/excon_subscriber' - ActiveSupport::Notifications.subscribe(/excon/, Airbrake::Rails::Excon.new) - ::Excon.defaults[:instrumentor] = ActiveSupport::Notifications - end - end + require 'airbrake/rails/railties/action_controller_tie' + Railties::ActionControllerTie.new.call end initializer('airbrake.active_record') do diff --git a/lib/airbrake/rails/railties/action_controller_tie.rb b/lib/airbrake/rails/railties/action_controller_tie.rb new file mode 100644 index 00000000..9820943c --- /dev/null +++ b/lib/airbrake/rails/railties/action_controller_tie.rb @@ -0,0 +1,92 @@ +# frozen_string_literal: true + +require 'airbrake/rails/action_controller' +require 'airbrake/rails/action_controller_route_subscriber' +require 'airbrake/rails/action_controller_notify_subscriber' +require 'airbrake/rails/action_controller_performance_breakdown_subscriber' + +module Airbrake + module Rails + module Railties + # Ties Airbrake APM (routes) and HTTP clients with Rails. + # + # @api private + # @since v13.0.1 + class ActionControllerTie + def initialize + @route_subscriber = Airbrake::Rails::ActionControllerRouteSubscriber.new + @notify_subscriber = Airbrake::Rails::ActionControllerNotifySubscriber.new( + ::Rails.version, + ) + @performance_breakdown_subscriber = + Airbrake::Rails::ActionControllerPerformanceBreakdownSubscriber.new + end + + def call + ActiveSupport.on_load(:action_controller, run_once: true, yield: self) do + # Patches ActionController with methods that allow us to retrieve + # interesting request data. Appends that information to notices. + ::ActionController::Base.include(Airbrake::Rails::ActionController) + + tie_routes_apm + tie_http_integrations + end + end + + private + + def tie_routes_apm + [ + # Cache route information for the duration of the request. + ['start_processing.action_controller', @route_subscriber], + + # Send route stats. + ['process_action.action_controller', @notify_subscriber], + + # Send performance breakdown: where a request spends its time. + ['process_action.action_controller', @performance_breakdown_subscriber], + ].each do |(event, callback)| + ActiveSupport::Notifications.subscribe(event, callback) + end + end + + def tie_http_integrations + tie_net_http + tie_curl + tie_http + tie_http_client + tie_typhoeus + tie_excon + end + + def tie_net_http + require 'airbrake/rails/net_http' if defined?(Net) && defined?(Net::HTTP) + end + + def tie_curl + require 'airbrake/rails/curb' if defined?(Curl) && defined?(Curl::CURB_VERSION) + end + + def tie_http + require 'airbrake/rails/http' if defined?(HTTP) && defined?(HTTP::Client) + end + + def tie_http_client + require 'airbrake/rails/http_client' if defined?(HTTPClient) + end + + def tie_typhoeus + require 'airbrake/rails/typhoeus' if defined?(Typhoeus) + end + + def tie_excon + return unless defined?(Excon) + + require 'airbrake/rails/excon_subscriber' + ActiveSupport::Notifications.subscribe(/excon/, Airbrake::Rails::Excon.new) + ::Excon.defaults[:instrumentor] = ActiveSupport::Notifications + end + end + end + end +end From 6278acbc58b67e52d661b74c89b8f5c88ec00354 Mon Sep 17 00:00:00 2001 From: Kyrylo Silin Date: Thu, 12 May 2022 19:05:29 +0300 Subject: [PATCH 46/50] rails: factor out airbrake.active_record 'tie' code into a class --- lib/airbrake/rails/railtie.rb | 39 +---------- .../rails/railties/active_record_tie.rb | 65 +++++++++++++++++++ 2 files changed, 67 insertions(+), 37 deletions(-) create mode 100644 lib/airbrake/rails/railties/active_record_tie.rb diff --git a/lib/airbrake/rails/railtie.rb b/lib/airbrake/rails/railtie.rb index 264cbd53..586f37ba 100644 --- a/lib/airbrake/rails/railtie.rb +++ b/lib/airbrake/rails/railtie.rb @@ -5,8 +5,6 @@ module Rails # This railtie works for any Rails application that supports railties (Rails # 3.2+ apps). It makes Airbrake Ruby work with Rails and report errors # occurring in the application automatically. - # - # rubocop:disable Metrics/BlockLength class Railtie < ::Rails::Railtie initializer('airbrake.middleware') do |app| require 'airbrake/rails/railties/middleware_tie' @@ -27,40 +25,8 @@ class Railtie < ::Rails::Railtie end initializer('airbrake.active_record') do - ActiveSupport.on_load(:active_record, run_once: true) do - # Reports exceptions occurring in some bugged ActiveRecord callbacks. - # Applicable only to the versions of Rails lower than 4.2. - if defined?(::Rails) && - Gem::Version.new(::Rails.version) <= Gem::Version.new('4.2') - require 'airbrake/rails/active_record' - include Airbrake::Rails::ActiveRecord - end - - if defined?(ActiveRecord) - # Send SQL queries. - require 'airbrake/rails/active_record_subscriber' - ActiveSupport::Notifications.subscribe( - 'sql.active_record', Airbrake::Rails::ActiveRecordSubscriber.new - ) - - # Filter out parameters from SQL body. - if ::ActiveRecord::Base.respond_to?(:connection_db_config) - # Rails 6.1+ deprecates "connection_config" in favor of - # "connection_db_config", so we need an updated call. - Airbrake.add_performance_filter( - Airbrake::Filters::SqlFilter.new( - ::ActiveRecord::Base.connection_db_config.configuration_hash[:adapter], - ), - ) - else - Airbrake.add_performance_filter( - Airbrake::Filters::SqlFilter.new( - ::ActiveRecord::Base.connection_config[:adapter], - ), - ) - end - end - end + require 'airbrake/rails/railties/active_record_tie' + Railties::ActiveRecordTie.new.call end initializer('airbrake.active_job') do @@ -84,6 +50,5 @@ class Railtie < ::Rails::Railtie end end end - # rubocop:enable Metrics/BlockLength end end diff --git a/lib/airbrake/rails/railties/active_record_tie.rb b/lib/airbrake/rails/railties/active_record_tie.rb new file mode 100644 index 00000000..42c006d6 --- /dev/null +++ b/lib/airbrake/rails/railties/active_record_tie.rb @@ -0,0 +1,65 @@ +# frozen_string_literal: true + +require 'airbrake/rails/active_record' +require 'airbrake/rails/active_record_subscriber' + +module Airbrake + module Rails + module Railties + # Ties Airbrake APM (queries) with Rails. + # + # @api private + # @since v13.0.1 + class ActiveRecordTie + def initialize + @active_record_subscriber = Airbrake::Rails::ActiveRecordSubscriber.new + end + + def call + ActiveSupport.on_load(:active_record, run_once: true, yield: self) do + tie_activerecord_callback_fix + tie_activerecord_apm + end + end + + private + + def tie_activerecord_callback_fix + # Reports exceptions occurring in some bugged ActiveRecord callbacks. + # Applicable only to the versions of Rails lower than 4.2. + return unless defined?(::Rails) + return if Gem::Version.new(::Rails.version) > Gem::Version.new('4.2') + + ActiveRecord::Base.include(Airbrake::Rails::ActiveRecord) + end + + def tie_activerecord_apm + return unless defined?(ActiveRecord) + + # Send SQL queries. + ActiveSupport::Notifications.subscribe( + 'sql.active_record', + @active_record_subscriber, + ) + + # Filter out parameters from SQL body. + if ::ActiveRecord::Base.respond_to?(:connection_db_config) + # Rails 6.1+ deprecates "connection_config" in favor of + # "connection_db_config", so we need an updated call. + Airbrake.add_performance_filter( + Airbrake::Filters::SqlFilter.new( + ::ActiveRecord::Base.connection_db_config.configuration_hash[:adapter], + ), + ) + else + Airbrake.add_performance_filter( + Airbrake::Filters::SqlFilter.new( + ::ActiveRecord::Base.connection_config[:adapter], + ), + ) + end + end + end + end + end +end From d4a2effd0bb548e735b688c19820b05ae55af2c2 Mon Sep 17 00:00:00 2001 From: Kyrylo Silin Date: Thu, 12 May 2022 19:42:39 +0300 Subject: [PATCH 47/50] railties/active_record: read 'adapter' without requiring a DB conn Fixes https://github.com/airbrake/airbrake/issues/1222 (Airbrake Gem Attempts to Connect to Database in Databaseless App in Rails 6) Good article: https://www.bigbinary.com/blog/rails-6-changed-activerecord-base-configurations-result-to-an-object We also add a guard that makes sure there's an ActiveRecord configuration present (it can be that ActiveRecord is required but not configured; why? I have no idea but it did happen to our customer and he's got no clue either). --- CHANGELOG.md | 3 ++ .../rails/railties/active_record_tie.rb | 39 ++++++++++++------- 2 files changed, 27 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f5ddde08..9fd8147c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,9 @@ Airbrake Changelog * Fixed support of APM on Rails 7+, where the reported time of a route was malformed, resulting in the complete rejection of the route stats by the backend ([#1223](https://github.com/airbrake/airbrake/issues/1223)) +* Fixed bug where Rails 6+ apps that don't require ActiveRecord crash when + Airbrake is installed + ([#1224](https://github.com/airbrake/airbrake/pull/1224)) ### [v13.0.0][v13.0.0] (January 18, 2022) diff --git a/lib/airbrake/rails/railties/active_record_tie.rb b/lib/airbrake/rails/railties/active_record_tie.rb index 42c006d6..78bd2036 100644 --- a/lib/airbrake/rails/railties/active_record_tie.rb +++ b/lib/airbrake/rails/railties/active_record_tie.rb @@ -34,7 +34,15 @@ def tie_activerecord_callback_fix end def tie_activerecord_apm - return unless defined?(ActiveRecord) + # Some Rails apps don't use ActiveRecord. + return unless defined?(::ActiveRecord) + + # However, some dependencies might still require it, so we need an + # extra check. Apps that don't need ActiveRecord will likely have no + # AR configurations defined. We will skip APM integration in that + # case. See: https://github.com/airbrake/airbrake/issues/1222 + configurations = ::ActiveRecord::Base.configurations + return unless configurations.any? # Send SQL queries. ActiveSupport::Notifications.subscribe( @@ -43,21 +51,22 @@ def tie_activerecord_apm ) # Filter out parameters from SQL body. - if ::ActiveRecord::Base.respond_to?(:connection_db_config) - # Rails 6.1+ deprecates "connection_config" in favor of - # "connection_db_config", so we need an updated call. - Airbrake.add_performance_filter( - Airbrake::Filters::SqlFilter.new( - ::ActiveRecord::Base.connection_db_config.configuration_hash[:adapter], - ), - ) - else - Airbrake.add_performance_filter( - Airbrake::Filters::SqlFilter.new( - ::ActiveRecord::Base.connection_config[:adapter], - ), - ) + sql_filter = Airbrake::Filters::SqlFilter.new( + detect_activerecord_adapter(configurations), + ) + Airbrake.add_performance_filter(sql_filter) + end + + # Rails 6+ introduces the `configs_for` API instead of the deprecated + # `#[]`, so we need an updated call. + def detect_activerecord_adapter(configurations) + unless configurations.respond_to?(:configs_for) + return configurations[::Rails.env]['adapter'] end + + cfg = configurations.configs_for(env_name: ::Rails.env).first + # Rails 7+ API : Rails 6 API. + cfg.respond_to?(:adapter) ? cfg.adapter : cfg.config['adapter'] end end end From 9dc2462aeea34dfe49e2a32b0096ce29c98cec23 Mon Sep 17 00:00:00 2001 From: Kyrylo Silin Date: Fri, 13 May 2022 12:45:46 +0300 Subject: [PATCH 48/50] Release v13.0.1 --- CHANGELOG.md | 3 +++ LICENSE.md | 2 +- lib/airbrake/version.rb | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9fd8147c..f6549952 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,8 @@ Airbrake Changelog ### master +### [v13.0.1][v13.0.1] (May 13, 2022) + * Fixed support of APM on Rails 7+, where the reported time of a route was malformed, resulting in the complete rejection of the route stats by the backend ([#1223](https://github.com/airbrake/airbrake/issues/1223)) @@ -1004,3 +1006,4 @@ Features: [v11.0.3]: https://github.com/airbrake/airbrake/releases/tag/v11.0.3 [v12.0.0]: https://github.com/airbrake/airbrake/releases/tag/v12.0.0 [v13.0.0]: https://github.com/airbrake/airbrake/releases/tag/v13.0.0 +[v13.0.1]: https://github.com/airbrake/airbrake/releases/tag/v13.0.1 diff --git a/LICENSE.md b/LICENSE.md index 114f60f9..3522d9ba 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,7 +1,7 @@ The MIT License =============== -Copyright © 2021 Airbrake Technologies, Inc. +Copyright © 2022 Airbrake Technologies, Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in diff --git a/lib/airbrake/version.rb b/lib/airbrake/version.rb index 506e6a2f..45378fe8 100644 --- a/lib/airbrake/version.rb +++ b/lib/airbrake/version.rb @@ -3,5 +3,5 @@ # We use Semantic Versioning v2.0.0 # More information: http://semver.org/ module Airbrake - AIRBRAKE_VERSION = '13.0.0' + AIRBRAKE_VERSION = '13.0.1' end From 9786603cb4ce8ef91be5fd00aea9ab7dcca1b476 Mon Sep 17 00:00:00 2001 From: Kyrylo Silin Date: Fri, 20 May 2022 15:46:45 +0300 Subject: [PATCH 49/50] rails/event: convert milliseconds into seconds for #time Fixes #1228 (Airbrake 500 Errors) Improves on 852ffd6219e3a6c3dba642c23fa8995279c06975. While 852ffd6219e3a6c3dba642c23fa8995279c06975 was the correct fix, it was fixed at the wrong place. Route stat reporting worked but other APM parts still suffered from the same bug. I simply didn't notice that. I also wanted to make the change testable. The correct place to fix the bug is the Event class. The downside is that we cannot write unit tests for it. --- CHANGELOG.md | 6 +++ .../action_controller_notify_subscriber.rb | 15 +----- lib/airbrake/rails/event.rb | 14 +++++- .../rails/railties/action_controller_tie.rb | 4 +- spec/integration/rails/rails_spec.rb | 31 ++++++++++++ ...ction_controller_notify_subscriber_spec.rb | 48 ++++++------------- 6 files changed, 67 insertions(+), 51 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f6549952..55119f49 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,12 @@ Airbrake Changelog ### master +* Fixed support of APM on Rails 7+, where the reported time of a performance + breakdowns and queries malformed, resulting in the complete rejection of the + performance breakdowns or queries by the backend. This improves on the fix + introduced in v13.0.1 + ([#1227](https://github.com/airbrake/airbrake/issues/1227)) + ### [v13.0.1][v13.0.1] (May 13, 2022) * Fixed support of APM on Rails 7+, where the reported time of a route was diff --git a/lib/airbrake/rails/action_controller_notify_subscriber.rb b/lib/airbrake/rails/action_controller_notify_subscriber.rb index 7fb4e8c4..f8fd94f7 100644 --- a/lib/airbrake/rails/action_controller_notify_subscriber.rb +++ b/lib/airbrake/rails/action_controller_notify_subscriber.rb @@ -9,10 +9,6 @@ module Rails # # @since v8.0.0 class ActionControllerNotifySubscriber - def initialize(rails_vsn) - @rails_7_or_above = rails_vsn.to_i >= 7 - end - def call(*args) return unless Airbrake::Config.instance.performance_stats @@ -27,16 +23,7 @@ def call(*args) route: route, status_code: event.status_code, timing: event.duration, - - # On Rails 7+ `ActiveSupport::Notifications::Event#time` returns an - # instance of Float. It represents monotonic time in milliseconds. - # Airbrake Ruby expects that the provided time is in seconds. Hence, - # we need to convert it from milliseconds to seconds. In the - # versions below Rails 7, time is an instance of Time. - # - # Relevant commit: - # https://github.com/rails/rails/commit/81d0dc90becfe0b8e7f7f26beb66c25d84b8ec7f - time: @rails_7_or_above ? event.time / 1000 : event.time, + time: event.time, ) end end diff --git a/lib/airbrake/rails/event.rb b/lib/airbrake/rails/event.rb index 793106b7..47063c20 100644 --- a/lib/airbrake/rails/event.rb +++ b/lib/airbrake/rails/event.rb @@ -10,10 +10,14 @@ class Event # @see https://github.com/rails/rails/issues/8987 HTML_RESPONSE_WILDCARD = "*/*" + # @return [Integer] + MILLISECOND = 1000 + include Airbrake::Loggable def initialize(*args) @event = ActiveSupport::Notifications::Event.new(*args) + @rails_7_or_greater = ::Rails::VERSION::MAJOR >= 7 end def method @@ -42,7 +46,15 @@ def view_runtime end def time - @event.time + # On Rails 7+ `ActiveSupport::Notifications::Event#time` returns an + # instance of Float. It represents monotonic time in milliseconds. + # Airbrake Ruby expects that the provided time is in seconds. Hence, + # we need to convert it from milliseconds to seconds. In the + # versions below Rails 7, time is an instance of Time. + # + # Relevant commit: + # https://github.com/rails/rails/commit/81d0dc90becfe0b8e7f7f26beb66c25d84b8ec7f + @rails_7_or_greater ? @event.time / MILLISECOND : @event.time end def groups diff --git a/lib/airbrake/rails/railties/action_controller_tie.rb b/lib/airbrake/rails/railties/action_controller_tie.rb index 9820943c..bc050fde 100644 --- a/lib/airbrake/rails/railties/action_controller_tie.rb +++ b/lib/airbrake/rails/railties/action_controller_tie.rb @@ -15,9 +15,7 @@ module Railties class ActionControllerTie def initialize @route_subscriber = Airbrake::Rails::ActionControllerRouteSubscriber.new - @notify_subscriber = Airbrake::Rails::ActionControllerNotifySubscriber.new( - ::Rails.version, - ) + @notify_subscriber = Airbrake::Rails::ActionControllerNotifySubscriber.new @performance_breakdown_subscriber = Airbrake::Rails::ActionControllerPerformanceBreakdownSubscriber.new end diff --git a/spec/integration/rails/rails_spec.rb b/spec/integration/rails/rails_spec.rb index 1c8f7b68..efbe6b0f 100644 --- a/spec/integration/rails/rails_spec.rb +++ b/spec/integration/rails/rails_spec.rb @@ -246,6 +246,7 @@ def force_http_libs_prepend describe "request performance hook" do before do allow(Airbrake).to receive(:notify) + allow(Airbrake).to receive(:notify_request) allow(config).to receive(:performance_stats).and_return(true) end @@ -272,6 +273,36 @@ def force_http_libs_prepend ) head '/crash' end + + context "when Rails version is below 7" do + before do + if Rails::VERSION::MAJOR >= 7 + skip("This test requires Rails 6 or lower, you're on Rails #{Rails.version}") + end + end + + it "reports time as an instance of Time" do + head '/crash' + expect(Airbrake).to have_received(:notify_request).with( + hash_including(time: an_instance_of(Time)), + ) + end + end + + context "when Rails version is 7+" do + before do + if Rails::VERSION::MAJOR < 7 + skip("This test requires Rails 7+, you're on Rails #{Rails.version}") + end + end + + it "reports time as an instance of Float" do + head '/crash' + expect(Airbrake).to have_received(:notify_request).with( + hash_including(time: an_instance_of(Float)), + ) + end + end end describe "query performance hook" do diff --git a/spec/unit/rails/action_controller_notify_subscriber_spec.rb b/spec/unit/rails/action_controller_notify_subscriber_spec.rb index 33dc4058..a7d70708 100644 --- a/spec/unit/rails/action_controller_notify_subscriber_spec.rb +++ b/spec/unit/rails/action_controller_notify_subscriber_spec.rb @@ -3,7 +3,7 @@ require 'airbrake/rails/action_controller_notify_subscriber' RSpec.describe Airbrake::Rails::ActionControllerNotifySubscriber do - subject(:subscriber) { described_class.new('1.0.0') } + subject(:subscriber) { described_class.new } after { Airbrake::Rack::RequestStore.clear } @@ -47,51 +47,33 @@ end context "and when the Airbrake config enables performance stats" do + let(:timestamp) { Time.now.to_f } + before do allow(Airbrake::Config.instance) .to receive(:performance_stats).and_return(true) allow(event).to receive(:method).and_return('GET') allow(event).to receive(:status_code).and_return(200) + allow(event).to receive(:time).and_return(timestamp) allow(event).to receive(:duration).and_return(1.234) end - context "and also when the passed Rails version is below 7" do - let(:time) { Time.new } - - subject(:subscriber) { described_class.new('6.0.0') } - - before { allow(event).to receive(:time).and_return(time) } - - it "sends request info to Airbrake" do - subscriber.call([]) - expect(Airbrake).to have_received(:notify_request).with( - method: 'GET', - route: '/test-route', - status_code: 200, - timing: 1.234, - time: time, - ) - end - end - - context "and also when the passed Rails version is 7+" do - let(:milliseconds) { 1652280862048.6873 } - - subject(:subscriber) { described_class.new('7.0.0') } - - before { allow(event).to receive(:time).and_return(milliseconds) } + it "sends request info to Airbrake" do + subscriber.call([]) - it "sends request info to Airbrake with time in seconds" do - subscriber.call([]) - expect(Airbrake).to have_received(:notify_request).with( + expect(Airbrake).to have_received(:notify_request).with( + hash_including( method: 'GET', route: '/test-route', status_code: 200, - timing: 1.234, - time: 1652280862.0486872, - ) - end + time: timestamp, + ), + ) + expect(event).to have_received(:method) + expect(event).to have_received(:status_code) + expect(event).to have_received(:time) + expect(event).to have_received(:duration) end end end From b7c71ea15345edd2e8b36280ce0ce076d1f66a55 Mon Sep 17 00:00:00 2001 From: Kyrylo Silin Date: Fri, 20 May 2022 17:44:20 +0300 Subject: [PATCH 50/50] Release v13.0.2 --- CHANGELOG.md | 3 +++ lib/airbrake/version.rb | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 55119f49..837e541e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,8 @@ Airbrake Changelog ### master +### [v13.0.2][v13.0.2] (May 20, 2022) + * Fixed support of APM on Rails 7+, where the reported time of a performance breakdowns and queries malformed, resulting in the complete rejection of the performance breakdowns or queries by the backend. This improves on the fix @@ -1013,3 +1015,4 @@ Features: [v12.0.0]: https://github.com/airbrake/airbrake/releases/tag/v12.0.0 [v13.0.0]: https://github.com/airbrake/airbrake/releases/tag/v13.0.0 [v13.0.1]: https://github.com/airbrake/airbrake/releases/tag/v13.0.1 +[v13.0.2]: https://github.com/airbrake/airbrake/releases/tag/v13.0.2 diff --git a/lib/airbrake/version.rb b/lib/airbrake/version.rb index 45378fe8..df319d85 100644 --- a/lib/airbrake/version.rb +++ b/lib/airbrake/version.rb @@ -3,5 +3,5 @@ # We use Semantic Versioning v2.0.0 # More information: http://semver.org/ module Airbrake - AIRBRAKE_VERSION = '13.0.1' + AIRBRAKE_VERSION = '13.0.2' end