bugsnag-capistrano 1.1.2 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/CHANGELOG.md +6 -4
- data/Gemfile +0 -4
- data/README.md +1 -2
- data/Rakefile +1 -8
- data/UPGRADING.md +27 -0
- data/VERSION +1 -1
- data/lib/bugsnag-capistrano/capistrano.rb +1 -1
- data/lib/bugsnag-capistrano/capistrano2.rb +13 -10
- data/lib/bugsnag-capistrano/release.rb +85 -0
- data/lib/bugsnag-capistrano/tasks/bugsnag.cap +12 -16
- data/spec/capistrano_spec.rb +12 -5
- data/spec/release_spec.rb +96 -0
- metadata +6 -8
- data/lib/bugsnag-capistrano/deploy.rb +0 -98
- data/lib/bugsnag-capistrano/tasks.rb +0 -2
- data/lib/bugsnag-capistrano/tasks/bugsnag-capistrano.rake +0 -85
- data/spec/deploy_spec.rb +0 -97
- data/spec/rake_spec.rb +0 -64
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: d7777843eff43a04d774d3bdee4d5a88dd73d6b1
|
4
|
+
data.tar.gz: 8289fc24a6372a988304b5195458c4d5552e06db
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7aba8fdb6fa4637c860f7648d418bc94c65252b900ff780828389572df7b81bdb82a6de1ed29e6cc7f2f5500ce5b5fe2fd0e5971dbec077e919839a50e7e80e7
|
7
|
+
data.tar.gz: 30486a327c9896b6a0d0bb2756f2e35a3e2787cf33a311d5db8f44d6b57358e6a0bd448b3f369bedb47ab6020c470e274c3287c774f30dda88e26529a97bf7ad
|
data/CHANGELOG.md
CHANGED
@@ -1,9 +1,11 @@
|
|
1
|
-
##
|
1
|
+
## 2.0.0 (03-04-2018)
|
2
2
|
|
3
|
-
|
3
|
+
Major changes have been made with the 2.0.0 release. For a full list please consult the [upgrading guide](https://github.com/bugsnag/bugsnag-capistrano/blob/master/UPGRADING.md).
|
4
|
+
|
5
|
+
### Enhancements
|
4
6
|
|
5
|
-
*
|
6
|
-
|
7
|
+
* Rewritten tool to notify [Bugsnag Build API](https://docs.bugsnag.com/build-integrations/)
|
8
|
+
| [#13](https://github.com/bugsnag/bugsnag-capistrano/pull/13)
|
7
9
|
|
8
10
|
## 1.1.1 (14-12-2017)
|
9
11
|
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -16,8 +16,7 @@ capturing exceptions from your applications.
|
|
16
16
|
|
17
17
|
## Getting started
|
18
18
|
|
19
|
-
* [Integrating with Capistrano](https://docs.bugsnag.com/
|
20
|
-
* [Integrating with Rake](https://docs.bugsnag.com/api/deploy-tracking/rake/)
|
19
|
+
* [Integrating with Capistrano](https://docs.bugsnag.com/build-integrations/capistrano/)
|
21
20
|
|
22
21
|
## Contributing
|
23
22
|
|
data/Rakefile
CHANGED
@@ -25,14 +25,7 @@ end
|
|
25
25
|
require 'rspec/core'
|
26
26
|
require "rspec/core/rake_task"
|
27
27
|
|
28
|
-
tags = '--format documentation
|
29
|
-
|
30
|
-
begin
|
31
|
-
require 'bugsnag'
|
32
|
-
tags += '--tag with_notifier '
|
33
|
-
rescue LoadError
|
34
|
-
tags += '--tag without_notifier '
|
35
|
-
end
|
28
|
+
tags = '--format documentation'
|
36
29
|
|
37
30
|
RSpec::Core::RakeTask.new(:spec) do |opts|
|
38
31
|
opts.rspec_opts = tags
|
data/UPGRADING.md
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# Upgrade Guide
|
2
|
+
|
3
|
+
## 1.x to 2.x
|
4
|
+
|
5
|
+
_Our Capistrano build-integration has changed to accommodate changes to our [Build API](https://docs.bugsnag.com/build-integrations/), and there may be changes required to continue to notify of your Capistrano releases_
|
6
|
+
|
7
|
+
#### Heroku
|
8
|
+
|
9
|
+
Heroku deployment notifications have been removed from this gem. You can find information on how to set up a Heroku deploy hook at [our documentation](https://docs.bugsnag.com/build-integrations/heroku/).
|
10
|
+
|
11
|
+
#### Rake
|
12
|
+
|
13
|
+
Rake deployment notifications have been removed from this gem. While we don't have an explicit replacement for the Rake tasks, information on how to send a build notification can be found in [our Build API documentation](https://docs.bugsnag.com/build-integrations/).
|
14
|
+
|
15
|
+
#### Task names
|
16
|
+
|
17
|
+
The task `:deploy` has been renamed to `:release`. Any references to it should be renamed accordingly.
|
18
|
+
|
19
|
+
#### Configuration
|
20
|
+
|
21
|
+
- `branch` has been removed.
|
22
|
+
- `bugsnag_builder` has been added. This should be the name of the person or machine that has triggered the release. Can also be set using the environment variables `BUGSNAG_BUILDER_NAME` or `USER`. Will default to the result of the `whoami` command on the releasing machine.
|
23
|
+
- `bugsnag_auto_assign_release` has been added. Thi#s will ensure **all** event notifications received will be assigned to this release. This should only be used if you are not using the `app_version` configuration option within your application. Can be set using the environment variable `BUGSNAG_AUTO_ASSIGN_RELEASE`. Will default to `false`.
|
24
|
+
- `bugsnag_source_control_provider` has been added. This contains the type of on-premise server the application uses for source-control, and therefore should only be used if an on-premise source-control solution is used. Valid settings are: `github-enterprise`, `gitlab-onpremise`, and `bitbucket-server`. Can be set using the environment variable `BUGSNAG_SOURCE_CONTROL_PROVIDER`. Defaults to `nil`.
|
25
|
+
- `bugsnag-metadata` has been added. This should be a hash containing any additional data you wish to attach to your release notification.
|
26
|
+
|
27
|
+
A full list of configuration options can be found at the [Capistrano build-integration guide](https://docs.bugsnag.com/build-integrations/capistrano/).
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
2.0.0
|
@@ -2,25 +2,28 @@ module Bugsnag
|
|
2
2
|
module Capistrano
|
3
3
|
def self.load_into(configuration)
|
4
4
|
configuration.load do
|
5
|
-
after "deploy", "bugsnag:
|
6
|
-
after "deploy:migrations", "bugsnag:deploy"
|
5
|
+
after "deploy", "bugsnag:release"
|
7
6
|
|
8
7
|
namespace :bugsnag do
|
9
|
-
desc "Notify Bugsnag that new production code has been
|
10
|
-
task :
|
8
|
+
desc "Notify Bugsnag that new production code has been released"
|
9
|
+
task :release, :except => { :no_release => true }, :on_error => :continue do
|
11
10
|
begin
|
12
|
-
|
11
|
+
auto_assign_release_bool = ENV["BUGSNAG_AUTO_ASSIGN_RELEASE"] == 'true'
|
12
|
+
Bugsnag::Capistrano::Release.notify({
|
13
13
|
:api_key => fetch(:bugsnag_api_key, ENV["BUGSNAG_API_KEY"]),
|
14
|
+
:app_version => fetch(:app_version, ENV["BUGSNAG_APP_VERSION"]),
|
15
|
+
:auto_assign_release => fetch(:bugsnag_auto_assign_release, auto_assign_release_bool),
|
16
|
+
:builder_name => fetch(:bugsnag_builder, ENV["BUGSNAG_BUILDER_NAME"] || ENV["USER"]),
|
17
|
+
:metadata => fetch(:bugsnag_metadata, nil),
|
14
18
|
:release_stage => fetch(:bugsnag_env) || ENV["BUGSNAG_RELEASE_STAGE"] || fetch(:rails_env) || fetch(:stage) || "production",
|
15
19
|
:revision => fetch(:current_revision, ENV["BUGSNAG_REVISION"]),
|
16
20
|
:repository => fetch(:repo_url, ENV["BUGSNAG_REPOSITORY"]),
|
17
|
-
:
|
18
|
-
:
|
19
|
-
:endpoint => fetch(:bugsnag_endpoint)
|
21
|
+
:source_control_provider => fetch(:bugsnag_source_control_provider, ENV["BUGSNAG_SOURCE_CONTROL_PROVIDER"]),
|
22
|
+
:endpoint => fetch(:bugsnag_endpoint, nil)
|
20
23
|
})
|
21
|
-
logger.info "Bugsnag
|
24
|
+
logger.info "Bugsnag release notification complete."
|
22
25
|
rescue
|
23
|
-
logger.important("
|
26
|
+
logger.important("Bugsnag release notification failed, #{$!.inspect}")
|
24
27
|
end
|
25
28
|
end
|
26
29
|
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
require "json"
|
2
|
+
require "net/http"
|
3
|
+
require "logger"
|
4
|
+
|
5
|
+
module Bugsnag
|
6
|
+
module Capistrano
|
7
|
+
class Release
|
8
|
+
|
9
|
+
HEADERS = {"Content-Type" => "application/json"}
|
10
|
+
DEFAULT_BUILD_ENDPOINT = "https://build.bugsnag.com/"
|
11
|
+
DEFAULT_BUILD_TOOL_NAME = "bugsnag-capistrano"
|
12
|
+
|
13
|
+
def self.notify(opts = {})
|
14
|
+
# Try and get some config from Bugsnag
|
15
|
+
begin
|
16
|
+
require 'bugsnag'
|
17
|
+
|
18
|
+
opts[:api_key] ||= Bugsnag.configuration.api_key
|
19
|
+
opts[:app_version] ||= Bugsnag.configuration.app_version
|
20
|
+
opts[:release_stage] ||= Bugsnag.configuration.release_stage
|
21
|
+
rescue LoadError
|
22
|
+
end
|
23
|
+
|
24
|
+
opts[:endpoint] ||= DEFAULT_BUILD_ENDPOINT
|
25
|
+
opts[:builder_name] ||= `whoami`
|
26
|
+
opts[:build_tool] ||= DEFAULT_BUILD_TOOL_NAME
|
27
|
+
|
28
|
+
parameters = {
|
29
|
+
"apiKey" => opts[:api_key],
|
30
|
+
"appVersion" => opts[:app_version],
|
31
|
+
"autoAssignRelease" => opts[:auto_assign_release],
|
32
|
+
"builderName" => opts[:builder_name],
|
33
|
+
"buildTool" => opts[:build_tool],
|
34
|
+
"metadata" => opts[:metadata],
|
35
|
+
"releaseStage" => opts[:release_stage],
|
36
|
+
"sourceControl" => {
|
37
|
+
"provider" => opts[:source_control_provider],
|
38
|
+
"revision" => opts[:revision],
|
39
|
+
"repository" => opts[:repository]
|
40
|
+
}
|
41
|
+
}
|
42
|
+
|
43
|
+
if parameters["apiKey"].nil?
|
44
|
+
logger.warn("Cannot deliver notification. Missing required apiKey")
|
45
|
+
elsif parameters["appVersion"].nil?
|
46
|
+
logger.warn("Cannot deliver notification. Missing required appVersion")
|
47
|
+
else
|
48
|
+
payload_string = ::JSON.dump(parameters)
|
49
|
+
self.deliver(opts[:endpoint], payload_string)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def self.deliver(url, body)
|
54
|
+
begin
|
55
|
+
request(url, body)
|
56
|
+
rescue StandardError => e
|
57
|
+
logger.warn("Notification to #{url} failed, #{e.inspect}")
|
58
|
+
logger.warn(e.backtrace)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def self.request(url, body)
|
63
|
+
uri = URI.parse(url)
|
64
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
65
|
+
http.read_timeout = 15
|
66
|
+
http.open_timeout = 15
|
67
|
+
|
68
|
+
http.use_ssl = uri.scheme == "https"
|
69
|
+
|
70
|
+
uri.path == "" ? "/" : uri.path
|
71
|
+
request = Net::HTTP::Post.new(uri, HEADERS)
|
72
|
+
request.body = body
|
73
|
+
http.request(request)
|
74
|
+
end
|
75
|
+
|
76
|
+
def self.logger
|
77
|
+
if @logger.nil?
|
78
|
+
@logger = Logger.new(STDOUT)
|
79
|
+
@logger.level = Logger::INFO
|
80
|
+
end
|
81
|
+
@logger
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -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:
|
15
|
+
after 'deploy:published', 'bugsnag:release'
|
23
16
|
end
|
24
17
|
|
25
|
-
desc 'Notify Bugsnag that new production code has been
|
26
|
-
task :
|
18
|
+
desc 'Notify Bugsnag that new production code has been released'
|
19
|
+
task :release do
|
27
20
|
run_locally do
|
28
21
|
begin
|
29
|
-
|
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
31
|
:repository => fetch(:repo_url, ENV["BUGSNAG_REPOSITORY"]),
|
34
|
-
:
|
35
|
-
:app_version => fetch(:app_version, ENV["BUGSNAG_APP_VERSION"]),
|
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
|
35
|
+
info 'Bugsnag release notification complete.'
|
39
36
|
rescue
|
40
|
-
error "Bugsnag
|
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
|
data/spec/capistrano_spec.rb
CHANGED
@@ -4,7 +4,7 @@ require 'rspec/mocks'
|
|
4
4
|
|
5
5
|
require 'webrick'
|
6
6
|
|
7
|
-
describe "bugsnag capistrano"
|
7
|
+
describe "bugsnag capistrano" do
|
8
8
|
|
9
9
|
server = nil
|
10
10
|
queue = Queue.new
|
@@ -29,16 +29,18 @@ describe "bugsnag capistrano", :always do
|
|
29
29
|
end
|
30
30
|
|
31
31
|
let(:request) { JSON.parse(queue.pop) }
|
32
|
-
|
32
|
+
|
33
33
|
it "sends a deploy notification to the set endpoint" do
|
34
34
|
ENV['BUGSNAG_ENDPOINT'] = "http://localhost:" + server.config[:Port].to_s + "/deploy"
|
35
|
-
|
35
|
+
ENV['BUGSNAG_APP_VERSION'] = "1"
|
36
|
+
|
36
37
|
Dir.chdir(example_path) do
|
37
38
|
system(exec_string)
|
38
39
|
end
|
39
40
|
|
40
41
|
payload = request()
|
41
42
|
expect(payload["apiKey"]).to eq('YOUR_API_KEY')
|
43
|
+
expect(payload["appVersion"]).to eq("1")
|
42
44
|
expect(payload["releaseStage"]).to eq('production')
|
43
45
|
end
|
44
46
|
|
@@ -49,6 +51,8 @@ describe "bugsnag capistrano", :always do
|
|
49
51
|
ENV['BUGSNAG_REVISION'] = "test"
|
50
52
|
ENV['BUGSNAG_APP_VERSION'] = "1"
|
51
53
|
ENV['BUGSNAG_REPOSITORY'] = "test@repo.com:test/test_repo.git"
|
54
|
+
ENV['BUGSNAG_SOURCE_CONTROL_PROVIDER'] = "github"
|
55
|
+
ENV['BUGSNAG_AUTO_ASSIGN_RELEASE'] = 'true'
|
52
56
|
|
53
57
|
Dir.chdir(example_path) do
|
54
58
|
system(exec_string)
|
@@ -57,9 +61,12 @@ describe "bugsnag capistrano", :always do
|
|
57
61
|
payload = request()
|
58
62
|
expect(payload["apiKey"]).to eq('this is a test key')
|
59
63
|
expect(payload["releaseStage"]).to eq('test')
|
60
|
-
expect(payload["repository"]).to eq("test@repo.com:test/test_repo.git")
|
61
64
|
expect(payload["appVersion"]).to eq("1")
|
62
|
-
expect(payload["
|
65
|
+
expect(payload["sourceControl"]).to_not be_nil
|
66
|
+
expect(payload["sourceControl"]["revision"]).to eq("test")
|
67
|
+
expect(payload["sourceControl"]["repository"]).to eq("test@repo.com:test/test_repo.git")
|
68
|
+
expect(payload["sourceControl"]["provider"]).to eq("github")
|
69
|
+
expect(payload["autoAssignRelease"]).to eq(true)
|
63
70
|
end
|
64
71
|
end
|
65
72
|
|
@@ -0,0 +1,96 @@
|
|
1
|
+
require 'webmock/rspec'
|
2
|
+
require 'rspec/expectations'
|
3
|
+
require 'rspec/mocks'
|
4
|
+
require 'logger'
|
5
|
+
require 'json'
|
6
|
+
|
7
|
+
require 'webrick'
|
8
|
+
|
9
|
+
require 'bugsnag-capistrano/release'
|
10
|
+
|
11
|
+
module Bugsnag::Capistrano
|
12
|
+
class Release
|
13
|
+
attr_accessor :logger
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe Bugsnag::Capistrano::Release do
|
18
|
+
it "should call notify_without bugsnag" do
|
19
|
+
expect(Bugsnag::Capistrano::Release).to receive(:deliver)
|
20
|
+
Bugsnag::Capistrano::Release.notify({:api_key => "test", :app_version => "1"})
|
21
|
+
end
|
22
|
+
|
23
|
+
it "delivers a request to the given url" do
|
24
|
+
url = "http://localhost:56456"
|
25
|
+
stub_request(:post, url)
|
26
|
+
.to_return(status:200, body: "")
|
27
|
+
Bugsnag::Capistrano::Release.deliver(url, nil)
|
28
|
+
end
|
29
|
+
|
30
|
+
it "delivers a body unmodified" do
|
31
|
+
body = ::JSON.dump({
|
32
|
+
"paramA" => 'a',
|
33
|
+
"paramB" => 'b',
|
34
|
+
"paramHash" => {
|
35
|
+
"one" => 1,
|
36
|
+
"two" => 2,
|
37
|
+
"three" => 3
|
38
|
+
}
|
39
|
+
})
|
40
|
+
url = "http://localhost:56456"
|
41
|
+
request = stub_request(:post, url)
|
42
|
+
.with(body: body, headers: { 'Content-Type' => 'application/json'})
|
43
|
+
.to_return(status:200, body: "")
|
44
|
+
Bugsnag::Capistrano::Release.deliver(url, body)
|
45
|
+
assert_requested request
|
46
|
+
end
|
47
|
+
|
48
|
+
it "cannot send without an apikey" do
|
49
|
+
expect(Bugsnag::Capistrano::Release).to_not receive(:deliver)
|
50
|
+
expect(Bugsnag::Capistrano::Release.logger).to receive(:warn).with("Cannot deliver notification. Missing required apiKey")
|
51
|
+
|
52
|
+
Bugsnag::Capistrano::Release.notify()
|
53
|
+
end
|
54
|
+
|
55
|
+
it "cannot send without an appVersion" do
|
56
|
+
expect(Bugsnag::Capistrano::Release).to_not receive(:deliver)
|
57
|
+
expect(Bugsnag::Capistrano::Release.logger).to receive(:warn).with("Cannot deliver notification. Missing required appVersion")
|
58
|
+
|
59
|
+
Bugsnag::Capistrano::Release.notify({:api_key => "test"})
|
60
|
+
end
|
61
|
+
|
62
|
+
context "with bugsnag installed" do
|
63
|
+
before do
|
64
|
+
module Kernel
|
65
|
+
alias_method :old_require, :require
|
66
|
+
def require(path)
|
67
|
+
old_require(path) unless /^bugsnag/.match(path)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
it "gets information from bugsnag configuration if available" do
|
73
|
+
config = double
|
74
|
+
allow(config).to receive(:api_key).and_return("bugsnag_api_key")
|
75
|
+
allow(config).to receive(:app_version).and_return("bugsnag_app_version")
|
76
|
+
allow(config).to receive(:release_stage).and_return("bugsnag_release_stage")
|
77
|
+
|
78
|
+
allow(Bugsnag).to receive(:configuration).and_return(config)
|
79
|
+
expect(Bugsnag::Capistrano::Release).to receive(:deliver) do |uri, body_string|
|
80
|
+
expect(uri).to eq(Bugsnag::Capistrano::Release::DEFAULT_BUILD_ENDPOINT)
|
81
|
+
body = ::JSON.parse(body_string)
|
82
|
+
expect(body["apiKey"]).to eq("bugsnag_api_key")
|
83
|
+
expect(body["appVersion"]).to eq("bugsnag_app_version")
|
84
|
+
expect(body["releaseStage"]).to eq("bugsnag_release_stage")
|
85
|
+
end
|
86
|
+
|
87
|
+
Bugsnag::Capistrano::Release.notify()
|
88
|
+
end
|
89
|
+
|
90
|
+
after do
|
91
|
+
module Kernel
|
92
|
+
alias_method :require, :old_require
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bugsnag-capistrano
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Keegan Lowenstein
|
@@ -11,7 +11,7 @@ authors:
|
|
11
11
|
autorequire:
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
|
-
date: 2018-
|
14
|
+
date: 2018-04-03 00:00:00.000000000 Z
|
15
15
|
dependencies: []
|
16
16
|
description: Correlate Capistrano deploys with new errors and increased error rates
|
17
17
|
in Bugsnag
|
@@ -31,18 +31,16 @@ files:
|
|
31
31
|
- LICENSE.txt
|
32
32
|
- README.md
|
33
33
|
- Rakefile
|
34
|
+
- UPGRADING.md
|
34
35
|
- VERSION
|
35
36
|
- bugsnag-capistrano.gemspec
|
36
37
|
- lib/bugsnag-capistrano.rb
|
37
38
|
- lib/bugsnag-capistrano/capistrano.rb
|
38
39
|
- lib/bugsnag-capistrano/capistrano2.rb
|
39
|
-
- lib/bugsnag-capistrano/
|
40
|
-
- lib/bugsnag-capistrano/tasks.rb
|
41
|
-
- lib/bugsnag-capistrano/tasks/bugsnag-capistrano.rake
|
40
|
+
- lib/bugsnag-capistrano/release.rb
|
42
41
|
- lib/bugsnag-capistrano/tasks/bugsnag.cap
|
43
42
|
- spec/capistrano_spec.rb
|
44
|
-
- spec/
|
45
|
-
- spec/rake_spec.rb
|
43
|
+
- spec/release_spec.rb
|
46
44
|
homepage: http://github.com/bugsnag/bugsnag-capistrano
|
47
45
|
licenses:
|
48
46
|
- MIT
|
@@ -63,7 +61,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
63
61
|
version: '0'
|
64
62
|
requirements: []
|
65
63
|
rubyforge_project:
|
66
|
-
rubygems_version: 2.
|
64
|
+
rubygems_version: 2.6.11
|
67
65
|
signing_key:
|
68
66
|
specification_version: 4
|
69
67
|
summary: Notify Bugsnag when deploying with Capistrano
|
@@ -1,98 +0,0 @@
|
|
1
|
-
require "json"
|
2
|
-
require "net/http"
|
3
|
-
require "logger"
|
4
|
-
|
5
|
-
module Bugsnag
|
6
|
-
module Capistrano
|
7
|
-
class Deploy
|
8
|
-
|
9
|
-
HEADERS = {"Content-Type" => "application/json"}
|
10
|
-
DEFAULT_DEPLOY_ENDPOINT = "https://notify.bugsnag.com/deploy"
|
11
|
-
|
12
|
-
def self.notify(opts = {})
|
13
|
-
begin
|
14
|
-
require 'bugsnag'
|
15
|
-
self.notify_using_bugsnag(opts)
|
16
|
-
rescue LoadError
|
17
|
-
self.notify_without_bugsnag(opts)
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
def self.notify_using_bugsnag(opts = {})
|
22
|
-
|
23
|
-
configuration = Bugsnag.configuration.dup
|
24
|
-
|
25
|
-
[:api_key, :app_version, :release_stage, :endpoint, :use_ssl,
|
26
|
-
:proxy_host, :proxy_port, :proxy_user, :proxy_password].each do |param|
|
27
|
-
unless opts[param].nil?
|
28
|
-
configuration.send :"#{param}=", opts[param]
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
if Gem::Version.new(Bugsnag::VERSION).release >= Gem::Version.new('6.0.0')
|
33
|
-
endpoint = configuration.endpoint + '/deploy'
|
34
|
-
else
|
35
|
-
endpoint = (configuration.use_ssl ? "https://" : "http://") + configuration.endpoint + '/deploy'
|
36
|
-
end
|
37
|
-
|
38
|
-
parameters = {
|
39
|
-
"apiKey" => configuration.api_key,
|
40
|
-
"releaseStage" => configuration.release_stage,
|
41
|
-
"appVersion" => configuration.app_version,
|
42
|
-
"revision" => opts[:revision],
|
43
|
-
"repository" => opts[:repository],
|
44
|
-
"branch" => opts[:branch]
|
45
|
-
}.reject {|k,v| v == nil}
|
46
|
-
|
47
|
-
raise RuntimeError.new("No API key found when notifying of deploy") if !parameters["apiKey"] || parameters["apiKey"].empty?
|
48
|
-
|
49
|
-
|
50
|
-
payload_string = ::JSON.dump(parameters)
|
51
|
-
Bugsnag::Delivery::Synchronous.deliver(endpoint, payload_string, configuration)
|
52
|
-
end
|
53
|
-
|
54
|
-
def self.notify_without_bugsnag(opts = {})
|
55
|
-
endpoint = (opts[:endpoint].nil? ? DEFAULT_DEPLOY_ENDPOINT : opts[:endpoint])
|
56
|
-
|
57
|
-
parameters = {
|
58
|
-
"apiKey" => opts[:api_key],
|
59
|
-
"releaseStage" => opts[:release_stage],
|
60
|
-
"appVersion" => opts[:app_version],
|
61
|
-
"revision" => opts[:revision],
|
62
|
-
"repository" => opts[:repository],
|
63
|
-
"branch" => opts[:branch]
|
64
|
-
}.reject {|k, v| v == nil}
|
65
|
-
|
66
|
-
raise RuntimeError.new("No API key found when notifying of deploy") if !parameters["apiKey"] || parameters["apiKey"].empty?
|
67
|
-
|
68
|
-
payload_string = ::JSON.dump(parameters)
|
69
|
-
self.deliver(endpoint, payload_string)
|
70
|
-
end
|
71
|
-
|
72
|
-
def self.deliver(url, body)
|
73
|
-
logger = Logger.new(STDOUT)
|
74
|
-
logger.level = Logger::INFO
|
75
|
-
begin
|
76
|
-
request(url, body)
|
77
|
-
rescue StandardError => e
|
78
|
-
logger.warn("Notification to #{url} failed, #{e.inspect}")
|
79
|
-
logger.warn(e.backtrace)
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
|
-
def self.request(url, body)
|
84
|
-
uri = URI.parse(url)
|
85
|
-
http = Net::HTTP.new(uri.host, uri.port)
|
86
|
-
http.read_timeout = 15
|
87
|
-
http.open_timeout = 15
|
88
|
-
|
89
|
-
http.use_ssl = uri.scheme == "https"
|
90
|
-
|
91
|
-
uri.path == "" ? "/" : uri.path
|
92
|
-
request = Net::HTTP::Post.new(uri, HEADERS)
|
93
|
-
request.body = body
|
94
|
-
http.request(request)
|
95
|
-
end
|
96
|
-
end
|
97
|
-
end
|
98
|
-
end
|
@@ -1,85 +0,0 @@
|
|
1
|
-
require "bugsnag-capistrano/deploy"
|
2
|
-
|
3
|
-
namespace :bugsnag do
|
4
|
-
|
5
|
-
desc "Notify Bugsnag of a new deploy."
|
6
|
-
task :deploy do
|
7
|
-
api_key = ENV["BUGSNAG_API_KEY"]
|
8
|
-
release_stage = ENV["BUGSNAG_RELEASE_STAGE"]
|
9
|
-
app_version = ENV["BUGSNAG_APP_VERSION"]
|
10
|
-
revision = ENV["BUGSNAG_REVISION"]
|
11
|
-
repository = ENV["BUGSNAG_REPOSITORY"]
|
12
|
-
branch = ENV["BUGSNAG_BRANCH"]
|
13
|
-
endpoint = ENV["BUGSNAG_ENDPOINT"]
|
14
|
-
|
15
|
-
Rake::Task["load"].invoke unless api_key
|
16
|
-
|
17
|
-
Bugsnag::Capistrano::Deploy.notify({
|
18
|
-
:api_key => api_key,
|
19
|
-
:release_stage => release_stage,
|
20
|
-
:app_version => app_version,
|
21
|
-
:revision => revision,
|
22
|
-
:repository => repository,
|
23
|
-
:branch => branch,
|
24
|
-
:endpoint => endpoint,
|
25
|
-
})
|
26
|
-
end
|
27
|
-
|
28
|
-
namespace :heroku do
|
29
|
-
desc "Add a heroku deploy hook to notify Bugsnag of deploys"
|
30
|
-
task :add_deploy_hook => :load do
|
31
|
-
# Wrapper to run command safely even in bundler
|
32
|
-
run_command = lambda { |command|
|
33
|
-
defined?(Bundler.with_clean_env) ? Bundler.with_clean_env { `#{command}` } : `#{command}`
|
34
|
-
}
|
35
|
-
|
36
|
-
# Fetch heroku config settings
|
37
|
-
config_command = "heroku config --shell"
|
38
|
-
config_command += " --app #{ENV["HEROKU_APP"]}" if ENV["HEROKU_APP"]
|
39
|
-
heroku_env = run_command.call(config_command).split(/[\n\r]/).each_with_object({}) do |c, obj|
|
40
|
-
k,v = c.split("=")
|
41
|
-
obj[k] = (v.nil? || v.strip.empty?) ? nil : v
|
42
|
-
end
|
43
|
-
|
44
|
-
# Check for Bugsnag API key (required) using Bugsnag configuration only if available
|
45
|
-
begin
|
46
|
-
require 'bugsnag'
|
47
|
-
api_key = heroku_env["BUGSNAG_API_KEY"] || Bugsnag.configuration.api_key || ENV["BUGSNAG_API_KEY"]
|
48
|
-
rescue LoadError
|
49
|
-
api_key = heroku_env["BUGSNAG_API_KEY"] || ENV["BUGSNAG_API_KEY"]
|
50
|
-
end
|
51
|
-
|
52
|
-
unless api_key
|
53
|
-
puts "Error: No API key found, have you run 'heroku config:set BUGSNAG_API_KEY=your-api-key'?"
|
54
|
-
next
|
55
|
-
end
|
56
|
-
|
57
|
-
# Build the request, making use of deploy hook variables
|
58
|
-
# (https://devcenter.heroku.com/articles/deploy-hooks#customizing-messages)
|
59
|
-
params = {
|
60
|
-
:apiKey => api_key,
|
61
|
-
:branch => "master",
|
62
|
-
:revision => "{{head_long}}",
|
63
|
-
:releaseStage => heroku_env["BUGSNAG_RELEASE_STAGE"] || heroku_env["RAILS_ENV"] || ENV["RAILS_ENV"] || "production"
|
64
|
-
}
|
65
|
-
repo = `git config --get remote.origin.url`.strip
|
66
|
-
params[:repository] = repo unless repo.empty?
|
67
|
-
|
68
|
-
# Add the hook
|
69
|
-
url = "https://notify.bugsnag.com/deploy?" + params.map {|k,v| "#{k}=#{v}"}.join("&")
|
70
|
-
command = "heroku addons:add deployhooks:http --url=\"#{url}\""
|
71
|
-
command += " --app #{ENV["HEROKU_APP"]}" if ENV["HEROKU_APP"]
|
72
|
-
|
73
|
-
puts "$ #{command}"
|
74
|
-
run_command.call(command)
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
|
-
end
|
79
|
-
|
80
|
-
task :load do
|
81
|
-
begin
|
82
|
-
Rake::Task["environment"].invoke
|
83
|
-
rescue
|
84
|
-
end
|
85
|
-
end
|
data/spec/deploy_spec.rb
DELETED
@@ -1,97 +0,0 @@
|
|
1
|
-
require 'webmock/rspec'
|
2
|
-
require 'rspec/expectations'
|
3
|
-
require 'rspec/mocks'
|
4
|
-
require 'logger'
|
5
|
-
require 'json'
|
6
|
-
|
7
|
-
require 'webrick'
|
8
|
-
|
9
|
-
require 'bugsnag-capistrano/deploy'
|
10
|
-
|
11
|
-
describe Bugsnag::Capistrano::Deploy do
|
12
|
-
describe "with notifier loadable", :with_notifier do
|
13
|
-
|
14
|
-
before do
|
15
|
-
require "bugsnag"
|
16
|
-
Bugsnag.configure do |config|
|
17
|
-
config.api_key = "TEST_API_KEY"
|
18
|
-
config.release_stage = "production"
|
19
|
-
config.logger = Logger.new(StringIO.new)
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
after do
|
24
|
-
Bugsnag.configuration.clear_request_data
|
25
|
-
end
|
26
|
-
|
27
|
-
it "should call notify_with_bugsnag" do
|
28
|
-
expect(Bugsnag::Delivery::Synchronous).to receive(:deliver).with(
|
29
|
-
"https://notify.bugsnag.com/deploy",
|
30
|
-
"{\"apiKey\":\"TEST_API_KEY\",\"releaseStage\":\"production\"}",
|
31
|
-
instance_of(Bugsnag::Configuration)
|
32
|
-
)
|
33
|
-
Bugsnag::Capistrano::Deploy.notify()
|
34
|
-
end
|
35
|
-
|
36
|
-
context "provide custom endpoint" do
|
37
|
-
before do
|
38
|
-
Bugsnag.configure do |config|
|
39
|
-
config.endpoint = "http://localhost:56302"
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
after do
|
44
|
-
Bugsnag.configure do |config|
|
45
|
-
config.endpoint = nil
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
it "uses the custom endpoint" do
|
50
|
-
expect(Bugsnag::Delivery::Synchronous).to receive(:deliver).with(
|
51
|
-
"http://localhost:56302/deploy",
|
52
|
-
"{\"apiKey\":\"TEST_API_KEY\",\"releaseStage\":\"production\"}",
|
53
|
-
instance_of(Bugsnag::Configuration)
|
54
|
-
)
|
55
|
-
Bugsnag::Capistrano::Deploy.notify()
|
56
|
-
end
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
describe "without notifier loadable", :without_notifier do
|
61
|
-
it "should call notify_without bugsnag" do
|
62
|
-
stub_request(:post, "https://notify.bugsnag.com/deploy").to_return(status:200, body: "")
|
63
|
-
expect(Bugsnag::Capistrano::Deploy).to receive(:deliver).with(
|
64
|
-
"https://notify.bugsnag.com/deploy",
|
65
|
-
"{\"apiKey\":\"test\"}"
|
66
|
-
)
|
67
|
-
Bugsnag::Capistrano::Deploy.notify({:api_key => "test"})
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
|
-
describe "the delivery function", :always do
|
72
|
-
it "delivers a request to the given url" do
|
73
|
-
url = "http://localhost:56456"
|
74
|
-
stub_request(:post, url)
|
75
|
-
.to_return(status:200, body: "")
|
76
|
-
Bugsnag::Capistrano::Deploy.deliver(url, nil)
|
77
|
-
end
|
78
|
-
|
79
|
-
it "delivers a body unmodified" do
|
80
|
-
body = ::JSON.dump({
|
81
|
-
"paramA" => 'a',
|
82
|
-
"paramB" => 'b',
|
83
|
-
"paramHash" => {
|
84
|
-
"one" => 1,
|
85
|
-
"two" => 2,
|
86
|
-
"three" => 3
|
87
|
-
}
|
88
|
-
})
|
89
|
-
url = "http://localhost:56456"
|
90
|
-
request = stub_request(:post, url)
|
91
|
-
.with(body: body, headers: { 'Content-Type' => 'application/json'})
|
92
|
-
.to_return(status:200, body: "")
|
93
|
-
Bugsnag::Capistrano::Deploy.deliver(url, body)
|
94
|
-
assert_requested request
|
95
|
-
end
|
96
|
-
end
|
97
|
-
end
|
data/spec/rake_spec.rb
DELETED
@@ -1,64 +0,0 @@
|
|
1
|
-
require 'webmock/rspec'
|
2
|
-
require 'rspec/expectations'
|
3
|
-
require 'rspec/mocks'
|
4
|
-
|
5
|
-
require 'webrick'
|
6
|
-
|
7
|
-
describe "bugsnag rake", :always do
|
8
|
-
|
9
|
-
server = nil
|
10
|
-
queue = Queue.new
|
11
|
-
fixture_path = '../examples/rake'
|
12
|
-
exec_string = 'bundle exec rake bugsnag:deploy'
|
13
|
-
example_path = File.join(File.dirname(__FILE__), fixture_path)
|
14
|
-
|
15
|
-
before do
|
16
|
-
server = WEBrick::HTTPServer.new :Port => 0, :Logger => WEBrick::Log.new(STDOUT), :AccessLog => []
|
17
|
-
server.mount_proc '/deploy' do |req, res|
|
18
|
-
queue.push req.body
|
19
|
-
res.status = 200
|
20
|
-
res.body = "OK\n"
|
21
|
-
end
|
22
|
-
Thread.new{ server.start }
|
23
|
-
end
|
24
|
-
|
25
|
-
after do
|
26
|
-
server.stop
|
27
|
-
queue.clear
|
28
|
-
end
|
29
|
-
|
30
|
-
let(:request) { JSON.parse(queue.pop) }
|
31
|
-
|
32
|
-
it "sends a deploy notification to the set endpoint" do
|
33
|
-
ENV['BUGSNAG_ENDPOINT'] = "http://localhost:" + server.config[:Port].to_s + "/deploy"
|
34
|
-
ENV['BUGSNAG_API_KEY'] = "YOUR_API_KEY"
|
35
|
-
|
36
|
-
Dir.chdir(example_path) do
|
37
|
-
system(exec_string)
|
38
|
-
end
|
39
|
-
|
40
|
-
payload = request()
|
41
|
-
expect(payload["apiKey"]).to eq('YOUR_API_KEY')
|
42
|
-
end
|
43
|
-
|
44
|
-
it "allows modifications of deployment characteristics" do
|
45
|
-
ENV['BUGSNAG_ENDPOINT'] = "http://localhost:" + server.config[:Port].to_s + "/deploy"
|
46
|
-
ENV['BUGSNAG_API_KEY'] = "this is a test key"
|
47
|
-
ENV['BUGSNAG_RELEASE_STAGE'] = "test"
|
48
|
-
ENV['BUGSNAG_REVISION'] = "test"
|
49
|
-
ENV['BUGSNAG_APP_VERSION'] = "1"
|
50
|
-
ENV['BUGSNAG_REPOSITORY'] = "test@repo.com:test/test_repo.git"
|
51
|
-
|
52
|
-
Dir.chdir(example_path) do
|
53
|
-
system(exec_string)
|
54
|
-
end
|
55
|
-
|
56
|
-
payload = request()
|
57
|
-
expect(payload["apiKey"]).to eq('this is a test key')
|
58
|
-
expect(payload["releaseStage"]).to eq('test')
|
59
|
-
expect(payload["repository"]).to eq("test@repo.com:test/test_repo.git")
|
60
|
-
expect(payload["appVersion"]).to eq("1")
|
61
|
-
expect(payload["revision"]).to eq("test")
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|