airbrakeV4rails5 4.3.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (98) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG +1716 -0
  3. data/Gemfile +3 -0
  4. data/Guardfile +6 -0
  5. data/INSTALL +20 -0
  6. data/LICENSE +61 -0
  7. data/README.md +148 -0
  8. data/README_FOR_HEROKU_ADDON.md +102 -0
  9. data/Rakefile +179 -0
  10. data/TESTED_AGAINST +7 -0
  11. data/airbrake.gemspec +41 -0
  12. data/bin/airbrake +12 -0
  13. data/features/metal.feature +34 -0
  14. data/features/rack.feature +60 -0
  15. data/features/rails.feature +324 -0
  16. data/features/rake.feature +33 -0
  17. data/features/sinatra.feature +126 -0
  18. data/features/step_definitions/file_steps.rb +14 -0
  19. data/features/step_definitions/rack_steps.rb +27 -0
  20. data/features/step_definitions/rails_application_steps.rb +267 -0
  21. data/features/step_definitions/rake_steps.rb +22 -0
  22. data/features/support/airbrake_shim.rb.template +11 -0
  23. data/features/support/aruba.rb +5 -0
  24. data/features/support/env.rb +39 -0
  25. data/features/support/matchers.rb +35 -0
  26. data/features/support/rails.rb +156 -0
  27. data/features/support/rake/Rakefile +77 -0
  28. data/features/user_informer.feature +57 -0
  29. data/generators/airbrake/airbrake_generator.rb +94 -0
  30. data/generators/airbrake/lib/insert_commands.rb +34 -0
  31. data/generators/airbrake/lib/rake_commands.rb +24 -0
  32. data/generators/airbrake/templates/airbrake_tasks.rake +25 -0
  33. data/generators/airbrake/templates/capistrano_hook.rb +6 -0
  34. data/generators/airbrake/templates/initializer.rb +4 -0
  35. data/install.rb +1 -0
  36. data/lib/airbrake.rb +191 -0
  37. data/lib/airbrake/backtrace.rb +103 -0
  38. data/lib/airbrake/capistrano.rb +103 -0
  39. data/lib/airbrake/capistrano3.rb +3 -0
  40. data/lib/airbrake/cli/client.rb +76 -0
  41. data/lib/airbrake/cli/options.rb +45 -0
  42. data/lib/airbrake/cli/printer.rb +33 -0
  43. data/lib/airbrake/cli/project.rb +17 -0
  44. data/lib/airbrake/cli/project_factory.rb +33 -0
  45. data/lib/airbrake/cli/runner.rb +49 -0
  46. data/lib/airbrake/cli/validator.rb +8 -0
  47. data/lib/airbrake/configuration.rb +366 -0
  48. data/lib/airbrake/jobs/send_job.rb +7 -0
  49. data/lib/airbrake/notice.rb +411 -0
  50. data/lib/airbrake/rack.rb +64 -0
  51. data/lib/airbrake/rails.rb +45 -0
  52. data/lib/airbrake/rails/action_controller_catcher.rb +32 -0
  53. data/lib/airbrake/rails/controller_methods.rb +146 -0
  54. data/lib/airbrake/rails/error_lookup.rb +35 -0
  55. data/lib/airbrake/rails/middleware.rb +63 -0
  56. data/lib/airbrake/rails3_tasks.rb +126 -0
  57. data/lib/airbrake/railtie.rb +44 -0
  58. data/lib/airbrake/rake_handler.rb +75 -0
  59. data/lib/airbrake/response.rb +29 -0
  60. data/lib/airbrake/sender.rb +213 -0
  61. data/lib/airbrake/shared_tasks.rb +59 -0
  62. data/lib/airbrake/sidekiq.rb +8 -0
  63. data/lib/airbrake/sinatra.rb +40 -0
  64. data/lib/airbrake/tasks.rb +81 -0
  65. data/lib/airbrake/tasks/airbrake.cap +28 -0
  66. data/lib/airbrake/user_informer.rb +36 -0
  67. data/lib/airbrake/utils/params_cleaner.rb +141 -0
  68. data/lib/airbrake/utils/rack_filters.rb +45 -0
  69. data/lib/airbrake/version.rb +3 -0
  70. data/lib/airbrake_tasks.rb +62 -0
  71. data/lib/rails/generators/airbrake/airbrake_generator.rb +155 -0
  72. data/lib/templates/rescue.erb +91 -0
  73. data/rails/init.rb +1 -0
  74. data/resources/README.md +34 -0
  75. data/resources/airbrake_2_4.xsd +89 -0
  76. data/resources/airbrake_3_0.json +52 -0
  77. data/resources/ca-bundle.crt +3376 -0
  78. data/script/integration_test.rb +35 -0
  79. data/test/airbrake_tasks_test.rb +161 -0
  80. data/test/backtrace_test.rb +215 -0
  81. data/test/capistrano_test.rb +44 -0
  82. data/test/configuration_test.rb +303 -0
  83. data/test/controller_methods_test.rb +230 -0
  84. data/test/helper.rb +233 -0
  85. data/test/integration.rb +13 -0
  86. data/test/integration/catcher_test.rb +371 -0
  87. data/test/logger_test.rb +79 -0
  88. data/test/notice_test.rb +494 -0
  89. data/test/notifier_test.rb +288 -0
  90. data/test/params_cleaner_test.rb +204 -0
  91. data/test/rack_test.rb +62 -0
  92. data/test/rails_initializer_test.rb +36 -0
  93. data/test/recursion_test.rb +10 -0
  94. data/test/response_test.rb +18 -0
  95. data/test/sender_test.rb +335 -0
  96. data/test/support/response_shim.xml +4 -0
  97. data/test/user_informer_test.rb +29 -0
  98. metadata +469 -0
@@ -0,0 +1,81 @@
1
+ require 'airbrake'
2
+ require File.join(File.dirname(__FILE__), 'shared_tasks')
3
+
4
+ namespace :airbrake do
5
+ desc "Verify your gem installation by sending a test exception to the airbrake service"
6
+ task :test => ['airbrake:log_stdout', :environment] do
7
+ RAILS_DEFAULT_LOGGER.level = Logger::DEBUG
8
+
9
+ Dir["app/controllers/application*.rb"].each { |file| require(File.expand_path(file)) }
10
+
11
+ class AirbrakeTestingException < RuntimeError; end
12
+
13
+ unless Airbrake.configuration.api_key
14
+ puts "Airbrake needs an API key configured! Check the README to see how to add it."
15
+ exit
16
+ end
17
+
18
+ Airbrake.configuration.development_environments = []
19
+
20
+ catcher = Airbrake::Rails::ActionControllerCatcher
21
+ in_controller = ApplicationController.included_modules.include?(catcher)
22
+ in_base = ActionController::Base.included_modules.include?(catcher)
23
+ if !in_controller || !in_base
24
+ puts "Rails initialization did not occur"
25
+ exit
26
+ end
27
+
28
+ puts "Configuration:"
29
+ Airbrake.configuration.to_hash.each do |key, value|
30
+ puts sprintf("%25s: %s", key.to_s, value.inspect.slice(0, 55))
31
+ end
32
+
33
+ unless defined?(ApplicationController)
34
+ puts "No ApplicationController found"
35
+ exit
36
+ end
37
+
38
+ puts 'Setting up the Controller.'
39
+ class ApplicationController
40
+ # This is to bypass any filters that may prevent access to the action.
41
+ prepend_before_filter :test_airbrake
42
+ def test_airbrake
43
+ puts "Raising '#{exception_class.name}' to simulate application failure."
44
+ raise exception_class.new, 'Testing airbrake via "rake airbrake:test". If you can see this, it works.'
45
+ end
46
+
47
+ def rescue_action(exception)
48
+ rescue_action_in_public exception
49
+ end
50
+
51
+ # Ensure we actually have an action to go to.
52
+ def verify; end
53
+
54
+ def consider_all_requests_local
55
+ false
56
+ end
57
+
58
+ def local_request?
59
+ false
60
+ end
61
+
62
+ def exception_class
63
+ exception_name = ENV['EXCEPTION'] || "AirbrakeTestingException"
64
+ exception_name.split("::").inject(Object){|klass, name| klass.const_get(name)}
65
+ rescue
66
+ Object.const_set(exception_name.gsub(/:+/, "_"), Class.new(Exception))
67
+ end
68
+
69
+ def logger
70
+ nil
71
+ end
72
+ end
73
+ class AirbrakeVerificationController < ApplicationController; end
74
+
75
+ puts 'Processing request.'
76
+ request = ActionController::TestRequest.new("REQUEST_URI" => "/airbrake_verification_controller")
77
+ response = ActionController::TestResponse.new
78
+ AirbrakeVerificationController.new.process(request, response)
79
+ end
80
+ end
81
+
@@ -0,0 +1,28 @@
1
+ namespace :airbrake do
2
+ desc <<-DESC
3
+ Notify Airbrake of the deployment by running the notification on the REMOTE machine.
4
+ - Run remotely so we use remote API keys, environment, etc.
5
+ DESC
6
+ task :deploy do
7
+ # update scm state to get the repository information
8
+ invoke "#{scm}:update"
9
+ on roles(:all) do
10
+ within release_path do
11
+ # XXX: Invoking deploy:set_rails_env would set :rails_env to proper
12
+ # value, but that would make us depend on capistrano-rails
13
+ with rails_env: fetch(:rails_env, fetch(:stage)) do
14
+ # Compose the command notify_command
15
+ airbrake_env = fetch(:airbrake_env, fetch(:rails_env, fetch(:stage)))
16
+ notify_command = "airbrake:deploy"
17
+ notify_command << " TO=#{airbrake_env}"
18
+ notify_command << " REVISION=#{fetch(:current_revision)} REPO=#{fetch(:repo_url)}"
19
+ notify_command << " USER=#{local_user.strip.shellescape}"
20
+
21
+ info "Notifying Airbrake of Deploy (#{notify_command})"
22
+ execute :rake, notify_command
23
+ info "Airbrake Notification Complete."
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,36 @@
1
+ module Airbrake
2
+ class UserInformer
3
+ def initialize(app)
4
+ @app = app
5
+ end
6
+
7
+ def replacement(with)
8
+ Airbrake.configuration.user_information.gsub(/\{\{\s*error_id\s*\}\}/, with.to_s)
9
+ end
10
+
11
+ def call(env)
12
+ dup._call(env)
13
+ end
14
+
15
+ def _call(env)
16
+ status, headers, body = @app.call(env)
17
+
18
+ if env['airbrake.error_id'] && Airbrake.configuration.user_information
19
+ new_body = []
20
+ replace = replacement(env['airbrake.error_id'])
21
+ body.each do |chunk|
22
+ new_body << chunk.gsub("<!-- AIRBRAKE ERROR -->", replace)
23
+ end
24
+ body.close if body.respond_to?(:close)
25
+ headers['Content-Length'] = new_body.inject(0){|sum, x| sum + x.bytesize}.to_s
26
+ body = new_body
27
+ end
28
+
29
+ [status, headers, body]
30
+
31
+ ensure
32
+ body.close if body && body.respond_to?(:close) && $!
33
+ end
34
+ end
35
+ end
36
+
@@ -0,0 +1,141 @@
1
+ module Airbrake
2
+ module Utils
3
+ class ParamsCleaner
4
+ attr_writer :blacklist_filters, :whitelist_filters, :to_clean
5
+ attr_reader :parameters, :cgi_data, :session_data
6
+
7
+ # Public: Initialize a new Airbrake::Utils::ParamsCleaner
8
+ #
9
+ # opts - The Hash options that contain filters and params (default: {}):
10
+ # :blacklist_filters - The Array of param keys that should be filtered
11
+ # :whitelist_filters - The Array of param keys that shouldn't be filtered
12
+ # :to_clean - The Hash of unfiltered params
13
+ # :blacklist_filters take precedence over the :whitelist_filters
14
+ def initialize(opts = {})
15
+ @blacklist_filters = (opts[:blacklist_filters] || []).flatten
16
+ @blacklist_filters.map!{|f| f.is_a?(Symbol) ? f.to_s : f }
17
+ @whitelist_filters = (opts[:whitelist_filters] || []).flatten
18
+ @whitelist_filters.map!{|f| f.is_a?(Symbol) ? f.to_s : f }
19
+ @to_clean = opts[:to_clean]
20
+ end
21
+
22
+ # Public: Takes the params to_clean passed in an initializer
23
+ # and filters them out by filters passed.
24
+ #
25
+ # Also normalizes unserializable data.
26
+ #
27
+ # Returns self, so that :parameters, :cgi_data, :session_data
28
+ # could be extracted
29
+ def clean
30
+ clean_parameters
31
+ clean_session_data
32
+ clean_cgi_data
33
+ clean_rack_request_data
34
+
35
+ self
36
+ end
37
+
38
+ private
39
+
40
+ def clean_parameters
41
+ return unless @to_clean[:parameters]
42
+
43
+ @parameters = if any_filters?
44
+ filter(clean_unserializable_data(@to_clean[:parameters]))
45
+ else
46
+ clean_unserializable_data(@to_clean[:parameters])
47
+ end
48
+ end
49
+
50
+ def clean_cgi_data
51
+ return unless @to_clean[:cgi_data]
52
+
53
+ @cgi_data = if any_filters?
54
+ filter(clean_unserializable_data(@to_clean[:cgi_data]))
55
+ else
56
+ clean_unserializable_data(@to_clean[:cgi_data])
57
+ end
58
+ end
59
+
60
+ def clean_session_data
61
+ return unless @to_clean[:session_data]
62
+
63
+ @session_data = if any_filters?
64
+ filter(clean_unserializable_data(@to_clean[:session_data]))
65
+ else
66
+ clean_unserializable_data(@to_clean[:session_data])
67
+ end
68
+ end
69
+
70
+ def clean_rack_request_data
71
+ if @cgi_data
72
+ @cgi_data.reject! do |key, val|
73
+ Airbrake::FILTERED_RACK_VARS.include?(key) || Airbrake::SENSITIVE_ENV_VARS.any?{|re| re.match(key)}
74
+ end
75
+ end
76
+ end
77
+
78
+ def any_filters?
79
+ @blacklist_filters.any? || @whitelist_filters.any?
80
+ end
81
+
82
+ def filter_key?(key)
83
+ blacklist_key?(key) || !whitelist_key?(key)
84
+ end
85
+
86
+ def blacklist_key?(key)
87
+ @blacklist_filters.any? do |filter|
88
+ key == filter || filter.is_a?(Regexp) && filter.match(key)
89
+ end
90
+ end
91
+
92
+ def whitelist_key?(key)
93
+ return true if @whitelist_filters.empty?
94
+ @whitelist_filters.any? do |filter|
95
+ key == filter || filter.is_a?(Regexp) && filter.match(key)
96
+ end
97
+ end
98
+
99
+ def filter(hash)
100
+ return hash unless hash.is_a?(Hash)
101
+
102
+ hash.each do |key, value|
103
+ if filter_key?(key)
104
+ hash[key] = "[FILTERED]"
105
+ elsif value.respond_to?(:to_hash)
106
+ filter(value)
107
+ elsif value.is_a?(Array)
108
+ hash[key] = value.map { |item| filter(item) }
109
+ end
110
+ end
111
+ end
112
+
113
+ # Removes non-serializable data. Allowed data types are strings, arrays,
114
+ # and hashes. All other types are converted to strings.
115
+ def clean_unserializable_data(data, stack = [])
116
+ return "[possible infinite recursion halted]" if stack.any?{|item| item == data.object_id }
117
+ if data.is_a?(String)
118
+ data
119
+ elsif data.is_a?(Hash)
120
+ data.inject({}) do |result, (key, value)|
121
+ result.merge!(key => clean_unserializable_data(value, stack + [data.object_id]))
122
+ end
123
+ elsif data.respond_to?(:to_hash)
124
+ data.to_hash.inject({}) do |result, (key, value)|
125
+ result.merge!(key => clean_unserializable_data(value, stack + [data.object_id]))
126
+ end
127
+ elsif data.respond_to?(:collect) && !data.respond_to?(:readlines)
128
+ data = data.collect do |value|
129
+ clean_unserializable_data(value, stack + [data.object_id])
130
+ end
131
+ elsif data.respond_to?(:to_ary)
132
+ data = data.to_ary.collect do |value|
133
+ clean_unserializable_data(value, stack + [data.object_id])
134
+ end
135
+ elsif data.respond_to?(:to_s)
136
+ data.nil? ? nil : data.to_s
137
+ end
138
+ end
139
+ end
140
+ end
141
+ end
@@ -0,0 +1,45 @@
1
+ module Airbrake
2
+ SENSITIVE_RACK_VARS = %w(
3
+ HTTP_X_CSRF_TOKEN
4
+ HTTP_COOKIE
5
+ HTTP_AUTHORIZATION
6
+
7
+ action_dispatch.request.unsigned_session_cookie
8
+ action_dispatch.cookies
9
+ action_dispatch.unsigned_session_cookie
10
+ action_dispatch.secret_key_base
11
+ action_dispatch.signed_cookie_salt
12
+ action_dispatch.encrypted_cookie_salt
13
+ action_dispatch.encrypted_signed_cookie_salt
14
+ action_dispatch.http_auth_salt
15
+ action_dispatch.secret_token
16
+
17
+ rack.request.cookie_hash
18
+ rack.request.cookie_string
19
+ rack.request.form_vars
20
+
21
+ rack.session
22
+ rack.session.options
23
+ )
24
+
25
+ RACK_VARS_CONTAINING_INSTANCES = %w(
26
+ action_controller.instance
27
+
28
+ action_dispatch.backtrace_cleaner
29
+ action_dispatch.routes
30
+ action_dispatch.logger
31
+ action_dispatch.key_generator
32
+
33
+ rack-cache.storage
34
+
35
+ rack.errors
36
+ rack.input
37
+ )
38
+
39
+ SENSITIVE_ENV_VARS = [
40
+ /secret/i,
41
+ /password/i
42
+ ]
43
+
44
+ FILTERED_RACK_VARS = SENSITIVE_RACK_VARS + SENSITIVE_ENV_VARS + RACK_VARS_CONTAINING_INSTANCES
45
+ end
@@ -0,0 +1,3 @@
1
+ module Airbrake
2
+ VERSION = "4.3.8".freeze
3
+ end
@@ -0,0 +1,62 @@
1
+ require 'net/http'
2
+ require 'uri'
3
+
4
+ # Capistrano tasks for notifying Airbrake of deploys
5
+ module AirbrakeTasks
6
+
7
+ # Alerts Airbrake of a deploy.
8
+ #
9
+ # @param [Hash] opts Data about the deploy that is set to Airbrake
10
+ #
11
+ # @option opts [String] :rails_env Environment of the deploy (production, staging)
12
+ # @option opts [String] :scm_revision The given revision/sha that is being deployed
13
+ # @option opts [String] :scm_repository Address of your repository to help with code lookups
14
+ # @option opts [String] :local_username Who is deploying
15
+ def self.deploy(opts = {})
16
+ unless Airbrake.configuration.api_key =~ /\S/
17
+ puts "I don't seem to be configured with an API key. Please check your configuration."
18
+ return false
19
+ end
20
+
21
+ unless opts[:rails_env] =~ /\S/
22
+ puts "I don't know to which Rails environment you are deploying (use the TO=production option)."
23
+ return false
24
+ end
25
+
26
+ dry_run = opts.delete(:dry_run)
27
+ params = {'api_key' => Airbrake.configuration.api_key}
28
+ opts.each {|k,v| params["deploy[#{k}]"] = v }
29
+
30
+ host = Airbrake.configuration.host || 'api.airbrake.io'
31
+ port = Airbrake.configuration.port
32
+
33
+ proxy = Net::HTTP.Proxy(Airbrake.configuration.proxy_host,
34
+ Airbrake.configuration.proxy_port,
35
+ Airbrake.configuration.proxy_user,
36
+ Airbrake.configuration.proxy_pass)
37
+ http = proxy.new(host, port)
38
+
39
+
40
+
41
+ # Handle Security
42
+ if Airbrake.configuration.secure?
43
+ http.use_ssl = true
44
+ http.ca_file = Airbrake.configuration.ca_bundle_path
45
+ http.verify_mode = OpenSSL::SSL::VERIFY_PEER
46
+ end
47
+
48
+ post = Net::HTTP::Post.new("/deploys.txt")
49
+ post.set_form_data(params)
50
+
51
+ if dry_run
52
+ puts http.inspect, params.inspect
53
+ return true
54
+ else
55
+ response = http.request(post)
56
+
57
+ puts response.body
58
+ return Net::HTTPSuccess === response
59
+ end
60
+ end
61
+ end
62
+
@@ -0,0 +1,155 @@
1
+ require 'rails/generators'
2
+
3
+ class AirbrakeGenerator < Rails::Generators::Base
4
+ desc "Creates the Airbrake initializer file at config/initializers/airbrake.rb"
5
+
6
+ class_option :api_key, :aliases => "-k", :type => :string,
7
+ :desc => "Your Airbrake API key"
8
+
9
+ class_option :heroku, :type => :boolean,
10
+ :desc => "Use the Heroku addon to provide your Airbrake API key"
11
+
12
+ class_option :app, :aliases => "-a", :type => :string,
13
+ :desc => "Your Heroku app name (only required if deploying to >1 Heroku app)"
14
+
15
+ class_option :secure, :type => :boolean,
16
+ :desc => "Use SSL connection"
17
+
18
+ class_option :test_mode, :aliases => "-t", :type => :boolean,
19
+ :desc => "Use Airbrake in test mode"
20
+
21
+ def self.source_root
22
+ @_airbrake_source_root ||= File.expand_path("../../../../../generators/airbrake/templates", __FILE__)
23
+ end
24
+
25
+ def install
26
+ ensure_api_key_was_configured
27
+ ensure_plugin_is_not_present
28
+ append_capistrano_hook if capistrano_present?
29
+ generate_initializer unless api_key_configured?
30
+ determine_api_key if heroku?
31
+ test_airbrake
32
+ end
33
+
34
+ private
35
+
36
+ def ensure_api_key_was_configured
37
+ if !options[:api_key] && !options[:heroku] && !api_key_configured?
38
+ puts "Must pass --api-key or --heroku or create config/initializers/airbrake.rb"
39
+ exit
40
+ end
41
+ end
42
+
43
+ def ensure_plugin_is_not_present
44
+ if plugin_is_present?
45
+ puts "You must first remove the airbrake plugin. Please run: script/plugin remove airbrake"
46
+ exit
47
+ end
48
+ end
49
+
50
+ def capistrano_present?
51
+ !Gem.loaded_specs['capistrano'].nil? &&
52
+ File.exists?('config/deploy.rb') &&
53
+ File.exists?('Capfile')
54
+ end
55
+
56
+ def append_capistrano_hook
57
+ if capistrano_version < Gem::Version.new('3')
58
+ append_file('config/deploy.rb', capistrano2_hook)
59
+ else
60
+ append_file('config/deploy.rb', capistrano3_hook)
61
+ end
62
+ end
63
+
64
+ def capistrano_version
65
+ Gem.loaded_specs['capistrano'].version
66
+ end
67
+
68
+ def capistrano2_hook
69
+ <<-HOOK
70
+
71
+ require './config/boot'
72
+ require 'airbrake/capistrano'
73
+ HOOK
74
+ end
75
+
76
+ def capistrano3_hook
77
+ <<-HOOK
78
+
79
+ require 'airbrake/capistrano3'
80
+ after "deploy:finished", "airbrake:deploy"
81
+ HOOK
82
+ end
83
+
84
+ def api_key_expression
85
+ if options[:api_key]
86
+ "'#{options[:api_key]}'"
87
+ elsif options[:heroku]
88
+ "ENV['AIRBRAKE_API_KEY']"
89
+ end
90
+ end
91
+
92
+ def generate_initializer
93
+ template 'initializer.rb', 'config/initializers/airbrake.rb'
94
+ end
95
+
96
+ def determine_api_key
97
+ puts "Attempting to determine your API Key from Heroku..."
98
+ ENV['AIRBRAKE_API_KEY'] = heroku_api_key
99
+ if ENV['AIRBRAKE_API_KEY'] =~ /\S/
100
+ puts "... Done."
101
+ puts "Heroku's Airbrake API Key is '#{ENV['AIRBRAKE_API_KEY']}'"
102
+ else
103
+ puts "... Failed."
104
+ puts "WARNING: We were unable to detect the Airbrake API Key from your Heroku environment."
105
+ puts "Your Heroku application environment may not be configured correctly."
106
+ exit 1
107
+ end
108
+ end
109
+
110
+ def heroku_var(var,app_name = nil)
111
+ app = app_name ? "-a #{app_name}" : ''
112
+ `heroku config:get #{var} #{app}`
113
+ end
114
+
115
+ def heroku_api_key
116
+ heroku_var("AIRBRAKE_API_KEY",options[:app]).split.find {|x| x if x =~ /\S/}
117
+ end
118
+
119
+ def secure?
120
+ options[:secure]
121
+ end
122
+
123
+ def test_mode?
124
+ options[:test_mode]
125
+ end
126
+
127
+ def heroku?
128
+ options[:heroku] ||
129
+ system("grep AIRBRAKE_API_KEY config/initializers/airbrake.rb") ||
130
+ system("grep AIRBRAKE_API_KEY config/environment.rb")
131
+ end
132
+
133
+ def api_key_configured?
134
+ File.exists?('config/initializers/airbrake.rb')
135
+ end
136
+
137
+ def test_airbrake
138
+ puts run("rake airbrake:test")
139
+ end
140
+
141
+ def plugin_is_present?
142
+ File.exists?('vendor/plugins/airbrake')
143
+ end
144
+
145
+ def configuration_output
146
+ output = <<-eos
147
+ Airbrake.configure do |config|
148
+ config.api_key = #{api_key_expression}
149
+ eos
150
+
151
+ output << " config.secure = true\n" if secure?
152
+ output << " config.test_mode = true\n" if test_mode?
153
+ output << "end"
154
+ end
155
+ end