appsignal 1.4.0.beta.1 → 2.0.0.beta.1

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.
@@ -1,122 +1,170 @@
1
- require 'appsignal/cli'
1
+ require "appsignal/cli"
2
2
 
3
3
  describe Appsignal::CLI::NotifyOfDeploy do
4
+ include CLIHelpers
5
+
4
6
  let(:out_stream) { StringIO.new }
5
- let(:cli) { Appsignal::CLI::NotifyOfDeploy }
6
- let(:config) { Appsignal::Config.new(project_fixture_path, {}) }
7
- let(:marker_data) { {:revision => 'aaaaa', :user => 'thijs', :environment => 'production'} }
8
- before do
9
- config.stub(:active? => true)
10
- end
7
+ let(:output) { out_stream.string }
11
8
  around do |example|
12
9
  capture_stdout(out_stream) { example.run }
13
10
  end
14
11
 
15
- describe ".run" do
16
- it "should validate that the config has been loaded and all options have been supplied" do
17
- cli.should_receive(:validate_active_config)
18
- cli.should_receive(:validate_required_options).with(
19
- {},
20
- [:revision, :user, :environment]
21
- )
22
- Appsignal::Marker.should_receive(:new).and_return(double(:transmit => true))
23
-
24
- cli.run({}, config)
12
+ define :include_deploy_notification do
13
+ match do |log|
14
+ log.include?("Notifying AppSignal of deploy with: ") &&
15
+ log.include?("AppSignal has been notified of this deploy!")
16
+ end
17
+ end
18
+ define :include_deploy_notification_with do |options|
19
+ match do |log|
20
+ return false unless options
21
+ values = "revision: #{options[:revision]}, user: #{options[:user]}"
22
+ log.include?("Notifying AppSignal of deploy with: #{values}") &&
23
+ log.include?("AppSignal has been notified of this deploy!")
24
+ end
25
+ end
26
+ define :include_config_error do
27
+ match do |log|
28
+ log.include? "Error: No valid config found."
29
+ end
30
+ end
31
+ define :include_missing_options do |options|
32
+ match do |log|
33
+ log.include? "Error: Missing options: #{options.join(", ")}"
25
34
  end
35
+ end
36
+
37
+ def run
38
+ run_cli("notify_of_deploy", options)
39
+ end
26
40
 
27
- it "should notify of a deploy" do
28
- marker = double
29
- Appsignal::Marker.should_receive(:new).with(
30
- {
31
- :revision => 'aaaaa',
32
- :user => 'thijs'
33
- },
34
- kind_of(Appsignal::Config)
35
- ).and_return(marker)
36
- marker.should_receive(:transmit)
37
-
38
- cli.run(marker_data, config)
41
+ context "without config" do
42
+ let(:config) { Appsignal::Config.new(tmp_dir, "production") }
43
+ let(:options) { {} }
44
+ around do |example|
45
+ Dir.chdir tmp_dir do
46
+ example.run
47
+ end
39
48
  end
40
49
 
41
- it "should notify of a deploy with no config file and a name specified" do
42
- ENV['PWD'] = '/nonsense'
43
- ENV['APPSIGNAL_PUSH_API_KEY'] = 'key'
44
-
45
- marker = double
46
- Appsignal::Marker.should_receive(:new).with(
47
- {
48
- :revision => 'aaaaa',
49
- :user => 'thijs'
50
- },
51
- kind_of(Appsignal::Config)
52
- ).and_return(marker)
53
- marker.should_receive(:transmit)
54
-
55
- cli.run(marker_data, config)
50
+ it "prints a config error" do
51
+ expect { run }.to raise_error(SystemExit)
52
+ expect(output).to include_config_error
53
+ expect(output).to_not include_deploy_notification
56
54
  end
57
55
  end
58
56
 
59
- describe "#validate_required_options" do
60
- let(:required_options) { [:option_1, :option_2, :option_3] }
61
-
62
- it "should do nothing with all options supplied" do
63
- cli.send(
64
- :validate_required_options,
65
- {
66
- :option_1 => 1,
67
- :option_2 => 2,
68
- :option_3 => 3
69
- },
70
- required_options
71
- )
72
- out_stream.string.should be_empty
57
+ context "with config" do
58
+ let(:config) { project_fixture_config }
59
+ before do
60
+ config[:name] = options[:name] if options[:name]
61
+ stub_api_request config, "markers", {
62
+ :revision => options[:revision],
63
+ :user => options[:user]
64
+ }
73
65
  end
74
-
75
- it "should print a message with one option missing and exit" do
76
- lambda {
77
- cli.send(
78
- :validate_required_options,
79
- {
80
- :option_1 => 1,
81
- :option_2 => 2
82
- },
83
- required_options
84
- )
85
- }.should raise_error(SystemExit)
86
- out_stream.string.should include('Missing options: option_3')
66
+ around do |example|
67
+ Dir.chdir project_fixture_path do
68
+ example.run
69
+ end
87
70
  end
88
71
 
89
- it "should print a message with multiple options missing and exit" do
90
- lambda {
91
- cli.send(
92
- :validate_required_options,
93
- {
94
- :option_1 => 1,
95
- :option_2 => ''
96
- },
97
- required_options
98
- )
99
- }.should raise_error(SystemExit)
100
- out_stream.string.should include("Missing options: option_2, option_3")
72
+ context "without environment" do
73
+ let(:options) { {:environment => "", :revision => "foo", :user => "thijs"} }
74
+ before do
75
+ # Makes the config "active"
76
+ ENV["APPSIGNAL_PUSH_API_KEY"] = "foo"
77
+ end
78
+
79
+ it "requires environment option" do
80
+ expect { run }.to raise_error(SystemExit)
81
+ expect(output).to include_missing_options(%w(environment))
82
+ expect(output).to_not include_deploy_notification
83
+ end
101
84
  end
102
- end
103
85
 
104
- describe "#validate_active_config" do
105
- context "when config is present" do
106
- it "should do nothing" do
107
- cli.send(:validate_active_config, config)
108
- out_stream.string.should be_empty
86
+ context "without known environment" do
87
+ let(:options) { {:environment => "foo"} }
88
+
89
+ it "prints a config error" do
90
+ expect { run }.to raise_error(SystemExit)
91
+ expect(output).to include_config_error
92
+ expect(output).to_not include_missing_options([])
93
+ expect(output).to_not include_deploy_notification
109
94
  end
110
95
  end
111
96
 
112
- context "when config is not active" do
113
- before { config.stub(:active? => false) }
97
+ context "with known environment" do
98
+ context "without required options" do
99
+ let(:options) { {:environment => "production"} }
100
+
101
+ it "prints a missing required options error" do
102
+ expect { run }.to raise_error(SystemExit)
103
+ expect(output).to_not include_config_error
104
+ expect(output).to include_missing_options(%w(revision user))
105
+ expect(output).to_not include_deploy_notification
106
+ end
107
+
108
+ context "with empty required option" do
109
+ let(:options) { {:environment => "production", :revision => "foo", :user => ""} }
110
+
111
+ it "prints a missing required option error" do
112
+ expect { run }.to raise_error(SystemExit)
113
+ expect(output).to_not include_config_error
114
+ expect(output).to include_missing_options(%w(user))
115
+ expect(output).to_not include_deploy_notification
116
+ end
117
+ end
118
+ end
119
+
120
+ context "with required options" do
121
+ let(:options) { {:environment => "production", :revision => "aaaaa", :user => "thijs"} }
122
+
123
+ it "notifies of a deploy" do
124
+ run
125
+ expect(output).to_not include_config_error
126
+ expect(output).to_not include_missing_options([])
127
+ expect(output).to include_deploy_notification_with(options)
128
+ end
129
+
130
+ context "with no app name configured" do
131
+ before { ENV["APPSIGNAL_APP_NAME"] = "" }
132
+
133
+ context "without name option" do
134
+ let(:options) { {:environment => "production", :revision => "aaaaa", :user => "thijs"} }
135
+
136
+ it "requires name option" do
137
+ expect { run }.to raise_error(SystemExit)
138
+ expect(output).to_not include_config_error
139
+ expect(output).to include_missing_options(%w(name))
140
+ expect(output).to_not include_deploy_notification
141
+ end
142
+ end
143
+
144
+ context "with name option" do
145
+ let(:options) { {:environment => "production", :revision => "aaaaa", :user => "thijs", :name => "foo"} }
146
+
147
+ it "notifies of a deploy with a custom name" do
148
+ run
149
+ expect(output).to_not include_config_error
150
+ expect(output).to_not include_missing_options([])
151
+ expect(output).to include_deploy_notification_with(options)
152
+ end
153
+ end
154
+ end
155
+
156
+ context "with name option" do
157
+ let(:options) do
158
+ {:environment => "production", :revision => "aaaaa", :user => "thijs", :name => "foo"}
159
+ end
114
160
 
115
- it "should print a message and exit" do
116
- lambda {
117
- cli.send(:validate_active_config, config)
118
- }.should raise_error(SystemExit)
119
- out_stream.string.should include('Exiting: No config file or push api key env var found')
161
+ it "notifies of a deploy with a custom name" do
162
+ run
163
+ expect(output).to_not include_config_error
164
+ expect(output).to_not include_missing_options([])
165
+ expect(output).to include_deploy_notification_with(options)
166
+ end
167
+ end
120
168
  end
121
169
  end
122
170
  end
@@ -35,7 +35,7 @@ describe Appsignal::CLI do
35
35
  cli.run([arg])
36
36
  }.should raise_error(SystemExit)
37
37
 
38
- out_stream.string.should include 'Appsignal'
38
+ out_stream.string.should include 'AppSignal'
39
39
  out_stream.string.should include '.'
40
40
  end
41
41
  end
@@ -72,21 +72,4 @@ describe Appsignal::CLI do
72
72
  ])
73
73
  end
74
74
  end
75
-
76
- describe "notify_of_deploy" do
77
- it "should call Appsignal::Install.install" do
78
- Appsignal::CLI::NotifyOfDeploy.should_receive(:run).with(
79
- {:revision=>"aaaaa", :user=>"thijs", :environment=>"production"},
80
- instance_of(Appsignal::Config)
81
- )
82
-
83
- cli.run([
84
- 'notify_of_deploy',
85
- '--name=project-production',
86
- '--revision=aaaaa',
87
- '--user=thijs',
88
- '--environment=production'
89
- ])
90
- end
91
- end
92
75
  end
@@ -29,6 +29,26 @@ describe Appsignal::Config do
29
29
  end
30
30
  end
31
31
  end
32
+
33
+ describe ":log" do
34
+ subject { config[:log] }
35
+
36
+ context "when running on Heroku" do
37
+ around { |example| recognize_as_heroku { example.run } }
38
+
39
+ it "is set to stdout" do
40
+ expect(subject).to eq("stdout")
41
+ end
42
+ end
43
+
44
+ context "when not running on Heroku" do
45
+ around { |example| recognize_as_container(:none) { example.run } }
46
+
47
+ it "is set to file" do
48
+ expect(subject).to eq("file")
49
+ end
50
+ end
51
+ end
32
52
  end
33
53
 
34
54
  describe "initial config" do
@@ -46,6 +66,7 @@ describe Appsignal::Config do
46
66
  it "merges with the default config" do
47
67
  expect(config.config_hash).to eq(
48
68
  :debug => false,
69
+ :log => 'file',
49
70
  :ignore_errors => [],
50
71
  :ignore_actions => [],
51
72
  :filter_parameters => [],
@@ -319,7 +340,7 @@ describe Appsignal::Config do
319
340
  expect(ENV['APPSIGNAL_APP_NAME']).to eq 'TestApp'
320
341
  expect(ENV['APPSIGNAL_ENVIRONMENT']).to eq 'production'
321
342
  expect(ENV['APPSIGNAL_AGENT_VERSION']).to eq Appsignal::Extension.agent_version
322
- expect(ENV['APPSIGNAL_LANGUAGE_INTEGRATION_VERSION']).to eq Appsignal::VERSION
343
+ expect(ENV['APPSIGNAL_LANGUAGE_INTEGRATION_VERSION']).to eq "ruby-#{Appsignal::VERSION}"
323
344
  expect(ENV['APPSIGNAL_HTTP_PROXY']).to eq 'http://localhost'
324
345
  expect(ENV['APPSIGNAL_IGNORE_ACTIONS']).to eq 'action1,action2'
325
346
  expect(ENV['APPSIGNAL_FILTER_PARAMETERS']).to eq 'password,confirm_password'
@@ -349,7 +370,11 @@ describe Appsignal::Config do
349
370
  let(:stdout) { StringIO.new }
350
371
  let(:config) { project_fixture_config('production', :log_path => log_path) }
351
372
  subject { config.log_file_path }
352
- around { |example| capture_stdout(stdout) { example.run } }
373
+ around do |example|
374
+ recognize_as_container(:none) do
375
+ capture_stdout(stdout) { example.run }
376
+ end
377
+ end
353
378
 
354
379
  context "when path is writable" do
355
380
  let(:log_path) { File.join(tmp_dir, 'writable-path') }
@@ -1,72 +1,55 @@
1
1
  require 'rake'
2
2
 
3
3
  describe Appsignal::Hooks::RakeHook do
4
- let(:app) { double(:current_scope => nil) }
5
- let(:task) { Rake::Task.new('task', app) }
6
- before do
7
- task.stub(
8
- :name => 'task:name',
9
- :execute_without_appsignal => true
10
- )
11
- end
12
- before :all do
13
- Appsignal::Hooks::RakeHook.new.install
4
+ let(:task) { Rake::Task.new('task:name', Rake::Application.new) }
5
+ before(:all) do
6
+ Appsignal.config = project_fixture_config
7
+ expect(Appsignal.active?).to be_true
8
+ Appsignal::Hooks.load_hooks
14
9
  end
15
10
 
16
11
  describe "#execute" do
17
- context "with transaction" do
18
- let!(:transaction) { background_job_transaction }
19
- let!(:agent) { double('Agent', :send_queue => true) }
20
- before do
21
- transaction.stub(:set_action)
22
- transaction.stub(:set_error)
23
- transaction.stub(:complete)
24
- SecureRandom.stub(:uuid => '123')
25
- Appsignal::Transaction.stub(:create => transaction)
26
- Appsignal.stub(:active? => true)
27
- end
28
-
29
- it "should call the original task" do
30
- expect( task ).to receive(:execute_without_appsignal).with('foo')
12
+ context "without error" do
13
+ it "creates no transaction" do
14
+ expect(Appsignal::Transaction).to_not receive(:create)
31
15
  end
32
16
 
33
- it "should not create a transaction" do
34
- expect( Appsignal::Transaction ).not_to receive(:create)
17
+ it "calls the original task" do
18
+ expect(task).to receive(:execute_without_appsignal).with('foo')
35
19
  end
36
20
 
37
- context "with an exception" do
38
- let(:exception) { VerySpecificError.new }
21
+ after { task.execute('foo') }
22
+ end
39
23
 
40
- before do
41
- task.stub(:execute_without_appsignal).and_raise(exception)
42
- end
24
+ context "with error" do
25
+ let(:error) { VerySpecificError.new }
26
+ let(:transaction) { background_job_transaction }
27
+ before do
28
+ task.enhance { raise error }
43
29
 
44
- it "should create a transaction" do
45
- expect( Appsignal::Transaction ).to receive(:create).with(
46
- '123',
47
- Appsignal::Transaction::BACKGROUND_JOB,
48
- kind_of(Appsignal::Transaction::GenericRequest)
49
- )
50
- end
30
+ expect(Appsignal::Transaction).to receive(:create).with(
31
+ kind_of(String),
32
+ Appsignal::Transaction::BACKGROUND_JOB,
33
+ kind_of(Appsignal::Transaction::GenericRequest)
34
+ ).and_return(transaction)
35
+ end
51
36
 
52
- it "should set the action on the transaction" do
53
- expect( transaction ).to receive(:set_action).with('task:name')
54
- end
37
+ it "sets the action" do
38
+ expect(transaction).to receive(:set_action).with('task:name')
39
+ end
55
40
 
56
- it "should add the exception to the transaction" do
57
- expect( transaction ).to receive(:set_error).with(exception)
58
- end
41
+ it "sets the error" do
42
+ expect(transaction).to receive(:set_error).with(error)
43
+ end
59
44
 
60
- it "should call complete! on the transaction" do
61
- expect( transaction ).to receive(:complete)
62
- end
45
+ it "completes the transaction and stops" do
46
+ expect(transaction).to receive(:complete).ordered
47
+ expect(Appsignal).to receive(:stop).with('rake').ordered
48
+ end
63
49
 
64
- it "should stop appsignal" do
65
- expect( Appsignal ).to receive(:stop)
66
- end
50
+ after do
51
+ expect { task.execute('foo') }.to raise_error VerySpecificError
67
52
  end
68
53
  end
69
-
70
- after { task.execute('foo') rescue VerySpecificError }
71
54
  end
72
55
  end