bugsnag-api 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +52 -0
- data/Rakefile +1 -0
- data/bugsnag-api.gemspec +25 -0
- data/lib/bugsnag/api.rb +29 -0
- data/lib/bugsnag/api/client.rb +200 -0
- data/lib/bugsnag/api/client/accounts.rb +37 -0
- data/lib/bugsnag/api/client/comments.rb +64 -0
- data/lib/bugsnag/api/client/errors.rb +75 -0
- data/lib/bugsnag/api/client/events.rb +54 -0
- data/lib/bugsnag/api/client/projects.rb +77 -0
- data/lib/bugsnag/api/client/users.rb +81 -0
- data/lib/bugsnag/api/configuration.rb +48 -0
- data/lib/bugsnag/api/error.rb +121 -0
- data/lib/bugsnag/api/response/raise_error.rb +22 -0
- data/lib/bugsnag/api/version.rb +5 -0
- metadata +105 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 4f70dd5425512569c5778aa3a89d852326195967
|
4
|
+
data.tar.gz: 254567403bf2c32834d25a7b4c23696f33748467
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 67c60e4aae21b293ad5b75b2cb60d26ba2774c43d512c49d3a140fd82b6f43d10de5739eec93ac7edceb481939bd86b1bdb80c92a952b5030f01e111ec6b1f29
|
7
|
+
data.tar.gz: 4b154b2bc908b61db969e19afc53a3f09f12a756d66292562d9d8a6a9fc9f2e7b60a0b1ac173404cb1d5099120dde7b41c5f0aadfa8641d771e247efefa4e357
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Bugsnag Inc.
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
Bugsnag API Ruby Toolkit
|
2
|
+
========================
|
3
|
+
|
4
|
+
The library allows for quick read-write access to the [Bugsnag API](https://bugsnag.com/docs/api) from Ruby applications. Use this library if you want to build your own applications which leverage data found in your Bugsnag dashboard. If you are looking to automatically detect crashes in your Ruby apps, you should take a look at the [Bugsnag Ruby Detection Library](https://bugsnag.com/docs/notifiers/ruby) instead.
|
5
|
+
|
6
|
+
This library shares code and philosophies with the fantastic [Octokit](https://github.com/octokit/octokit.rb) library.
|
7
|
+
|
8
|
+
|
9
|
+
## Installation
|
10
|
+
|
11
|
+
Add this line to your application's Gemfile:
|
12
|
+
|
13
|
+
gem "bugsnag-api"
|
14
|
+
|
15
|
+
And then execute:
|
16
|
+
|
17
|
+
$ bundle
|
18
|
+
|
19
|
+
Or install it yourself as:
|
20
|
+
|
21
|
+
$ gem install bugsnag-api
|
22
|
+
|
23
|
+
|
24
|
+
## Usage
|
25
|
+
|
26
|
+
```ruby
|
27
|
+
# Configure a Bugsnag API client
|
28
|
+
Bugsnag::Api.configure do |config|
|
29
|
+
config.api_token = "your-account-api-token"
|
30
|
+
end
|
31
|
+
|
32
|
+
# Fetch information about the authenticated account
|
33
|
+
account = Bugsnag::Api.account
|
34
|
+
|
35
|
+
# Get a list of users on this account
|
36
|
+
users = Bugsnag::Api.users(account.id)
|
37
|
+
|
38
|
+
# Get a list of the projects on this account
|
39
|
+
projects = Bugsnag::Api.projects(account.id)
|
40
|
+
|
41
|
+
# Get a list of errors on a project
|
42
|
+
errors = Bugsnag::Api.errors(projects.first.id)
|
43
|
+
```
|
44
|
+
|
45
|
+
|
46
|
+
## Contributing
|
47
|
+
|
48
|
+
1. Fork it
|
49
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
50
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
51
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
52
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/bugsnag-api.gemspec
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'bugsnag/api/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "bugsnag-api"
|
8
|
+
spec.version = Bugsnag::Api::VERSION
|
9
|
+
spec.authors = ["James Smith"]
|
10
|
+
spec.email = ["james@bugsnag.com"]
|
11
|
+
spec.description = %q{Bugsnag API toolkit for ruby}
|
12
|
+
spec.summary = %q{Bugsnag API toolkit for ruby}
|
13
|
+
spec.homepage = "https://github.com/bugsnag/bugsnag-api-ruby"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_dependency "sawyer", '~> 0.5.3'
|
22
|
+
|
23
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
24
|
+
spec.add_development_dependency "rake"
|
25
|
+
end
|
data/lib/bugsnag/api.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
require "bugsnag/api/client"
|
2
|
+
require "bugsnag/api/configuration"
|
3
|
+
require "bugsnag/api/error"
|
4
|
+
require "bugsnag/api/version"
|
5
|
+
|
6
|
+
module Bugsnag
|
7
|
+
module Api
|
8
|
+
class << self
|
9
|
+
def configure
|
10
|
+
yield(configuration) if block_given?
|
11
|
+
end
|
12
|
+
|
13
|
+
def configuration
|
14
|
+
@configuration ||= Bugsnag::Api::Configuration.new
|
15
|
+
end
|
16
|
+
|
17
|
+
def client
|
18
|
+
@client ||= Bugsnag::Api::Client.new(configuration)
|
19
|
+
end
|
20
|
+
|
21
|
+
|
22
|
+
private
|
23
|
+
def method_missing(method_name, *args, &block)
|
24
|
+
return super unless client.respond_to?(method_name)
|
25
|
+
client.send(method_name, *args, &block)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,200 @@
|
|
1
|
+
require "sawyer"
|
2
|
+
|
3
|
+
require "bugsnag/api/client/accounts"
|
4
|
+
require "bugsnag/api/client/comments"
|
5
|
+
require "bugsnag/api/client/errors"
|
6
|
+
require "bugsnag/api/client/events"
|
7
|
+
require "bugsnag/api/client/projects"
|
8
|
+
require "bugsnag/api/client/users"
|
9
|
+
|
10
|
+
module Bugsnag
|
11
|
+
module Api
|
12
|
+
|
13
|
+
# Client for the Bugsnag API
|
14
|
+
#
|
15
|
+
# @see https://bugsnag.com/docs/api
|
16
|
+
class Client
|
17
|
+
include Bugsnag::Api::Client::Accounts
|
18
|
+
include Bugsnag::Api::Client::Comments
|
19
|
+
include Bugsnag::Api::Client::Errors
|
20
|
+
include Bugsnag::Api::Client::Events
|
21
|
+
include Bugsnag::Api::Client::Projects
|
22
|
+
include Bugsnag::Api::Client::Users
|
23
|
+
|
24
|
+
# Header keys that can be passed in options hash to {#get},{#head}
|
25
|
+
CONVENIENCE_HEADERS = Set.new([:accept, :content_type])
|
26
|
+
|
27
|
+
def initialize(options = {})
|
28
|
+
if options.is_a?(Bugsnag::Api::Configuration)
|
29
|
+
@configuration = options
|
30
|
+
else
|
31
|
+
configuration.load(options)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def configuration
|
36
|
+
@configuration ||= Configuration.new
|
37
|
+
end
|
38
|
+
|
39
|
+
# Make a HTTP GET request
|
40
|
+
#
|
41
|
+
# @param url [String] The path, relative to {#endpoint}
|
42
|
+
# @param options [Hash] Query and header params for request
|
43
|
+
# @return [Sawyer::Resource]
|
44
|
+
def get(url, options = {})
|
45
|
+
request :get, url, parse_query_and_convenience_headers(options)
|
46
|
+
end
|
47
|
+
|
48
|
+
# Make a HTTP POST request
|
49
|
+
#
|
50
|
+
# @param url [String] The path, relative to {#endpoint}
|
51
|
+
# @param options [Hash] Body and header params for request
|
52
|
+
# @return [Sawyer::Resource]
|
53
|
+
def post(url, options = {})
|
54
|
+
request :post, url, options
|
55
|
+
end
|
56
|
+
|
57
|
+
# Make a HTTP PUT request
|
58
|
+
#
|
59
|
+
# @param url [String] The path, relative to {#endpoint}
|
60
|
+
# @param options [Hash] Body and header params for request
|
61
|
+
# @return [Sawyer::Resource]
|
62
|
+
def put(url, options = {})
|
63
|
+
request :put, url, options
|
64
|
+
end
|
65
|
+
|
66
|
+
# Make a HTTP PATCH request
|
67
|
+
#
|
68
|
+
# @param url [String] The path, relative to {#endpoint}
|
69
|
+
# @param options [Hash] Body and header params for request
|
70
|
+
# @return [Sawyer::Resource]
|
71
|
+
def patch(url, options = {})
|
72
|
+
request :patch, url, options
|
73
|
+
end
|
74
|
+
|
75
|
+
# Make a HTTP DELETE request
|
76
|
+
#
|
77
|
+
# @param url [String] The path, relative to {#endpoint}
|
78
|
+
# @param options [Hash] Query and header params for request
|
79
|
+
# @return [Sawyer::Resource]
|
80
|
+
def delete(url, options = {})
|
81
|
+
request :delete, url, options
|
82
|
+
end
|
83
|
+
|
84
|
+
# Make a HTTP HEAD request
|
85
|
+
#
|
86
|
+
# @param url [String] The path, relative to {#endpoint}
|
87
|
+
# @param options [Hash] Query and header params for request
|
88
|
+
# @return [Sawyer::Resource]
|
89
|
+
def head(url, options = {})
|
90
|
+
request :head, url, parse_query_and_convenience_headers(options)
|
91
|
+
end
|
92
|
+
|
93
|
+
# Make one or more HTTP GET requests, optionally fetching
|
94
|
+
# the next page of results from URL in Link response header based
|
95
|
+
# on value in {#auto_paginate}.
|
96
|
+
#
|
97
|
+
# @param url [String] The path, relative to {#endpoint}
|
98
|
+
# @param options [Hash] Query and header params for request
|
99
|
+
# @param block [Block] Block to perform the data concatination of the
|
100
|
+
# multiple requests. The block is called with two parameters, the first
|
101
|
+
# contains the contents of the requests so far and the second parameter
|
102
|
+
# contains the latest response.
|
103
|
+
# @return [Sawyer::Resource]
|
104
|
+
def paginate(url, options = {}, &block)
|
105
|
+
opts = parse_query_and_convenience_headers(options.dup)
|
106
|
+
if configuration.auto_paginate || configuration.per_page
|
107
|
+
opts[:query][:per_page] ||= configuration.per_page || (configuration.auto_paginate ? 100 : nil)
|
108
|
+
end
|
109
|
+
|
110
|
+
data = request(:get, url, opts)
|
111
|
+
|
112
|
+
if configuration.auto_paginate
|
113
|
+
while @last_response.rels[:next]
|
114
|
+
@last_response = @last_response.rels[:next].get
|
115
|
+
if block_given?
|
116
|
+
yield(data, @last_response)
|
117
|
+
else
|
118
|
+
data.concat(@last_response.data) if @last_response.data.is_a?(Array)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
data
|
124
|
+
end
|
125
|
+
|
126
|
+
# Hypermedia agent for the Bugsnag API
|
127
|
+
#
|
128
|
+
# @return [Sawyer::Agent]
|
129
|
+
def agent
|
130
|
+
@agent ||= Sawyer::Agent.new(configuration.endpoint, sawyer_options) do |http|
|
131
|
+
http.headers[:content_type] = "application/json"
|
132
|
+
http.headers[:user_agent] = configuration.user_agent
|
133
|
+
|
134
|
+
if basic_authenticated?
|
135
|
+
http.basic_auth configuration.email, configuration.password
|
136
|
+
elsif token_authenticated?
|
137
|
+
http.authorization "token", configuration.api_token
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
# Response for last HTTP request
|
143
|
+
#
|
144
|
+
# @return [Sawyer::Response]
|
145
|
+
def last_response
|
146
|
+
@last_response if defined? @last_response
|
147
|
+
end
|
148
|
+
|
149
|
+
def basic_authenticated?
|
150
|
+
!!(configuration.email && configuration.password)
|
151
|
+
end
|
152
|
+
|
153
|
+
def token_authenticated?
|
154
|
+
!!configuration.api_token
|
155
|
+
end
|
156
|
+
|
157
|
+
|
158
|
+
private
|
159
|
+
def request(method, path, data, options = {})
|
160
|
+
if data.is_a?(Hash)
|
161
|
+
options[:query] = data.delete(:query) || {}
|
162
|
+
options[:headers] = data.delete(:headers) || {}
|
163
|
+
if accept = data.delete(:accept)
|
164
|
+
options[:headers][:accept] = accept
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
@last_response = response = agent.call(method, URI::Parser.new.escape(path.to_s), data, options)
|
169
|
+
response.data
|
170
|
+
end
|
171
|
+
|
172
|
+
def sawyer_options
|
173
|
+
opts = {
|
174
|
+
:links_parser => Sawyer::LinkParsers::Simple.new
|
175
|
+
}
|
176
|
+
conn_opts = configuration.connection_options
|
177
|
+
conn_opts[:builder] = configuration.middleware if configuration.middleware
|
178
|
+
conn_opts[:proxy] = configuration.proxy if configuration.proxy
|
179
|
+
opts[:faraday] = Faraday.new(conn_opts)
|
180
|
+
|
181
|
+
opts
|
182
|
+
end
|
183
|
+
|
184
|
+
def parse_query_and_convenience_headers(options)
|
185
|
+
headers = options.fetch(:headers, {})
|
186
|
+
CONVENIENCE_HEADERS.each do |h|
|
187
|
+
if header = options.delete(h)
|
188
|
+
headers[h] = header
|
189
|
+
end
|
190
|
+
end
|
191
|
+
query = options.delete(:query)
|
192
|
+
opts = {:query => options}
|
193
|
+
opts[:query].merge!(query) if query && query.is_a?(Hash)
|
194
|
+
opts[:headers] = headers unless headers.empty?
|
195
|
+
|
196
|
+
opts
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|
200
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Bugsnag
|
2
|
+
module Api
|
3
|
+
class Client
|
4
|
+
|
5
|
+
# Methods for the Accounts API
|
6
|
+
#
|
7
|
+
# @see https://bugsnag.com/docs/api/accounts
|
8
|
+
module Accounts
|
9
|
+
# List your accounts
|
10
|
+
#
|
11
|
+
# @return [Array<Sawyer::Resource>] List of users
|
12
|
+
# @see https://bugsnag.com/docs/api/accounts#list-your-accounts
|
13
|
+
# @example
|
14
|
+
# Bugsnag::Api.accounts
|
15
|
+
def accounts(options = {})
|
16
|
+
paginate "accounts", options
|
17
|
+
end
|
18
|
+
|
19
|
+
# Get a single account
|
20
|
+
#
|
21
|
+
# @param account [String] Bugsnag account id
|
22
|
+
# @return [Sawyer::Resource]
|
23
|
+
# @see https://bugsnag.com/docs/api/accounts#get-the-authenticated-account
|
24
|
+
# @see https://bugsnag.com/docs/api/accounts#get-account-details
|
25
|
+
# @example
|
26
|
+
# Bugsnag::Api.account("515fb9337c1074f6fd000009")
|
27
|
+
def account(account=nil, options = {})
|
28
|
+
if account.nil?
|
29
|
+
get "account", options
|
30
|
+
else
|
31
|
+
get "accounts/#{account}", options
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
module Bugsnag
|
2
|
+
module Api
|
3
|
+
class Client
|
4
|
+
|
5
|
+
# Methods for the Comments API
|
6
|
+
#
|
7
|
+
# @see https://bugsnag.com/docs/api/comments
|
8
|
+
module Comments
|
9
|
+
# List an error's comments
|
10
|
+
#
|
11
|
+
# @param error [String] Bugsnag error for which to list comments
|
12
|
+
# @return [Array<Sawyer::Resource>] List of comments
|
13
|
+
# @see https://bugsnag.com/docs/api/comments#list-an-error-s-comments
|
14
|
+
# @example
|
15
|
+
# Bugsnag::Api.comments("515fb9337c1074f6fd000009")
|
16
|
+
def comments(error, options = {})
|
17
|
+
paginate "errors/#{error}/comments", options
|
18
|
+
end
|
19
|
+
|
20
|
+
# Get a single comment
|
21
|
+
#
|
22
|
+
# @param comment [String] A Bugsnag comment ID
|
23
|
+
# @return [Sawyer::Resource] The comment you requested, if it exists
|
24
|
+
# @see https://bugsnag.com/docs/api/comments#get-comment-details
|
25
|
+
# @example
|
26
|
+
# Bugsnag::Api.comment("50baed119bf39c1431000004")
|
27
|
+
def comment(comment, options = {})
|
28
|
+
get "comments/#{comment}", options
|
29
|
+
end
|
30
|
+
|
31
|
+
# Create a comment
|
32
|
+
#
|
33
|
+
# @param error [String] The Bugsnag error to create the comment on
|
34
|
+
# @option message [String] The comment's message
|
35
|
+
# @see https://bugsnag.com/docs/api/comments#create-a-comment
|
36
|
+
# @example
|
37
|
+
# Bugsnag::Api.create_comment("515fb9337c1074f6fd000009", message: "Oops!")
|
38
|
+
def create_comment(error, message, options = {})
|
39
|
+
post "errors/#{error}/comments", options.merge({:message => message})
|
40
|
+
end
|
41
|
+
|
42
|
+
# Update a comment
|
43
|
+
#
|
44
|
+
# @param error [String] The Bugsnag comment to update
|
45
|
+
# @return [Sawyer::Resource] The updated comment
|
46
|
+
# @see https://bugsnag.com/docs/api/comments#update-a-comment
|
47
|
+
# @example
|
48
|
+
# Bugsnag::Api.update_comment("50baed119bf39c1431000004", message: "Fixed!")
|
49
|
+
def update_comment(comment, message, options = {})
|
50
|
+
patch "comments/#{comment}", options.merge({:message => message})
|
51
|
+
end
|
52
|
+
|
53
|
+
# Delete a comment
|
54
|
+
#
|
55
|
+
# @param comment [String] The Bugsnag comment to delete
|
56
|
+
# @return [Boolean] `true` if comment was deleted
|
57
|
+
# @see https://bugsnag.com/docs/api/comments#delete-a-comment
|
58
|
+
def delete_comment(comment, options = {})
|
59
|
+
delete "comments/#{comment}", options
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
module Bugsnag
|
2
|
+
module Api
|
3
|
+
class Client
|
4
|
+
|
5
|
+
# Methods for the Errors API
|
6
|
+
#
|
7
|
+
# @see https://bugsnag.com/docs/api/errors
|
8
|
+
module Errors
|
9
|
+
# List a project's errors
|
10
|
+
#
|
11
|
+
# @param project [String] Bugsnag project for which to list errors
|
12
|
+
# @return [Array<Sawyer::Resource>] List of errors
|
13
|
+
# @see https://bugsnag.com/docs/api/errors#list-a-project-s-errors
|
14
|
+
# @example
|
15
|
+
# Bugsnag::Api.errors("50baed119bf39c1431000004")
|
16
|
+
def errors(project, options = {})
|
17
|
+
paginate "projects/#{project}/errors", options
|
18
|
+
end
|
19
|
+
|
20
|
+
# Get a single error
|
21
|
+
#
|
22
|
+
# @param error [String] A Bugsnag error
|
23
|
+
# @return [Sawyer::Resource] The error you requested, if it exists
|
24
|
+
# @see https://bugsnag.com/docs/api/errors#get-error-details
|
25
|
+
# @example
|
26
|
+
# Bugsnag::Api.error("518031bcd775355c48a1cd4e")
|
27
|
+
def error(error, options = {})
|
28
|
+
get "errors/#{error}", options
|
29
|
+
end
|
30
|
+
|
31
|
+
# Resolve an error
|
32
|
+
#
|
33
|
+
# @param error [String] A Bugsnag error
|
34
|
+
# @return [Sawyer::Resource] The updated error
|
35
|
+
# @see https://bugsnag.com/docs/api/errors#update-an-error-s-status
|
36
|
+
# @example
|
37
|
+
# Bugsnag::Api.resolve_error("518031bcd775355c48a1cd4e")
|
38
|
+
def resolve_error(error, options = {})
|
39
|
+
patch "errors/#{error}", options.merge({:resolved => true})
|
40
|
+
end
|
41
|
+
|
42
|
+
# Re-open an error
|
43
|
+
#
|
44
|
+
# @param error [String] A Bugsnag error
|
45
|
+
# @return [Sawyer::Resource] The updated error
|
46
|
+
# @see https://bugsnag.com/docs/api/errors#update-an-error-s-status
|
47
|
+
# @example
|
48
|
+
# Bugsnag::Api.reopen_error("518031bcd775355c48a1cd4e")
|
49
|
+
def reopen_error(error, options = {})
|
50
|
+
patch "errors/#{error}", options.merge({:resolved => false})
|
51
|
+
end
|
52
|
+
|
53
|
+
# Update an error
|
54
|
+
#
|
55
|
+
# @param error [String] A Bugsnag error
|
56
|
+
# @return [Sawyer::Resource] The updated error
|
57
|
+
# @see https://bugsnag.com/docs/api/errors#update-an-error-s-status
|
58
|
+
# @example
|
59
|
+
# Bugsnag::Api.update_error("518031bcd775355c48a1cd4e")
|
60
|
+
def update_error(error, options = {})
|
61
|
+
patch "errors/#{error}", options
|
62
|
+
end
|
63
|
+
|
64
|
+
# Delete an error
|
65
|
+
#
|
66
|
+
# @param error [String] A Bugsnag error
|
67
|
+
# @return [Boolean] `true` if error was deleted
|
68
|
+
# @see https://bugsnag.com/docs/api/errors#delete-an-error
|
69
|
+
def delete_error(error, options = {})
|
70
|
+
delete "errors/#{error}", options
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module Bugsnag
|
2
|
+
module Api
|
3
|
+
class Client
|
4
|
+
|
5
|
+
# Methods for the Events API
|
6
|
+
#
|
7
|
+
# @see https://bugsnag.com/docs/api/events
|
8
|
+
module Events
|
9
|
+
# List a project's events
|
10
|
+
#
|
11
|
+
# @param project [String] Bugsnag project for which to list events
|
12
|
+
# @return [Array<Sawyer::Resource>] List of events
|
13
|
+
# @see https://bugsnag.com/docs/api/events#list-a-project-s-events
|
14
|
+
# @example
|
15
|
+
# Bugsnag::Api.events("50baed119bf39c1431000004")
|
16
|
+
def events(project, options = {})
|
17
|
+
paginate "projects/#{project}/events", options
|
18
|
+
end
|
19
|
+
alias :project_events :events
|
20
|
+
|
21
|
+
# List an error's events
|
22
|
+
#
|
23
|
+
# @param error [String] Bugsnag error for which to list events
|
24
|
+
# @return [Array<Sawyer::Resource>] List of events
|
25
|
+
# @see https://bugsnag.com/docs/api/events#list-an-error-s-events
|
26
|
+
# @example
|
27
|
+
# Bugsnag::Api.error_events("518031bcd775355c48a1cd4e")
|
28
|
+
def error_events(error, options = {})
|
29
|
+
paginate "error/#{error}/events", options
|
30
|
+
end
|
31
|
+
|
32
|
+
# Get a single event
|
33
|
+
#
|
34
|
+
# @param event [String] A Bugsnag event id
|
35
|
+
# @return [Sawyer::Resource] The event you requested, if it exists
|
36
|
+
# @see https://bugsnag.com/docs/api/events#get-event-details
|
37
|
+
# @example
|
38
|
+
# Bugsnag::Api.event("51f5d152f002c6686d013a22")
|
39
|
+
def event(error, options = {})
|
40
|
+
get "events/#{event}", options
|
41
|
+
end
|
42
|
+
|
43
|
+
# Delete an event
|
44
|
+
#
|
45
|
+
# @param event [String] A Bugsnag event
|
46
|
+
# @return [Boolean] `true` if event was deleted
|
47
|
+
# @see https://bugsnag.com/docs/api/events#delete-an-event
|
48
|
+
def delete_event(event, options = {})
|
49
|
+
delete "events/#{event}", options
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
module Bugsnag
|
2
|
+
module Api
|
3
|
+
class Client
|
4
|
+
|
5
|
+
# Methods for the Projects API
|
6
|
+
#
|
7
|
+
# @see https://bugsnag.com/docs/api/projects
|
8
|
+
module Projects
|
9
|
+
# List account projects
|
10
|
+
#
|
11
|
+
# @param account [String] Bugsnag account for which to list projects
|
12
|
+
# @return [Array<Sawyer::Resource>] List of projects
|
13
|
+
# @see https://bugsnag.com/docs/api/projects#list-an-account-s-projects
|
14
|
+
# @example
|
15
|
+
# Bugsnag::Api.projects("515fb9337c1074f6fd000009")
|
16
|
+
def projects(account, options = {})
|
17
|
+
paginate "accounts/#{account}/projects", options
|
18
|
+
end
|
19
|
+
alias :account_projects :projects
|
20
|
+
|
21
|
+
# List user projects
|
22
|
+
#
|
23
|
+
# @param account [String] Bugsnag user for which to list projects
|
24
|
+
# @return [Array<Sawyer::Resource>] List of projects
|
25
|
+
# @see https://bugsnag.com/docs/api/projects#list-a-user-s-projects
|
26
|
+
# @example
|
27
|
+
# Bugsnag::Api.user_projects("515fb9337c1074f6fd000007")
|
28
|
+
def user_projects(user, options = {})
|
29
|
+
paginate "user/#{user}/projects", options
|
30
|
+
end
|
31
|
+
|
32
|
+
# Get a single project
|
33
|
+
#
|
34
|
+
# @param project [String] A Bugsnag project
|
35
|
+
# @return [Sawyer::Resource] The project you requested, if it exists
|
36
|
+
# @see https://bugsnag.com/docs/api/projects#get-project-details
|
37
|
+
# @example
|
38
|
+
# Bugsnag::Api.project("50baed119bf39c1431000004")
|
39
|
+
def project(project, options = {})
|
40
|
+
get "projects/#{project}", options
|
41
|
+
end
|
42
|
+
|
43
|
+
# Create a project
|
44
|
+
#
|
45
|
+
# @param account [String] The Bugsnag account to create project on
|
46
|
+
# @option name [String] The project's name
|
47
|
+
# @option type [String] The type of the project
|
48
|
+
# @see https://bugsnag.com/docs/api/projects#create-a-project
|
49
|
+
# @example
|
50
|
+
# Bugsnag::Api.create_project("515fb9337c1074f6fd000009", name: "Website")
|
51
|
+
def create_project(account, options = {})
|
52
|
+
post "accounts/#{account}/projects", options
|
53
|
+
end
|
54
|
+
|
55
|
+
# Update a project
|
56
|
+
#
|
57
|
+
# @param project [String] A Bugsnag project
|
58
|
+
# @return [Sawyer::Resource] The updated project
|
59
|
+
# @see https://bugsnag.com/docs/api/projects#update-a-project
|
60
|
+
# @example
|
61
|
+
# Bugsnag::Api.update_project("50baed119bf39c1431000004", name: "Dashboard")
|
62
|
+
def update_project(project, options = {})
|
63
|
+
patch "projects/#{project}", options
|
64
|
+
end
|
65
|
+
|
66
|
+
# Delete a project
|
67
|
+
#
|
68
|
+
# @param project [String] A Bugsnag project
|
69
|
+
# @return [Boolean] `true` if project was deleted
|
70
|
+
# @see https://bugsnag.com/docs/api/projects#delete-a-project
|
71
|
+
def delete_project(project, options = {})
|
72
|
+
delete "projects/#{project}", options
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
module Bugsnag
|
2
|
+
module Api
|
3
|
+
class Client
|
4
|
+
|
5
|
+
# Methods for the Users API
|
6
|
+
#
|
7
|
+
# @see https://bugsnag.com/docs/api/users
|
8
|
+
module Users
|
9
|
+
# List account users
|
10
|
+
#
|
11
|
+
# @param account [String] Bugsnag account for which to list users
|
12
|
+
# @return [Array<Sawyer::Resource>] List of users
|
13
|
+
# @see https://bugsnag.com/docs/api/users#list-an-account-s-users
|
14
|
+
def users(account, options = {})
|
15
|
+
paginate "accounts/#{account}/users", options
|
16
|
+
end
|
17
|
+
alias :account_users :users
|
18
|
+
|
19
|
+
# List project users
|
20
|
+
#
|
21
|
+
# @param account [String] Bugsnag account for which to list users
|
22
|
+
# @return [Array<Sawyer::Resource>] List of users
|
23
|
+
# @see https://bugsnag.com/docs/api/users#list-an-project-s-users
|
24
|
+
def project_users(project, options = {})
|
25
|
+
paginate "projects/#{project}/users", options
|
26
|
+
end
|
27
|
+
|
28
|
+
# Get a single user
|
29
|
+
#
|
30
|
+
# @param user [String] Bugsnag user id.
|
31
|
+
# @return [Sawyer::Resource]
|
32
|
+
# @see https://bugsnag.com/docs/api/users#get-the-authenticated-user
|
33
|
+
# @see https://bugsnag.com/docs/api/users#get-user-details
|
34
|
+
# @example
|
35
|
+
# Bugsnag::Api.user("515fb9337c1074f6fd000007")
|
36
|
+
def user(user=nil, options = {})
|
37
|
+
if user.nil?
|
38
|
+
get "user", options
|
39
|
+
else
|
40
|
+
get "users/#{user}", options
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
# Invite a user to an account
|
45
|
+
#
|
46
|
+
# @param account [String] Bugsnag account to invite user to.
|
47
|
+
# @option email [String] The email address of the invitee
|
48
|
+
# @option admin [Boolean] Should the invitee be an account admin?
|
49
|
+
# @option project_ids [Array<String>] Array of accessible project ids
|
50
|
+
# @see https://bugsnag.com/docs/api/users#invite-a-user-to-an-account
|
51
|
+
# @example
|
52
|
+
# Bugsnag::Api.invite_user("515fb9337c1074f6fd000009", "james@example.com")
|
53
|
+
def invite_user(account, email, options = {})
|
54
|
+
post "accounts/#{account}/users", options.merge({:email => email})
|
55
|
+
end
|
56
|
+
|
57
|
+
# Update a user's account permissions
|
58
|
+
#
|
59
|
+
# @param account [String] Bugsnag account to update pemissions for
|
60
|
+
# @param user {String} Bugsnag user to update permissions for
|
61
|
+
# @see https://bugsnag.com/docs/api/users#update-a-user-s-account-permissions
|
62
|
+
# @example
|
63
|
+
# Bugsnag::Api.update_user_permissions("515fb9337c1074f6fd000009", "515fb9337c1074f6fd000007", admin: false)
|
64
|
+
def update_user_permissions(account, user, options = {})
|
65
|
+
patch "accounts/#{account}/users/#{user}", options
|
66
|
+
end
|
67
|
+
|
68
|
+
# Remove a user from an account
|
69
|
+
#
|
70
|
+
# @param account [String] Bugsnag account to remove user from
|
71
|
+
# @param user [String] Bugsnag user to remove
|
72
|
+
# @see https://bugsnag.com/docs/api/users#delete-a-user-from-an-account
|
73
|
+
# @example
|
74
|
+
# Bugsnag::Api.remove_user("515fb9337c1074f6fd000009", "515fb9337c1074f6fd000007")
|
75
|
+
def remove_user(account, user, options = {})
|
76
|
+
delete "accounts/#{account}/users/#{user}", options
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require "bugsnag/api/response/raise_error"
|
2
|
+
|
3
|
+
module Bugsnag
|
4
|
+
module Api
|
5
|
+
|
6
|
+
# Configuration storage and defaults for {Client}
|
7
|
+
class Configuration
|
8
|
+
|
9
|
+
# Default API endpoint
|
10
|
+
DEFAULT_ENDPOINT = "https://api.bugsnag.com"
|
11
|
+
|
12
|
+
# Default User Agent header string
|
13
|
+
DEFAULT_USER_AGENT = "Bugsnag API Ruby Gem #{Bugsnag::Api::VERSION}"
|
14
|
+
|
15
|
+
# In Faraday 0.9, Faraday::Builder was renamed to Faraday::RackBuilder
|
16
|
+
RACK_BUILDER_CLASS = defined?(Faraday::RackBuilder) ? Faraday::RackBuilder : Faraday::Builder
|
17
|
+
|
18
|
+
# Default Faraday middleware stack
|
19
|
+
DEFAULT_MIDDLEWARE = RACK_BUILDER_CLASS.new do |builder|
|
20
|
+
builder.use Bugsnag::Api::Response::RaiseError
|
21
|
+
builder.adapter Faraday.default_adapter
|
22
|
+
end
|
23
|
+
|
24
|
+
# Configuration options
|
25
|
+
attr_accessor :email, :password, :api_token, :endpoint, :user_agent,
|
26
|
+
:proxy, :middleware, :connection_options, :auto_paginate,
|
27
|
+
:per_page
|
28
|
+
|
29
|
+
# Set up configuration defaults
|
30
|
+
def initialize
|
31
|
+
@endpoint = DEFAULT_ENDPOINT
|
32
|
+
@user_agent = DEFAULT_USER_AGENT
|
33
|
+
@middleware = DEFAULT_MIDDLEWARE
|
34
|
+
@auto_paginate = false
|
35
|
+
@connection_options = {
|
36
|
+
:headers => {
|
37
|
+
:user_agent => DEFAULT_USER_AGENT
|
38
|
+
}
|
39
|
+
}
|
40
|
+
end
|
41
|
+
|
42
|
+
# Load configuration from hash
|
43
|
+
def load(options = {})
|
44
|
+
options.each {|k,v| self.send("#{k}=", v) if self.respond_to?("#{k}=")}
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,121 @@
|
|
1
|
+
module Bugsnag
|
2
|
+
module Api
|
3
|
+
# Custom error class for rescuing from all Bugsnag API errors
|
4
|
+
class Error < StandardError
|
5
|
+
|
6
|
+
# Returns the appropriate Bugnsag::Api::Error subclass based
|
7
|
+
# on status and response message
|
8
|
+
#
|
9
|
+
# @param [Hash] response HTTP response
|
10
|
+
# @return [Octokit::Error]
|
11
|
+
def self.from_response(response)
|
12
|
+
status = response[:status].to_i
|
13
|
+
body = response[:body].to_s
|
14
|
+
headers = response[:response_headers]
|
15
|
+
|
16
|
+
if klass = case status
|
17
|
+
when 400 then Bugsnag::Api::BadRequest
|
18
|
+
when 401 then Bugsnag::Api::Unauthorized
|
19
|
+
when 403 then Bugsnag::Api::Forbidden
|
20
|
+
when 404 then Bugsnag::Api::NotFound
|
21
|
+
when 405 then Bugsnag::Api::MethodNotAllowed
|
22
|
+
when 406 then Bugsnag::Api::NotAcceptable
|
23
|
+
when 409 then Bugsnag::Api::Conflict
|
24
|
+
when 415 then Bugsnag::Api::UnsupportedMediaType
|
25
|
+
when 422 then Bugsnag::Api::UnprocessableEntity
|
26
|
+
when 400..499 then Bugsnag::Api::ClientError
|
27
|
+
when 500 then Bugsnag::Api::InternalServerError
|
28
|
+
when 501 then Bugsnag::Api::NotImplemented
|
29
|
+
when 502 then Bugsnag::Api::BadGateway
|
30
|
+
when 503 then Bugsnag::Api::ServiceUnavailable
|
31
|
+
when 500..599 then Bugsnag::Api::ServerError
|
32
|
+
end
|
33
|
+
klass.new(response)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def initialize(response=nil)
|
38
|
+
@response = response
|
39
|
+
super(response_error)
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
def data
|
45
|
+
@data ||=
|
46
|
+
if (body = @response[:body]) && !body.empty?
|
47
|
+
if body.is_a?(String) &&
|
48
|
+
@response[:response_headers] &&
|
49
|
+
@response[:response_headers][:content_type] =~ /json/
|
50
|
+
|
51
|
+
Sawyer::Agent.serializer.decode(body)
|
52
|
+
else
|
53
|
+
body
|
54
|
+
end
|
55
|
+
else
|
56
|
+
nil
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def response_error
|
61
|
+
"Error: #{data[:error]}" if data.is_a?(Hash) && data[:error]
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
# Raised on errors in the 400-499 range
|
66
|
+
class ClientError < Error; end
|
67
|
+
|
68
|
+
# Raised when Bugsnag returns a 400 HTTP status code
|
69
|
+
class BadRequest < ClientError; end
|
70
|
+
|
71
|
+
# Raised when Bugsnag returns a 401 HTTP status code
|
72
|
+
class Unauthorized < ClientError; end
|
73
|
+
|
74
|
+
# Raised when Bugsnag returns a 403 HTTP status code
|
75
|
+
class Forbidden < ClientError; end
|
76
|
+
|
77
|
+
# Raised when Bugsnag returns a 404 HTTP status code
|
78
|
+
class NotFound < ClientError; end
|
79
|
+
|
80
|
+
# Raised when Bugsnag returns a 405 HTTP status code
|
81
|
+
class MethodNotAllowed < ClientError; end
|
82
|
+
|
83
|
+
# Raised when Bugsnag returns a 406 HTTP status code
|
84
|
+
class NotAcceptable < ClientError; end
|
85
|
+
|
86
|
+
# Raised when Bugsnag returns a 409 HTTP status code
|
87
|
+
class Conflict < ClientError; end
|
88
|
+
|
89
|
+
# Raised when Bugsnag returns a 414 HTTP status code
|
90
|
+
class UnsupportedMediaType < ClientError; end
|
91
|
+
|
92
|
+
# Raised when Bugsnag returns a 422 HTTP status code
|
93
|
+
class UnprocessableEntity < ClientError; end
|
94
|
+
|
95
|
+
# Raised on errors in the 500-599 range
|
96
|
+
class ServerError < Error; end
|
97
|
+
|
98
|
+
# Raised when Bugsnag returns a 500 HTTP status code
|
99
|
+
class InternalServerError < ServerError; end
|
100
|
+
|
101
|
+
# Raised when Bugsnag returns a 501 HTTP status code
|
102
|
+
class NotImplemented < ServerError; end
|
103
|
+
|
104
|
+
# Raised when Bugsnag returns a 502 HTTP status code
|
105
|
+
class BadGateway < ServerError; end
|
106
|
+
|
107
|
+
# Raised when Bugsnag returns a 503 HTTP status code
|
108
|
+
class ServiceUnavailable < ServerError; end
|
109
|
+
|
110
|
+
# Raised when client fails to provide valid Content-Type
|
111
|
+
class MissingContentType < ArgumentError; end
|
112
|
+
|
113
|
+
# Raised when a method requires account-level credentials
|
114
|
+
# but none were provided
|
115
|
+
class AccountCredentialsRequired < StandardError; end
|
116
|
+
|
117
|
+
# Raised when a method requires user-level credentials
|
118
|
+
# but none were provided
|
119
|
+
class UserCredentialsRequired < StandardError; end
|
120
|
+
end
|
121
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require "faraday"
|
2
|
+
require "bugsnag/api/error"
|
3
|
+
|
4
|
+
module Bugsnag
|
5
|
+
module Api
|
6
|
+
# Faraday response middleware
|
7
|
+
module Response
|
8
|
+
|
9
|
+
# This class raises an Bugsnag-flavored exception based
|
10
|
+
# HTTP status codes returned by the API
|
11
|
+
class RaiseError < Faraday::Response::Middleware
|
12
|
+
|
13
|
+
private
|
14
|
+
def on_complete(response)
|
15
|
+
if error = Bugsnag::Api::Error.from_response(response)
|
16
|
+
raise error
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
metadata
ADDED
@@ -0,0 +1,105 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: bugsnag-api
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- James Smith
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-08-25 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: sawyer
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 0.5.3
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 0.5.3
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: bundler
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ~>
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.3'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ~>
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.3'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
description: Bugsnag API toolkit for ruby
|
56
|
+
email:
|
57
|
+
- james@bugsnag.com
|
58
|
+
executables: []
|
59
|
+
extensions: []
|
60
|
+
extra_rdoc_files: []
|
61
|
+
files:
|
62
|
+
- .gitignore
|
63
|
+
- Gemfile
|
64
|
+
- LICENSE.txt
|
65
|
+
- README.md
|
66
|
+
- Rakefile
|
67
|
+
- bugsnag-api.gemspec
|
68
|
+
- lib/bugsnag/api.rb
|
69
|
+
- lib/bugsnag/api/client.rb
|
70
|
+
- lib/bugsnag/api/client/accounts.rb
|
71
|
+
- lib/bugsnag/api/client/comments.rb
|
72
|
+
- lib/bugsnag/api/client/errors.rb
|
73
|
+
- lib/bugsnag/api/client/events.rb
|
74
|
+
- lib/bugsnag/api/client/projects.rb
|
75
|
+
- lib/bugsnag/api/client/users.rb
|
76
|
+
- lib/bugsnag/api/configuration.rb
|
77
|
+
- lib/bugsnag/api/error.rb
|
78
|
+
- lib/bugsnag/api/response/raise_error.rb
|
79
|
+
- lib/bugsnag/api/version.rb
|
80
|
+
homepage: https://github.com/bugsnag/bugsnag-api-ruby
|
81
|
+
licenses:
|
82
|
+
- MIT
|
83
|
+
metadata: {}
|
84
|
+
post_install_message:
|
85
|
+
rdoc_options: []
|
86
|
+
require_paths:
|
87
|
+
- lib
|
88
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
89
|
+
requirements:
|
90
|
+
- - '>='
|
91
|
+
- !ruby/object:Gem::Version
|
92
|
+
version: '0'
|
93
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
94
|
+
requirements:
|
95
|
+
- - '>='
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
version: '0'
|
98
|
+
requirements: []
|
99
|
+
rubyforge_project:
|
100
|
+
rubygems_version: 2.0.14
|
101
|
+
signing_key:
|
102
|
+
specification_version: 4
|
103
|
+
summary: Bugsnag API toolkit for ruby
|
104
|
+
test_files: []
|
105
|
+
has_rdoc:
|