bugsnag-capistrano 1.1.0 → 2.1.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.
@@ -1,46 +1,42 @@
1
1
  namespace :load do
2
-
3
2
  task :defaults do
4
-
5
3
  set :bugsnag_default_hooks, ->{ true }
6
-
7
4
  end
8
-
9
5
  end
10
6
 
11
7
  namespace :deploy do
12
-
13
8
  before :starting, :bugsnag_hooks do
14
9
  invoke 'bugsnag:add_default_hooks' if fetch(:bugsnag_default_hooks)
15
10
  end
16
-
17
11
  end
18
12
 
19
13
  namespace :bugsnag do
20
-
21
14
  task :add_default_hooks do
22
- after 'deploy:published', 'bugsnag:deploy'
15
+ after 'deploy:published', 'bugsnag:release'
23
16
  end
24
17
 
25
- desc 'Notify Bugsnag that new production code has been deployed'
26
- task :deploy do
18
+ desc 'Notify Bugsnag that new production code has been released'
19
+ task :release do
27
20
  run_locally do
28
21
  begin
29
- Bugsnag::Capistrano::Deploy.notify({
22
+ auto_assign_release_bool = ENV["BUGSNAG_AUTO_ASSIGN_RELEASE"] == 'true'
23
+ Bugsnag::Capistrano::Release.notify({
30
24
  :api_key => fetch(:bugsnag_api_key, ENV["BUGSNAG_API_KEY"]),
25
+ :app_version => fetch(:app_version, ENV["BUGSNAG_APP_VERSION"]),
26
+ :auto_assign_release => fetch(:bugsnag_auto_assign_release, auto_assign_release_bool),
27
+ :builder_name => fetch(:bugsnag_builder, ENV["BUGSNAG_BUILDER_NAME"] || ENV["USER"]),
28
+ :metadata => fetch(:bugsnag_metadata),
31
29
  :release_stage => fetch(:bugsnag_env) || ENV["BUGSNAG_RELEASE_STAGE"] || fetch(:rails_env) || fetch(:stage) || "production",
32
30
  :revision => fetch(:current_revision, ENV["BUGSNAG_REVISION"]),
33
- :repository => fetch(:repo_url, ENV["BUGSNAG_REPOSITORY"]),
34
- :branch => fetch(:branch, ENV["BUGSNAG_BRANCH"]),
35
- :app_version => fetch(:app_version, ENV["BUGSNAG_APP_VERSION"]),
31
+ :repository => fetch(:bugsnag_repo_url, fetch(:repo_url, ENV["BUGSNAG_REPOSITORY"])),
32
+ :source_control_provider => fetch(:bugsnag_source_control_provider, ENV["BUGSNAG_SOURCE_CONTROL_PROVIDER"]),
36
33
  :endpoint => fetch(:bugsnag_endpoint)
37
34
  })
38
- info 'Bugsnag deploy notification complete.'
35
+ info 'Bugsnag release notification complete.'
39
36
  rescue
40
- error "Bugsnag deploy notification failed, #{$!.inspect}"
37
+ error "Bugsnag release notification failed, #{$!.inspect}"
41
38
  end
42
39
  end
43
40
  end
44
-
45
41
  end
46
42
  # vi:ft=ruby
@@ -1,65 +1,116 @@
1
- require 'webmock/rspec'
2
- require 'rspec/expectations'
3
- require 'rspec/mocks'
4
-
5
- require 'webrick'
6
-
7
- describe "bugsnag capistrano", :always do
8
-
9
- server = nil
10
- queue = Queue.new
11
- cap_2 = ENV['CAP_2_TEST'] == 'true'
12
- fixture_path = cap_2 ? '../examples/capistrano2' : '../examples/capistrano3'
13
- exec_string = cap_2 ? 'bundle exec cap deploy' : 'bundle exec cap test deploy'
14
- example_path = File.join(File.dirname(__FILE__), fixture_path)
15
-
16
- before do
17
- server = WEBrick::HTTPServer.new :Port => 0, :Logger => WEBrick::Log.new(STDOUT), :AccessLog => []
18
- server.mount_proc '/deploy' do |req, res|
19
- queue.push req.body
20
- res.status = 200
21
- res.body = "OK\n"
22
- end
23
- Thread.new{ server.start }
24
- end
1
+ require_relative './spec_helper'
25
2
 
26
- after do
27
- server.stop
28
- queue.clear
29
- end
3
+ describe "bugsnag capistrano" do
4
+ server = Helpers::Server.new
5
+
6
+ before { server.start }
7
+ after { server.stop }
30
8
 
31
- let(:request) { JSON.parse(queue.pop) }
32
-
33
9
  it "sends a deploy notification to the set endpoint" do
34
- ENV['BUGSNAG_ENDPOINT'] = "http://localhost:" + server.config[:Port].to_s + "/deploy"
35
-
36
- Dir.chdir(example_path) do
37
- system(exec_string)
10
+ ENV['BUGSNAG_ENDPOINT'] = server.url
11
+ ENV['BUGSNAG_APP_VERSION'] = "1"
12
+
13
+ Dir.chdir(Helpers::Capistrano.example_path) do
14
+ system(Helpers::Capistrano.deploy_command)
38
15
  end
39
16
 
40
- payload = request()
17
+ payload = server.last_request
41
18
  expect(payload["apiKey"]).to eq('YOUR_API_KEY')
19
+ expect(payload["appVersion"]).to eq("1")
42
20
  expect(payload["releaseStage"]).to eq('production')
43
21
  end
44
22
 
45
23
  it "allows modifications of deployment characteristics" do
46
- ENV['BUGSNAG_ENDPOINT'] = "http://localhost:" + server.config[:Port].to_s + "/deploy"
24
+ ENV['BUGSNAG_ENDPOINT'] = server.url
47
25
  ENV['BUGSNAG_API_KEY'] = "this is a test key"
48
26
  ENV['BUGSNAG_RELEASE_STAGE'] = "test"
49
27
  ENV['BUGSNAG_REVISION'] = "test"
50
28
  ENV['BUGSNAG_APP_VERSION'] = "1"
51
29
  ENV['BUGSNAG_REPOSITORY'] = "test@repo.com:test/test_repo.git"
30
+ ENV['BUGSNAG_SOURCE_CONTROL_PROVIDER'] = "github"
31
+ ENV['BUGSNAG_AUTO_ASSIGN_RELEASE'] = 'true'
52
32
 
53
- Dir.chdir(example_path) do
54
- system(exec_string)
33
+ Dir.chdir(Helpers::Capistrano.example_path) do
34
+ system(Helpers::Capistrano.deploy_command)
55
35
  end
56
36
 
57
- payload = request()
37
+ payload = server.last_request
58
38
  expect(payload["apiKey"]).to eq('this is a test key')
59
39
  expect(payload["releaseStage"]).to eq('test')
60
- expect(payload["repository"]).to eq("test@repo.com:test/test_repo.git")
61
40
  expect(payload["appVersion"]).to eq("1")
62
- expect(payload["revision"]).to eq("test")
41
+ expect(payload["sourceControl"]).to_not be_nil
42
+ expect(payload["sourceControl"]["revision"]).to eq("test")
43
+ expect(payload["sourceControl"]["repository"]).to eq("test@repo.com:test/test_repo.git")
44
+ expect(payload["sourceControl"]["provider"]).to eq("github")
45
+ expect(payload["autoAssignRelease"]).to eq(true)
63
46
  end
64
- end
65
47
 
48
+ it "uses 'repo_url' in preference to 'BUGSNAG_REPOSITORY'" do
49
+ ENV['BUGSNAG_REPOSITORY'] = "unused@repo.com:unused/unused_repo.git"
50
+
51
+ capfile = Helpers::Capistrano.generate_capfile({
52
+ bugsnag_api_key: "this is a test key",
53
+ app_version: "1",
54
+ bugsnag_auto_assign_release: true,
55
+ bugsnag_builder: "bob",
56
+ bugsnag_metadata: { a: 1, b: 2 },
57
+ bugsnag_env: "test",
58
+ current_revision: "test1234",
59
+ repo_url: "test@repo.com:test/test_repo.git",
60
+ bugsnag_source_control_provider: "github",
61
+ bugsnag_endpoint: server.url,
62
+ })
63
+
64
+ Helpers::Capistrano.run(capfile)
65
+
66
+ payload = server.last_request
67
+
68
+ expect(payload["apiKey"]).to eq('this is a test key')
69
+ expect(payload["appVersion"]).to eq("1")
70
+ expect(payload["autoAssignRelease"]).to eq(true)
71
+ expect(payload["builderName"]).to eq("bob")
72
+ expect(payload["buildTool"]).to eq("bugsnag-capistrano")
73
+ expect(payload["metadata"]).to eq({ "a" => 1, "b" => 2 })
74
+ expect(payload["releaseStage"]).to eq("test")
75
+ expect(payload["sourceControl"]).to eq({
76
+ "revision" => "test1234",
77
+ "repository" => "test@repo.com:test/test_repo.git",
78
+ "provider" => "github",
79
+ })
80
+ end
81
+
82
+ it "uses 'bugsnag_repo_url' in preference to 'repo_url'" do
83
+ ENV['BUGSNAG_REPOSITORY'] = "unused@repo.com:unused/unused_repo.git"
84
+
85
+ capfile = Helpers::Capistrano.generate_capfile({
86
+ bugsnag_api_key: "this is a test key",
87
+ app_version: "1",
88
+ bugsnag_auto_assign_release: true,
89
+ bugsnag_builder: "bob",
90
+ bugsnag_metadata: { a: 1, b: 2 },
91
+ bugsnag_env: "test",
92
+ current_revision: "test1234",
93
+ repo_url: "test@repo.com:test/test_repo.git",
94
+ bugsnag_repo_url: "https://repo.com/test/test_repo.git",
95
+ bugsnag_source_control_provider: "github",
96
+ bugsnag_endpoint: server.url,
97
+ })
98
+
99
+ Helpers::Capistrano.run(capfile)
100
+
101
+ payload = server.last_request
102
+
103
+ expect(payload["apiKey"]).to eq('this is a test key')
104
+ expect(payload["appVersion"]).to eq("1")
105
+ expect(payload["autoAssignRelease"]).to eq(true)
106
+ expect(payload["builderName"]).to eq("bob")
107
+ expect(payload["buildTool"]).to eq("bugsnag-capistrano")
108
+ expect(payload["metadata"]).to eq({ "a" => 1, "b" => 2 })
109
+ expect(payload["releaseStage"]).to eq("test")
110
+ expect(payload["sourceControl"]).to eq({
111
+ "revision" => "test1234",
112
+ "repository" => "https://repo.com/test/test_repo.git",
113
+ "provider" => "github",
114
+ })
115
+ end
116
+ end
@@ -0,0 +1,71 @@
1
+ require 'tmpdir'
2
+ require 'fileutils'
3
+
4
+ module Helpers
5
+ class Capistrano
6
+ def self.version_2?
7
+ ENV['CAP_2_TEST'] == 'true'
8
+ end
9
+
10
+ def self.deploy_command
11
+ return 'bundle exec cap deploy' if version_2?
12
+
13
+ 'bundle exec cap test deploy'
14
+ end
15
+
16
+ def self.example_path
17
+ fixture_path = version_2? ? '../../examples/capistrano2' : '../../examples/capistrano3'
18
+
19
+ File.join(File.dirname(__FILE__), fixture_path)
20
+ end
21
+
22
+ def self.generate_capfile(variables)
23
+ return generate_v2_capfile(variables) if version_2?
24
+
25
+ capfile = <<-RUBY.gsub(/^\s+/, "")
26
+ require "capistrano/setup"
27
+
28
+ require "capistrano/deploy"
29
+ require "capistrano/scm/git"
30
+ install_plugin Capistrano::SCM::Git
31
+
32
+ require "bugsnag-capistrano"
33
+ RUBY
34
+
35
+ # add calls to set each variable - "set(:key, value)"
36
+ variables.each do |key, value|
37
+ capfile << "set(:#{key}, #{value.inspect})\n"
38
+ end
39
+
40
+ capfile
41
+ end
42
+
43
+ def self.generate_v2_capfile(variables)
44
+ capfile = "require 'bugsnag-capistrano'\n"
45
+
46
+ # add calls to set each variable - "set(:key, value)"
47
+ variables.each do |key, value|
48
+ capfile << "set(:#{key}, #{value.inspect})\n"
49
+ end
50
+
51
+ # add an empty deploy task
52
+ capfile << "task :deploy do\nend"
53
+
54
+ capfile
55
+ end
56
+
57
+ def self.run(capfile)
58
+ Dir.mktmpdir do |path|
59
+ FileUtils.cp_r("#{example_path}/.", path)
60
+
61
+ File.open("#{path}/Capfile", "w") do |file|
62
+ file.write(capfile)
63
+ end
64
+
65
+ Dir.chdir(path) do
66
+ system(deploy_command)
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,63 @@
1
+ require 'json'
2
+ require 'webrick'
3
+
4
+ module Helpers
5
+ class Server
6
+ def initialize
7
+ @queue = Queue.new
8
+ @server = nil
9
+ @thread = nil
10
+ end
11
+
12
+ def start
13
+ @server = WEBrick::HTTPServer.new({
14
+ Port: 0,
15
+ Logger: WEBrick::Log.new(STDOUT),
16
+ AccessLog: []
17
+ })
18
+
19
+ @server.mount_proc('/deploy') do |req, res|
20
+ @queue.push(req.body)
21
+
22
+ res.status = 200
23
+ res.body = "OK\n"
24
+ end
25
+
26
+ @thread = Thread.new { @server.start }
27
+
28
+ loop do
29
+ break if @server.status == :Running
30
+
31
+ sleep(0.1)
32
+ end
33
+ end
34
+
35
+ def stop
36
+ @queue.clear
37
+ @server.stop
38
+ @thread.join(5)
39
+ @server = nil
40
+ end
41
+
42
+ def url
43
+ raise "Server is not running!" if @server.nil?
44
+
45
+ "http://localhost:" + @server.config[:Port].to_s + "/deploy"
46
+ end
47
+
48
+ def last_request
49
+ retries = 0
50
+
51
+ begin
52
+ JSON.parse(@queue.pop(true))
53
+ rescue ThreadError
54
+ raise if retries >= 10
55
+
56
+ retries += 1
57
+ sleep(0.1)
58
+
59
+ retry
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,94 @@
1
+ require_relative './spec_helper'
2
+
3
+ require 'rspec/expectations'
4
+ require 'rspec/mocks'
5
+ require 'webmock/rspec'
6
+
7
+ require 'bugsnag-capistrano/release'
8
+
9
+ module Bugsnag::Capistrano
10
+ class Release
11
+ attr_accessor :logger
12
+ end
13
+ end
14
+
15
+ describe Bugsnag::Capistrano::Release do
16
+ it "should call notify_without bugsnag" do
17
+ expect(Bugsnag::Capistrano::Release).to receive(:deliver)
18
+ Bugsnag::Capistrano::Release.notify({:api_key => "test", :app_version => "1"})
19
+ end
20
+
21
+ it "delivers a request to the given url" do
22
+ url = "http://localhost:56456"
23
+ stub_request(:post, url)
24
+ .to_return(status:200, body: "")
25
+ Bugsnag::Capistrano::Release.deliver(url, nil)
26
+ end
27
+
28
+ it "delivers a body unmodified" do
29
+ body = ::JSON.dump({
30
+ "paramA" => 'a',
31
+ "paramB" => 'b',
32
+ "paramHash" => {
33
+ "one" => 1,
34
+ "two" => 2,
35
+ "three" => 3
36
+ }
37
+ })
38
+ url = "http://localhost:56456"
39
+ request = stub_request(:post, url)
40
+ .with(body: body, headers: { 'Content-Type' => 'application/json'})
41
+ .to_return(status:200, body: "")
42
+ Bugsnag::Capistrano::Release.deliver(url, body)
43
+ assert_requested request
44
+ end
45
+
46
+ it "cannot send without an apikey" do
47
+ expect(Bugsnag::Capistrano::Release).to_not receive(:deliver)
48
+ expect(Bugsnag::Capistrano::Release.logger).to receive(:warn).with("Cannot deliver notification. Missing required apiKey")
49
+
50
+ Bugsnag::Capistrano::Release.notify()
51
+ end
52
+
53
+ it "cannot send without an appVersion" do
54
+ expect(Bugsnag::Capistrano::Release).to_not receive(:deliver)
55
+ expect(Bugsnag::Capistrano::Release.logger).to receive(:warn).with("Cannot deliver notification. Missing required appVersion")
56
+
57
+ Bugsnag::Capistrano::Release.notify({:api_key => "test"})
58
+ end
59
+
60
+ context "with bugsnag installed" do
61
+ before do
62
+ module Kernel
63
+ alias_method :old_require, :require
64
+ def require(path)
65
+ old_require(path) unless /^bugsnag/.match(path)
66
+ end
67
+ end
68
+ end
69
+
70
+ it "gets information from bugsnag configuration if available" do
71
+ config = double
72
+ allow(config).to receive(:api_key).and_return("bugsnag_api_key")
73
+ allow(config).to receive(:app_version).and_return("bugsnag_app_version")
74
+ allow(config).to receive(:release_stage).and_return("bugsnag_release_stage")
75
+
76
+ allow(Bugsnag).to receive(:configuration).and_return(config)
77
+ expect(Bugsnag::Capistrano::Release).to receive(:deliver) do |uri, body_string|
78
+ expect(uri).to eq(Bugsnag::Capistrano::Release::DEFAULT_BUILD_ENDPOINT)
79
+ body = ::JSON.parse(body_string)
80
+ expect(body["apiKey"]).to eq("bugsnag_api_key")
81
+ expect(body["appVersion"]).to eq("bugsnag_app_version")
82
+ expect(body["releaseStage"]).to eq("bugsnag_release_stage")
83
+ end
84
+
85
+ Bugsnag::Capistrano::Release.notify()
86
+ end
87
+
88
+ after do
89
+ module Kernel
90
+ alias_method :require, :old_require
91
+ end
92
+ end
93
+ end
94
+ end