honeybadger 1.10.3 → 1.11.0.beta1
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/Appraisals +10 -0
- data/CHANGELOG.md +17 -10
- data/Gemfile.lock +1 -1
- data/features/rails.feature +6 -4
- data/features/step_definitions/rails_steps.rb +8 -0
- data/features/support/rails.rb +5 -0
- data/gemfiles/rack.gemfile.lock +1 -1
- data/gemfiles/rails2.3.gemfile.lock +1 -1
- data/gemfiles/rails3.0.gemfile.lock +1 -1
- data/gemfiles/rails3.1.gemfile.lock +1 -1
- data/gemfiles/rails3.2.gemfile.lock +1 -1
- data/gemfiles/rails4.gemfile.lock +1 -1
- data/gemfiles/rails4_cap3.gemfile +13 -0
- data/gemfiles/rails4_cap3.gemfile.lock +204 -0
- data/gemfiles/rake.gemfile.lock +1 -1
- data/gemfiles/sinatra.gemfile.lock +1 -1
- data/honeybadger.gemspec +7 -4
- data/lib/honeybadger.rb +14 -1
- data/lib/honeybadger/capistrano.rb +4 -45
- data/lib/honeybadger/capistrano/legacy.rb +45 -0
- data/lib/honeybadger/capistrano/tasks.rake +67 -0
- data/lib/honeybadger/configuration.rb +2 -2
- data/lib/honeybadger/monitor/worker.rb +1 -1
- data/lib/honeybadger/notice.rb +10 -1
- data/lib/honeybadger/rack.rb +1 -0
- data/lib/honeybadger/rails.rb +8 -0
- data/lib/honeybadger/railtie.rb +1 -7
- data/lib/honeybadger/stats.rb +1 -1
- data/lib/honeybadger/templates/{feedback_form.html.erb → feedback_form.erb} +12 -9
- data/lib/honeybadger/user_feedback.rb +47 -17
- data/lib/honeybadger_tasks.rb +3 -3
- data/lib/rails/generators/honeybadger/honeybadger_generator.rb +1 -2
- data/spec/honeybadger/capistrano_spec.rb +26 -23
- data/spec/honeybadger/configuration_spec.rb +25 -21
- data/spec/honeybadger/notice_spec.rb +30 -37
- data/spec/honeybadger/notifier_spec.rb +60 -4
- data/spec/honeybadger/rack_spec.rb +1 -0
- data/spec/honeybadger/user_feedback_spec.rb +29 -4
- data/spec/honeybadger_tasks_spec.rb +13 -4
- metadata +9 -6
- data/spec/honeybadger/stats_spec.rb +0 -57
data/lib/honeybadger_tasks.rb
CHANGED
@@ -17,12 +17,12 @@ module HoneybadgerTasks
|
|
17
17
|
def self.deploy(opts = {})
|
18
18
|
api_key = opts.delete(:api_key) || Honeybadger.configuration.api_key
|
19
19
|
unless api_key =~ /\S/
|
20
|
-
puts "I don't seem to be configured with an API key. Please check your configuration."
|
20
|
+
$stderr.puts "I don't seem to be configured with an API key. Please check your configuration."
|
21
21
|
return false
|
22
22
|
end
|
23
23
|
|
24
24
|
unless opts[:environment] =~ /\S/
|
25
|
-
puts "I don't know to which environment you are deploying (use the TO=production option)."
|
25
|
+
$stderr.puts "I don't know to which environment you are deploying (use the TO=production option)."
|
26
26
|
return false
|
27
27
|
end
|
28
28
|
|
@@ -60,7 +60,7 @@ module HoneybadgerTasks
|
|
60
60
|
puts "Succesfully recorded deployment"
|
61
61
|
return true
|
62
62
|
else
|
63
|
-
puts response.body
|
63
|
+
$stderr.puts "Error recording deployment: #{response.class} -- #{response.body || 'no response'}"
|
64
64
|
return false
|
65
65
|
end
|
66
66
|
end
|
@@ -36,9 +36,8 @@ class HoneybadgerGenerator < Rails::Generators::Base
|
|
36
36
|
|
37
37
|
def append_capistrano_hook
|
38
38
|
if File.exists?('config/deploy.rb') && File.exists?('Capfile')
|
39
|
-
append_file('
|
39
|
+
append_file('Capfile', <<-HOOK)
|
40
40
|
|
41
|
-
require './config/boot'
|
42
41
|
require 'honeybadger/capistrano'
|
43
42
|
HOOK
|
44
43
|
end
|
@@ -1,33 +1,36 @@
|
|
1
1
|
require 'spec_helper'
|
2
|
+
require 'capistrano'
|
2
3
|
|
3
|
-
|
4
|
-
|
4
|
+
if defined?(Capistrano::Configuration.instance)
|
5
|
+
describe 'Honeybadger::Capistrano' do
|
6
|
+
require 'capistrano/configuration'
|
7
|
+
require 'honeybadger/capistrano'
|
5
8
|
|
6
|
-
|
7
|
-
before(:each) do
|
8
|
-
reset_config
|
9
|
+
before { reset_config }
|
9
10
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
11
|
+
before(:each) do
|
12
|
+
@configuration = Capistrano::Configuration.new
|
13
|
+
Honeybadger::Capistrano.load_into(@configuration)
|
14
|
+
@configuration.dry_run = true
|
15
|
+
end
|
14
16
|
|
15
|
-
|
16
|
-
|
17
|
-
|
17
|
+
it "defines honeybadger:deploy task" do
|
18
|
+
expect(@configuration.find_task('honeybadger:deploy')).not_to be_nil
|
19
|
+
end
|
18
20
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
21
|
+
it "logs when calling honeybadger:deploy task" do
|
22
|
+
@configuration.set(:current_revision, '084505b1c0e0bcf1526e673bb6ac99fbcb18aecc')
|
23
|
+
@configuration.set(:repository, 'repository')
|
24
|
+
@configuration.set(:current_release, '/home/deploy/rails_app/honeybadger')
|
25
|
+
io = StringIO.new
|
26
|
+
logger = Capistrano::Logger.new(:output => io)
|
27
|
+
logger.level = Capistrano::Logger::MAX_LEVEL
|
26
28
|
|
27
|
-
|
28
|
-
|
29
|
+
@configuration.logger = logger
|
30
|
+
@configuration.find_and_execute_task('honeybadger:deploy')
|
29
31
|
|
30
|
-
|
31
|
-
|
32
|
+
expect(io.string).to include '** Notifying Honeybadger of Deploy'
|
33
|
+
expect(io.string).to include '** Honeybadger Notification Complete'
|
34
|
+
end
|
32
35
|
end
|
33
36
|
end
|
@@ -3,6 +3,7 @@ require 'socket'
|
|
3
3
|
|
4
4
|
describe Honeybadger::Configuration do
|
5
5
|
it "provides default values" do
|
6
|
+
assert_config_default :api_key, nil
|
6
7
|
assert_config_default :proxy_host, nil
|
7
8
|
assert_config_default :proxy_port, nil
|
8
9
|
assert_config_default :proxy_user, nil
|
@@ -206,29 +207,32 @@ describe Honeybadger::Configuration do
|
|
206
207
|
expect(config.public?).to be_true
|
207
208
|
end
|
208
209
|
|
209
|
-
|
210
|
-
config
|
211
|
-
config.features = {}
|
212
|
-
expect(config.public?).to be_false
|
213
|
-
end
|
210
|
+
describe "#metrics?" do
|
211
|
+
let(:config) { Honeybadger::Configuration.new }
|
214
212
|
|
215
|
-
|
216
|
-
|
217
|
-
config.environment_name = 'production'
|
218
|
-
expect(config.metrics?).to be_true
|
219
|
-
end
|
213
|
+
context "when public" do
|
214
|
+
before { config.stub(:public?).and_return(true) }
|
220
215
|
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
config.metrics = false
|
225
|
-
expect(config.metrics?).to be_false
|
226
|
-
end
|
216
|
+
it "sends metrics by default" do
|
217
|
+
expect(config.metrics?).to be_true
|
218
|
+
end
|
227
219
|
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
220
|
+
context "when disabled" do
|
221
|
+
before { config.metrics = false }
|
222
|
+
|
223
|
+
it "does not send metrics" do
|
224
|
+
expect(config.metrics?).to be_false
|
225
|
+
end
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
context "when not public" do
|
230
|
+
before { config.stub(:public?).and_return(false) }
|
231
|
+
|
232
|
+
it "does not send metrics" do
|
233
|
+
expect(config.metrics?).to be_false
|
234
|
+
end
|
235
|
+
end
|
232
236
|
end
|
233
237
|
|
234
238
|
it "uses the assigned logger if set" do
|
@@ -237,7 +241,7 @@ describe Honeybadger::Configuration do
|
|
237
241
|
expect(config.logger).to eq "CUSTOM LOGGER"
|
238
242
|
end
|
239
243
|
|
240
|
-
it
|
244
|
+
it "gives a new instance if non defined" do
|
241
245
|
Honeybadger.configuration = nil
|
242
246
|
expect(Honeybadger.configuration).to be_a Honeybadger::Configuration
|
243
247
|
end
|
@@ -14,15 +14,6 @@ describe Honeybadger::Notice do
|
|
14
14
|
Honeybadger::Notice.new(configuration.merge(args))
|
15
15
|
end
|
16
16
|
|
17
|
-
def stub_request(attrs = {})
|
18
|
-
double('request', { :parameters => { 'one' => 'two' },
|
19
|
-
:protocol => 'http',
|
20
|
-
:host => 'some.host',
|
21
|
-
:request_uri => '/some/uri',
|
22
|
-
:session => { :to_hash => { 'a' => 'b' } },
|
23
|
-
:env => { 'three' => 'four' } }.update(attrs))
|
24
|
-
end
|
25
|
-
|
26
17
|
context '#deliver' do
|
27
18
|
context 'sender is configured' do
|
28
19
|
it "delivers to sender" do
|
@@ -313,53 +304,55 @@ describe Honeybadger::Notice do
|
|
313
304
|
assert_filters_hash(:session_data)
|
314
305
|
end
|
315
306
|
|
316
|
-
|
317
|
-
let(:params_filters) { [] }
|
318
|
-
let(:notice) { build_notice(:params_filters => params_filters, :url => url) }
|
319
|
-
|
320
|
-
context 'filtered params in query' do
|
321
|
-
let(:params_filters) { [:bar] }
|
322
|
-
let(:url) { 'https://www.honeybadger.io/?foo=1&bar=2&baz=3' }
|
307
|
+
context 'filtered parameters in query string' do
|
308
|
+
let(:params_filters) { [:foo, :bar] }
|
323
309
|
|
310
|
+
describe '#url' do
|
311
|
+
let(:notice) { build_notice(:params_filters => params_filters, :url => 'https://www.honeybadger.io/?foo=1&bar=2&baz=3') }
|
324
312
|
it 'filters query' do
|
325
|
-
expect(notice.url).to eq 'https://www.honeybadger.io/?foo=
|
313
|
+
expect(notice.url).to eq 'https://www.honeybadger.io/?foo=[FILTERED]&bar=[FILTERED]&baz=3'
|
326
314
|
end
|
327
315
|
end
|
328
316
|
|
329
|
-
|
330
|
-
let(:
|
317
|
+
describe '#cgi_data' do
|
318
|
+
let(:cgi_data) { { 'QUERY_STRING' => 'foo=1&bar=2&baz=3', 'ORIGINAL_FULLPATH' => '/?foo=1&bar=2&baz=3' } }
|
319
|
+
let(:notice) { build_notice(:params_filters => params_filters, :cgi_data => cgi_data) }
|
320
|
+
|
321
|
+
subject { notice.cgi_data }
|
331
322
|
|
332
|
-
it '
|
333
|
-
expect(
|
323
|
+
it 'filters QUERY_STRING key' do
|
324
|
+
expect(subject['QUERY_STRING']).to eq 'foo=[FILTERED]&bar=[FILTERED]&baz=3'
|
334
325
|
end
|
326
|
+
|
327
|
+
it 'filters ORIGINAL_FULLPATH key' do
|
328
|
+
expect(subject['ORIGINAL_FULLPATH']).to eq '/?foo=[FILTERED]&bar=[FILTERED]&baz=3'
|
329
|
+
end
|
330
|
+
end
|
331
|
+
end
|
332
|
+
|
333
|
+
describe '#filter_url' do
|
334
|
+
let(:notice) { build_notice(:params_filters => [], :url => url) }
|
335
|
+
subject { notice.send(:filter_url, url) }
|
336
|
+
|
337
|
+
context 'malformed query' do
|
338
|
+
let(:url) { 'https://www.honeybadger.io/?foobar12' }
|
339
|
+
it { should eq url }
|
335
340
|
end
|
336
341
|
|
337
342
|
context 'no query' do
|
338
343
|
let(:url) { 'https://www.honeybadger.io' }
|
339
|
-
|
340
|
-
it 'keeps original URL' do
|
341
|
-
expect(notice.url).to eq url
|
342
|
-
end
|
344
|
+
it { should eq url }
|
343
345
|
end
|
344
346
|
|
345
347
|
context 'malformed url' do
|
346
348
|
let(:url) { 'http s ! honeybadger' }
|
347
|
-
|
348
|
-
|
349
|
-
expect { URI.parse(url) }.to raise_error
|
350
|
-
end
|
351
|
-
|
352
|
-
it 'keeps original URL' do
|
353
|
-
expect(notice.url).to eq url
|
354
|
-
end
|
349
|
+
before { expect { URI.parse(url) }.to raise_error }
|
350
|
+
it { should eq url }
|
355
351
|
end
|
356
352
|
|
357
353
|
context 'complex url' do
|
358
354
|
let(:url) { 'https://foo:bar@www.honeybadger.io:123/asdf/?foo=1&bar=2&baz=3' }
|
359
|
-
|
360
|
-
it 'keeps original URL' do
|
361
|
-
expect(notice.url).to eq url
|
362
|
-
end
|
355
|
+
it { should eq url }
|
363
356
|
end
|
364
357
|
end
|
365
358
|
|
@@ -7,10 +7,6 @@ describe 'Honeybadger' do
|
|
7
7
|
class ContinuedException < Exception
|
8
8
|
end
|
9
9
|
|
10
|
-
before(:each) do
|
11
|
-
reset_config
|
12
|
-
end
|
13
|
-
|
14
10
|
def assert_sends(notice, notice_args)
|
15
11
|
Honeybadger::Notice.should_receive(:new).with(hash_including(notice_args))
|
16
12
|
Honeybadger.sender.should_receive(:send_to_honeybadger).with(notice)
|
@@ -24,6 +20,66 @@ describe 'Honeybadger' do
|
|
24
20
|
Honeybadger.configure { |config| config.environment_name = 'development' }
|
25
21
|
end
|
26
22
|
|
23
|
+
before(:each) { reset_config }
|
24
|
+
|
25
|
+
describe "#ping" do
|
26
|
+
let(:config) { Honeybadger::Configuration.new }
|
27
|
+
let(:sender) { double() }
|
28
|
+
|
29
|
+
let(:invoke_subject) { Honeybadger.ping(config) }
|
30
|
+
subject { invoke_subject }
|
31
|
+
|
32
|
+
before do
|
33
|
+
config.framework = 'Rails 4.1.0'
|
34
|
+
config.environment_name = 'production'
|
35
|
+
config.hostname = 'twix'
|
36
|
+
stub_const('Honeybadger::VERSION', '1.11.0')
|
37
|
+
|
38
|
+
Honeybadger.stub(:sender).and_return(sender)
|
39
|
+
end
|
40
|
+
|
41
|
+
context "configuration is public" do
|
42
|
+
before { config.stub(:public?).and_return(true) }
|
43
|
+
|
44
|
+
it "pings the sender" do
|
45
|
+
sender.should_receive(:ping).with(hash_including(:version => '1.11.0', :framework => 'Rails 4.1.0', :environment => 'production', :hostname => 'twix'))
|
46
|
+
invoke_subject
|
47
|
+
end
|
48
|
+
|
49
|
+
context "result is truthy" do
|
50
|
+
before { sender.should_receive(:ping).and_return(result) }
|
51
|
+
|
52
|
+
context "result does not contain features" do
|
53
|
+
let(:result) { {} }
|
54
|
+
it { should be_nil }
|
55
|
+
specify { expect { subject }.not_to change(config, :features) }
|
56
|
+
end
|
57
|
+
|
58
|
+
context "result contains features" do
|
59
|
+
let(:result) { {'features' => {'notices' => true, 'metrics' => true}} }
|
60
|
+
it { should eq result['features'] }
|
61
|
+
specify { expect { subject }.to change(config, :features).to(result['features']) }
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
context "result is falsey" do
|
66
|
+
before { sender.should_receive(:ping) }
|
67
|
+
it { should be_nil }
|
68
|
+
specify { expect { invoke_subject }.not_to change(config, :features) }
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
context "configuration is not public" do
|
73
|
+
before { config.stub(:public?).and_return(false) }
|
74
|
+
it { should be_nil }
|
75
|
+
|
76
|
+
it "doesn't attempt to ping sender" do
|
77
|
+
sender.should_not_receive(:ping)
|
78
|
+
invoke_subject
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
27
83
|
it "yields and save a configuration when configuring" do
|
28
84
|
yielded_configuration = nil
|
29
85
|
Honeybadger.configure do |config|
|
@@ -12,11 +12,12 @@ describe Honeybadger::UserFeedback do
|
|
12
12
|
let(:response) { Net::HTTP.get_response(URI.parse("http://example.com/")) }
|
13
13
|
|
14
14
|
before do
|
15
|
+
reset_config
|
15
16
|
ShamRack.mount(informer_app, "example.com")
|
16
17
|
end
|
17
18
|
|
18
19
|
context "feedback feature is disabled by ping" do
|
19
|
-
it
|
20
|
+
it "does not modify the output" do
|
20
21
|
expect(response.body).to eq '<!-- HONEYBADGER FEEDBACK -->'
|
21
22
|
end
|
22
23
|
end
|
@@ -29,25 +30,49 @@ describe Honeybadger::UserFeedback do
|
|
29
30
|
context "there is a honeybadger id" do
|
30
31
|
let(:honeybadger_id) { 1 }
|
31
32
|
|
32
|
-
it
|
33
|
+
it "modifies output" do
|
33
34
|
rendered_length = informer_app.render_form(1).size
|
34
35
|
expect(response.body).to match(/honeybadger_feedback_token/)
|
35
36
|
expect(response["Content-Length"].to_i).to eq rendered_length
|
36
37
|
end
|
37
38
|
|
39
|
+
context "a project root is configured" do
|
40
|
+
let(:tmp_dir) { File.expand_path('../../../tmp', __FILE__) }
|
41
|
+
let(:template_dir) { File.join(tmp_dir, 'lib', 'honeybadger', 'templates') }
|
42
|
+
let(:template_file) { File.join(template_dir, 'feedback_form.erb') }
|
43
|
+
|
44
|
+
before do
|
45
|
+
FileUtils.mkdir_p(template_dir)
|
46
|
+
FileUtils.rm_f(template_file)
|
47
|
+
Honeybadger.configure(true) do |config|
|
48
|
+
config.project_root = tmp_dir
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
context "custom template is implemented" do
|
53
|
+
before do
|
54
|
+
File.open(template_file, 'w') { |f| f.write 'custom feedback form' }
|
55
|
+
end
|
56
|
+
|
57
|
+
it "renders with custom template" do
|
58
|
+
expect(response.body).to match(/custom feedback form/)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
38
63
|
context "feedback feature is disabled by customer" do
|
39
64
|
before do
|
40
65
|
Honeybadger.configuration.feedback = false
|
41
66
|
end
|
42
67
|
|
43
|
-
it
|
68
|
+
it "does not modify the output" do
|
44
69
|
expect(response.body).to eq '<!-- HONEYBADGER FEEDBACK -->'
|
45
70
|
end
|
46
71
|
end
|
47
72
|
end
|
48
73
|
|
49
74
|
context "there is no honeybadger id" do
|
50
|
-
it
|
75
|
+
it "does not modify the output" do
|
51
76
|
expect(response.body).to eq '<!-- HONEYBADGER FEEDBACK -->'
|
52
77
|
end
|
53
78
|
end
|
@@ -17,14 +17,17 @@ describe HoneybadgerTasks do
|
|
17
17
|
end
|
18
18
|
|
19
19
|
context "being quiet" do
|
20
|
-
before
|
20
|
+
before do
|
21
|
+
HoneybadgerTasks.stub(:puts)
|
22
|
+
$stderr.stub(:puts)
|
23
|
+
end
|
21
24
|
|
22
25
|
context "in a configured project" do
|
23
26
|
before(:each) { Honeybadger.configure { |config| config.api_key = "1234123412341234" } }
|
24
27
|
|
25
28
|
context "on deploy({})" do
|
26
29
|
it "complains about missing rails env" do
|
27
|
-
|
30
|
+
$stderr.should_receive(:puts).with(/which environment/i)
|
28
31
|
HoneybadgerTasks.deploy({})
|
29
32
|
end
|
30
33
|
|
@@ -95,11 +98,17 @@ describe HoneybadgerTasks do
|
|
95
98
|
end
|
96
99
|
|
97
100
|
it "puts the response body on failure" do
|
98
|
-
|
101
|
+
$stderr.should_receive(:puts).with(/body/)
|
99
102
|
@http_proxy.should_receive(:request).with(anything).and_return(unsuccessful_response('body'))
|
100
103
|
HoneybadgerTasks.deploy(@options)
|
101
104
|
end
|
102
105
|
|
106
|
+
it "puts the response class on failure" do
|
107
|
+
$stderr.should_receive(:puts).with(/Net::HTTPClientError/)
|
108
|
+
@http_proxy.should_receive(:request).with(anything).and_return(unsuccessful_response)
|
109
|
+
HoneybadgerTasks.deploy(@options)
|
110
|
+
end
|
111
|
+
|
103
112
|
it "returns false on failure" do
|
104
113
|
@http_proxy.should_receive(:request).with(anything).and_return(unsuccessful_response('body'))
|
105
114
|
output = HoneybadgerTasks.deploy(@options)
|
@@ -148,7 +157,7 @@ describe HoneybadgerTasks do
|
|
148
157
|
|
149
158
|
context "on deploy(:environment => 'staging')" do
|
150
159
|
it "complains about missing api key" do
|
151
|
-
|
160
|
+
$stderr.should_receive(:puts).with(/api key/i)
|
152
161
|
HoneybadgerTasks.deploy(:environment => "staging")
|
153
162
|
end
|
154
163
|
|