airbrake 4.3.8 → 5.0.0
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.
- checksums.yaml +4 -4
- data/lib/airbrake/capistrano/tasks.rb +64 -0
- data/lib/airbrake/delayed_job/plugin.rb +48 -0
- data/lib/airbrake/rack/middleware.rb +45 -0
- data/lib/airbrake/rack/notice_builder.rb +80 -0
- data/lib/airbrake/rack/user.rb +51 -0
- data/lib/airbrake/rails/action_controller.rb +35 -0
- data/lib/airbrake/rails/active_job.rb +23 -0
- data/lib/airbrake/rails/active_record.rb +40 -0
- data/lib/airbrake/rails/railtie.rb +61 -0
- data/lib/airbrake/rake/task_ext.rb +61 -0
- data/lib/airbrake/rake/tasks.rb +93 -0
- data/lib/airbrake/resque/failure.rb +19 -0
- data/lib/airbrake/sidekiq/error_handler.rb +35 -0
- data/lib/airbrake/version.rb +4 -1
- data/lib/airbrake.rb +16 -185
- data/lib/generators/airbrake_generator.rb +25 -0
- data/lib/generators/airbrake_initializer.rb.erb +55 -0
- data/spec/airbrake_spec.rb +0 -0
- data/spec/apps/rack/dummy_app.rb +17 -0
- data/spec/apps/rails/dummy_app.rb +150 -0
- data/spec/apps/rails/dummy_task.rake +20 -0
- data/spec/apps/rails/logs/32.log +13358 -0
- data/spec/apps/rails/logs/40.log +6854 -0
- data/spec/apps/rails/logs/41.log +3170 -0
- data/spec/apps/rails/logs/42.log +23919 -0
- data/spec/apps/rails/logs/50.log +10976 -0
- data/spec/apps/sinatra/dummy_app.rb +12 -0
- data/spec/integration/rack/rack_spec.rb +17 -0
- data/spec/integration/rails/rails_spec.rb +135 -0
- data/spec/integration/rails/rake_spec.rb +160 -0
- data/spec/integration/shared_examples/rack_examples.rb +106 -0
- data/spec/integration/sinatra/sinatra_spec.rb +15 -0
- data/spec/spec_helper.rb +127 -0
- data/spec/unit/rack/middleware_spec.rb +80 -0
- data/spec/unit/rack/notice_builder_spec.rb +35 -0
- data/spec/unit/rack/user_spec.rb +78 -0
- data/spec/unit/rake/tasks_spec.rb +40 -0
- data/spec/unit/sidekiq/error_handler_spec.rb +29 -0
- metadata +108 -323
- data/CHANGELOG +0 -1716
- data/Gemfile +0 -3
- data/Guardfile +0 -6
- data/INSTALL +0 -20
- data/LICENSE +0 -61
- data/README.md +0 -148
- data/README_FOR_HEROKU_ADDON.md +0 -102
- data/Rakefile +0 -179
- data/TESTED_AGAINST +0 -7
- data/airbrake.gemspec +0 -41
- data/bin/airbrake +0 -12
- data/features/metal.feature +0 -34
- data/features/rack.feature +0 -60
- data/features/rails.feature +0 -324
- data/features/rake.feature +0 -33
- data/features/sinatra.feature +0 -126
- data/features/step_definitions/file_steps.rb +0 -14
- data/features/step_definitions/rack_steps.rb +0 -27
- data/features/step_definitions/rails_application_steps.rb +0 -267
- data/features/step_definitions/rake_steps.rb +0 -22
- data/features/support/airbrake_shim.rb.template +0 -11
- data/features/support/aruba.rb +0 -5
- data/features/support/env.rb +0 -39
- data/features/support/matchers.rb +0 -35
- data/features/support/rails.rb +0 -156
- data/features/support/rake/Rakefile +0 -77
- data/features/user_informer.feature +0 -57
- data/generators/airbrake/airbrake_generator.rb +0 -94
- data/generators/airbrake/lib/insert_commands.rb +0 -34
- data/generators/airbrake/lib/rake_commands.rb +0 -24
- data/generators/airbrake/templates/airbrake_tasks.rake +0 -25
- data/generators/airbrake/templates/capistrano_hook.rb +0 -6
- data/generators/airbrake/templates/initializer.rb +0 -4
- data/install.rb +0 -1
- data/lib/airbrake/backtrace.rb +0 -103
- data/lib/airbrake/capistrano.rb +0 -103
- data/lib/airbrake/capistrano3.rb +0 -3
- data/lib/airbrake/cli/client.rb +0 -76
- data/lib/airbrake/cli/options.rb +0 -45
- data/lib/airbrake/cli/printer.rb +0 -33
- data/lib/airbrake/cli/project.rb +0 -17
- data/lib/airbrake/cli/project_factory.rb +0 -33
- data/lib/airbrake/cli/runner.rb +0 -49
- data/lib/airbrake/cli/validator.rb +0 -8
- data/lib/airbrake/configuration.rb +0 -366
- data/lib/airbrake/jobs/send_job.rb +0 -7
- data/lib/airbrake/notice.rb +0 -411
- data/lib/airbrake/rack.rb +0 -64
- data/lib/airbrake/rails/action_controller_catcher.rb +0 -32
- data/lib/airbrake/rails/controller_methods.rb +0 -146
- data/lib/airbrake/rails/error_lookup.rb +0 -35
- data/lib/airbrake/rails/middleware.rb +0 -63
- data/lib/airbrake/rails.rb +0 -45
- data/lib/airbrake/rails3_tasks.rb +0 -126
- data/lib/airbrake/railtie.rb +0 -46
- data/lib/airbrake/rake_handler.rb +0 -75
- data/lib/airbrake/response.rb +0 -29
- data/lib/airbrake/sender.rb +0 -213
- data/lib/airbrake/shared_tasks.rb +0 -59
- data/lib/airbrake/sidekiq.rb +0 -8
- data/lib/airbrake/sinatra.rb +0 -40
- data/lib/airbrake/tasks/airbrake.cap +0 -28
- data/lib/airbrake/tasks.rb +0 -81
- data/lib/airbrake/user_informer.rb +0 -36
- data/lib/airbrake/utils/params_cleaner.rb +0 -141
- data/lib/airbrake/utils/rack_filters.rb +0 -45
- data/lib/airbrake_tasks.rb +0 -62
- data/lib/rails/generators/airbrake/airbrake_generator.rb +0 -155
- data/lib/templates/rescue.erb +0 -91
- data/rails/init.rb +0 -1
- data/resources/README.md +0 -34
- data/resources/airbrake_2_4.xsd +0 -89
- data/resources/airbrake_3_0.json +0 -52
- data/resources/ca-bundle.crt +0 -3376
- data/script/integration_test.rb +0 -35
- data/test/airbrake_tasks_test.rb +0 -161
- data/test/backtrace_test.rb +0 -215
- data/test/capistrano_test.rb +0 -44
- data/test/configuration_test.rb +0 -303
- data/test/controller_methods_test.rb +0 -230
- data/test/helper.rb +0 -233
- data/test/integration/catcher_test.rb +0 -371
- data/test/integration.rb +0 -13
- data/test/logger_test.rb +0 -79
- data/test/notice_test.rb +0 -494
- data/test/notifier_test.rb +0 -288
- data/test/params_cleaner_test.rb +0 -204
- data/test/rack_test.rb +0 -62
- data/test/rails_initializer_test.rb +0 -36
- data/test/recursion_test.rb +0 -10
- data/test/response_test.rb +0 -18
- data/test/sender_test.rb +0 -335
- data/test/support/response_shim.xml +0 -4
- data/test/user_informer_test.rb +0 -29
@@ -1,94 +0,0 @@
|
|
1
|
-
require File.expand_path(File.dirname(__FILE__) + "/lib/insert_commands.rb")
|
2
|
-
require File.expand_path(File.dirname(__FILE__) + "/lib/rake_commands.rb")
|
3
|
-
|
4
|
-
class AirbrakeGenerator < Rails::Generator::Base
|
5
|
-
def add_options!(opt)
|
6
|
-
opt.on('-k', '--api-key=key', String, "Your Airbrake API key") { |v| options[:api_key] = v}
|
7
|
-
opt.on('-h', '--heroku', "Use the Heroku addon to provide your Airbrake API key") { |v| options[:heroku] = v}
|
8
|
-
opt.on('-a', '--app=myapp', String, "Your Heroku app name (only required if deploying to >1 Heroku app)") { |v| options[:app] = v}
|
9
|
-
end
|
10
|
-
|
11
|
-
def manifest
|
12
|
-
if !api_key_configured? && !options[:api_key] && !options[:heroku]
|
13
|
-
puts "Must pass --api-key or --heroku or create config/initializers/airbrake.rb"
|
14
|
-
exit
|
15
|
-
end
|
16
|
-
if plugin_is_present?
|
17
|
-
puts "You must first remove the airbrake plugin. Please run: script/plugin remove airbrake"
|
18
|
-
exit
|
19
|
-
end
|
20
|
-
record do |m|
|
21
|
-
m.directory 'lib/tasks'
|
22
|
-
m.file 'airbrake_tasks.rake', 'lib/tasks/airbrake_tasks.rake'
|
23
|
-
if ['config/deploy.rb', 'Capfile'].all? { |file| File.exists?(file) }
|
24
|
-
m.append_to 'config/deploy.rb', capistrano_hook
|
25
|
-
end
|
26
|
-
if api_key_expression
|
27
|
-
if use_initializer?
|
28
|
-
m.template 'initializer.rb', 'config/initializers/airbrake.rb',
|
29
|
-
:assigns => {:api_key => api_key_expression}
|
30
|
-
else
|
31
|
-
m.template 'initializer.rb', 'config/airbrake.rb',
|
32
|
-
:assigns => {:api_key => api_key_expression}
|
33
|
-
m.append_to 'config/environment.rb', "require 'config/airbrake'"
|
34
|
-
end
|
35
|
-
end
|
36
|
-
determine_api_key if heroku?
|
37
|
-
m.rake "airbrake:test", :generate_only => true
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
def api_key_expression
|
42
|
-
s = if options[:api_key]
|
43
|
-
"'#{options[:api_key]}'"
|
44
|
-
elsif options[:heroku]
|
45
|
-
"ENV['HOPTOAD_API_KEY']"
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
def determine_api_key
|
50
|
-
puts "Attempting to determine your API Key from Heroku..."
|
51
|
-
ENV['HOPTOAD_API_KEY'] = heroku_api_key
|
52
|
-
if ENV['HOPTOAD_API_KEY'] =~ /\S/
|
53
|
-
puts "... Done."
|
54
|
-
puts "Heroku's Airbrake API Key is '#{ENV['HOPTOAD_API_KEY']}'"
|
55
|
-
else
|
56
|
-
puts "... Failed."
|
57
|
-
puts "WARNING: We were unable to detect the Airbrake API Key from your Heroku environment."
|
58
|
-
puts "Your Heroku application environment may not be configured correctly."
|
59
|
-
exit 1
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
def heroku_var(var,app_name = nil)
|
64
|
-
app = app_name ? "--app #{app_name}" : ''
|
65
|
-
`heroku config #{app} | grep -E "#{var.upcase}" | awk '{ print $3; }'`.strip
|
66
|
-
end
|
67
|
-
|
68
|
-
def heroku_api_key
|
69
|
-
heroku_var("(hoptoad|airbrake)_api_key",options[:app]).split.find {|x| x =~ /\S/ }
|
70
|
-
end
|
71
|
-
|
72
|
-
def heroku?
|
73
|
-
options[:heroku] ||
|
74
|
-
system("grep HOPTOAD_API_KEY config/initializers/airbrake.rb") ||
|
75
|
-
system("grep HOPTOAD_API_KEY config/environment.rb")
|
76
|
-
end
|
77
|
-
|
78
|
-
def use_initializer?
|
79
|
-
::Rails::VERSION::MAJOR > 1
|
80
|
-
end
|
81
|
-
|
82
|
-
def api_key_configured?
|
83
|
-
File.exists?('config/initializers/airbrake.rb') ||
|
84
|
-
system("grep Airbrake config/environment.rb")
|
85
|
-
end
|
86
|
-
|
87
|
-
def capistrano_hook
|
88
|
-
IO.read(source_path('capistrano_hook.rb'))
|
89
|
-
end
|
90
|
-
|
91
|
-
def plugin_is_present?
|
92
|
-
File.exists?('vendor/plugins/airbrake')
|
93
|
-
end
|
94
|
-
end
|
@@ -1,34 +0,0 @@
|
|
1
|
-
# Mostly pinched from http://github.com/ryanb/nifty-generators/tree/master
|
2
|
-
|
3
|
-
Rails::Generator::Commands::Base.class_eval do
|
4
|
-
def file_contains?(relative_destination, line)
|
5
|
-
File.read(destination_path(relative_destination)).include?(line)
|
6
|
-
end
|
7
|
-
end
|
8
|
-
|
9
|
-
Rails::Generator::Commands::Create.class_eval do
|
10
|
-
def append_to(file, line)
|
11
|
-
logger.insert "#{line} appended to #{file}"
|
12
|
-
unless options[:pretend] || file_contains?(file, line)
|
13
|
-
File.open(file, "a") do |file|
|
14
|
-
file.puts
|
15
|
-
file.puts line
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
Rails::Generator::Commands::Destroy.class_eval do
|
22
|
-
def append_to(file, line)
|
23
|
-
logger.remove "#{line} removed from #{file}"
|
24
|
-
unless options[:pretend]
|
25
|
-
gsub_file file, "\n#{line}", ''
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
Rails::Generator::Commands::List.class_eval do
|
31
|
-
def append_to(file, line)
|
32
|
-
logger.insert "#{line} appended to #{file}"
|
33
|
-
end
|
34
|
-
end
|
@@ -1,24 +0,0 @@
|
|
1
|
-
Rails::Generator::Commands::Create.class_eval do
|
2
|
-
def rake(cmd, opts = {})
|
3
|
-
logger.rake "rake #{cmd}"
|
4
|
-
unless system("rake #{cmd}")
|
5
|
-
logger.rake "#{cmd} failed. Rolling back"
|
6
|
-
command(:destroy).invoke!
|
7
|
-
end
|
8
|
-
end
|
9
|
-
end
|
10
|
-
|
11
|
-
Rails::Generator::Commands::Destroy.class_eval do
|
12
|
-
def rake(cmd, opts = {})
|
13
|
-
unless opts[:generate_only]
|
14
|
-
logger.rake "rake #{cmd}"
|
15
|
-
system "rake #{cmd}"
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
Rails::Generator::Commands::List.class_eval do
|
21
|
-
def rake(cmd, opts = {})
|
22
|
-
logger.rake "rake #{cmd}"
|
23
|
-
end
|
24
|
-
end
|
@@ -1,25 +0,0 @@
|
|
1
|
-
# Don't load anything when running the gems:* tasks.
|
2
|
-
# Otherwise, airbrake will be considered a framework gem.
|
3
|
-
# https://thoughtbot.lighthouseapp.com/projects/14221/tickets/629
|
4
|
-
unless ARGV.any? {|a| a =~ /^gems/}
|
5
|
-
|
6
|
-
Dir[File.join(Rails.root, 'vendor', 'gems', 'airbrake-*')].each do |vendored_notifier|
|
7
|
-
$: << File.join(vendored_notifier, 'lib')
|
8
|
-
end
|
9
|
-
|
10
|
-
begin
|
11
|
-
require 'airbrake/tasks'
|
12
|
-
rescue LoadError => exception
|
13
|
-
namespace :airbrake do
|
14
|
-
%w(deploy test log_stdout).each do |task_name|
|
15
|
-
desc "Missing dependency for airbrake:#{task_name}"
|
16
|
-
task task_name do
|
17
|
-
$stderr.puts "Failed to run airbrake:#{task_name} because of missing dependency."
|
18
|
-
$stderr.puts "You probably need to run `rake gems:install` to install the airbrake gem"
|
19
|
-
abort exception.inspect
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
end
|
data/install.rb
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
puts IO.read(File.join(File.dirname(__FILE__), 'INSTALL'))
|
data/lib/airbrake/backtrace.rb
DELETED
@@ -1,103 +0,0 @@
|
|
1
|
-
module Airbrake
|
2
|
-
# Front end to parsing the backtrace for each notice
|
3
|
-
class Backtrace
|
4
|
-
|
5
|
-
# Handles backtrace parsing line by line
|
6
|
-
class Line
|
7
|
-
|
8
|
-
# regexp (optionnally allowing leading X: for windows support)
|
9
|
-
INPUT_FORMAT = %r{^((?:[a-zA-Z]:)?[^:]+):(\d+)(?::in `([^']+)')?$}.freeze
|
10
|
-
|
11
|
-
# The file portion of the line (such as app/models/user.rb)
|
12
|
-
attr_reader :file
|
13
|
-
|
14
|
-
# The line number portion of the line
|
15
|
-
attr_reader :number
|
16
|
-
|
17
|
-
# The method_name of the line (such as index)
|
18
|
-
attr_reader :method_name
|
19
|
-
|
20
|
-
# Parses a single line of a given backtrace
|
21
|
-
# @param [String] unparsed_line The raw line from +caller+ or some backtrace
|
22
|
-
# @return [Line] The parsed backtrace line
|
23
|
-
def self.parse(unparsed_line)
|
24
|
-
_, file, number, method_name = unparsed_line.match(INPUT_FORMAT).to_a
|
25
|
-
new(file, number, method_name)
|
26
|
-
end
|
27
|
-
|
28
|
-
def initialize(file, number, method_name)
|
29
|
-
@file = file
|
30
|
-
@number = number
|
31
|
-
@method_name = method_name
|
32
|
-
end
|
33
|
-
|
34
|
-
# Reconstructs the line in a readable fashion
|
35
|
-
def to_s
|
36
|
-
"#{file}:#{number}:in `#{method_name}'"
|
37
|
-
end
|
38
|
-
|
39
|
-
def ==(other)
|
40
|
-
to_s == other.to_s
|
41
|
-
end
|
42
|
-
|
43
|
-
def inspect
|
44
|
-
"<Line:#{to_s}>"
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
# holder for an Array of Backtrace::Line instances
|
49
|
-
attr_reader :lines
|
50
|
-
|
51
|
-
def self.parse(ruby_backtrace, opts = {})
|
52
|
-
ruby_lines = split_multiline_backtrace(ruby_backtrace)
|
53
|
-
|
54
|
-
filters = opts[:filters] || []
|
55
|
-
filtered_lines = ruby_lines.to_a.map do |line|
|
56
|
-
filters.inject(line) do |l, proc|
|
57
|
-
proc.call(l)
|
58
|
-
end
|
59
|
-
end.compact
|
60
|
-
|
61
|
-
lines = filtered_lines.collect do |unparsed_line|
|
62
|
-
Line.parse(unparsed_line)
|
63
|
-
end
|
64
|
-
|
65
|
-
new(lines)
|
66
|
-
end
|
67
|
-
|
68
|
-
def initialize(lines)
|
69
|
-
@lines = lines
|
70
|
-
end
|
71
|
-
|
72
|
-
def inspect
|
73
|
-
"<Backtrace: " + lines.collect { |line| line.inspect }.join(", ") + ">"
|
74
|
-
end
|
75
|
-
|
76
|
-
def to_s
|
77
|
-
content = []
|
78
|
-
lines.each do |line|
|
79
|
-
content << line
|
80
|
-
end
|
81
|
-
content.join("\n")
|
82
|
-
end
|
83
|
-
|
84
|
-
def ==(other)
|
85
|
-
if other.respond_to?(:lines)
|
86
|
-
lines == other.lines
|
87
|
-
else
|
88
|
-
false
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
|
-
private
|
93
|
-
|
94
|
-
def self.split_multiline_backtrace(backtrace)
|
95
|
-
backtrace = [backtrace] unless backtrace.respond_to?(:to_a)
|
96
|
-
if backtrace.to_a.size == 1
|
97
|
-
backtrace.to_a.first.split(/\n\s*/)
|
98
|
-
else
|
99
|
-
backtrace
|
100
|
-
end
|
101
|
-
end
|
102
|
-
end
|
103
|
-
end
|
data/lib/airbrake/capistrano.rb
DELETED
@@ -1,103 +0,0 @@
|
|
1
|
-
# Defines deploy:notify_airbrake which will send information about the deploy to Airbrake.
|
2
|
-
require 'capistrano'
|
3
|
-
|
4
|
-
module Airbrake
|
5
|
-
module Capistrano
|
6
|
-
# What follows is a copy-paste backport of the shellescape method
|
7
|
-
# included in Ruby 1.9 and greater. The FSF's guidance on a snippet
|
8
|
-
# of this size indicates that such a small function is not subject
|
9
|
-
# to copyright and as such there is no risk of a license conflict:
|
10
|
-
# See www.gnu.org/prep/maintain/maintain.html#Legally-Significant
|
11
|
-
#
|
12
|
-
# Escapes a string so that it can be safely used in a Bourne shell
|
13
|
-
# command line. +str+ can be a non-string object that responds to
|
14
|
-
# +to_s+.
|
15
|
-
#
|
16
|
-
# Note that a resulted string should be used unquoted and is not
|
17
|
-
# intended for use in double quotes nor in single quotes.
|
18
|
-
#
|
19
|
-
# argv = Shellwords.escape("It's better to give than to receive")
|
20
|
-
# argv #=> "It\\'s\\ better\\ to\\ give\\ than\\ to\\ receive"
|
21
|
-
#
|
22
|
-
# String#shellescape is a shorthand for this function.
|
23
|
-
#
|
24
|
-
# argv = "It's better to give than to receive".shellescape
|
25
|
-
# argv #=> "It\\'s\\ better\\ to\\ give\\ than\\ to\\ receive"
|
26
|
-
#
|
27
|
-
# # Search files in lib for method definitions
|
28
|
-
# pattern = "^[ \t]*def "
|
29
|
-
# open("| grep -Ern #{pattern.shellescape} lib") { |grep|
|
30
|
-
# grep.each_line { |line|
|
31
|
-
# file, lineno, matched_line = line.split(':', 3)
|
32
|
-
# # ...
|
33
|
-
# }
|
34
|
-
# }
|
35
|
-
#
|
36
|
-
# It is the caller's responsibility to encode the string in the right
|
37
|
-
# encoding for the shell environment where this string is used.
|
38
|
-
#
|
39
|
-
# Multibyte characters are treated as multibyte characters, not bytes.
|
40
|
-
#
|
41
|
-
# Returns an empty quoted String if +str+ has a length of zero.
|
42
|
-
def self.shellescape(str)
|
43
|
-
str = str.to_s
|
44
|
-
|
45
|
-
# An empty argument will be skipped, so return empty quotes.
|
46
|
-
return "''" if str.empty?
|
47
|
-
|
48
|
-
str = str.dup
|
49
|
-
|
50
|
-
# Treat multibyte characters as is. It is caller's responsibility
|
51
|
-
# to encode the string in the right encoding for the shell
|
52
|
-
# environment.
|
53
|
-
str.gsub!(/([^A-Za-z0-9_\-.,:\/@\n])/, "\\\\\\1")
|
54
|
-
|
55
|
-
# A LF cannot be escaped with a backslash because a backslash + LF
|
56
|
-
# combo is regarded as line continuation and simply ignored.
|
57
|
-
str.gsub!(/\n/, "'\n'")
|
58
|
-
|
59
|
-
return str
|
60
|
-
end
|
61
|
-
|
62
|
-
def self.load_into(configuration)
|
63
|
-
configuration.load do
|
64
|
-
after "deploy", "airbrake:deploy"
|
65
|
-
after "deploy:migrations", "airbrake:deploy"
|
66
|
-
after "deploy:cold", "airbrake:deploy"
|
67
|
-
|
68
|
-
namespace :airbrake do
|
69
|
-
desc <<-DESC
|
70
|
-
Notify Airbrake of the deployment by running the notification on the REMOTE machine.
|
71
|
-
- Run remotely so we use remote API keys, environment, etc.
|
72
|
-
DESC
|
73
|
-
task :deploy, :except => { :no_release => true } do
|
74
|
-
rack_env = fetch(:rack_env, nil)
|
75
|
-
rails_env = fetch(:rails_env, nil)
|
76
|
-
airbrake_env = fetch(:airbrake_env, rack_env || rails_env || "production")
|
77
|
-
local_user = ENV['USER'] || ENV['USERNAME']
|
78
|
-
executable = RUBY_PLATFORM.downcase.include?('mswin') ? fetch(:rake, 'rake.bat') : fetch(:rake, 'bundle exec rake ')
|
79
|
-
directory = configuration.release_path
|
80
|
-
notify_command = "cd #{directory}; #{executable}"
|
81
|
-
notify_command << " RACK_ENV=#{rack_env}" if rack_env
|
82
|
-
notify_command << " RAILS_ENV=#{rails_env}" if rails_env
|
83
|
-
notify_command << " airbrake:deploy TO=#{airbrake_env} REVISION=#{current_revision} REPO=#{repository} USER=#{Airbrake::Capistrano::shellescape(local_user)}"
|
84
|
-
notify_command << " DRY_RUN=true" if dry_run
|
85
|
-
logger.info "Notifying Airbrake of Deploy (#{notify_command})"
|
86
|
-
if configuration.dry_run
|
87
|
-
logger.info "DRY RUN: Notification not actually run."
|
88
|
-
else
|
89
|
-
result = ""
|
90
|
-
run(notify_command, :once => true) { |ch, stream, data| result << data }
|
91
|
-
# TODO: Check if SSL is active on account via result content.
|
92
|
-
end
|
93
|
-
logger.info "Airbrake Notification Complete."
|
94
|
-
end
|
95
|
-
end
|
96
|
-
end
|
97
|
-
end
|
98
|
-
end
|
99
|
-
end
|
100
|
-
|
101
|
-
if Capistrano::Configuration.instance
|
102
|
-
Airbrake::Capistrano.load_into(Capistrano::Configuration.instance)
|
103
|
-
end
|
data/lib/airbrake/capistrano3.rb
DELETED
data/lib/airbrake/cli/client.rb
DELETED
@@ -1,76 +0,0 @@
|
|
1
|
-
require File.expand_path( "../runner", __FILE__)
|
2
|
-
|
3
|
-
module Client
|
4
|
-
extend self
|
5
|
-
|
6
|
-
def options
|
7
|
-
Runner.options
|
8
|
-
end
|
9
|
-
|
10
|
-
def fetch_projects
|
11
|
-
uri = URI.parse "http://#{options.account}.airbrake.io"\
|
12
|
-
"/data_api/v1/projects.xml?auth_token=#{options.auth_token}"
|
13
|
-
http = Net::HTTP.new(uri.host,uri.port)
|
14
|
-
request = Net::HTTP::Get.new(uri.request_uri)
|
15
|
-
response = http.request(request)
|
16
|
-
response.body
|
17
|
-
end
|
18
|
-
|
19
|
-
def create_project
|
20
|
-
uri = URI.parse "http://#{options.account}.airbrake.io"\
|
21
|
-
"/data_api/v1/projects.xml"
|
22
|
-
http = Net::HTTP.new(uri.host,uri.port)
|
23
|
-
request = Net::HTTP::Post.new(uri.request_uri)
|
24
|
-
request.set_form_data('project[name]' => options.name,'auth_token' => options.auth_token)
|
25
|
-
response = http.request(request)
|
26
|
-
response.body
|
27
|
-
|
28
|
-
print_project_response(response.body)
|
29
|
-
end
|
30
|
-
|
31
|
-
def create_deploy
|
32
|
-
uri = URI.parse "http://airbrake.io/deploys.txt"
|
33
|
-
http = Net::HTTP.new(uri.host,uri.port)
|
34
|
-
request = Net::HTTP::Post.new(uri.request_uri)
|
35
|
-
opts = { 'api_key' => options.api_key }.merge!(deploy_opts)
|
36
|
-
request.set_form_data(opts)
|
37
|
-
response = http.request(request)
|
38
|
-
puts response.message if response.respond_to?(:message)
|
39
|
-
end
|
40
|
-
|
41
|
-
def deploy_opts
|
42
|
-
opts = {}
|
43
|
-
['rails_env', 'scm_revision', 'scm_repository', 'local_username'].each do |attr|
|
44
|
-
opts.merge!("deploy[#{attr}]" => options.send(attr))
|
45
|
-
end
|
46
|
-
opts
|
47
|
-
end
|
48
|
-
|
49
|
-
def print_projects
|
50
|
-
factory = ProjectFactory.new
|
51
|
-
projects = fetch_projects
|
52
|
-
factory.create_projects_from_xml(projects)
|
53
|
-
abort "No projects were fetched. Did you provide the correct auth token?" if projects.match(/error/m)
|
54
|
-
puts "\nProjects\n" + "".rjust(63,"#")
|
55
|
-
factory.projects.each do |project|
|
56
|
-
puts project
|
57
|
-
end
|
58
|
-
puts
|
59
|
-
end
|
60
|
-
|
61
|
-
def print_project_response(response)
|
62
|
-
case response
|
63
|
-
when /errors/
|
64
|
-
puts "Error creating project: #{response.gsub("\n","").scan(/.*<error[^>]*>(.*?)<\/error>.*/).last.first.gsub(/\s{1,}/," ")}"
|
65
|
-
when /project/
|
66
|
-
project = Project.new(:id => response[/<id[^>]*>(.*?)<\/id>/,1],
|
67
|
-
:name => response[/<name[^>]*>(.*?)<\/name>/,1],
|
68
|
-
:api_key => response[/<api-key[^>]*>(.*?)<\/api-key>/,1])
|
69
|
-
puts "\nProject details\n" + "".rjust(63,"#")
|
70
|
-
puts project
|
71
|
-
else
|
72
|
-
puts "Unexpected error. Please try again!\n"
|
73
|
-
puts response
|
74
|
-
end
|
75
|
-
end
|
76
|
-
end
|
data/lib/airbrake/cli/options.rb
DELETED
@@ -1,45 +0,0 @@
|
|
1
|
-
class Options
|
2
|
-
|
3
|
-
ATTRIBUTES = [:error, :message, :api_key, :host, :port, :auth_token, :name,
|
4
|
-
:account, :rails_env, :scm_revision, :scm_repository, :local_username]
|
5
|
-
|
6
|
-
ATTRIBUTES.each do |attribute|
|
7
|
-
attr_reader attribute
|
8
|
-
end
|
9
|
-
|
10
|
-
private
|
11
|
-
|
12
|
-
# You should not write to this from outside
|
13
|
-
ATTRIBUTES.each do |attribute|
|
14
|
-
attr_writer attribute
|
15
|
-
end
|
16
|
-
|
17
|
-
public
|
18
|
-
|
19
|
-
# Parses all the options passed and stores them in attributes
|
20
|
-
def initialize(array = [])
|
21
|
-
opts = Hash[*array]
|
22
|
-
self.error = opts.delete("-e") || opts.delete("--error") { RuntimeError }
|
23
|
-
self.message = opts.delete("-m") || opts.delete("--message") { "I've made a huge mistake" }
|
24
|
-
self.api_key = opts.delete("-k") || opts.delete("--api-key") || config_from_file.api_key || ENV["AIRBRAKE_API_KEY"]
|
25
|
-
self.host = opts.delete("-h") || opts.delete("--host") || config_from_file.host
|
26
|
-
self.port = opts.delete("-p") || opts.delete("--port") || config_from_file.port
|
27
|
-
self.auth_token = opts.delete("-t") || opts.delete("--auth-token") || ENV["AIRBRAKE_AUTH_TOKEN"]
|
28
|
-
self.name = opts.delete("-n") || opts.delete("--name")
|
29
|
-
self.account = opts.delete("-a") || opts.delete("--account") || ENV["AIRBRAKE_ACCOUNT"]
|
30
|
-
self.rails_env = opts.delete("-E") || opts.delete("--rails-env") || ENV["RAILS_ENV"] || "production"
|
31
|
-
self.scm_revision = opts.delete("-r") || opts.delete("--scm-revision") || ENV["REVISION"]
|
32
|
-
self.scm_repository = opts.delete("-R") || opts.delete("--scm-repository") || ENV["REPO"]
|
33
|
-
self.local_username = opts.delete("-u") || opts.delete("--local-username") || ENV["USER"]
|
34
|
-
opts
|
35
|
-
end
|
36
|
-
|
37
|
-
# Fallback to read from the initializer
|
38
|
-
def config_from_file
|
39
|
-
begin
|
40
|
-
load "config/initializers/airbrake.rb"
|
41
|
-
rescue LoadError
|
42
|
-
end
|
43
|
-
Airbrake.configuration
|
44
|
-
end
|
45
|
-
end
|
data/lib/airbrake/cli/printer.rb
DELETED
@@ -1,33 +0,0 @@
|
|
1
|
-
module Printer
|
2
|
-
def self.print(collection)
|
3
|
-
collection.each do |element|
|
4
|
-
puts element
|
5
|
-
end
|
6
|
-
end
|
7
|
-
|
8
|
-
def self.print_usage
|
9
|
-
puts <<-USAGE
|
10
|
-
Usage: airbrake [COMMAND] [OPTION]...
|
11
|
-
Commands:
|
12
|
-
raise # Raise an exception specified by ERROR and MESSAGE.
|
13
|
-
list # List all the projects for given AUTH_TOKEN and ACCOUNT.
|
14
|
-
create # Create a project with the given NAME.
|
15
|
-
deploy # Send a new deployment notification to a project that matches the API_KEY.
|
16
|
-
|
17
|
-
Options:
|
18
|
-
-e, [--error=ERROR] # Error class to raise. Default: RuntimeError
|
19
|
-
-m, [--message=MESSAGE] # Error message. Default: "I've made a huge mistake"
|
20
|
-
-k, [--api-key=API_KEY] # Api key of your Airbrake application
|
21
|
-
-h, [--host=HOST] # URL of the Airbrake API server. Default: api.airbrake.io
|
22
|
-
-p, [--port=PORT] # Port of the Airbrake API server. Default: 80
|
23
|
-
-t, [--auth-token=AUTH_TOKEN] # The auth token used for API requests
|
24
|
-
-a, [--account=ACCOUNT] # The account used for API requests
|
25
|
-
-n, [--name=NAME] # The name of the project you're trying to create
|
26
|
-
-E, [--rails-env=NAME] # The name of the environment you're deploying to. Default: production
|
27
|
-
-r, [--scm-revision=REVISION] # SCM revision for deployment info
|
28
|
-
-R, [--scm-repository=REPO] # SCM repository for deployment info
|
29
|
-
-u, [--local-username=USER] # The name of the user who is deploying
|
30
|
-
-h, [--help] # Show this usage
|
31
|
-
USAGE
|
32
|
-
end
|
33
|
-
end
|
data/lib/airbrake/cli/project.rb
DELETED
@@ -1,17 +0,0 @@
|
|
1
|
-
class Project
|
2
|
-
attr_writer :name, :id, :api_key
|
3
|
-
|
4
|
-
def initialize(attributes = {})
|
5
|
-
attributes.keys.each do |key|
|
6
|
-
instance_variable_set("@#{key}",attributes[key])
|
7
|
-
end
|
8
|
-
end
|
9
|
-
|
10
|
-
def to_s
|
11
|
-
"#{@name}".rjust(20) + "(#{@id}):".rjust(10) + " #{@api_key}"
|
12
|
-
end
|
13
|
-
|
14
|
-
def valid?
|
15
|
-
@name && @id && @api_key
|
16
|
-
end
|
17
|
-
end
|
@@ -1,33 +0,0 @@
|
|
1
|
-
require File.expand_path( "../project", __FILE__)
|
2
|
-
# Responsible for creating projects when needed.
|
3
|
-
# Creates them from XML received.
|
4
|
-
class ProjectFactory
|
5
|
-
attr_reader :project, :projects
|
6
|
-
|
7
|
-
def initialize
|
8
|
-
@project = Project.new
|
9
|
-
@projects = []
|
10
|
-
end
|
11
|
-
|
12
|
-
def create_projects_from_xml(xml)
|
13
|
-
xml.split("\n").each do |line|
|
14
|
-
/<name[^>]*>(.*)<\/name>/ =~ line
|
15
|
-
name = $1
|
16
|
-
project.name = name.capitalize if name
|
17
|
-
/<id[^>]*>(.*)<\/id>/ =~ line
|
18
|
-
id = $1
|
19
|
-
project.id = id if id
|
20
|
-
/<api-key[^>]*>(.*)<\/api-key>/ =~ line
|
21
|
-
api_key = $1
|
22
|
-
project.api_key = api_key if api_key
|
23
|
-
check_project
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
def check_project
|
28
|
-
if @project.valid?
|
29
|
-
projects << @project
|
30
|
-
@project = Project.new
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
data/lib/airbrake/cli/runner.rb
DELETED
@@ -1,49 +0,0 @@
|
|
1
|
-
require File.expand_path( "../project_factory", __FILE__)
|
2
|
-
require File.expand_path( "../options", __FILE__)
|
3
|
-
require File.expand_path( "../validator", __FILE__)
|
4
|
-
require File.expand_path( "../printer", __FILE__)
|
5
|
-
require File.expand_path( "../client", __FILE__)
|
6
|
-
|
7
|
-
module Runner
|
8
|
-
extend Validator
|
9
|
-
|
10
|
-
extend self
|
11
|
-
|
12
|
-
attr_accessor :options
|
13
|
-
|
14
|
-
def run!(command, cli_options = {})
|
15
|
-
|
16
|
-
self.options = Options.new(cli_options)
|
17
|
-
|
18
|
-
case command
|
19
|
-
when 'raise'
|
20
|
-
validates :api_key
|
21
|
-
Airbrake.configure do |c|
|
22
|
-
c.api_key = options.api_key
|
23
|
-
c.host = options.host if options.host
|
24
|
-
c.port = options.port if options.port
|
25
|
-
c.secure = options.port.to_i == 443
|
26
|
-
end
|
27
|
-
exception_id = Airbrake.notify(:error_class => options.error,
|
28
|
-
:error_message => "#{options.error}: #{options.message}",
|
29
|
-
:cgi_data => ENV)
|
30
|
-
abort "Error sending exception to Airbrake server. Try again later." unless exception_id
|
31
|
-
puts "Exception sent successfully: http://airbrake.io/locate/#{exception_id}"
|
32
|
-
|
33
|
-
when "list"
|
34
|
-
validates :auth_token, :account
|
35
|
-
Client.print_projects
|
36
|
-
|
37
|
-
when "create"
|
38
|
-
validates :auth_token, :account
|
39
|
-
Client.create_project
|
40
|
-
|
41
|
-
when "deploy"
|
42
|
-
validates :api_key
|
43
|
-
Client.create_deploy
|
44
|
-
|
45
|
-
else
|
46
|
-
Printer.print_usage
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|