fastlane 2.126.0.beta.20190606200048 → 2.126.0.beta.20190607200028

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 (47) hide show
  1. checksums.yaml +4 -4
  2. data/fastlane/lib/fastlane/actions/app_store_build_number.rb +1 -1
  3. data/fastlane/lib/fastlane/version.rb +1 -1
  4. data/fastlane_core/lib/fastlane_core/build_watcher.rb +3 -4
  5. data/pilot/lib/pilot/build_manager.rb +7 -7
  6. data/pilot/lib/pilot/manager.rb +2 -2
  7. data/pilot/lib/pilot/tester_exporter.rb +3 -3
  8. data/pilot/lib/pilot/tester_manager.rb +2 -2
  9. data/spaceship/lib/spaceship/connect_api.rb +2 -17
  10. data/spaceship/lib/spaceship/connect_api/{models/model.rb → model.rb} +5 -4
  11. data/spaceship/lib/spaceship/connect_api/response.rb +4 -7
  12. data/spaceship/lib/spaceship/connect_api/testflight/base.rb +41 -0
  13. data/spaceship/lib/spaceship/connect_api/testflight/client.rb +553 -0
  14. data/spaceship/lib/spaceship/connect_api/testflight/models/app.rb +99 -0
  15. data/spaceship/lib/spaceship/connect_api/testflight/models/beta_app_localization.rb +30 -0
  16. data/spaceship/lib/spaceship/connect_api/testflight/models/beta_app_review_detail.rb +34 -0
  17. data/spaceship/lib/spaceship/connect_api/testflight/models/beta_app_review_submission.rb +28 -0
  18. data/spaceship/lib/spaceship/connect_api/testflight/models/beta_build_localization.rb +22 -0
  19. data/spaceship/lib/spaceship/connect_api/testflight/models/beta_build_metric.rb +26 -0
  20. data/spaceship/lib/spaceship/connect_api/testflight/models/beta_group.rb +43 -0
  21. data/spaceship/lib/spaceship/connect_api/testflight/models/beta_tester.rb +58 -0
  22. data/spaceship/lib/spaceship/connect_api/testflight/models/beta_tester_metric.rb +45 -0
  23. data/spaceship/lib/spaceship/connect_api/testflight/models/build.rb +146 -0
  24. data/spaceship/lib/spaceship/connect_api/testflight/models/build_beta_detail.rb +58 -0
  25. data/spaceship/lib/spaceship/connect_api/testflight/models/build_delivery.rb +38 -0
  26. data/spaceship/lib/spaceship/connect_api/testflight/models/pre_release_version.rb +22 -0
  27. data/spaceship/lib/spaceship/connect_api/testflight/models/user.rb +52 -0
  28. data/spaceship/lib/spaceship/connect_api/testflight/testflight.rb +27 -0
  29. data/spaceship/lib/spaceship/test_flight/build.rb +3 -3
  30. data/spaceship/lib/spaceship/test_flight/build_trains.rb +1 -1
  31. metadata +34 -33
  32. data/spaceship/lib/spaceship/connect_api/base.rb +0 -39
  33. data/spaceship/lib/spaceship/connect_api/client.rb +0 -551
  34. data/spaceship/lib/spaceship/connect_api/models/app.rb +0 -97
  35. data/spaceship/lib/spaceship/connect_api/models/beta_app_localization.rb +0 -28
  36. data/spaceship/lib/spaceship/connect_api/models/beta_app_review_detail.rb +0 -32
  37. data/spaceship/lib/spaceship/connect_api/models/beta_app_review_submission.rb +0 -26
  38. data/spaceship/lib/spaceship/connect_api/models/beta_build_localization.rb +0 -20
  39. data/spaceship/lib/spaceship/connect_api/models/beta_build_metric.rb +0 -24
  40. data/spaceship/lib/spaceship/connect_api/models/beta_group.rb +0 -41
  41. data/spaceship/lib/spaceship/connect_api/models/beta_tester.rb +0 -56
  42. data/spaceship/lib/spaceship/connect_api/models/beta_tester_metric.rb +0 -43
  43. data/spaceship/lib/spaceship/connect_api/models/build.rb +0 -144
  44. data/spaceship/lib/spaceship/connect_api/models/build_beta_detail.rb +0 -56
  45. data/spaceship/lib/spaceship/connect_api/models/build_delivery.rb +0 -36
  46. data/spaceship/lib/spaceship/connect_api/models/pre_release_version.rb +0 -20
  47. data/spaceship/lib/spaceship/connect_api/models/user.rb +0 -50
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 61b4101d42b906b61eca04fa40634b785bc3422b
4
- data.tar.gz: dc2d90be2d1fd77826e2f9ae2b4d024191743cf0
3
+ metadata.gz: d91d9d80b7f521a1830910eb7fd026640a56a698
4
+ data.tar.gz: 7dccfc7b62dabaa8a56885ca65f0b074817f0157
5
5
  SHA512:
6
- metadata.gz: b6e4dcc9647440b2a8aab7ae69f2db28fb20ed0b3f27af3e416505261fc1bbd03da1576f51960a8909da5be60eb01ff0d8f4a96d57c99b2fb7c9a0014a53be51
7
- data.tar.gz: dd1d9d09003164e0e7c97d7d733f7c9e8bdd803c7c793f627db1ac08e2b5a2a24ed9c15a7199b7c74b6ad27a1b965c9c7e6986ecc6e7400125f6bf5518ee3868
6
+ metadata.gz: 040c1029f885f87674fd9d817bfc2bea1ec7dd3580c7470b4b6850d537802016ef96af40e3f8ecddff63662699e946758229dbda4c4856cfcd8630d49e5b4ffc
7
+ data.tar.gz: f33329bc76c620f62268bf5c02b638913904d85659e88bba29cf3341291d3d079be08261dabf48b162e3d8a4e177b9cded99f6d0fe0f51cc9ee23ff37de0c443
@@ -49,7 +49,7 @@ module Fastlane
49
49
  UI.message("Fetching the latest build number for #{version_number_message}")
50
50
 
51
51
  # Get latest build for optional version number and return build number if found
52
- client = Spaceship::ConnectAPI::Base.client
52
+ client = Spaceship::ConnectAPI::TestFlight.client
53
53
  build = client.get_builds(filter: filter, sort: "-version", includes: "preReleaseVersion", limit: 1).first
54
54
  if build
55
55
  build_nr = build.version
@@ -1,5 +1,5 @@
1
1
  module Fastlane
2
- VERSION = '2.126.0.beta.20190606200048'.freeze
2
+ VERSION = '2.126.0.beta.20190607200028'.freeze
3
3
  DESCRIPTION = "The easiest way to automate beta deployments and releases for your iOS and Android apps".freeze
4
4
  MINIMUM_XCODE_RELEASE = "7.0".freeze
5
5
  RUBOCOP_REQUIREMENT = '0.49.1'.freeze
@@ -1,5 +1,4 @@
1
- require 'spaceship/connect_api/models/build'
2
- require 'spaceship/connect_api/models/build_delivery'
1
+ require 'spaceship/connect_api'
3
2
 
4
3
  require_relative 'ui/ui'
5
4
 
@@ -48,12 +47,12 @@ module FastlaneCore
48
47
  watched_app_version = remove_version_leading_zeros(version: watched_app_version)
49
48
  watched_build_version = remove_version_leading_zeros(version: watched_build_version)
50
49
 
51
- build_deliveries = Spaceship::ConnectAPI::BuildDelivery.all(app_id: app_id, version: watched_app_version, build_number: watched_build_version)
50
+ build_deliveries = Spaceship::ConnectAPI::TestFlight::BuildDelivery.all(app_id: app_id, version: watched_app_version, build_number: watched_build_version)
52
51
  build_delivery = build_deliveries.first
53
52
 
54
53
  # Get processed builds when no longer in build deliveries
55
54
  if build_delivery.nil?
56
- matched_builds = Spaceship::ConnectAPI::Build.all(
55
+ matched_builds = Spaceship::ConnectAPI::TestFlight::Build.all(
57
56
  app_id: app_id,
58
57
  version: watched_app_version,
59
58
  build_number: watched_build_version,
@@ -100,14 +100,14 @@ module Pilot
100
100
  end
101
101
 
102
102
  # Get latest uploaded build if no build specified
103
- build ||= Spaceship::ConnectAPI::Build.all(app_id: app.id, sort: "-uploadedDate", limit: 1).first
103
+ build ||= Spaceship::ConnectAPI::TestFlight::Build.all(app_id: app.id, sort: "-uploadedDate", limit: 1).first
104
104
 
105
105
  # Verify the build has all the includes that we need
106
106
  # and fetch a new build if not
107
107
  if build && (!build.app || !build.build_beta_detail || !build.pre_release_version)
108
108
  UI.important("Build did include information for app, build beta detail and pre release version")
109
109
  UI.important("Fetching a new build with all the information needed")
110
- build = Spaceship::ConnectAPI::Build.get(build_id: build.id)
110
+ build = Spaceship::ConnectAPI::TestFlight::Build.get(build_id: build.id)
111
111
  end
112
112
 
113
113
  # Error out if no build
@@ -328,7 +328,7 @@ module Pilot
328
328
  uses_non_exempt_encryption = options[:uses_non_exempt_encryption]
329
329
  attributes = { usesNonExemptEncryption: uses_non_exempt_encryption }
330
330
 
331
- client = Spaceship::ConnectAPI::Base.client
331
+ client = Spaceship::ConnectAPI::TestFlight.client
332
332
  client.patch_builds(build_id: uploaded_build.id, attributes: attributes)
333
333
 
334
334
  UI.important("Export compliance has been set to '#{uses_non_exempt_encryption}'. Need to wait for build to finishing processing again...")
@@ -350,7 +350,7 @@ module Pilot
350
350
  attributes[:demoAccountRequired] = info[:demo_account_required] if info.key?(:demo_account_required)
351
351
  attributes[:notes] = info[:notes] if info.key?(:notes)
352
352
 
353
- client = Spaceship::ConnectAPI::Base.client
353
+ client = Spaceship::ConnectAPI::TestFlight.client
354
354
  client.patch_beta_app_review_detail(app_id: build.app.id, attributes: attributes)
355
355
  end
356
356
 
@@ -392,7 +392,7 @@ module Pilot
392
392
  attributes[:tvOsPrivacyPolicy] = info[:tv_os_privacy_policy_url] if info.key?(:tv_os_privacy_policy_url)
393
393
  attributes[:description] = info[:description] if info.key?(:description)
394
394
 
395
- client = Spaceship::ConnectAPI::Base.client
395
+ client = Spaceship::ConnectAPI::TestFlight.client
396
396
  if localization
397
397
  client.patch_beta_app_localizations(localization_id: localization.id, attributes: attributes)
398
398
  else
@@ -435,7 +435,7 @@ module Pilot
435
435
  attributes = {}
436
436
  attributes[:whatsNew] = self.class.sanitize_changelog(info[:whats_new]) if info.key?(:whats_new)
437
437
 
438
- client = Spaceship::ConnectAPI::Base.client
438
+ client = Spaceship::ConnectAPI::TestFlight.client
439
439
  if localization
440
440
  client.patch_beta_build_localizations(localization_id: localization.id, attributes: attributes)
441
441
  else
@@ -450,7 +450,7 @@ module Pilot
450
450
  attributes = {}
451
451
  attributes[:autoNotifyEnabled] = info[:auto_notify_enabled] if info.key?(:auto_notify_enabled)
452
452
 
453
- client = Spaceship::ConnectAPI::Base.client
453
+ client = Spaceship::ConnectAPI::TestFlight.client
454
454
  client.patch_build_beta_details(build_beta_details_id: build_beta_detail.id, attributes: attributes)
455
455
  end
456
456
  end
@@ -29,7 +29,7 @@ module Pilot
29
29
  def app
30
30
  @app_id ||= fetch_app_id
31
31
 
32
- @app ||= Spaceship::ConnectAPI::App.get(app_id: @app_id)
32
+ @app ||= Spaceship::ConnectAPI::TestFlight::App.get(app_id: @app_id)
33
33
  unless @app
34
34
  UI.user_error!("Could not find app with #{(config[:apple_id] || config[:app_identifier])}")
35
35
  end
@@ -48,7 +48,7 @@ module Pilot
48
48
  config[:app_identifier] = fetch_app_identifier
49
49
 
50
50
  if config[:app_identifier]
51
- @app ||= Spaceship::ConnectAPI::App.find(config[:app_identifier])
51
+ @app ||= Spaceship::ConnectAPI::TestFlight::App.find(config[:app_identifier])
52
52
  UI.user_error!("Couldn't find app '#{config[:app_identifier]}' on the account of '#{config[:username]}' on App Store Connect") unless @app
53
53
  @app_id ||= @app.id
54
54
  end
@@ -15,7 +15,7 @@ module Pilot
15
15
  if app
16
16
  testers = app.get_beta_testers(includes: "apps,betaTesterMetrics,betaGroups")
17
17
  else
18
- testers = Spaceship::ConnectAPI::BetaTester.all(includes: "apps,betaTesterMetrics,betaGroups")
18
+ testers = Spaceship::ConnectAPI::TestFlight::BetaTester.all(includes: "apps,betaTesterMetrics,betaGroups")
19
19
  end
20
20
 
21
21
  file = config[:testers_file_path]
@@ -41,13 +41,13 @@ module Pilot
41
41
 
42
42
  def find_app(apple_id: nil, app_identifier: nil)
43
43
  if app_identifier
44
- app = Spaceship::ConnectAPI::App.find(app_identifier)
44
+ app = Spaceship::ConnectAPI::TestFlight::App.find(app_identifier)
45
45
  UI.user_error!("Could not find an app by #{app_identifier}") unless app
46
46
  return app
47
47
  end
48
48
 
49
49
  if apple_id
50
- app = Spaceship::ConnectAPI::App.get(app_id: apple_id)
50
+ app = Spaceship::ConnectAPI::TestFlight::App.get(app_id: apple_id)
51
51
  UI.user_error!("Could not find an app by #{apple_id}") unless app
52
52
  return app
53
53
  end
@@ -83,13 +83,13 @@ module Pilot
83
83
 
84
84
  def find_app(apple_id: nil, app_identifier: nil)
85
85
  if app_identifier
86
- app = Spaceship::ConnectAPI::App.find(app_identifier)
86
+ app = Spaceship::ConnectAPI::TestFlight::App.find(app_identifier)
87
87
  UI.user_error!("Could not find an app by #{app_identifier}") unless app
88
88
  return app
89
89
  end
90
90
 
91
91
  if apple_id
92
- app = Spaceship::ConnectAPI::App.get(app_id: apple_id)
92
+ app = Spaceship::ConnectAPI::TestFlight::App.get(app_id: apple_id)
93
93
  UI.user_error!("Could not find an app by #{apple_id}") unless app
94
94
  return app
95
95
  end
@@ -1,20 +1,5 @@
1
- require 'spaceship/connect_api/client'
2
- require 'spaceship/connect_api/base'
1
+ require 'spaceship/connect_api/model'
3
2
  require 'spaceship/connect_api/response'
4
3
  require 'spaceship/connect_api/token'
5
4
 
6
- require 'spaceship/connect_api/models/model'
7
- require 'spaceship/connect_api/models/app'
8
- require 'spaceship/connect_api/models/beta_app_localization'
9
- require 'spaceship/connect_api/models/beta_build_localization'
10
- require 'spaceship/connect_api/models/beta_build_metric'
11
- require 'spaceship/connect_api/models/beta_app_review_detail'
12
- require 'spaceship/connect_api/models/beta_app_review_submission'
13
- require 'spaceship/connect_api/models/beta_group'
14
- require 'spaceship/connect_api/models/beta_tester'
15
- require 'spaceship/connect_api/models/beta_tester_metric'
16
- require 'spaceship/connect_api/models/build'
17
- require 'spaceship/connect_api/models/build_delivery'
18
- require 'spaceship/connect_api/models/build_beta_detail'
19
- require 'spaceship/connect_api/models/pre_release_version'
20
- require 'spaceship/connect_api/models/user'
5
+ require 'spaceship/connect_api/testflight/testflight'
@@ -1,4 +1,5 @@
1
1
  require_relative '../base'
2
+ require_relative './testflight/base'
2
3
 
3
4
  module Spaceship
4
5
  module ConnectAPI
@@ -11,8 +12,8 @@ module Spaceship
11
12
  end
12
13
 
13
14
  module ClassMethods
14
- def client
15
- return Spaceship::ConnectAPI::Base.client
15
+ def testflight_client
16
+ return Spaceship::ConnectAPI::TestFlight::Base.client
16
17
  end
17
18
  end
18
19
 
@@ -30,8 +31,8 @@ module Spaceship
30
31
  end
31
32
  end
32
33
 
33
- def client
34
- return Spaceship::ConnectAPI::Base.client
34
+ def testflight_client
35
+ return Spaceship::ConnectAPI::TestFlight::Base.client
35
36
  end
36
37
 
37
38
  #
@@ -1,5 +1,4 @@
1
- require_relative './base'
2
- require_relative './models/model'
1
+ require_relative './model'
3
2
 
4
3
  module Spaceship
5
4
  module ConnectAPI
@@ -7,14 +6,12 @@ module Spaceship
7
6
  include Enumerable
8
7
  attr_reader :body
9
8
  attr_reader :status
9
+ attr_reader :client
10
10
 
11
- def initialize(body: nil, status: nil)
11
+ def initialize(body: nil, status: nil, client: nil)
12
12
  @body = body
13
13
  @status = status
14
- end
15
-
16
- def client
17
- return Spaceship::ConnectAPI::Base.client
14
+ @client = client
18
15
  end
19
16
 
20
17
  def next_url
@@ -0,0 +1,41 @@
1
+ require_relative '../../base'
2
+ require_relative '../../tunes/tunes_client'
3
+
4
+ module Spaceship
5
+ module ConnectAPI
6
+ module TestFlight
7
+ class Base < Spaceship::Base
8
+ def self.client
9
+ # Verify there is a client that can be used
10
+ if Spaceship::Tunes.client
11
+ # Initialize new client if new or if team changed
12
+ if @client.nil? || @client.team_id != Spaceship::Tunes.client.team_id
13
+ @client = Client.client_with_authorization_from(Spaceship::Tunes.client)
14
+ end
15
+ end
16
+
17
+ # Need to handle not having a client but this shouldn't ever happen
18
+ raise "Please login using `Spaceship::Tunes.login('user', 'password')`" unless @client
19
+
20
+ @client
21
+ end
22
+
23
+ ##
24
+ # Have subclasses inherit the client from their superclass
25
+ #
26
+ # Essentially, we are making a class-inheritable-accessor as described here:
27
+ # https://apidock.com/rails/v4.2.7/Class/class_attribute
28
+ def self.inherited(subclass)
29
+ this_class = self
30
+ subclass.define_singleton_method(:client) do
31
+ this_class.client
32
+ end
33
+ end
34
+
35
+ def to_json
36
+ raw_data.to_json
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,553 @@
1
+ require_relative '../../client'
2
+ require_relative '../response'
3
+
4
+ module Spaceship
5
+ # rubocop:disable Metrics/ClassLength
6
+ module ConnectAPI
7
+ module TestFlight
8
+ class Client < Spaceship::Client
9
+ ##
10
+ # Spaceship HTTP client for the App Store Connect API.
11
+ #
12
+ # This client is solely responsible for the making HTTP requests and
13
+ # parsing their responses. Parameters should be either named parameters, or
14
+ # for large request data bodies, pass in anything that can resond to
15
+ # `to_json`.
16
+ #
17
+ # Each request method should validate the required parameters. A required parameter is one that would result in 400-range response if it is not supplied.
18
+ # Each request method should make only one request. For more high-level logic, put code in the data models.
19
+
20
+ def self.hostname
21
+ 'https://appstoreconnect.apple.com/iris/v1/'
22
+ end
23
+
24
+ #
25
+ # Helpers
26
+ #
27
+
28
+ def build_params(filter: nil, includes: nil, limit: nil, sort: nil, cursor: nil)
29
+ params = {}
30
+
31
+ filter = filter.delete_if { |k, v| v.nil? } if filter
32
+
33
+ params[:filter] = filter if filter && !filter.empty?
34
+ params[:include] = includes if includes
35
+ params[:limit] = limit if limit
36
+ params[:sort] = sort if sort
37
+ params[:cursor] = cursor if cursor
38
+
39
+ return params
40
+ end
41
+
42
+ def get(url_or_path, params = nil)
43
+ response = request(:get) do |req|
44
+ req.url(url_or_path)
45
+ req.options.params_encoder = Faraday::NestedParamsEncoder
46
+ req.params = params if params
47
+ end
48
+ handle_response(response)
49
+ end
50
+
51
+ def post(url_or_path, body)
52
+ response = request(:post) do |req|
53
+ req.url(url_or_path)
54
+ req.body = body.to_json
55
+ req.headers['Content-Type'] = 'application/json'
56
+ end
57
+ handle_response(response)
58
+ end
59
+
60
+ def patch(url_or_path, body)
61
+ response = request(:patch) do |req|
62
+ req.url(url_or_path)
63
+ req.body = body.to_json
64
+ req.headers['Content-Type'] = 'application/json'
65
+ end
66
+ handle_response(response)
67
+ end
68
+
69
+ def delete(url_or_path, params = nil, body = nil)
70
+ response = request(:delete) do |req|
71
+ req.url(url_or_path)
72
+ req.options.params_encoder = Faraday::NestedParamsEncoder if params
73
+ req.params = params if params
74
+ req.body = body.to_json if body
75
+ req.headers['Content-Type'] = 'application/json' if body
76
+ end
77
+ handle_response(response)
78
+ end
79
+
80
+ #
81
+ # apps
82
+ #
83
+
84
+ def get_apps(filter: {}, includes: nil, limit: nil, sort: nil)
85
+ # GET
86
+ # https://appstoreconnect.apple.com/iris/v1/apps
87
+ params = build_params(filter: filter, includes: includes, limit: limit, sort: sort)
88
+ get("apps", params)
89
+ end
90
+
91
+ def get_app(app_id: nil, includes: nil)
92
+ # GET
93
+ # https://appstoreconnect.apple.com/iris/v1/apps/<app_id>
94
+ params = build_params(filter: nil, includes: includes, limit: nil, sort: nil)
95
+ get("apps/#{app_id}", params)
96
+ end
97
+
98
+ #
99
+ # betaAppLocalizations
100
+ #
101
+
102
+ def get_beta_app_localizations(filter: {}, includes: nil, limit: nil, sort: nil)
103
+ # GET
104
+ # https://appstoreconnect.apple.com/iris/v1/betaAppLocalizations?filter[app]=<app_id>
105
+ params = build_params(filter: filter, includes: includes, limit: limit, sort: sort)
106
+ get("betaAppLocalizations", params)
107
+ end
108
+
109
+ def post_beta_app_localizations(app_id: nil, attributes: {})
110
+ # POST
111
+ # https://appstoreconnect.apple.com/iris/v1/betaAppLocalizations
112
+ path = "betaAppLocalizations"
113
+
114
+ body = {
115
+ data: {
116
+ attributes: attributes,
117
+ type: "betaAppLocalizations",
118
+ relationships: {
119
+ app: {
120
+ data: {
121
+ type: "apps",
122
+ id: app_id
123
+ }
124
+ }
125
+ }
126
+ }
127
+ }
128
+
129
+ post(path, body)
130
+ end
131
+
132
+ def patch_beta_app_localizations(localization_id: nil, attributes: {})
133
+ # PATCH
134
+ # https://appstoreconnect.apple.com/iris/v1/apps/<app_id>/betaAppLocalizations/<localization_id>
135
+ path = "betaAppLocalizations/#{localization_id}"
136
+
137
+ body = {
138
+ data: {
139
+ attributes: attributes,
140
+ id: localization_id,
141
+ type: "betaAppLocalizations"
142
+ }
143
+ }
144
+
145
+ patch(path, body)
146
+ end
147
+
148
+ #
149
+ # betaAppReviewDetails
150
+ #
151
+
152
+ def get_beta_app_review_detail(filter: {}, includes: nil, limit: nil, sort: nil)
153
+ # GET
154
+ # https://appstoreconnect.apple.com/iris/v1/betaAppReviewDetails?filter[app]=<app_id>
155
+ params = build_params(filter: filter, includes: includes, limit: limit, sort: sort)
156
+ get("betaAppReviewDetails", params)
157
+ end
158
+
159
+ def patch_beta_app_review_detail(app_id: nil, attributes: {})
160
+ # PATCH
161
+ # https://appstoreconnect.apple.com/iris/v1/apps/<app_id>/betaAppReviewDetails
162
+ path = "betaAppReviewDetails/#{app_id}"
163
+
164
+ body = {
165
+ data: {
166
+ attributes: attributes,
167
+ id: app_id,
168
+ type: "betaAppReviewDetails"
169
+ }
170
+ }
171
+
172
+ patch(path, body)
173
+ end
174
+
175
+ #
176
+ # betaAppReviewSubmissions
177
+ #
178
+
179
+ def get_beta_app_review_submissions(filter: {}, includes: nil, limit: nil, sort: nil, cursor: nil)
180
+ # GET
181
+ # https://appstoreconnect.apple.com/iris/v1/betaAppReviewSubmissions
182
+ params = build_params(filter: filter, includes: includes, limit: limit, sort: sort, cursor: cursor)
183
+ get("betaAppReviewSubmissions", params)
184
+ end
185
+
186
+ def post_beta_app_review_submissions(build_id: nil)
187
+ # POST
188
+ # https://appstoreconnect.apple.com/iris/v1/betaAppReviewSubmissions
189
+ path = "betaAppReviewSubmissions"
190
+ body = {
191
+ data: {
192
+ type: "betaAppReviewSubmissions",
193
+ relationships: {
194
+ build: {
195
+ data: {
196
+ type: "builds",
197
+ id: build_id
198
+ }
199
+ }
200
+ }
201
+ }
202
+ }
203
+
204
+ post(path, body)
205
+ end
206
+
207
+ def delete_beta_app_review_submission(beta_app_review_submission_id: nil)
208
+ # DELETE
209
+ # https://appstoreconnect.apple.com/iris/v1/betaAppReviewSubmissions/<beta_app_review_submission_id>
210
+ params = build_params(filter: nil, includes: nil, limit: nil, sort: nil, cursor: nil)
211
+ delete("betaAppReviewSubmissions/#{beta_app_review_submission_id}", params)
212
+ end
213
+
214
+ #
215
+ # betaBuildLocalizations
216
+ #
217
+
218
+ def get_beta_build_localizations(filter: {}, includes: nil, limit: nil, sort: nil)
219
+ # GET
220
+ # https://appstoreconnect.apple.com/iris/v1/betaBuildLocalizations
221
+ path = "betaBuildLocalizations"
222
+ params = build_params(filter: filter, includes: includes, limit: limit, sort: sort)
223
+ get(path, params)
224
+ end
225
+
226
+ def post_beta_build_localizations(build_id: nil, attributes: {})
227
+ # POST
228
+ # https://appstoreconnect.apple.com/iris/v1/betaBuildLocalizations
229
+ path = "betaBuildLocalizations"
230
+
231
+ body = {
232
+ data: {
233
+ attributes: attributes,
234
+ type: "betaBuildLocalizations",
235
+ relationships: {
236
+ build: {
237
+ data: {
238
+ type: "builds",
239
+ id: build_id
240
+ }
241
+ }
242
+ }
243
+ }
244
+ }
245
+
246
+ post(path, body)
247
+ end
248
+
249
+ def patch_beta_build_localizations(localization_id: nil, feedbackEmail: nil, attributes: {})
250
+ # PATCH
251
+ # https://appstoreconnect.apple.com/iris/v1/apps/<app_id>/betaBuildLocalizations
252
+ path = "betaBuildLocalizations/#{localization_id}"
253
+
254
+ body = {
255
+ data: {
256
+ attributes: attributes,
257
+ id: localization_id,
258
+ type: "betaBuildLocalizations"
259
+ }
260
+ }
261
+
262
+ patch(path, body)
263
+ end
264
+
265
+ #
266
+ # betaBuildMetrics
267
+ #
268
+
269
+ def get_beta_build_metrics(filter: {}, includes: nil, limit: nil, sort: nil)
270
+ # GET
271
+ # https://appstoreconnect.apple.com/iris/v1/betaBuildMetrics
272
+ params = build_params(filter: filter, includes: includes, limit: limit, sort: sort)
273
+ get("betaBuildMetrics", params)
274
+ end
275
+
276
+ #
277
+ # betaGroups
278
+ #
279
+
280
+ def get_beta_groups(filter: {}, includes: nil, limit: nil, sort: nil)
281
+ # GET
282
+ # https://appstoreconnect.apple.com/iris/v1/betaGroups
283
+ params = build_params(filter: filter, includes: includes, limit: limit, sort: sort)
284
+ get("betaGroups", params)
285
+ end
286
+
287
+ def add_beta_groups_to_build(build_id: nil, beta_group_ids: [])
288
+ # POST
289
+ # https://appstoreconnect.apple.com/iris/v1/builds/<build_id>/relationships/betaGroups
290
+ path = "builds/#{build_id}/relationships/betaGroups"
291
+ body = {
292
+ data: beta_group_ids.map do |id|
293
+ {
294
+ type: "betaGroups",
295
+ id: id
296
+ }
297
+ end
298
+ }
299
+
300
+ post(path, body)
301
+ end
302
+
303
+ #
304
+ # betaTesters
305
+ #
306
+
307
+ def get_beta_testers(filter: {}, includes: nil, limit: nil, sort: nil)
308
+ # GET
309
+ # https://appstoreconnect.apple.com/iris/v1/betaTesters
310
+ params = build_params(filter: filter, includes: includes, limit: limit, sort: sort)
311
+ get("betaTesters", params)
312
+ end
313
+
314
+ # beta_testers - [{email: "", firstName: "", lastName: ""}]
315
+ def post_bulk_beta_tester_assignments(beta_group_id: nil, beta_testers: nil)
316
+ # POST
317
+ # https://appstoreconnect.apple.com/iris/v1/bulkBetaTesterAssignments
318
+ beta_testers || []
319
+
320
+ beta_testers.map do |tester|
321
+ tester[:errors] = []
322
+ end
323
+
324
+ body = {
325
+ data: {
326
+ attributes: {
327
+ betaTesters: beta_testers
328
+ },
329
+ relationships: {
330
+ betaGroup: {
331
+ data: {
332
+ type: "betaGroups",
333
+ id: beta_group_id
334
+ }
335
+ }
336
+ },
337
+ type: "bulkBetaTesterAssignments"
338
+ }
339
+ }
340
+
341
+ post("bulkBetaTesterAssignments", body)
342
+ end
343
+
344
+ def delete_beta_tester_from_apps(beta_tester_id: nil, app_ids: [])
345
+ # DELETE
346
+ # https://appstoreconnect.apple.com/iris/v1/betaTesters/<beta_tester_id>/relationships/apps
347
+ path = "betaTesters/#{beta_tester_id}/relationships/apps"
348
+ body = {
349
+ data: app_ids.map do |id|
350
+ {
351
+ type: "apps",
352
+ id: id
353
+ }
354
+ end
355
+ }
356
+
357
+ delete(path, nil, body)
358
+ end
359
+
360
+ def delete_beta_tester_from_beta_groups(beta_tester_id: nil, beta_group_ids: [])
361
+ # DELETE
362
+ # https://appstoreconnect.apple.com/iris/v1/betaTesters/<beta_tester_id>/relationships/betaGroups
363
+ path = "betaTesters/#{beta_tester_id}/relationships/betaGroups"
364
+ body = {
365
+ data: beta_group_ids.map do |id|
366
+ {
367
+ type: "betaGroups",
368
+ id: id
369
+ }
370
+ end
371
+ }
372
+
373
+ delete(path, nil, body)
374
+ end
375
+
376
+ #
377
+ # betaTesterMetrics
378
+ #
379
+
380
+ def get_beta_tester_metrics(filter: {}, includes: nil, limit: nil, sort: nil)
381
+ # GET
382
+ # https://appstoreconnect.apple.com/iris/v1/betaTesterMetrics
383
+ params = build_params(filter: filter, includes: includes, limit: limit, sort: sort)
384
+ get("betaTesterMetrics", params)
385
+ end
386
+
387
+ #
388
+ # builds
389
+ #
390
+
391
+ def get_builds(filter: {}, includes: "buildBetaDetail,betaBuildMetrics", limit: 10, sort: "uploadedDate", cursor: nil)
392
+ # GET
393
+ # https://appstoreconnect.apple.com/iris/v1/builds
394
+ params = build_params(filter: filter, includes: includes, limit: limit, sort: sort, cursor: cursor)
395
+ get("builds", params)
396
+ end
397
+
398
+ def get_build(build_id: nil, includes: nil)
399
+ # GET
400
+ # https://appstoreconnect.apple.com/iris/v1/builds/<build_id>?
401
+ params = build_params(filter: nil, includes: includes, limit: nil, sort: nil, cursor: nil)
402
+ get("builds/#{build_id}", params)
403
+ end
404
+
405
+ def patch_builds(build_id: nil, attributes: {})
406
+ # PATCH
407
+ # https://appstoreconnect.apple.com/iris/v1/builds/<build_id>
408
+ path = "builds/#{build_id}"
409
+
410
+ body = {
411
+ data: {
412
+ attributes: attributes,
413
+ id: build_id,
414
+ type: "builds"
415
+ }
416
+ }
417
+
418
+ patch(path, body)
419
+ end
420
+
421
+ #
422
+ # buildBetaDetails
423
+ #
424
+
425
+ def get_build_beta_details(filter: {}, includes: nil, limit: nil, sort: nil)
426
+ # GET
427
+ # https://appstoreconnect.apple.com/iris/v1/buildBetaDetails
428
+ params = build_params(filter: filter, includes: includes, limit: limit, sort: sort)
429
+ get("buildBetaDetails", params)
430
+ end
431
+
432
+ def patch_build_beta_details(build_beta_details_id: nil, attributes: {})
433
+ # PATCH
434
+ # https://appstoreconnect.apple.com/iris/v1/buildBetaDetails/<build_beta_details_id>
435
+ path = "buildBetaDetails/#{build_beta_details_id}"
436
+
437
+ body = {
438
+ data: {
439
+ attributes: attributes,
440
+ id: build_beta_details_id,
441
+ type: "buildBetaDetails"
442
+ }
443
+ }
444
+
445
+ patch(path, body)
446
+ end
447
+
448
+ #
449
+ # buildDeliveries
450
+ #
451
+
452
+ def get_build_deliveries(filter: {}, includes: nil, limit: nil, sort: nil)
453
+ # GET
454
+ # https://appstoreconnect.apple.com/iris/v1/buildDeliveries
455
+ params = build_params(filter: filter, includes: includes, limit: limit, sort: sort)
456
+ get("buildDeliveries", params)
457
+ end
458
+
459
+ #
460
+ # preReleaseVersions
461
+ #
462
+
463
+ def get_pre_release_versions(filter: {}, includes: nil, limit: nil, sort: nil)
464
+ # GET
465
+ # https://appstoreconnect.apple.com/iris/v1/preReleaseVersions
466
+ params = build_params(filter: filter, includes: includes, limit: limit, sort: sort)
467
+ get("preReleaseVersions", params)
468
+ end
469
+
470
+ #
471
+ # users
472
+ #
473
+
474
+ def get_users(filter: {}, includes: nil, limit: nil, sort: nil)
475
+ # GET
476
+ # https://appstoreconnect.apple.com/iris/v1/users
477
+ params = build_params(filter: filter, includes: includes, limit: limit, sort: sort)
478
+ get("users", params)
479
+ end
480
+
481
+ protected
482
+
483
+ def handle_response(response)
484
+ if (200...300).cover?(response.status) && (response.body.nil? || response.body.empty?)
485
+ return
486
+ end
487
+
488
+ raise InternalServerError, "Server error got #{response.status}" if (500...600).cover?(response.status)
489
+
490
+ unless response.body.kind_of?(Hash)
491
+ raise UnexpectedResponse, response.body
492
+ end
493
+
494
+ raise UnexpectedResponse, response.body['error'] if response.body['error']
495
+
496
+ raise UnexpectedResponse, handle_errors(response) if response.body['errors']
497
+
498
+ raise UnexpectedResponse, "Temporary App Store Connect error: #{response.body}" if response.body['statusCode'] == 'ERROR'
499
+
500
+ return Spaceship::ConnectAPI::Response.new(body: response.body, status: response.status, client: self)
501
+ end
502
+
503
+ def handle_errors(response)
504
+ # Example error format
505
+ # {
506
+ # "errors" : [ {
507
+ # "id" : "ce8c391e-f858-411b-a14b-5aa26e0915f2",
508
+ # "status" : "400",
509
+ # "code" : "PARAMETER_ERROR.INVALID",
510
+ # "title" : "A parameter has an invalid value",
511
+ # "detail" : "'uploadedDate3' is not a valid field name",
512
+ # "source" : {
513
+ # "parameter" : "sort"
514
+ # }
515
+ # } ]
516
+ # }
517
+
518
+ return response.body['errors'].map do |error|
519
+ "#{error['title']} - #{error['detail']}"
520
+ end.join(" ")
521
+ end
522
+
523
+ private
524
+
525
+ # used to assert all of the named parameters are supplied values
526
+ #
527
+ # @raises NameError if the values are nil
528
+ def assert_required_params(method_name, binding)
529
+ parameter_names = method(method_name).parameters.map { |_, v| v }
530
+ parameter_names.each do |name|
531
+ if local_variable_get(binding, name).nil?
532
+ raise NameError, "`#{name}' is a required parameter"
533
+ end
534
+ end
535
+ end
536
+
537
+ def local_variable_get(binding, name)
538
+ if binding.respond_to?(:local_variable_get)
539
+ binding.local_variable_get(name)
540
+ else
541
+ binding.eval(name.to_s)
542
+ end
543
+ end
544
+
545
+ def provider_id
546
+ return team_id if self.provider.nil?
547
+ self.provider.provider_id
548
+ end
549
+ end
550
+ end
551
+ end
552
+ # rubocop:enable Metrics/ClassLength
553
+ end