bugsnag-api 2.0.1 → 2.1.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.
Files changed (89) hide show
  1. checksums.yaml +5 -5
  2. data/.buildkite/pipeline.yml +6 -0
  3. data/.github/ISSUE_TEMPLATE/A.md +14 -0
  4. data/.github/ISSUE_TEMPLATE/bug_report.md +47 -0
  5. data/.github/ISSUE_TEMPLATE/feature_request.md +24 -0
  6. data/.github/PULL_REQUEST_TEMPLATE.md +16 -0
  7. data/.github/support.md +19 -0
  8. data/.github/workflows/tests.yml +53 -0
  9. data/.rubocop.yml +4 -0
  10. data/.rubocop_todo.yml +271 -0
  11. data/CHANGELOG.md +34 -0
  12. data/CONTRIBUTING.md +1 -1
  13. data/Gemfile +9 -0
  14. data/README.md +77 -2
  15. data/bugsnag-api.gemspec +48 -6
  16. data/config/.gitignore +1 -0
  17. data/docker-compose.yml +9 -0
  18. data/dockerfiles/Dockerfile.audit +5 -0
  19. data/lib/bugsnag/api/client/collaborators.rb +1 -2
  20. data/lib/bugsnag/api/client/comments.rb +1 -1
  21. data/lib/bugsnag/api/client/currentuser.rb +0 -1
  22. data/lib/bugsnag/api/client/errors.rb +12 -11
  23. data/lib/bugsnag/api/client/eventfields.rb +1 -2
  24. data/lib/bugsnag/api/client/events.rb +1 -2
  25. data/lib/bugsnag/api/client/organizations.rb +1 -2
  26. data/lib/bugsnag/api/client/pivots.rb +1 -2
  27. data/lib/bugsnag/api/client/projects.rb +2 -3
  28. data/lib/bugsnag/api/client/releases.rb +38 -0
  29. data/lib/bugsnag/api/client/stability.rb +16 -0
  30. data/lib/bugsnag/api/client/trends.rb +8 -5
  31. data/lib/bugsnag/api/client.rb +23 -3
  32. data/lib/bugsnag/api/configuration.rb +1 -1
  33. data/lib/bugsnag/api/error.rb +1 -1
  34. data/lib/bugsnag/api/response/raise_error.rb +0 -2
  35. data/lib/bugsnag/api/version.rb +1 -1
  36. data/scripts/license_finder.sh +4 -0
  37. data/spec/bugsnag/api/client/releases_spec.rb +184 -0
  38. data/spec/bugsnag/api/client/stability_spec.rb +32 -0
  39. data/spec/bugsnag/api/client_spec.rb +69 -7
  40. data/spec/bugsnag/api_spec.rb +2 -0
  41. data/spec/cassettes/Bugsnag_Api_Client/_get/handles_query_params.yml +13 -21
  42. data/spec/cassettes/Bugsnag_Api_Client/_last_response/caches_the_last_agent_response.yml +13 -21
  43. data/spec/cassettes/Bugsnag_Api_Client_Collaborators/_invitecollaborator/creates_and_returns_a_collaborator.yml +14 -26
  44. data/spec/cassettes/Bugsnag_Api_Client_Collaborators/_invitecollaborator/invites_multiple_collaborators.yml +14 -26
  45. data/spec/cassettes/Bugsnag_Api_Client_Collaborators/given_a_collaborator_exists/_collaborator/returns_a_collaborator.yml +29 -53
  46. data/spec/cassettes/Bugsnag_Api_Client_Collaborators/given_a_collaborator_exists/_collaborators/returns_a_list_of_all_organization_collaborators.yml +30 -55
  47. data/spec/cassettes/Bugsnag_Api_Client_Collaborators/given_a_collaborator_exists/_collaborators/returns_a_list_of_all_project_collaborators.yml +30 -55
  48. data/spec/cassettes/Bugsnag_Api_Client_Collaborators/given_a_collaborator_exists/_collaborators/throws_an_argument_error_if_neither_org_id_or_project_id_are_provided.yml +14 -26
  49. data/spec/cassettes/Bugsnag_Api_Client_Collaborators/given_a_collaborator_exists/_delete_collaborator/deletes_a_collaborator.yml +14 -26
  50. data/spec/cassettes/Bugsnag_Api_Client_Collaborators/given_a_collaborator_exists/_update_collaborator_permissions/updates_and_returns_the_collaborator.yml +29 -53
  51. data/spec/cassettes/Bugsnag_Api_Client_Collaborators/given_a_collaborator_exists/_view_collaborator_projects/returns_a_list_of_projects_belonging_to_the_collaborator.yml +49 -55
  52. data/spec/cassettes/Bugsnag_Api_Client_Comments/_create_comment/creates_a_comment_on_the_error.yml +17 -29
  53. data/spec/cassettes/Bugsnag_Api_Client_Comments/given_a_comment_has_been_created/_comment/retrieves_the_comment_specified.yml +32 -56
  54. data/spec/cassettes/Bugsnag_Api_Client_Comments/given_a_comment_has_been_created/_comments/retrieves_all_comments_on_an_error.yml +33 -57
  55. data/spec/cassettes/Bugsnag_Api_Client_Comments/given_a_comment_has_been_created/_delete_comment/deletes_the_comment_and_returns_true.yml +17 -29
  56. data/spec/cassettes/Bugsnag_Api_Client_Comments/given_a_comment_has_been_created/_update_comment/updates_the_message_on_a_comment.yml +32 -56
  57. data/spec/cassettes/Bugsnag_Api_Client_CurrentUser/_list_organizations/when_using_auth_token/returns_the_organization_the_auth_token_belongs_to.yml +14 -27
  58. data/spec/cassettes/Bugsnag_Api_Client_CurrentUser/_list_organizations/when_using_user_credentials/returns_users_organizations.yml +17 -31
  59. data/spec/cassettes/Bugsnag_Api_Client_CurrentUser/_list_projects/when_using_auth_token/lists_current_user_s_projects_in_the_organization.yml +34 -28
  60. data/spec/cassettes/Bugsnag_Api_Client_CurrentUser/_list_projects/when_using_user_credentials/lists_current_user_s_projects_in_the_organization.yml +37 -32
  61. data/spec/cassettes/Bugsnag_Api_Client_Errors/_error/returns_a_single_error.yml +14 -28
  62. data/spec/cassettes/Bugsnag_Api_Client_Errors/_errors/returns_errors_on_the_project.yml +16 -30
  63. data/spec/cassettes/Bugsnag_Api_Client_Errors/_update_errors/updates_and_returns_the_updated_errors.yml +13 -25
  64. data/spec/cassettes/Bugsnag_Api_Client_Events/_error_events/lists_all_error_events.yml +19 -30
  65. data/spec/cassettes/Bugsnag_Api_Client_Events/_event/returns_the_specified_event.yml +16 -199
  66. data/spec/cassettes/Bugsnag_Api_Client_Events/_events/returns_the_a_list_of_project_errors.yml +19 -30
  67. data/spec/cassettes/Bugsnag_Api_Client_Events/_latest_event/returns_the_last_event_on_an_error.yml +16 -199
  68. data/spec/cassettes/Bugsnag_Api_Client_Organizations/_create_organization/creates_a_new_organization.yml +17 -30
  69. data/spec/cassettes/Bugsnag_Api_Client_Organizations/with_organization/_delete_organization/deletes_the_organization.yml +32 -58
  70. data/spec/cassettes/Bugsnag_Api_Client_Organizations/with_organization/_organization/returns_the_requested_organization.yml +35 -61
  71. data/spec/cassettes/Bugsnag_Api_Client_Organizations/with_organization/_update_organization/updates_and_returns_the_organization.yml +35 -61
  72. data/spec/cassettes/Bugsnag_Api_Client_Projects/_create_project/creates_a_new_project.yml +14 -26
  73. data/spec/cassettes/Bugsnag_Api_Client_Projects/given_a_project/_delete_project/deletes_the_project.yml +26 -50
  74. data/spec/cassettes/Bugsnag_Api_Client_Projects/given_a_project/_project/returns_the_requested_project.yml +29 -53
  75. data/spec/cassettes/Bugsnag_Api_Client_Projects/given_a_project/_regenerate_api_key/removes_the_current_api_key_and_replaces_it_with_a_new_api_key.yml +29 -53
  76. data/spec/cassettes/Bugsnag_Api_Client_Projects/given_a_project/_update_project/updates_and_returns_the_project.yml +29 -53
  77. data/spec/cassettes/Bugsnag_Api_Client_Releases/_release/gets_a_single_release.yml +87 -0
  78. data/spec/cassettes/Bugsnag_Api_Client_Releases/_release_groups/accepts_parameters.yml +90 -0
  79. data/spec/cassettes/Bugsnag_Api_Client_Releases/_release_groups/gets_releases_in_a_release_group.yml +87 -0
  80. data/spec/cassettes/Bugsnag_Api_Client_Releases/_releases/accepts_parameters.yml +92 -0
  81. data/spec/cassettes/Bugsnag_Api_Client_Releases/_releases/gets_as_list_of_releases.yml +91 -0
  82. data/spec/cassettes/Bugsnag_Api_Client_Stability/_stability_trend/gets_the_stability_trend.yml +87 -0
  83. data/spec/cassettes/Bugsnag_Api_Client_Trends/_trends_buckets/returns_a_list_of_error_trends_in_bucket_form.yml +14 -26
  84. data/spec/cassettes/Bugsnag_Api_Client_Trends/_trends_buckets/returns_a_list_of_project_trends_in_bucket_form.yml +14 -26
  85. data/spec/cassettes/Bugsnag_Api_Client_Trends/_trends_resolution/returns_a_list_of_project_trends_in_resolution_form.yml +14 -26
  86. data/spec/cassettes/Bugsnag_Api_Client_Trends/_trends_resolution/returns_a_list_of_trends_in_resolution_form.yml +14 -26
  87. data/spec/spec_helper.rb +35 -7
  88. metadata +67 -24
  89. data/.travis.yml +0 -17
data/bugsnag-api.gemspec CHANGED
@@ -18,13 +18,55 @@ Gem::Specification.new do |spec|
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
19
  spec.require_paths = ["lib"]
20
20
 
21
- spec.add_dependency "sawyer", '~> 0.8.1'
21
+ if RUBY_VERSION < "2.2.0"
22
+ spec.add_dependency "sawyer", '0.8.1'
23
+
24
+ spec.add_development_dependency "rake", "< 12.0.0"
25
+ spec.add_development_dependency "rubocop", "0.41.2"
26
+ spec.add_development_dependency "faker", "1.3.0"
27
+
28
+ # i18n is used by faker
29
+ spec.add_development_dependency "i18n", "< 1.0.0"
30
+
31
+ # crack is used by webmock
32
+ spec.add_development_dependency "crack", "< 0.4.5"
33
+ else
34
+ spec.add_dependency "sawyer", '~> 0.8.1'
35
+
36
+ spec.add_development_dependency "rake"
37
+ spec.add_development_dependency "rubocop", "~> 0.52.1"
38
+ spec.add_development_dependency "faker", "> 1.7.3"
39
+ end
40
+
41
+ if RUBY_VERSION < "2.0.0"
42
+ spec.add_development_dependency "webmock", "2.3.2"
43
+ spec.add_development_dependency "addressable", "2.3.6"
44
+
45
+ # hashdiff is used by webmock
46
+ spec.add_development_dependency "hashdiff", "< 0.3.8"
47
+
48
+ # parser is used by rubocop
49
+ spec.add_development_dependency "parser", "< 2.5.0"
50
+ else
51
+ spec.add_development_dependency "webmock", "> 2.3.2"
52
+ spec.add_development_dependency "addressable", "> 2.3.6"
53
+ end
54
+
55
+ if RUBY_VERSION < "2.0.0"
56
+ spec.add_development_dependency "json", "< 2.0.0"
57
+ elsif RUBY_VERSION < "2.3.0"
58
+ spec.add_development_dependency "json", "< 2.6.0"
59
+ else
60
+ spec.add_development_dependency "json"
61
+ end
62
+
63
+ # public_suffix is used by addressable & sawyer
64
+ if RUBY_VERSION < "2.0.0"
65
+ spec.add_development_dependency "public_suffix", "< 1.5.0"
66
+ elsif RUBY_VERSION < "2.1.0"
67
+ spec.add_development_dependency "public_suffix", "< 3.0.0"
68
+ end
22
69
 
23
- spec.add_development_dependency "rake"
24
70
  spec.add_development_dependency "rspec", "~> 3.0"
25
- spec.add_development_dependency "webmock", RUBY_VERSION <= '2.0.0' ? '2.3.2': '>2.3.2'
26
- spec.add_development_dependency "addressable", RUBY_VERSION <= '2.0.0' ? '2.3.6': '>2.3.6'
27
- spec.add_development_dependency "faker", RUBY_VERSION <= '2.0.0' ? '1.3.0' : '>1.7.3'
28
71
  spec.add_development_dependency "vcr", "~> 2.9"
29
- spec.add_development_dependency "json"
30
72
  end
data/config/.gitignore ADDED
@@ -0,0 +1 @@
1
+ global.yml
@@ -0,0 +1,9 @@
1
+ version: '3.6'
2
+ services:
3
+
4
+ license_finder:
5
+ build:
6
+ dockerfile: dockerfiles/Dockerfile.audit
7
+ context: .
8
+ volumes:
9
+ - ./:/scan
@@ -0,0 +1,5 @@
1
+ FROM licensefinder/license_finder
2
+
3
+ WORKDIR /scan
4
+
5
+ CMD /scan/scripts/license_finder.sh
@@ -19,7 +19,7 @@ module Bugsnag
19
19
  # @argument project_id [String] ID of project to get collaborators from (conflicts with org_id)
20
20
  # @argument org_id [String] ID of organization to get collaborators from (conflicts with project_id)
21
21
  #
22
- # @option per_page [Number] Amount of results per-page
22
+ # @option per_page [Number] Amount of results per-page
23
23
  # @return [Array<Sawyer::Resource>] List of Collaborators
24
24
  # @see http://docs.bugsnagapiv2.apiary.io/#reference/organizations/collaborators/list-collaborators
25
25
  # @see http://docs.bugsnagapiv2.apiary.io/#reference/organizations/collaborators/list-collaborators-on-a-project
@@ -84,4 +84,3 @@ module Bugsnag
84
84
  end
85
85
  end
86
86
  end
87
-
@@ -44,7 +44,7 @@ module Bugsnag
44
44
 
45
45
  # Delete a Comment
46
46
  #
47
- # @return
47
+ # @return
48
48
  # @see http://docs.bugsnagapiv2.apiary.io/#reference/errors/comments/delete-a-comment
49
49
  def delete_comment(id, options = {})
50
50
  boolean_from_response :delete, "comments/#{id}", options
@@ -30,4 +30,3 @@ module Bugsnag
30
30
  end
31
31
  end
32
32
  end
33
-
@@ -8,6 +8,8 @@ module Bugsnag
8
8
  module Errors
9
9
  # List the Errors on a Project
10
10
  #
11
+ # @argument id [String] optional ID of error to retrieve
12
+ #
11
13
  # @option base [String] Only Error Events occuring before this time will be returned
12
14
  # @option sort [String] Which field to sort by, one of: last_seen, first_seen, users, events, unsorted
13
15
  # @option direction [String] Which direction to sort the result by, one of: asc, desc
@@ -15,16 +17,14 @@ module Bugsnag
15
17
  # @return [Array<Sawyer::Resource>] List of Project Errors
16
18
  # @see http://docs.bugsnagapiv2.apiary.io/#reference/errors/errors/list-the-errors-on-a-project
17
19
  def errors(project_id, id=nil, options = {})
18
- paginate "projects/#{project_id}/errors", options
20
+ if id.nil?
21
+ paginate "projects/#{project_id}/errors", options
22
+ else
23
+ get "projects/#{project_id}/errors/#{id}", options
24
+ end
19
25
  end
20
26
 
21
- # View an Error
22
- #
23
- # @return [Sawyer::Resource] Requested Error
24
- # @see http://docs.bugsnagapiv2.apiary.io/#reference/errors/errors/view-an-error
25
- def error(project_id, id, options = {})
26
- get "projects/#{project_id}/errors/#{id}", options
27
- end
27
+ alias error errors
28
28
 
29
29
  # Update an Error
30
30
  #
@@ -42,7 +42,9 @@ module Bugsnag
42
42
  when String
43
43
  patch "projects/#{project_id}/errors/#{ids}", options.merge({:operation => operation})
44
44
  when Array
45
- patch "projects/#{project_id}/errors", options.merge({:operation => operation, :query => {:error_ids => ids.join(' ')}})
45
+ defaults = {:operation => operation, :query => {:error_ids => ids.join(' ')}}
46
+ merged_opts = deep_merge(defaults, options)
47
+ patch "projects/#{project_id}/errors", merged_opts
46
48
  else
47
49
  raise ArgumentError, "ids must be a String or an Array"
48
50
  end
@@ -53,7 +55,7 @@ module Bugsnag
53
55
  # @argument error_id [String] ID of error to delete (conflicts with project_id)
54
56
  # @argument project_id [String] Id of project to delete all errors from (conflicts with error_id)
55
57
  #
56
- # @return
58
+ # @return
57
59
  # @see http://docs.bugsnagapiv2.apiary.io/#reference/errors/errors/delete-an-error
58
60
  def delete_errors(project_id, error_id=nil, options = {})
59
61
  if !error_id.nil?
@@ -66,4 +68,3 @@ module Bugsnag
66
68
  end
67
69
  end
68
70
  end
69
-
@@ -38,7 +38,7 @@ module Bugsnag
38
38
 
39
39
  # Delete a custom Event Field
40
40
  #
41
- # @return
41
+ # @return
42
42
  # @see http://docs.bugsnagapiv2.apiary.io/#reference/projects/event-fields/delete-a-custom-event-field
43
43
  def delete_event_field(project_id, display_id, options = {})
44
44
  boolean_from_resposne :delete, "project/#{project_id}/event_fields/#{display_id}", options
@@ -47,4 +47,3 @@ module Bugsnag
47
47
  end
48
48
  end
49
49
  end
50
-
@@ -16,7 +16,7 @@ module Bugsnag
16
16
 
17
17
  # Delete an Event
18
18
  #
19
- # @return
19
+ # @return
20
20
  # @see http://docs.bugsnagapiv2.apiary.io/#reference/errors/events/delete-an-event
21
21
  def delete_event(project_id, id, options = {})
22
22
  boolean_from_response :delete, "projects/#{project_id}/events/#{id}", options
@@ -57,4 +57,3 @@ module Bugsnag
57
57
  end
58
58
  end
59
59
  end
60
-
@@ -34,7 +34,7 @@ module Bugsnag
34
34
 
35
35
  # Delete an Organization
36
36
  #
37
- # @return
37
+ # @return
38
38
  # @see http://docs.bugsnagapiv2.apiary.io/#reference/organizations/organizations/delete-an-organization
39
39
  def delete_organization(id, options = {})
40
40
  boolean_from_response :delete, "organizations/#{id}", options
@@ -43,4 +43,3 @@ module Bugsnag
43
43
  end
44
44
  end
45
45
  end
46
-
@@ -26,7 +26,7 @@ module Bugsnag
26
26
  #
27
27
  # @option filters [Object] An optional filter object, see http://docs.bugsnagapiv2.apiary.io/#introduction/filtering
28
28
  # @option sort [String] Sorting method
29
- # @option base [String] Only Events occuring before this time will be used
29
+ # @option base [String] Only Events occuring before this time will be used
30
30
  # @return [Array<Sawyer::Resource>] List of values for the Pivots requested
31
31
  # @see http://docs.bugsnagapiv2.apiary.io/#reference/errors/pivots/list-values-of-a-pivot-on-an-error
32
32
  def pivot_values(project_id, ef_display_id, error_id=nil, options = {})
@@ -40,4 +40,3 @@ module Bugsnag
40
40
  end
41
41
  end
42
42
  end
43
-
@@ -42,7 +42,7 @@ module Bugsnag
42
42
 
43
43
  # Regenerate a Project's notifier API key
44
44
  #
45
- # @return
45
+ # @return
46
46
  # @see http://docs.bugsnagapiv2.apiary.io/#reference/projects/projects/regenerate-a-project's-notifier-api-key
47
47
  def regenerate_api_key(id, options = {})
48
48
  delete "projects/#{id}/api_key", options
@@ -50,7 +50,7 @@ module Bugsnag
50
50
 
51
51
  # Delete a Project
52
52
  #
53
- # @return
53
+ # @return
54
54
  # @see http://docs.bugsnagapiv2.apiary.io/#reference/organizations/organizations/delete-an-organization
55
55
  def delete_project(id, options = {})
56
56
  boolean_from_response :delete, "projects/#{id}", options
@@ -59,4 +59,3 @@ module Bugsnag
59
59
  end
60
60
  end
61
61
  end
62
-
@@ -0,0 +1,38 @@
1
+ module Bugsnag
2
+ module Api
3
+ class Client
4
+ # Methods for the Releases API
5
+ module Releases
6
+ # List the Releases in a Project
7
+ #
8
+ # @option release_stage [String] Only Releases with this release stage will be returned
9
+ # @option base [String] Only Releases created before this time will be returned
10
+ # @option sort [String] How to sort the results, one of: timestamp, percent_of_sessions
11
+ # @option offset [Number] The pagination offset
12
+ # @option per_page [Number] The number of results to return per page
13
+ # @return [Array<Sawyer::Resource>] List of Events for the specified Error
14
+ # @see https://bugsnagapiv2.docs.apiary.io/#reference/projects/releases/list-releases-on-a-project
15
+ def releases(project_id, options = {})
16
+ get "projects/#{project_id}/releases", options
17
+ end
18
+
19
+ # View a single Release
20
+ #
21
+ # @see https://bugsnagapiv2.docs.apiary.io/#reference/projects/releases/view-a-release
22
+ def release(project_id, release_id, options = {})
23
+ get "projects/#{project_id}/releases/#{release_id}", options
24
+ end
25
+
26
+ # List the Releases in a Release Group
27
+ #
28
+ # @option per_page [Number] The number of results to return per page
29
+ # @option page_token [String] Value from the next relation in the Link response header to obtain the next page of results
30
+ # @return [Array<Sawyer::Resource>] List of Releases for the specified Release Group
31
+ # @see https://bugsnagapiv2.docs.apiary.io/#reference/projects/releases/list-releases-on-a-release-group
32
+ def releases_in_group(release_group_id, options = {})
33
+ get "release_groups/#{release_group_id}/releases", options
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,16 @@
1
+ module Bugsnag
2
+ module Api
3
+ class Client
4
+ # Methods for the Stability API
5
+ module Stability
6
+ # View the stability trend for a project
7
+ #
8
+ # @return [Sawyer::Resource] Stability trend
9
+ # @see https://bugsnagapiv2.docs.apiary.io/#reference/projects/stability-trend/view-the-stability-trend-for-a-project
10
+ def stability_trend(id, options = {})
11
+ get "projects/#{id}/stability_trend", options
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -12,10 +12,12 @@ module Bugsnag
12
12
  # @return [Array<Sawyer::Resource>] List of Trends as requested
13
13
  # @see http://docs.bugsnagapiv2.apiary.io/#reference/errors/trends/list-the-trends-for-an-error-(buckets)
14
14
  def trends_buckets(project_id, buckets_count, error_id=nil, options = {})
15
+ defaults = {:query => {:buckets_count => buckets_count}}
16
+ merged_opts = deep_merge(defaults, options)
15
17
  if !error_id.nil?
16
- get "projects/#{project_id}/errors/#{error_id}/trend", options.merge({:query => {:buckets_count => buckets_count}})
18
+ get "projects/#{project_id}/errors/#{error_id}/trend", merged_opts
17
19
  else
18
- get "projects/#{project_id}/trend", options.merge({:query => {:buckets_count => buckets_count}})
20
+ get "projects/#{project_id}/trend", merged_opts
19
21
  end
20
22
  end
21
23
 
@@ -25,14 +27,15 @@ module Bugsnag
25
27
  # @return [Array<Sawyer::Resource>] List of Trends as requested
26
28
  # @see http://docs.bugsnagapiv2.apiary.io/#reference/errors/trends/list-the-trends-for-an-error-(buckets)
27
29
  def trends_resolution(project_id, resolution, error_id=nil, options = {})
30
+ defaults = {:query => {:resolution => resolution}}
31
+ merged_opts = deep_merge(defaults, options)
28
32
  if !error_id.nil?
29
- get "projects/#{project_id}/errors/#{error_id}/trend", options.merge({:query => {:resolution => resolution}})
33
+ get "projects/#{project_id}/errors/#{error_id}/trend", merged_opts
30
34
  else
31
- get "projects/#{project_id}/trend", options.merge({:query => {:resolution => resolution}})
35
+ get "projects/#{project_id}/trend", merged_opts
32
36
  end
33
37
  end
34
38
  end
35
39
  end
36
40
  end
37
41
  end
38
-
@@ -10,6 +10,10 @@ require "bugsnag/api/client/events"
10
10
  require "bugsnag/api/client/pivots"
11
11
  require "bugsnag/api/client/trends"
12
12
  require "bugsnag/api/client/comments"
13
+ require "bugsnag/api/client/stability"
14
+ require "bugsnag/api/client/releases"
15
+
16
+ require "base64"
13
17
 
14
18
  module Bugsnag
15
19
  module Api
@@ -28,6 +32,8 @@ module Bugsnag
28
32
  include Bugsnag::Api::Client::Pivots
29
33
  include Bugsnag::Api::Client::Trends
30
34
  include Bugsnag::Api::Client::Comments
35
+ include Bugsnag::Api::Client::Stability
36
+ include Bugsnag::Api::Client::Releases
31
37
 
32
38
  # Header keys that can be passed in options hash to {#get},{#head}
33
39
  CONVENIENCE_HEADERS = Set.new([:accept, :content_type])
@@ -143,6 +149,18 @@ module Bugsnag
143
149
  !!configuration.auth_token
144
150
  end
145
151
 
152
+ # Merges hashes together cleanly, favouring RHS values
153
+ #
154
+ # @return [Hash]
155
+ def deep_merge(l_hash, r_hash)
156
+ l_hash.merge(r_hash) do |_key, l_val, r_val|
157
+ if l_val.is_a?(Hash) && r_val.is_a?(Hash)
158
+ deep_merge(l_val, r_val)
159
+ else
160
+ r_val
161
+ end
162
+ end
163
+ end
146
164
 
147
165
  private
148
166
  def agent
@@ -153,9 +171,11 @@ module Bugsnag
153
171
  http.headers[:user_agent] = configuration.user_agent
154
172
 
155
173
  if basic_authenticated?
156
- http.basic_auth configuration.email, configuration.password
174
+ credentials = Base64.strict_encode64("#{configuration.email}:#{configuration.password}")
175
+
176
+ http.headers[:Authorization] = "Basic #{credentials}"
157
177
  elsif token_authenticated?
158
- http.authorization "token", configuration.auth_token
178
+ http.headers[:Authorization] = "token #{configuration.auth_token}"
159
179
  end
160
180
  end
161
181
  end
@@ -173,7 +193,7 @@ module Bugsnag
173
193
  end
174
194
  end
175
195
 
176
- @last_response = response = agent.call(method, URI.escape(path.to_s), data, options)
196
+ @last_response = response = agent.call(method, path.to_s, data, options)
177
197
  response.data
178
198
  end
179
199
 
@@ -45,7 +45,7 @@ module Bugsnag
45
45
 
46
46
  # Load configuration from hash
47
47
  def load(options = {})
48
- options.each {|k,v| self.send("#{k}=", v) if self.respond_to?("#{k}=") && !v.nil?}
48
+ options.each { |k,v| self.send("#{k}=", v) if self.respond_to?("#{k}=") && !v.nil?}
49
49
  end
50
50
  end
51
51
  end
@@ -3,7 +3,7 @@ module Bugsnag
3
3
  # Custom error class for rescuing from all Bugsnag API errors
4
4
  class Error < StandardError
5
5
 
6
- # Returns the appropriate Bugnsag::Api::Error subclass based
6
+ # Returns the appropriate Bugsnag::Api::Error subclass based
7
7
  # on status and response message
8
8
  #
9
9
  # @param [Hash] response HTTP response
@@ -9,8 +9,6 @@ module Bugsnag
9
9
  # This class raises an Bugsnag-flavored exception based
10
10
  # HTTP status codes returned by the API
11
11
  class RaiseError < Faraday::Response::Middleware
12
-
13
- private
14
12
  def on_complete(response)
15
13
  if error = Bugsnag::Api::Error.from_response(response)
16
14
  raise error
@@ -1,5 +1,5 @@
1
1
  module Bugsnag
2
2
  module Api
3
- VERSION = "2.0.1"
3
+ VERSION = "2.1.1"
4
4
  end
5
5
  end
@@ -0,0 +1,4 @@
1
+ #!/bin/bash
2
+ curl https://raw.githubusercontent.com/bugsnag/license-audit/master/config/decision_files/global.yml -o config/global.yml
3
+ bundle install
4
+ license_finder --decisions-file=config/global.yml
@@ -0,0 +1,184 @@
1
+ require "spec_helper"
2
+
3
+ describe Bugsnag::Api::Client::Releases do
4
+ before do
5
+ @client = auth_token_client
6
+ @project_id = test_bugsnag_project_id
7
+ @release_id = test_bugsnag_release_id
8
+ @release_group_id = test_bugsnag_release_group_id
9
+
10
+ Bugsnag::Api.reset!
11
+ end
12
+
13
+ describe ".releases", :vcr do
14
+ it "gets as list of releases" do
15
+ releases = @client.releases(@project_id)
16
+
17
+ expect(releases).to be_an_instance_of(Array)
18
+
19
+ releases.map!(&:to_h)
20
+
21
+ expect(releases.first[:id]).to eq(@release_id)
22
+ expect(releases.first[:project_id]).to eq(@project_id)
23
+ expect(releases.first[:release_group_id]).to eq(@release_group_id)
24
+
25
+ expect(releases).to all have_key(:id)
26
+ expect(releases).to all have_key(:project_id)
27
+ expect(releases).to all have_key(:release_group_id)
28
+ expect(releases).to all have_key(:release_time)
29
+ expect(releases).to all have_key(:release_source)
30
+ expect(releases).to all have_key(:app_version)
31
+ expect(releases).to all have_key(:app_version_code)
32
+ expect(releases).to all have_key(:app_bundle_version)
33
+ expect(releases).to all have_key(:build_label)
34
+ expect(releases).to all have_key(:builder_name)
35
+ expect(releases).to all have_key(:build_tool)
36
+ expect(releases).to all have_key(:errors_introduced_count)
37
+ expect(releases).to all have_key(:errors_seen_count)
38
+ expect(releases).to all have_key(:sessions_count_in_last_24h)
39
+ expect(releases).to all have_key(:total_sessions_count)
40
+ expect(releases).to all have_key(:unhandled_sessions_count)
41
+ expect(releases).to all have_key(:accumulative_daily_users_seen)
42
+ expect(releases).to all have_key(:accumulative_daily_users_with_unhandled)
43
+ expect(releases).to all have_key(:metadata)
44
+ expect(releases).to all have_key(:release_stage)
45
+ end
46
+
47
+ it "accepts parameters" do
48
+ releases = @client.releases(
49
+ @project_id,
50
+ {
51
+ release_stage: 'development',
52
+ base: '2021-07-21T12:00:00Z',
53
+ sort: 'percent_of_sessions',
54
+ offset: 0,
55
+ per_page: 1
56
+ }
57
+ )
58
+
59
+ expect(releases).to be_an_instance_of(Array)
60
+
61
+ releases.map!(&:to_h)
62
+
63
+ expect(releases.first[:id]).to eq(@release_id)
64
+ expect(releases.first[:project_id]).to eq(@project_id)
65
+ expect(releases.first[:release_group_id]).to eq(@release_group_id)
66
+
67
+ expect(releases).to all have_key(:id)
68
+ expect(releases).to all have_key(:project_id)
69
+ expect(releases).to all have_key(:release_group_id)
70
+ expect(releases).to all have_key(:release_time)
71
+ expect(releases).to all have_key(:release_source)
72
+ expect(releases).to all have_key(:app_version)
73
+ expect(releases).to all have_key(:app_version_code)
74
+ expect(releases).to all have_key(:app_bundle_version)
75
+ expect(releases).to all have_key(:build_label)
76
+ expect(releases).to all have_key(:builder_name)
77
+ expect(releases).to all have_key(:build_tool)
78
+ expect(releases).to all have_key(:errors_introduced_count)
79
+ expect(releases).to all have_key(:errors_seen_count)
80
+ expect(releases).to all have_key(:sessions_count_in_last_24h)
81
+ expect(releases).to all have_key(:total_sessions_count)
82
+ expect(releases).to all have_key(:unhandled_sessions_count)
83
+ expect(releases).to all have_key(:accumulative_daily_users_seen)
84
+ expect(releases).to all have_key(:accumulative_daily_users_with_unhandled)
85
+ expect(releases).to all have_key(:metadata)
86
+ expect(releases).to all have_key(:release_stage)
87
+ end
88
+ end
89
+
90
+ describe ".release", :vcr do
91
+ it "gets a single release" do
92
+ release = @client.release(@project_id, @release_id)
93
+
94
+ expect(release.id).to eq(@release_id)
95
+ expect(release.project_id).to eq(@project_id)
96
+ expect(release.release_group_id).to eq(@release_group_id)
97
+ expect(release.release_time).not_to be_nil
98
+ expect(release.release_source).not_to be_nil
99
+ expect(release.app_version).not_to be_nil
100
+ expect(release.app_version_code).not_to be_nil
101
+ expect(release.app_bundle_version).not_to be_nil
102
+ expect(release.build_label).not_to be_nil
103
+ expect(release.builder_name).not_to be_nil
104
+ expect(release.build_tool).not_to be_nil
105
+ expect(release.errors_introduced_count).not_to be_nil
106
+ expect(release.errors_seen_count).not_to be_nil
107
+ expect(release.sessions_count_in_last_24h).not_to be_nil
108
+ expect(release.total_sessions_count).not_to be_nil
109
+ expect(release.unhandled_sessions_count).not_to be_nil
110
+ expect(release.accumulative_daily_users_seen).not_to be_nil
111
+ expect(release.accumulative_daily_users_with_unhandled).not_to be_nil
112
+ expect(release.metadata).not_to be_nil
113
+ expect(release.release_stage).not_to be_nil
114
+ end
115
+ end
116
+
117
+ describe ".release_groups", :vcr do
118
+ it "gets releases in a release group" do
119
+ releases = @client.releases_in_group(@release_group_id)
120
+
121
+ expect(releases).to be_an_instance_of(Array)
122
+
123
+ releases.map!(&:to_h)
124
+
125
+ expect(releases.first[:id]).to eq(@release_id)
126
+ expect(releases.first[:project_id]).to eq(@project_id)
127
+ expect(releases.first[:release_group_id]).to eq(@release_group_id)
128
+
129
+ expect(releases).to all have_key(:id)
130
+ expect(releases).to all have_key(:project_id)
131
+ expect(releases).to all have_key(:release_group_id)
132
+ expect(releases).to all have_key(:release_time)
133
+ expect(releases).to all have_key(:release_source)
134
+ expect(releases).to all have_key(:app_version)
135
+ expect(releases).to all have_key(:app_version_code)
136
+ expect(releases).to all have_key(:app_bundle_version)
137
+ expect(releases).to all have_key(:build_label)
138
+ expect(releases).to all have_key(:builder_name)
139
+ expect(releases).to all have_key(:build_tool)
140
+ expect(releases).to all have_key(:errors_introduced_count)
141
+ expect(releases).to all have_key(:errors_seen_count)
142
+ expect(releases).to all have_key(:sessions_count_in_last_24h)
143
+ expect(releases).to all have_key(:total_sessions_count)
144
+ expect(releases).to all have_key(:unhandled_sessions_count)
145
+ expect(releases).to all have_key(:accumulative_daily_users_seen)
146
+ expect(releases).to all have_key(:accumulative_daily_users_with_unhandled)
147
+ expect(releases).to all have_key(:metadata)
148
+ expect(releases).to all have_key(:release_stage)
149
+ end
150
+
151
+ it "accepts parameters" do
152
+ releases = @client.releases_in_group(@release_group_id, { per_page: 1 })
153
+
154
+ expect(releases).to be_an_instance_of(Array)
155
+
156
+ releases.map!(&:to_h)
157
+
158
+ expect(releases.first[:id]).to eq(@release_id)
159
+ expect(releases.first[:project_id]).to eq(@project_id)
160
+ expect(releases.first[:release_group_id]).to eq(@release_group_id)
161
+
162
+ expect(releases).to all have_key(:id)
163
+ expect(releases).to all have_key(:project_id)
164
+ expect(releases).to all have_key(:release_group_id)
165
+ expect(releases).to all have_key(:release_time)
166
+ expect(releases).to all have_key(:release_source)
167
+ expect(releases).to all have_key(:app_version)
168
+ expect(releases).to all have_key(:app_version_code)
169
+ expect(releases).to all have_key(:app_bundle_version)
170
+ expect(releases).to all have_key(:build_label)
171
+ expect(releases).to all have_key(:builder_name)
172
+ expect(releases).to all have_key(:build_tool)
173
+ expect(releases).to all have_key(:errors_introduced_count)
174
+ expect(releases).to all have_key(:errors_seen_count)
175
+ expect(releases).to all have_key(:sessions_count_in_last_24h)
176
+ expect(releases).to all have_key(:total_sessions_count)
177
+ expect(releases).to all have_key(:unhandled_sessions_count)
178
+ expect(releases).to all have_key(:accumulative_daily_users_seen)
179
+ expect(releases).to all have_key(:accumulative_daily_users_with_unhandled)
180
+ expect(releases).to all have_key(:metadata)
181
+ expect(releases).to all have_key(:release_stage)
182
+ end
183
+ end
184
+ end
@@ -0,0 +1,32 @@
1
+ require "spec_helper"
2
+
3
+ describe Bugsnag::Api::Client::Stability do
4
+ before do
5
+ @client = auth_token_client
6
+ @project_id = test_bugsnag_project_id
7
+
8
+ Bugsnag::Api.reset!
9
+ end
10
+
11
+ describe ".stability_trend", :vcr do
12
+ it "gets the stability trend" do
13
+ stability_trend = @client.stability_trend(@project_id)
14
+
15
+ expect(stability_trend.project_id).to eq(@project_id)
16
+ expect(stability_trend.release_stage_name).not_to be_nil
17
+ expect(stability_trend.timeline_points).to be_an_instance_of(Array)
18
+
19
+ # convert each "Sawyer::Resource" to a hash so we can use the "have_key" matcher
20
+ timeline_points = stability_trend.timeline_points.map(&:to_h)
21
+
22
+ expect(timeline_points).to all have_key(:bucket_start)
23
+ expect(timeline_points).to all have_key(:bucket_end)
24
+ expect(timeline_points).to all have_key(:total_sessions_count)
25
+ expect(timeline_points).to all have_key(:unhandled_sessions_count)
26
+ expect(timeline_points).to all have_key(:users_seen)
27
+ expect(timeline_points).to all have_key(:users_with_unhandled)
28
+
29
+ assert_requested(:get, bugsnag_url("/projects/#{@project_id}/stability_trend"))
30
+ end
31
+ end
32
+ end