projectlocker_errata 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +908 -0
- data/Gemfile +3 -0
- data/Guardfile +6 -0
- data/INSTALL +20 -0
- data/MIT-LICENSE +23 -0
- data/README.md +460 -0
- data/README_FOR_HEROKU_ADDON.md +94 -0
- data/Rakefile +223 -0
- data/SUPPORTED_RAILS_VERSIONS +38 -0
- data/TESTING.md +41 -0
- data/features/metal.feature +18 -0
- data/features/rack.feature +60 -0
- data/features/rails.feature +272 -0
- data/features/rails_with_js_notifier.feature +97 -0
- data/features/rake.feature +27 -0
- data/features/sinatra.feature +29 -0
- data/features/step_definitions/file_steps.rb +10 -0
- data/features/step_definitions/metal_steps.rb +23 -0
- data/features/step_definitions/rack_steps.rb +23 -0
- data/features/step_definitions/rails_application_steps.rb +478 -0
- data/features/step_definitions/rake_steps.rb +17 -0
- data/features/support/env.rb +18 -0
- data/features/support/matchers.rb +35 -0
- data/features/support/projectlocker_errata_shim.rb.template +16 -0
- data/features/support/rails.rb +201 -0
- data/features/support/rake/Rakefile +68 -0
- data/features/support/terminal.rb +107 -0
- data/features/user_informer.feature +63 -0
- data/generators/projectlocker_errata/lib/insert_commands.rb +34 -0
- data/generators/projectlocker_errata/lib/rake_commands.rb +24 -0
- data/generators/projectlocker_errata/projectlocker_errata_generator.rb +94 -0
- data/generators/projectlocker_errata/templates/capistrano_hook.rb +6 -0
- data/generators/projectlocker_errata/templates/initializer.rb +6 -0
- data/generators/projectlocker_errata/templates/projectlocker_errata_tasks.rake +25 -0
- data/install.rb +1 -0
- data/lib/projectlocker_errata/backtrace.rb +108 -0
- data/lib/projectlocker_errata/capistrano.rb +43 -0
- data/lib/projectlocker_errata/configuration.rb +305 -0
- data/lib/projectlocker_errata/notice.rb +390 -0
- data/lib/projectlocker_errata/rack.rb +54 -0
- data/lib/projectlocker_errata/rails/action_controller_catcher.rb +30 -0
- data/lib/projectlocker_errata/rails/controller_methods.rb +85 -0
- data/lib/projectlocker_errata/rails/error_lookup.rb +33 -0
- data/lib/projectlocker_errata/rails/javascript_notifier.rb +47 -0
- data/lib/projectlocker_errata/rails/middleware/exceptions_catcher.rb +33 -0
- data/lib/projectlocker_errata/rails.rb +40 -0
- data/lib/projectlocker_errata/rails3_tasks.rb +98 -0
- data/lib/projectlocker_errata/railtie.rb +48 -0
- data/lib/projectlocker_errata/rake_handler.rb +65 -0
- data/lib/projectlocker_errata/sender.rb +128 -0
- data/lib/projectlocker_errata/shared_tasks.rb +47 -0
- data/lib/projectlocker_errata/tasks.rb +83 -0
- data/lib/projectlocker_errata/user_informer.rb +27 -0
- data/lib/projectlocker_errata/utils/blank.rb +53 -0
- data/lib/projectlocker_errata/version.rb +3 -0
- data/lib/projectlocker_errata.rb +159 -0
- data/lib/projectlocker_errata_tasks.rb +64 -0
- data/lib/rails/generators/projectlocker_errata/projectlocker_errata_generator.rb +100 -0
- data/lib/templates/javascript_notifier.erb +15 -0
- data/lib/templates/rescue.erb +91 -0
- data/projectlocker_errata.gemspec +39 -0
- data/rails/init.rb +1 -0
- data/resources/README.md +34 -0
- data/resources/ca-bundle.crt +3376 -0
- data/script/integration_test.rb +38 -0
- data/test/airbrake_2_3.xsd +88 -0
- data/test/backtrace_test.rb +162 -0
- data/test/capistrano_test.rb +34 -0
- data/test/catcher_test.rb +333 -0
- data/test/configuration_test.rb +236 -0
- data/test/helper.rb +263 -0
- data/test/javascript_notifier_test.rb +51 -0
- data/test/logger_test.rb +79 -0
- data/test/notice_test.rb +490 -0
- data/test/notifier_test.rb +276 -0
- data/test/projectlocker_errata_tasks_test.rb +170 -0
- data/test/rack_test.rb +58 -0
- data/test/rails_initializer_test.rb +36 -0
- data/test/recursion_test.rb +10 -0
- data/test/sender_test.rb +288 -0
- data/test/user_informer_test.rb +29 -0
- metadata +440 -0
@@ -0,0 +1,159 @@
|
|
1
|
+
require "girl_friday"
|
2
|
+
require 'net/http'
|
3
|
+
require 'net/https'
|
4
|
+
require 'rubygems'
|
5
|
+
require 'projectlocker_errata/utils/blank'
|
6
|
+
require 'projectlocker_errata/version'
|
7
|
+
require 'projectlocker_errata/configuration'
|
8
|
+
require 'projectlocker_errata/notice'
|
9
|
+
require 'projectlocker_errata/sender'
|
10
|
+
require 'projectlocker_errata/backtrace'
|
11
|
+
require 'projectlocker_errata/rack'
|
12
|
+
require 'projectlocker_errata/user_informer'
|
13
|
+
|
14
|
+
require 'projectlocker_errata/railtie' if defined?(Rails::Railtie)
|
15
|
+
|
16
|
+
module ProjectlockerErrata
|
17
|
+
API_VERSION = "2.3"
|
18
|
+
LOG_PREFIX = "** [ProjectlockerErrata] "
|
19
|
+
|
20
|
+
HEADERS = {
|
21
|
+
'Content-type' => 'text/xml',
|
22
|
+
'Accept' => 'text/xml, application/xml'
|
23
|
+
}
|
24
|
+
|
25
|
+
class << self
|
26
|
+
# The sender object is responsible for delivering formatted data to the ProjectlockerErrata server.
|
27
|
+
# Must respond to #send_to_projectlocker_errata. See ProjectlockerErrata::Sender.
|
28
|
+
attr_accessor :sender
|
29
|
+
|
30
|
+
# A ProjectlockerErrata configuration object. Must act like a hash and return sensible
|
31
|
+
# values for all ProjectlockerErrata configuration options. See ProjectlockerErrata::Configuration.
|
32
|
+
attr_writer :configuration
|
33
|
+
|
34
|
+
# Tell the log that the Notifier is good to go
|
35
|
+
def report_ready
|
36
|
+
write_verbose_log("Notifier #{VERSION} ready to catch errors")
|
37
|
+
end
|
38
|
+
|
39
|
+
# Prints out the environment info to the log for debugging help
|
40
|
+
def report_environment_info
|
41
|
+
write_verbose_log("Environment Info: #{environment_info}")
|
42
|
+
end
|
43
|
+
|
44
|
+
# Prints out the response body from ProjectlockerErrata for debugging help
|
45
|
+
def report_response_body(response)
|
46
|
+
write_verbose_log("Response from ProjectlockerErrata: \n#{response}")
|
47
|
+
end
|
48
|
+
|
49
|
+
# Prints out the details about the notice that wasn't sent to server
|
50
|
+
def report_notice(notice)
|
51
|
+
write_verbose_log("Notice details: \n#{notice}")
|
52
|
+
end
|
53
|
+
|
54
|
+
# Returns the Ruby version, Rails version, and current Rails environment
|
55
|
+
def environment_info
|
56
|
+
info = "[Ruby: #{RUBY_VERSION}]"
|
57
|
+
info << " [#{configuration.framework}]" if configuration.framework
|
58
|
+
info << " [Env: #{configuration.environment_name}]" if configuration.environment_name
|
59
|
+
end
|
60
|
+
|
61
|
+
# Writes out the given message to the #logger
|
62
|
+
def write_verbose_log(message)
|
63
|
+
logger.debug LOG_PREFIX + message if logger
|
64
|
+
end
|
65
|
+
|
66
|
+
# Look for the Rails logger currently defined
|
67
|
+
def logger
|
68
|
+
self.configuration.logger
|
69
|
+
end
|
70
|
+
|
71
|
+
# Call this method to modify defaults in your initializers.
|
72
|
+
#
|
73
|
+
# @example
|
74
|
+
# ProjectlockerErrata.configure do |config|
|
75
|
+
# config.api_key = '1234567890abcdef'
|
76
|
+
# config.secure = false
|
77
|
+
# end
|
78
|
+
def configure(silent = false)
|
79
|
+
yield(configuration)
|
80
|
+
self.sender = Sender.new(configuration)
|
81
|
+
report_ready unless silent
|
82
|
+
self.sender
|
83
|
+
end
|
84
|
+
|
85
|
+
# The configuration object.
|
86
|
+
# @see ProjectlockerErrata.configure
|
87
|
+
def configuration
|
88
|
+
@configuration ||= Configuration.new
|
89
|
+
end
|
90
|
+
|
91
|
+
# Sends an exception manually using this method, even when you are not in a controller.
|
92
|
+
#
|
93
|
+
# @param [Exception] exception The exception you want to notify ProjectlockerErrata about.
|
94
|
+
# @param [Hash] opts Data that will be sent to ProjectlockerErrata.
|
95
|
+
#
|
96
|
+
# @option opts [String] :api_key The API key for this project. The API key is a unique identifier that ProjectlockerErrata uses for identification.
|
97
|
+
# @option opts [String] :error_message The error returned by the exception (or the message you want to log).
|
98
|
+
# @option opts [String] :backtrace A backtrace, usually obtained with +caller+.
|
99
|
+
# @option opts [String] :rack_env The Rack environment.
|
100
|
+
# @option opts [String] :session The contents of the user's session.
|
101
|
+
# @option opts [String] :environment_name The application environment name.
|
102
|
+
def notify(exception, opts = {})
|
103
|
+
send_notice(build_notice_for(exception, opts))
|
104
|
+
end
|
105
|
+
|
106
|
+
# Sends the notice unless it is one of the default ignored exceptions
|
107
|
+
# @see ProjectlockerErrata.notify
|
108
|
+
def notify_or_ignore(exception, opts = {})
|
109
|
+
notice = build_notice_for(exception, opts)
|
110
|
+
send_notice(notice) unless notice.ignore?
|
111
|
+
end
|
112
|
+
|
113
|
+
def build_lookup_hash_for(exception, options = {})
|
114
|
+
notice = build_notice_for(exception, options)
|
115
|
+
|
116
|
+
result = {}
|
117
|
+
result[:action] = notice.action rescue nil
|
118
|
+
result[:component] = notice.component rescue nil
|
119
|
+
result[:error_class] = notice.error_class if notice.error_class
|
120
|
+
result[:environment_name] = 'production'
|
121
|
+
|
122
|
+
unless notice.backtrace.lines.empty?
|
123
|
+
result[:file] = notice.backtrace.lines.first.file
|
124
|
+
result[:line_number] = notice.backtrace.lines.first.number
|
125
|
+
end
|
126
|
+
|
127
|
+
result
|
128
|
+
end
|
129
|
+
|
130
|
+
private
|
131
|
+
|
132
|
+
def send_notice(notice)
|
133
|
+
if configuration.public?
|
134
|
+
if configuration.async?
|
135
|
+
configuration.async.call(notice)
|
136
|
+
else
|
137
|
+
sender.send_to_projectlocker_errata(notice)
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
def build_notice_for(exception, opts = {})
|
143
|
+
exception = unwrap_exception(exception)
|
144
|
+
opts = opts.merge(:exception => exception) if exception.is_a?(Exception)
|
145
|
+
opts = opts.merge(exception.to_hash) if exception.respond_to?(:to_hash)
|
146
|
+
Notice.new(configuration.merge(opts))
|
147
|
+
end
|
148
|
+
|
149
|
+
def unwrap_exception(exception)
|
150
|
+
if exception.respond_to?(:original_exception)
|
151
|
+
exception.original_exception
|
152
|
+
elsif exception.respond_to?(:continued_exception)
|
153
|
+
exception.continued_exception
|
154
|
+
else
|
155
|
+
exception
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
require 'uri'
|
3
|
+
|
4
|
+
# Capistrano tasks for notifying ProjectlockerErrata of deploys
|
5
|
+
module ProjectlockerErrataTasks
|
6
|
+
|
7
|
+
# Alerts ProjectlockerErrata of a deploy.
|
8
|
+
#
|
9
|
+
# @param [Hash] opts Data about the deploy that is set to ProjectlockerErrata
|
10
|
+
#
|
11
|
+
# @option opts [String] :api_key Api key of you ProjectlockerErrata application
|
12
|
+
# @option opts [String] :rails_env Environment of the deploy (production, staging)
|
13
|
+
# @option opts [String] :scm_revision The given revision/sha that is being deployed
|
14
|
+
# @option opts [String] :scm_repository Address of your repository to help with code lookups
|
15
|
+
# @option opts [String] :local_username Who is deploying
|
16
|
+
def self.deploy(opts = {})
|
17
|
+
api_key = opts.delete(:api_key) || ProjectlockerErrata.configuration.api_key
|
18
|
+
if api_key.blank?
|
19
|
+
puts "I don't seem to be configured with an API key. Please check your configuration."
|
20
|
+
return false
|
21
|
+
end
|
22
|
+
|
23
|
+
if opts[:rails_env].blank?
|
24
|
+
puts "I don't know to which Rails environment you are deploying (use the TO=production option)."
|
25
|
+
return false
|
26
|
+
end
|
27
|
+
|
28
|
+
dry_run = opts.delete(:dry_run)
|
29
|
+
params = {'api_key' => api_key}
|
30
|
+
opts.each {|k,v| params["deploy[#{k}]"] = v }
|
31
|
+
|
32
|
+
host = ProjectlockerErrata.configuration.host || 'errors.projectlocker.com'
|
33
|
+
port = ProjectlockerErrata.configuration.port
|
34
|
+
|
35
|
+
proxy = Net::HTTP.Proxy(ProjectlockerErrata.configuration.proxy_host,
|
36
|
+
ProjectlockerErrata.configuration.proxy_port,
|
37
|
+
ProjectlockerErrata.configuration.proxy_user,
|
38
|
+
ProjectlockerErrata.configuration.proxy_pass)
|
39
|
+
http = proxy.new(host, port)
|
40
|
+
|
41
|
+
|
42
|
+
|
43
|
+
# Handle Security
|
44
|
+
if ProjectlockerErrata.configuration.secure?
|
45
|
+
http.use_ssl = true
|
46
|
+
http.ca_file = ProjectlockerErrata.configuration.ca_bundle_path
|
47
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
48
|
+
end
|
49
|
+
|
50
|
+
post = Net::HTTP::Post.new("/deploys.txt")
|
51
|
+
post.set_form_data(params)
|
52
|
+
|
53
|
+
if dry_run
|
54
|
+
puts http.inspect, params.inspect
|
55
|
+
return true
|
56
|
+
else
|
57
|
+
response = http.request(post)
|
58
|
+
|
59
|
+
puts response.body
|
60
|
+
return Net::HTTPSuccess === response
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
@@ -0,0 +1,100 @@
|
|
1
|
+
require 'rails/generators'
|
2
|
+
|
3
|
+
class ProjectlockerErrataGenerator < Rails::Generators::Base
|
4
|
+
|
5
|
+
class_option :api_key, :aliases => "-k", :type => :string, :desc => "Your ProjectlockerErrata API key"
|
6
|
+
class_option :heroku, :type => :boolean, :desc => "Use the Heroku addon to provide your ProjectlockerErrata API key"
|
7
|
+
class_option :app, :aliases => "-a", :type => :string, :desc => "Your Heroku app name (only required if deploying to >1 Heroku app)"
|
8
|
+
|
9
|
+
def self.source_root
|
10
|
+
@_projectlocker_errata_source_root ||= File.expand_path("../../../../../generators/projectlocker_errata/templates", __FILE__)
|
11
|
+
end
|
12
|
+
|
13
|
+
def install
|
14
|
+
ensure_api_key_was_configured
|
15
|
+
ensure_plugin_is_not_present
|
16
|
+
append_capistrano_hook
|
17
|
+
generate_initializer unless api_key_configured?
|
18
|
+
determine_api_key if heroku?
|
19
|
+
test_projectlocker_errata
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def ensure_api_key_was_configured
|
25
|
+
if !options[:api_key] && !options[:heroku] && !api_key_configured?
|
26
|
+
puts "Must pass --api-key or --heroku or create config/initializers/projectlocker_errata.rb"
|
27
|
+
exit
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def ensure_plugin_is_not_present
|
32
|
+
if plugin_is_present?
|
33
|
+
puts "You must first remove the projectlocker_errata plugin. Please run: script/plugin remove projectlocker_errata"
|
34
|
+
exit
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def append_capistrano_hook
|
39
|
+
if File.exists?('config/deploy.rb') && File.exists?('Capfile')
|
40
|
+
append_file('config/deploy.rb', <<-HOOK)
|
41
|
+
|
42
|
+
require './config/boot'
|
43
|
+
require 'projectlocker_errata/capistrano'
|
44
|
+
HOOK
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def api_key_expression
|
49
|
+
s = if options[:api_key]
|
50
|
+
"'#{options[:api_key]}'"
|
51
|
+
elsif options[:heroku]
|
52
|
+
"ENV['HOPTOAD_API_KEY']"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def generate_initializer
|
57
|
+
template 'initializer.rb', 'config/initializers/projectlocker_errata.rb'
|
58
|
+
end
|
59
|
+
|
60
|
+
def determine_api_key
|
61
|
+
puts "Attempting to determine your API Key from Heroku..."
|
62
|
+
ENV['HOPTOAD_API_KEY'] = heroku_api_key
|
63
|
+
if ENV['HOPTOAD_API_KEY'].blank?
|
64
|
+
puts "... Failed."
|
65
|
+
puts "WARNING: We were unable to detect the ProjectlockerErrata API Key from your Heroku environment."
|
66
|
+
puts "Your Heroku application environment may not be configured correctly."
|
67
|
+
exit 1
|
68
|
+
else
|
69
|
+
puts "... Done."
|
70
|
+
puts "Heroku's ProjectlockerErrata API Key is '#{ENV['HOPTOAD_API_KEY']}'"
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def heroku_var(var,app_name = nil)
|
75
|
+
app = app_name ? "--app #{app_name}" : ''
|
76
|
+
`heroku config #{app} | grep -E "#{var.upcase}" | awk '{ print $3; }'`.strip
|
77
|
+
end
|
78
|
+
|
79
|
+
def heroku_api_key
|
80
|
+
heroku_var("(hoptoad|projectlocker_errata)_api_key",options[:app]).split.find {|x| x unless x.blank?}
|
81
|
+
end
|
82
|
+
|
83
|
+
def heroku?
|
84
|
+
options[:heroku] ||
|
85
|
+
system("grep HOPTOAD_API_KEY config/initializers/projectlocker_errata.rb") ||
|
86
|
+
system("grep HOPTOAD_API_KEY config/environment.rb")
|
87
|
+
end
|
88
|
+
|
89
|
+
def api_key_configured?
|
90
|
+
File.exists?('config/initializers/projectlocker_errata.rb')
|
91
|
+
end
|
92
|
+
|
93
|
+
def test_projectlocker_errata
|
94
|
+
puts run("rake projectlocker_errata:test --trace")
|
95
|
+
end
|
96
|
+
|
97
|
+
def plugin_is_present?
|
98
|
+
File.exists?('vendor/plugins/projectlocker_errata')
|
99
|
+
end
|
100
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
<%= javascript_tag %Q{
|
2
|
+
(function(){
|
3
|
+
var notifierJsScheme = (("https:" == document.location.protocol) ? "https://" : "http://");
|
4
|
+
document.write(unescape("%3Cscript src='" + notifierJsScheme + "#{host}/javascripts/notifier.js' type='text/javascript'%3E%3C/script%3E"));
|
5
|
+
})();
|
6
|
+
}%>
|
7
|
+
|
8
|
+
<%= javascript_tag %Q{
|
9
|
+
window.Airbrake = (typeof(Airbrake) == 'undefined' && typeof(Hoptoad) != 'undefined') ? Hoptoad : Airbrake
|
10
|
+
Airbrake.setKey('#{api_key}');
|
11
|
+
Airbrake.setHost('#{host}');
|
12
|
+
Airbrake.setEnvironment('#{environment}');
|
13
|
+
Airbrake.setErrorDefaults({ url: "#{escape_javascript url}", component: "#{controller_name}", action: "#{action_name}" });
|
14
|
+
}
|
15
|
+
%>
|
@@ -0,0 +1,91 @@
|
|
1
|
+
<script type="text/javascript">
|
2
|
+
var ProjectlockerErrata = {
|
3
|
+
host : <%= host.to_json %>,
|
4
|
+
api_key : <%= api_key.to_json %>,
|
5
|
+
notice : <%= notice.to_json %>,
|
6
|
+
message : 'This error exists in production!',
|
7
|
+
|
8
|
+
initialize: function() {
|
9
|
+
if (this.initialized) {
|
10
|
+
return;
|
11
|
+
} else {
|
12
|
+
this.initialized = true;
|
13
|
+
}
|
14
|
+
|
15
|
+
var data = [];
|
16
|
+
|
17
|
+
for (var key in this.notice) {
|
18
|
+
data[data.length] = 'notice[' + key + ']=' + this.notice[key];
|
19
|
+
}
|
20
|
+
|
21
|
+
data[data.length] = 'notice[api_key]=' + this.api_key;
|
22
|
+
data[data.length] = 'callback=ProjectlockerErrata.onSuccess';
|
23
|
+
data[data.length] = '_=' + (new Date()).getTime();
|
24
|
+
|
25
|
+
var head = document.getElementsByTagName('head')[0];
|
26
|
+
var done = false;
|
27
|
+
|
28
|
+
var
|
29
|
+
script = document.createElement('script');
|
30
|
+
script.src = 'http://' + this.host + '/notices_api/v1/notices/exist?' +
|
31
|
+
data.join('&');
|
32
|
+
script.type = 'text/javascript';
|
33
|
+
script.onload = script.onreadystatechange = function(){
|
34
|
+
if (!done && (!this.readyState ||
|
35
|
+
this.readyState == 'loaded' || this.readyState == 'complete')) {
|
36
|
+
|
37
|
+
done = true;
|
38
|
+
|
39
|
+
// Handle memory leak in IE. (via jQuery)
|
40
|
+
script.onload = script.onreadystatechange = null;
|
41
|
+
head.removeChild(script);
|
42
|
+
}
|
43
|
+
};
|
44
|
+
|
45
|
+
head.appendChild(script);
|
46
|
+
},
|
47
|
+
|
48
|
+
onSuccess: function(error) {
|
49
|
+
var body = document.getElementsByTagName('body')[0];
|
50
|
+
var text = document.createTextNode(this.message);
|
51
|
+
var element = document.createElement('a');
|
52
|
+
|
53
|
+
element.id = 'projectlocker_errata';
|
54
|
+
element.href = 'http://' + error.subdomain + '.' + this.host +
|
55
|
+
'/projects/' + error.project_id + '/errors/' + error.id;
|
56
|
+
element.appendChild(text);
|
57
|
+
|
58
|
+
body.insertBefore(element, body.firstChild);
|
59
|
+
|
60
|
+
var h1 = document.getElementsByTagName('h1')[0];
|
61
|
+
var pre = document.getElementsByTagName('pre')[0];
|
62
|
+
var wrapper = document.createElement('div');
|
63
|
+
|
64
|
+
wrapper.id = 'wrapper';
|
65
|
+
wrapper.appendChild(h1);
|
66
|
+
wrapper.appendChild(pre);
|
67
|
+
|
68
|
+
body.insertBefore(wrapper, body.children[1]);
|
69
|
+
}
|
70
|
+
};
|
71
|
+
|
72
|
+
window.onload = function() {
|
73
|
+
ProjectlockerErrata.initialize.apply(ProjectlockerErrata);
|
74
|
+
};
|
75
|
+
</script>
|
76
|
+
|
77
|
+
<style type="text/css">
|
78
|
+
#projectlocker_errata {
|
79
|
+
background: #FFF url(http://projectlocker_errata.io/images/fell-off-the-toad.gif) no-repeat top right;
|
80
|
+
color: #F00;
|
81
|
+
padding: 45px 101px 45px 12px;
|
82
|
+
font-size: 14px;
|
83
|
+
font-weight: bold;
|
84
|
+
display: block;
|
85
|
+
float: right;
|
86
|
+
}
|
87
|
+
|
88
|
+
#wrapper {
|
89
|
+
padding-right: 360px;
|
90
|
+
}
|
91
|
+
</style>
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "projectlocker_errata/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = %q{projectlocker_errata}
|
7
|
+
s.version = ProjectlockerErrata::VERSION.dup
|
8
|
+
s.summary = %q{Exception reporting service for ProjectLocker}
|
9
|
+
|
10
|
+
s.require_paths = ["lib"]
|
11
|
+
s.files = Dir["{generators/**/*,lib/**/*,rails/**/*,resources/*,script/*}"] +
|
12
|
+
%w(projectlocker_errata.gemspec CHANGELOG Gemfile Guardfile INSTALL MIT-LICENSE Rakefile README_FOR_HEROKU_ADDON.md README.md TESTING.md SUPPORTED_RAILS_VERSIONS install.rb)
|
13
|
+
s.test_files = Dir.glob("{test,spec,features}/**/*")
|
14
|
+
|
15
|
+
s.add_runtime_dependency("builder")
|
16
|
+
s.add_runtime_dependency("girl_friday")
|
17
|
+
|
18
|
+
s.add_development_dependency("actionpack", "~> 2.3.8")
|
19
|
+
s.add_development_dependency("activerecord", "~> 2.3.8")
|
20
|
+
s.add_development_dependency("activesupport", "~> 2.3.8")
|
21
|
+
s.add_development_dependency("mocha", "0.10.5")
|
22
|
+
s.add_development_dependency("bourne", ">= 1.0")
|
23
|
+
s.add_development_dependency("cucumber", "~> 0.10.6")
|
24
|
+
s.add_development_dependency("fakeweb", "~> 1.3.0")
|
25
|
+
s.add_development_dependency("nokogiri", "~> 1.4.3.1")
|
26
|
+
s.add_development_dependency("rspec", "~> 2.6.0")
|
27
|
+
s.add_development_dependency("sham_rack", "~> 1.3.0")
|
28
|
+
s.add_development_dependency("shoulda", "~> 2.11.3")
|
29
|
+
s.add_development_dependency("capistrano", "~> 2.8.0")
|
30
|
+
s.add_development_dependency("guard" )
|
31
|
+
s.add_development_dependency("guard-test" )
|
32
|
+
s.add_development_dependency("simplecov" )
|
33
|
+
|
34
|
+
s.authors = ["Airbrake", "C. G. Brown"]
|
35
|
+
s.email = %q{support@projectlocker.com}
|
36
|
+
s.homepage = "http://www.projectlocker.com"
|
37
|
+
|
38
|
+
s.platform = Gem::Platform::RUBY
|
39
|
+
end
|
data/rails/init.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'projectlocker_errata/rails'
|
data/resources/README.md
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
Airbrake Resources
|
2
|
+
==================
|
3
|
+
|
4
|
+
Airbrake has an SSL mode available to paying plans. SSL Certificate Authority (CA) certificates are not kept current by default on many environments. When CA certs are stale, Airbrake cannot verify Airbrake's production SSL cert and error reports fail. To avoid this, we now package local CA certs. The production of these certs is detailed here.
|
5
|
+
|
6
|
+
Building ca-bundle.crt
|
7
|
+
----------------------
|
8
|
+
|
9
|
+
From https://gist.github.com/996292.
|
10
|
+
|
11
|
+
If you want to use curl or net-http/open-uri to access https resources, you will often (always?) get an error, because they don't have the large number of root certificates installed that web browsers have.
|
12
|
+
|
13
|
+
You can manually install the root certs, but first you have to get them from somewhere. [This article](http://notetoself.vrensk.com/2008/09/verified-https-in-ruby/) gives a nice description of how to do that. The [source of the cert files](http://curl.haxx.se/ca/cacert.pem) it points to is hosted by the curl project, who kindly provide it in the .pem format.
|
14
|
+
|
15
|
+
**problem:** Sadly, ironically, and comically, it's not possible to access that file via https! Luckily, the awesome curl project does provide us with the script that they use to produce the file, so we can do it securely ourselves. Here's how.
|
16
|
+
|
17
|
+
1. `git clone https://github.com/bagder/curl.git`
|
18
|
+
2. `cd curl/lib`
|
19
|
+
3. edit `mk-ca-bundle.pl` and change:
|
20
|
+
|
21
|
+
```perl
|
22
|
+
my $url = 'http://mxr.mozilla.org/mozilla/source/security/nss/lib/ckfw/builtins/certdata.txt?raw=1';
|
23
|
+
```
|
24
|
+
|
25
|
+
to
|
26
|
+
|
27
|
+
```perl
|
28
|
+
my $url = 'https://mxr.mozilla.org/mozilla/source/security/nss/lib/ckfw/builtins/certdata.txt?raw=1';
|
29
|
+
```
|
30
|
+
|
31
|
+
(change `http` to `https`)
|
32
|
+
4. `./mk-ca-bundle.pl`
|
33
|
+
|
34
|
+
Ta da!
|