fastlane 2.125.0.beta.20190531200016 → 2.125.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +70 -70
  3. data/fastlane/lib/fastlane/actions/.slack.rb.swp +0 -0
  4. data/fastlane/lib/fastlane/actions/.update_project_provisioning.rb.swp +0 -0
  5. data/fastlane/lib/fastlane/version.rb +1 -1
  6. data/fastlane/swift/Deliverfile.swift +1 -1
  7. data/fastlane/swift/FastlaneSwiftRunner/FastlaneSwiftRunner.xcodeproj/project.xcworkspace/xcuserdata/josh.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  8. data/fastlane/swift/Gymfile.swift +1 -1
  9. data/fastlane/swift/Matchfile.swift +1 -1
  10. data/fastlane/swift/Precheckfile.swift +1 -1
  11. data/fastlane/swift/Scanfile.swift +1 -1
  12. data/fastlane/swift/Screengrabfile.swift +1 -1
  13. data/fastlane/swift/Snapshotfile.swift +1 -1
  14. data/fastlane_core/lib/fastlane_core/build_watcher.rb +31 -15
  15. data/pilot/lib/pilot/.build_manager.rb.swp +0 -0
  16. data/pilot/lib/pilot/.manager.rb.swp +0 -0
  17. data/pilot/lib/pilot/build_manager.rb +133 -101
  18. data/pilot/lib/pilot/manager.rb +9 -9
  19. data/pilot/lib/pilot/tester_exporter.rb +27 -11
  20. data/pilot/lib/pilot/tester_manager.rb +48 -98
  21. data/spaceship/lib/spaceship/connect_api.rb +18 -0
  22. data/spaceship/lib/spaceship/connect_api/.DS_Store +0 -0
  23. data/spaceship/lib/spaceship/connect_api/client.rb +297 -156
  24. data/spaceship/lib/spaceship/connect_api/models/.app.rb.swp +0 -0
  25. data/spaceship/lib/spaceship/connect_api/models/.build.rb.swp +0 -0
  26. data/spaceship/lib/spaceship/connect_api/models/.model.rb.swp +0 -0
  27. data/spaceship/lib/spaceship/connect_api/models/app.rb +97 -0
  28. data/spaceship/lib/spaceship/connect_api/models/beta_app_localization.rb +28 -0
  29. data/spaceship/lib/spaceship/connect_api/models/beta_app_review_detail.rb +32 -0
  30. data/spaceship/lib/spaceship/connect_api/models/beta_app_review_submission.rb +26 -0
  31. data/spaceship/lib/spaceship/connect_api/models/beta_build_localization.rb +20 -0
  32. data/spaceship/lib/spaceship/connect_api/models/beta_build_metric.rb +24 -0
  33. data/spaceship/lib/spaceship/connect_api/models/beta_group.rb +41 -0
  34. data/spaceship/lib/spaceship/connect_api/models/beta_tester.rb +56 -0
  35. data/spaceship/lib/spaceship/connect_api/models/beta_tester_metric.rb +43 -0
  36. data/spaceship/lib/spaceship/connect_api/models/build.rb +144 -0
  37. data/spaceship/lib/spaceship/connect_api/models/build_beta_detail.rb +56 -0
  38. data/spaceship/lib/spaceship/connect_api/models/build_delivery.rb +36 -0
  39. data/spaceship/lib/spaceship/connect_api/models/model.rb +165 -0
  40. data/spaceship/lib/spaceship/connect_api/models/pre_release_version.rb +20 -0
  41. data/spaceship/lib/spaceship/connect_api/models/user.rb +50 -0
  42. data/spaceship/lib/spaceship/connect_api/response.rb +70 -0
  43. data/spaceship/lib/spaceship/connect_api/token.rb +44 -0
  44. data/spaceship/lib/spaceship/test_flight/build_trains.rb +1 -1
  45. metadata +73 -33
@@ -27,9 +27,9 @@ module Pilot
27
27
 
28
28
  # The app object we're currently using
29
29
  def app
30
- @apple_id ||= fetch_apple_id
30
+ @app_id ||= fetch_app_id
31
31
 
32
- @app ||= Spaceship::Tunes::Application.find(@apple_id)
32
+ @app ||= Spaceship::ConnectAPI::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
@@ -42,20 +42,20 @@ module Pilot
42
42
  # Config Related
43
43
  ################
44
44
 
45
- def fetch_apple_id
46
- @apple_id ||= config[:apple_id]
47
- return @apple_id if @apple_id
45
+ def fetch_app_id
46
+ @app_id ||= config[:apple_id]
47
+ return @app_id if @app_id
48
48
  config[:app_identifier] = fetch_app_identifier
49
49
 
50
50
  if config[:app_identifier]
51
- @app ||= Spaceship::Tunes::Application.find(config[:app_identifier])
51
+ @app ||= Spaceship::ConnectAPI::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
- apple_id ||= @app.apple_id
53
+ @app_id ||= @app.id
54
54
  end
55
55
 
56
- apple_id ||= UI.input("Could not automatically find the app ID, please enter it here (e.g. 956814360): ")
56
+ @app_id ||= UI.input("Could not automatically find the app ID, please enter it here (e.g. 956814360): ")
57
57
 
58
- return apple_id
58
+ return @app_id
59
59
  end
60
60
 
61
61
  def fetch_app_identifier
@@ -1,5 +1,4 @@
1
1
  require 'spaceship/tunes/application'
2
- require 'spaceship/test_flight/tester'
3
2
  require_relative 'tester_util'
4
3
  require_relative 'module'
5
4
  require_relative 'manager'
@@ -12,13 +11,11 @@ module Pilot
12
11
  start(options)
13
12
  require 'csv'
14
13
 
15
- app_filter = (config[:apple_id] || config[:app_identifier])
16
- if app_filter
17
- app = Spaceship::Tunes::Application.find(app_filter)
18
-
19
- testers = Spaceship::TestFlight::Tester.all(app_id: app.apple_id)
14
+ app = find_app(apple_id: options[:apple_id], app_identifier: options[:app_identifier])
15
+ if app
16
+ testers = app.get_beta_testers(includes: "apps,betaTesterMetrics,betaGroups")
20
17
  else
21
- testers = Spaceship::TestFlight::Tester.all
18
+ testers = Spaceship::ConnectAPI::BetaTester.all(includes: "apps,betaTesterMetrics,betaGroups")
22
19
  end
23
20
 
24
21
  file = config[:testers_file_path]
@@ -27,10 +24,13 @@ module Pilot
27
24
  csv << ['First', 'Last', 'Email', 'Groups', 'Installed Version', 'Install Date']
28
25
 
29
26
  testers.each do |tester|
30
- group_names = tester.groups.join(";") || ""
31
- latest_install_info = tester.latest_install_info
32
- install_version = latest_install_info["latestInstalledShortVersion"] || ""
33
- pretty_date = tester.pretty_install_date || ""
27
+ group_names = tester.beta_groups.map(&:name).join(";") || ""
28
+
29
+ metric = (tester.beta_tester_metrics || []).first
30
+ if metric.installed?
31
+ install_version = "#{metric.installed_cf_bundle_short_version_string} (#{metric.installed_cf_bundle_version})"
32
+ pretty_date = metric.installed_cf_bundle_version
33
+ end
34
34
 
35
35
  csv << [tester.first_name, tester.last_name, tester.email, group_names, install_version, pretty_date]
36
36
  end
@@ -38,5 +38,21 @@ module Pilot
38
38
  UI.success("Successfully exported CSV to #{file}")
39
39
  end
40
40
  end
41
+
42
+ def find_app(apple_id: nil, app_identifier: nil)
43
+ if app_identifier
44
+ app = Spaceship::ConnectAPI::App.find(app_identifier)
45
+ UI.user_error!("Could not find an app by #{app_identifier}") unless app
46
+ return app
47
+ end
48
+
49
+ if apple_id
50
+ app = Spaceship::ConnectAPI::App.get(app_id: apple_id)
51
+ UI.user_error!("Could not find an app by #{apple_id}") unless app
52
+ return app
53
+ end
54
+
55
+ UI.user_error!("You must include an `app_identifier` to `list_testers`")
56
+ end
41
57
  end
42
58
  end
@@ -7,35 +7,30 @@ module Pilot
7
7
  class TesterManager < Manager
8
8
  def add_tester(options)
9
9
  start(options)
10
- app = find_app(app_filter: config[:apple_id] || config[:app_identifier])
10
+ app = find_app(apple_id: config[:apple_id], app_identifier: config[:app_identifier])
11
11
  UI.user_error!("You must provide either a Apple ID for the app (with the `:apple_id` option) or app identifier (with the `:app_identifier` option)") unless app
12
12
 
13
13
  groups_param = config[:groups]
14
14
  UI.user_error!("You must provide 1 or more groups (with the `:groups` option)") unless groups_param
15
15
 
16
- tester = find_app_tester(email: config[:email], app: app)
17
- tester ||= create_tester(
18
- email: config[:email],
19
- first_name: config[:first_name],
20
- last_name: config[:last_name],
21
- app: app
22
- )
23
- begin
24
- # Groups are now required
25
- groups = Spaceship::TestFlight::Group.add_tester_to_groups!(tester: tester, app: app, groups: config[:groups])
26
- group_names = groups.map(&:name).join(", ")
27
- UI.success("Successfully added tester to group(s): #{group_names} in app: #{app.name}")
28
- rescue => ex
29
- UI.error("Could not add #{tester.email} to app: #{app.name}")
30
- raise ex
16
+ app.get_beta_groups.select do |group|
17
+ next unless groups_param.include?(group.name)
18
+ user = {
19
+ email: config[:email],
20
+ firstName: config[:first_name],
21
+ lastName: config[:last_name]
22
+ }
23
+ group.post_bulk_beta_tester_assignments(beta_testers: [user])
31
24
  end
25
+
26
+ group_names = groups_param.join(';')
27
+ UI.success("Successfully added tester #{config[:email]} to app #{app.name} in group(s) #{group_names}")
32
28
  end
33
29
 
34
30
  def find_tester(options)
35
31
  start(options)
36
32
 
37
- app_filter = (config[:apple_id] || config[:app_identifier])
38
- app = find_app(app_filter: app_filter)
33
+ app = find_app(apple_id: config[:apple_id], app_identifier: config[:app_identifier])
39
34
 
40
35
  tester = find_app_tester(email: config[:email], app: app)
41
36
  UI.user_error!("Tester #{config[:email]} not found") unless tester
@@ -47,35 +42,24 @@ module Pilot
47
42
  def remove_tester(options)
48
43
  start(options)
49
44
 
50
- app_filter = (config[:apple_id] || config[:app_identifier])
51
- app = find_app(app_filter: app_filter)
45
+ app = find_app(apple_id: config[:apple_id], app_identifier: config[:app_identifier])
52
46
 
53
47
  tester = find_app_tester(email: config[:email], app: app)
54
48
  UI.user_error!("Tester #{config[:email]} not found") unless tester
55
49
 
56
- unless app
57
- tester.delete!
58
- UI.success("Successfully removed tester #{tester.email} from Users and Roles")
59
- return
60
- end
61
-
62
50
  begin
63
51
  # If no groups are passed to options, remove the tester from the app-level,
64
52
  # otherwise remove the tester from the groups specified.
65
53
  if config[:groups].nil?
66
- test_flight_testers = Spaceship::TestFlight::Tester.search(app_id: app.apple_id, text: tester.email, is_email_exact_match: true)
67
-
68
- if test_flight_testers.length > 1
69
- UI.user_error!("Could not remove #{tester.email} from app: #{app.name}, reason: too many matches: #{test_flight_testers}")
70
- elsif test_flight_testers.length == 0
71
- UI.user_error!("Could not remove #{tester.email} from app: #{app.name}, reason: unable to find tester on app")
72
- end
73
- test_flight_tester = test_flight_testers.first
74
- test_flight_tester.remove_from_app!(app_id: app.apple_id)
75
- UI.success("Successfully removed tester, #{test_flight_tester.email}, from app: #{app.name}")
54
+ tester.delete_from_apps(apps: [app])
55
+ UI.success("Successfully removed tester #{tester.email} from app: #{app.name}")
76
56
  else
77
- groups = Spaceship::TestFlight::Group.remove_tester_from_groups!(tester: tester, app: app, groups: config[:groups])
78
- group_names = groups.map(&:name).join(", ")
57
+ groups = tester.beta_groups.select do |group|
58
+ config[:groups].include?(group.name)
59
+ end
60
+ tester.delete_from_beta_groups(beta_groups: groups)
61
+
62
+ group_names = groups.map(&:name)
79
63
  UI.success("Successfully removed tester #{tester.email} from app #{app.name} in group(s) #{group_names}")
80
64
  end
81
65
  rescue => ex
@@ -87,9 +71,9 @@ module Pilot
87
71
  def list_testers(options)
88
72
  start(options)
89
73
 
90
- app_filter = (config[:apple_id] || config[:app_identifier])
91
- if app_filter
92
- list_testers_by_app(app_filter)
74
+ app = find_app(apple_id: config[:apple_id], app_identifier: config[:app_identifier])
75
+ if app
76
+ list_testers_by_app(app)
93
77
  else
94
78
  UI.user_error!("You must include an `app_identifier` to `list_testers`")
95
79
  end
@@ -97,30 +81,24 @@ module Pilot
97
81
 
98
82
  private
99
83
 
100
- def find_app(app_filter: nil)
101
- if app_filter
102
- app = Spaceship::Tunes::Application.find(app_filter)
103
- UI.user_error!("Could not find an app by #{app_filter}") unless app
84
+ def find_app(apple_id: nil, app_identifier: nil)
85
+ if app_identifier
86
+ app = Spaceship::ConnectAPI::App.find(app_identifier)
87
+ UI.user_error!("Could not find an app by #{app_identifier}") unless app
88
+ return app
89
+ end
90
+
91
+ if apple_id
92
+ app = Spaceship::ConnectAPI::App.get(app_id: apple_id)
93
+ UI.user_error!("Could not find an app by #{apple_id}") unless app
104
94
  return app
105
95
  end
106
- nil
96
+
97
+ UI.user_error!("You must include an `app_identifier` to `list_testers`")
107
98
  end
108
99
 
109
100
  def find_app_tester(email: nil, app: nil)
110
- current_user = find_current_user
111
- app_apple_id = app.nil? ? nil : app.apple_id
112
-
113
- if current_user.admin?
114
- tester = Spaceship::TestFlight::Tester.find(app_id: app_apple_id, email: email)
115
- elsif current_user.app_manager?
116
- unless app_apple_id
117
- UI.user_error!("Account #{current_user.email_address} is only an 'App Manager' and therefore you must also define what app this tester (#{email}) should be added to")
118
- end
119
- tester = Spaceship::TestFlight::Tester.find(app_id: app_apple_id, email: email)
120
- else
121
- UI.user_error!("Account #{current_user.email_address} doesn't have a role that is allowed to administer app testers, current roles: #{current_user.roles}")
122
- tester = nil
123
- end
101
+ tester = app.get_beta_testers(filter: { email: email }, includes: "apps,betaTesterMetrics,betaGroups").first
124
102
 
125
103
  if tester
126
104
  UI.success("Found existing tester #{email}")
@@ -129,46 +107,16 @@ module Pilot
129
107
  return tester
130
108
  end
131
109
 
132
- def find_current_user
133
- current_user_email = Spaceship::Tunes.client.user_email
134
- current_user_apple_id = Spaceship::Tunes.client.user
135
-
136
- current_user = Spaceship::Tunes::Members.find(current_user_email)
137
- unless current_user
138
- UI.user_error!("Unable to find a member for AppleID: #{current_user_apple_id}, email: #{current_user_email}")
139
- end
140
- return current_user
141
- end
142
-
143
- def create_tester(email: nil, first_name: nil, last_name: nil, app: nil)
144
- current_user = find_current_user
145
- if current_user.admin? || current_user.app_manager?
146
- Spaceship::TestFlight::Tester.create_app_level_tester(app_id: app.apple_id,
147
- first_name: first_name || '',
148
- last_name: last_name || '',
149
- email: email)
150
-
151
- UI.success("Successfully added tester: #{email} to app: #{app.name}")
152
- return Spaceship::TestFlight::Tester.find(app_id: app.apple_id, email: email)
153
- else
154
- UI.user_error!("Current account doesn't have permission to create a tester")
155
- end
156
- rescue => ex
157
- UI.error("Could not create tester #{email}")
158
- raise ex
159
- end
110
+ def list_testers_by_app(app)
111
+ testers = app.get_beta_testers(includes: "apps,betaTesterMetrics,betaGroups")
160
112
 
161
- def list_testers_by_app(app_filter)
162
- app = Spaceship::Tunes::Application.find(app_filter)
163
- UI.user_error!("Couldn't find app with '#{app_filter}'") unless app
164
- testers = Spaceship::TestFlight::Tester.all(app_id: app.apple_id)
165
113
  list_by_app(testers, "All Testers")
166
114
  end
167
115
 
168
116
  def list_by_app(all_testers, title)
169
117
  headers = ["First", "Last", "Email", "Groups"]
170
118
  list(all_testers, "#{title} (#{all_testers.count})", headers) do |tester|
171
- tester_groups = tester.groups.nil? ? nil : tester.groups.join(";")
119
+ tester_groups = tester.beta_groups.nil? ? nil : tester.beta_groups.map(&:name).join(";")
172
120
  [
173
121
  tester.first_name,
174
122
  tester.last_name,
@@ -200,13 +148,15 @@ module Pilot
200
148
  rows << ["Last name", tester.last_name]
201
149
  rows << ["Email", tester.email]
202
150
 
203
- if tester.groups.to_s.length > 0
204
- rows << ["Groups", tester.groups.join(";")]
151
+ if tester.beta_groups
152
+ rows << ["Groups", tester.beta_groups.map(&:name).join(";")]
205
153
  end
206
154
 
207
- if tester.latest_installed_date
208
- rows << ["Latest Version", "#{tester.latest_install_info['latestInstalledShortVersion']} (#{tester.latest_install_info['latestInstalledVersion']})"]
209
- rows << ["Latest Install Date", tester.pretty_install_date]
155
+ metric = (tester.beta_tester_metrics || []).first
156
+ if metric.installed?
157
+ rows << ["Latest Version", "#{metric.installed_cf_bundle_short_version_string} (#{metric.installed_cf_bundle_version})"]
158
+ rows << ["Latest Install Date", metric.installed_cf_bundle_version]
159
+ rows << ["Installed", metric.installed?]
210
160
  end
211
161
 
212
162
  puts(Terminal::Table.new(
@@ -1,2 +1,20 @@
1
1
  require 'spaceship/connect_api/client'
2
2
  require 'spaceship/connect_api/base'
3
+ require 'spaceship/connect_api/response'
4
+ require 'spaceship/connect_api/token'
5
+
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'
@@ -1,6 +1,8 @@
1
1
  require_relative '../client'
2
+ require_relative './response'
2
3
 
3
4
  module Spaceship
5
+ # rubocop:disable Metrics/ClassLength
4
6
  module ConnectAPI
5
7
  class Client < Spaceship::Client
6
8
  ##
@@ -18,9 +20,15 @@ module Spaceship
18
20
  'https://appstoreconnect.apple.com/iris/v1/'
19
21
  end
20
22
 
23
+ #
24
+ # Helpers
25
+ #
26
+
21
27
  def build_params(filter: nil, includes: nil, limit: nil, sort: nil, cursor: nil)
22
28
  params = {}
23
29
 
30
+ filter = filter.delete_if { |k, v| v.nil? } if filter
31
+
24
32
  params[:filter] = filter if filter && !filter.empty?
25
33
  params[:include] = includes if includes
26
34
  params[:limit] = limit if limit
@@ -30,62 +38,71 @@ module Spaceship
30
38
  return params
31
39
  end
32
40
 
33
- def get_beta_app_review_detail(filter: {}, includes: nil, limit: nil, sort: nil)
34
- # GET
35
- # https://appstoreconnect.apple.com/iris/v1/betaAppReviewDetails?filter[app]=<app_id>
36
- params = build_params(filter: filter, includes: includes, limit: limit, sort: sort)
37
-
38
- response = request(:get, "betaAppReviewDetails") do |req|
41
+ def get(url_or_path, params = nil)
42
+ response = request(:get) do |req|
43
+ req.url(url_or_path)
39
44
  req.options.params_encoder = Faraday::NestedParamsEncoder
40
- req.params = params
45
+ req.params = params if params
41
46
  end
42
47
  handle_response(response)
43
48
  end
44
49
 
45
- def patch_beta_app_review_detail(app_id: nil, attributes: {})
46
- # PATCH
47
- # https://appstoreconnect.apple.com/iris/v1/apps/<app_id>/betaAppReviewDetails
48
- path = "betaAppReviewDetails/#{app_id}"
49
-
50
- body = {
51
- data: {
52
- attributes: attributes,
53
- id: app_id,
54
- type: "betaAppReviewDetails"
55
- }
56
- }
50
+ def post(url_or_path, body)
51
+ response = request(:post) do |req|
52
+ req.url(url_or_path)
53
+ req.body = body.to_json
54
+ req.headers['Content-Type'] = 'application/json'
55
+ end
56
+ handle_response(response)
57
+ end
57
58
 
59
+ def patch(url_or_path, body)
58
60
  response = request(:patch) do |req|
59
- req.url(path)
61
+ req.url(url_or_path)
60
62
  req.body = body.to_json
61
63
  req.headers['Content-Type'] = 'application/json'
62
64
  end
63
65
  handle_response(response)
64
66
  end
65
67
 
66
- def get_beta_app_localizations(filter: {}, includes: nil, limit: nil, sort: nil)
67
- # GET
68
- # https://appstoreconnect.apple.com/iris/v1/betaAppLocalizations?filter[app]=<app_id>
69
- params = build_params(filter: filter, includes: includes, limit: limit, sort: sort)
70
-
71
- response = request(:get, "betaAppLocalizations") do |req|
72
- req.options.params_encoder = Faraday::NestedParamsEncoder
73
- req.params = params
68
+ def delete(url_or_path, params = nil, body = nil)
69
+ response = request(:delete) do |req|
70
+ req.url(url_or_path)
71
+ req.options.params_encoder = Faraday::NestedParamsEncoder if params
72
+ req.params = params if params
73
+ req.body = body.to_json if body
74
+ req.headers['Content-Type'] = 'application/json' if body
74
75
  end
75
76
  handle_response(response)
76
77
  end
77
78
 
78
- def get_beta_build_localizations(filter: {}, includes: nil, limit: nil, sort: nil)
79
+ #
80
+ # apps
81
+ #
82
+
83
+ def get_apps(filter: {}, includes: nil, limit: nil, sort: nil)
79
84
  # GET
80
- # https://appstoreconnect.apple.com/iris/v1/betaBuildLocalizations?filter[build]=<build_id>
81
- path = "betaBuildLocalizations"
85
+ # https://appstoreconnect.apple.com/iris/v1/apps
82
86
  params = build_params(filter: filter, includes: includes, limit: limit, sort: sort)
87
+ get("apps", params)
88
+ end
83
89
 
84
- response = request(:get, path) do |req|
85
- req.options.params_encoder = Faraday::NestedParamsEncoder
86
- req.params = params
87
- end
88
- handle_response(response)
90
+ def get_app(app_id: nil, includes: nil)
91
+ # GET
92
+ # https://appstoreconnect.apple.com/iris/v1/apps/<app_id>
93
+ params = build_params(filter: nil, includes: includes, limit: nil, sort: nil)
94
+ get("apps/#{app_id}", params)
95
+ end
96
+
97
+ #
98
+ # betaAppLocalizations
99
+ #
100
+
101
+ def get_beta_app_localizations(filter: {}, includes: nil, limit: nil, sort: nil)
102
+ # GET
103
+ # https://appstoreconnect.apple.com/iris/v1/betaAppLocalizations?filter[app]=<app_id>
104
+ params = build_params(filter: filter, includes: includes, limit: limit, sort: sort)
105
+ get("betaAppLocalizations", params)
89
106
  end
90
107
 
91
108
  def post_beta_app_localizations(app_id: nil, attributes: {})
@@ -108,12 +125,7 @@ module Spaceship
108
125
  }
109
126
  }
110
127
 
111
- response = request(:post) do |req|
112
- req.url(path)
113
- req.body = body.to_json
114
- req.headers['Content-Type'] = 'application/json'
115
- end
116
- handle_response(response)
128
+ post(path, body)
117
129
  end
118
130
 
119
131
  def patch_beta_app_localizations(localization_id: nil, attributes: {})
@@ -129,12 +141,85 @@ module Spaceship
129
141
  }
130
142
  }
131
143
 
132
- response = request(:patch) do |req|
133
- req.url(path)
134
- req.body = body.to_json
135
- req.headers['Content-Type'] = 'application/json'
136
- end
137
- handle_response(response)
144
+ patch(path, body)
145
+ end
146
+
147
+ #
148
+ # betaAppReviewDetails
149
+ #
150
+
151
+ def get_beta_app_review_detail(filter: {}, includes: nil, limit: nil, sort: nil)
152
+ # GET
153
+ # https://appstoreconnect.apple.com/iris/v1/betaAppReviewDetails?filter[app]=<app_id>
154
+ params = build_params(filter: filter, includes: includes, limit: limit, sort: sort)
155
+ get("betaAppReviewDetails", params)
156
+ end
157
+
158
+ def patch_beta_app_review_detail(app_id: nil, attributes: {})
159
+ # PATCH
160
+ # https://appstoreconnect.apple.com/iris/v1/apps/<app_id>/betaAppReviewDetails
161
+ path = "betaAppReviewDetails/#{app_id}"
162
+
163
+ body = {
164
+ data: {
165
+ attributes: attributes,
166
+ id: app_id,
167
+ type: "betaAppReviewDetails"
168
+ }
169
+ }
170
+
171
+ patch(path, body)
172
+ end
173
+
174
+ #
175
+ # betaAppReviewSubmissions
176
+ #
177
+
178
+ def get_beta_app_review_submissions(filter: {}, includes: nil, limit: nil, sort: nil, cursor: nil)
179
+ # GET
180
+ # https://appstoreconnect.apple.com/iris/v1/betaAppReviewSubmissions
181
+ params = build_params(filter: filter, includes: includes, limit: limit, sort: sort, cursor: cursor)
182
+ get("betaAppReviewSubmissions", params)
183
+ end
184
+
185
+ def post_beta_app_review_submissions(build_id: nil)
186
+ # POST
187
+ # https://appstoreconnect.apple.com/iris/v1/betaAppReviewSubmissions
188
+ path = "betaAppReviewSubmissions"
189
+ body = {
190
+ data: {
191
+ type: "betaAppReviewSubmissions",
192
+ relationships: {
193
+ build: {
194
+ data: {
195
+ type: "builds",
196
+ id: build_id
197
+ }
198
+ }
199
+ }
200
+ }
201
+ }
202
+
203
+ post(path, body)
204
+ end
205
+
206
+ def delete_beta_app_review_submission(beta_app_review_submission_id: nil)
207
+ # DELETE
208
+ # https://appstoreconnect.apple.com/iris/v1/betaAppReviewSubmissions/<beta_app_review_submission_id>
209
+ params = build_params(filter: nil, includes: nil, limit: nil, sort: nil, cursor: nil)
210
+ delete("betaAppReviewSubmissions/#{beta_app_review_submission_id}", params)
211
+ end
212
+
213
+ #
214
+ # betaBuildLocalizations
215
+ #
216
+
217
+ def get_beta_build_localizations(filter: {}, includes: nil, limit: nil, sort: nil)
218
+ # GET
219
+ # https://appstoreconnect.apple.com/iris/v1/betaBuildLocalizations
220
+ path = "betaBuildLocalizations"
221
+ params = build_params(filter: filter, includes: includes, limit: limit, sort: sort)
222
+ get(path, params)
138
223
  end
139
224
 
140
225
  def post_beta_build_localizations(build_id: nil, attributes: {})
@@ -157,12 +242,7 @@ module Spaceship
157
242
  }
158
243
  }
159
244
 
160
- response = request(:post) do |req|
161
- req.url(path)
162
- req.body = body.to_json
163
- req.headers['Content-Type'] = 'application/json'
164
- end
165
- handle_response(response)
245
+ post(path, body)
166
246
  end
167
247
 
168
248
  def patch_beta_build_localizations(localization_id: nil, feedbackEmail: nil, attributes: {})
@@ -178,69 +258,147 @@ module Spaceship
178
258
  }
179
259
  }
180
260
 
181
- response = request(:patch) do |req|
182
- req.url(path)
183
- req.body = body.to_json
184
- req.headers['Content-Type'] = 'application/json'
185
- end
186
- handle_response(response)
261
+ patch(path, body)
187
262
  end
188
263
 
189
- def get_build_beta_details(filter: {}, includes: nil, limit: nil, sort: nil)
264
+ #
265
+ # betaBuildMetrics
266
+ #
267
+
268
+ def get_beta_build_metrics(filter: {}, includes: nil, limit: nil, sort: nil)
190
269
  # GET
191
- # https://appstoreconnect.apple.com/iris/v1/buildBetaDetails
270
+ # https://appstoreconnect.apple.com/iris/v1/betaBuildMetrics
192
271
  params = build_params(filter: filter, includes: includes, limit: limit, sort: sort)
272
+ get("betaBuildMetrics", params)
273
+ end
193
274
 
194
- response = request(:get, "buildBetaDetails") do |req|
195
- req.options.params_encoder = Faraday::NestedParamsEncoder
196
- req.params = params
197
- end
198
- handle_response(response)
275
+ #
276
+ # betaGroups
277
+ #
278
+
279
+ def get_beta_groups(filter: {}, includes: nil, limit: nil, sort: nil)
280
+ # GET
281
+ # https://appstoreconnect.apple.com/iris/v1/betaGroups
282
+ params = build_params(filter: filter, includes: includes, limit: limit, sort: sort)
283
+ get("betaGroups", params)
199
284
  end
200
285
 
201
- def patch_build_beta_details(build_beta_details_id: nil, attributes: {})
202
- # PATCH
203
- # https://appstoreconnect.apple.com/iris/v1/buildBetaDetails/<build_beta_details_id>
204
- path = "buildBetaDetails/#{build_beta_details_id}"
286
+ def add_beta_groups_to_build(build_id: nil, beta_group_ids: [])
287
+ # POST
288
+ # https://appstoreconnect.apple.com/iris/v1/builds/<build_id>/relationships/betaGroups
289
+ path = "builds/#{build_id}/relationships/betaGroups"
290
+ body = {
291
+ data: beta_group_ids.map do |id|
292
+ {
293
+ type: "betaGroups",
294
+ id: id
295
+ }
296
+ end
297
+ }
298
+
299
+ post(path, body)
300
+ end
301
+
302
+ #
303
+ # betaTesters
304
+ #
305
+
306
+ def get_beta_testers(filter: {}, includes: nil, limit: nil, sort: nil)
307
+ # GET
308
+ # https://appstoreconnect.apple.com/iris/v1/betaTesters
309
+ params = build_params(filter: filter, includes: includes, limit: limit, sort: sort)
310
+ get("betaTesters", params)
311
+ end
312
+
313
+ # beta_testers - [{email: "", firstName: "", lastName: ""}]
314
+ def post_bulk_beta_tester_assignments(beta_group_id: nil, beta_testers: nil)
315
+ # POST
316
+ # https://appstoreconnect.apple.com/iris/v1/bulkBetaTesterAssignments
317
+ beta_testers || []
318
+
319
+ beta_testers.map do |tester|
320
+ tester[:errors] = []
321
+ end
205
322
 
206
323
  body = {
207
324
  data: {
208
- attributes: attributes,
209
- id: build_beta_details_id,
210
- type: "buildBetaDetails"
325
+ attributes: {
326
+ betaTesters: beta_testers
327
+ },
328
+ relationships: {
329
+ betaGroup: {
330
+ data: {
331
+ type: "betaGroups",
332
+ id: beta_group_id
333
+ }
334
+ }
335
+ },
336
+ type: "bulkBetaTesterAssignments"
211
337
  }
212
338
  }
213
339
 
214
- response = request(:patch) do |req|
215
- req.url(path)
216
- req.body = body.to_json
217
- req.headers['Content-Type'] = 'application/json'
218
- end
219
- handle_response(response)
340
+ post("bulkBetaTesterAssignments", body)
220
341
  end
221
342
 
222
- def get_build_deliveries(filter: {}, includes: nil, limit: 10, sort: nil)
343
+ def delete_beta_tester_from_apps(beta_tester_id: nil, app_ids: [])
344
+ # DELETE
345
+ # https://appstoreconnect.apple.com/iris/v1/betaTesters/<beta_tester_id>/relationships/apps
346
+ path = "betaTesters/#{beta_tester_id}/relationships/apps"
347
+ body = {
348
+ data: app_ids.map do |id|
349
+ {
350
+ type: "apps",
351
+ id: id
352
+ }
353
+ end
354
+ }
355
+
356
+ delete(path, nil, body)
357
+ end
358
+
359
+ def delete_beta_tester_from_beta_groups(beta_tester_id: nil, beta_group_ids: [])
360
+ # DELETE
361
+ # https://appstoreconnect.apple.com/iris/v1/betaTesters/<beta_tester_id>/relationships/betaGroups
362
+ path = "betaTesters/#{beta_tester_id}/relationships/betaGroups"
363
+ body = {
364
+ data: beta_group_ids.map do |id|
365
+ {
366
+ type: "betaGroups",
367
+ id: id
368
+ }
369
+ end
370
+ }
371
+
372
+ delete(path, nil, body)
373
+ end
374
+
375
+ #
376
+ # betaTesterMetrics
377
+ #
378
+
379
+ def get_beta_tester_metrics(filter: {}, includes: nil, limit: nil, sort: nil)
223
380
  # GET
224
- # https://appstoreconnect.apple.com/iris/v1/buildDeliveries
381
+ # https://appstoreconnect.apple.com/iris/v1/betaTesterMetrics
225
382
  params = build_params(filter: filter, includes: includes, limit: limit, sort: sort)
226
-
227
- response = request(:get, "buildDeliveries") do |req|
228
- req.options.params_encoder = Faraday::NestedParamsEncoder
229
- req.params = params
230
- end
231
- handle_response(response)
383
+ get("betaTesterMetrics", params)
232
384
  end
233
385
 
234
- def get_builds(filter: {}, includes: "buildBetaDetail,betaBuildMetrics", limit: 10, sort: "uploadedDate", cursor: nil, only_data: true)
386
+ #
387
+ # builds
388
+ #
389
+
390
+ def get_builds(filter: {}, includes: "buildBetaDetail,betaBuildMetrics", limit: 10, sort: "uploadedDate", cursor: nil)
235
391
  # GET
236
392
  # https://appstoreconnect.apple.com/iris/v1/builds
237
393
  params = build_params(filter: filter, includes: includes, limit: limit, sort: sort, cursor: cursor)
394
+ get("builds", params)
395
+ end
238
396
 
239
- response = request(:get, "builds") do |req|
240
- req.options.params_encoder = Faraday::NestedParamsEncoder
241
- req.params = params
242
- end
243
- handle_response(response, only_data: only_data)
397
+ def get_build(build_id: nil, includes: nil)
398
+ # GET
399
+ # https://appstoreconnect.apple.com/iris/v1/builds/<build_id>?
400
+ params = build_params(filter: nil, includes: includes, limit: nil, sort: nil, cursor: nil)
401
+ get("builds/#{build_id}", params)
244
402
  end
245
403
 
246
404
  def patch_builds(build_id: nil, attributes: {})
@@ -256,88 +414,72 @@ module Spaceship
256
414
  }
257
415
  }
258
416
 
259
- response = request(:patch) do |req|
260
- req.url(path)
261
- req.body = body.to_json
262
- req.headers['Content-Type'] = 'application/json'
263
- end
264
- handle_response(response)
417
+ patch(path, body)
265
418
  end
266
419
 
267
- def post_beta_app_review_submissions(build_id: nil)
268
- # POST
269
- # https://appstoreconnect.apple.com/iris/v1/betaAppReviewSubmissions
420
+ #
421
+ # buildBetaDetails
422
+ #
423
+
424
+ def get_build_beta_details(filter: {}, includes: nil, limit: nil, sort: nil)
425
+ # GET
426
+ # https://appstoreconnect.apple.com/iris/v1/buildBetaDetails
427
+ params = build_params(filter: filter, includes: includes, limit: limit, sort: sort)
428
+ get("buildBetaDetails", params)
429
+ end
430
+
431
+ def patch_build_beta_details(build_beta_details_id: nil, attributes: {})
432
+ # PATCH
433
+ # https://appstoreconnect.apple.com/iris/v1/buildBetaDetails/<build_beta_details_id>
434
+ path = "buildBetaDetails/#{build_beta_details_id}"
270
435
 
271
436
  body = {
272
437
  data: {
273
- type: "betaAppReviewSubmissions",
274
- relationships: {
275
- build: {
276
- data: {
277
- type: "builds",
278
- id: build_id
279
- }
280
- }
281
- }
438
+ attributes: attributes,
439
+ id: build_beta_details_id,
440
+ type: "buildBetaDetails"
282
441
  }
283
442
  }
284
443
 
285
- response = request(:post) do |req|
286
- req.url("betaAppReviewSubmissions")
287
- req.body = body.to_json
288
- req.headers['Content-Type'] = 'application/json'
289
- end
290
- handle_response(response)
444
+ patch(path, body)
291
445
  end
292
446
 
293
- def get_pre_release_versions(filter: {}, includes: nil, limit: 40, sort: nil)
447
+ #
448
+ # buildDeliveries
449
+ #
450
+
451
+ def get_build_deliveries(filter: {}, includes: nil, limit: nil, sort: nil)
294
452
  # GET
295
- # https://appstoreconnect.apple.com/iris/v1/preReleaseVersions
453
+ # https://appstoreconnect.apple.com/iris/v1/buildDeliveries
296
454
  params = build_params(filter: filter, includes: includes, limit: limit, sort: sort)
297
-
298
- response = request(:get, "preReleaseVersions") do |req|
299
- req.options.params_encoder = Faraday::NestedParamsEncoder
300
- req.params = params
301
- end
302
- handle_response(response)
455
+ get("buildDeliveries", params)
303
456
  end
304
457
 
305
- def get_beta_groups(filter: {}, includes: nil, limit: 40, sort: nil)
458
+ #
459
+ # preReleaseVersions
460
+ #
461
+
462
+ def get_pre_release_versions(filter: {}, includes: nil, limit: nil, sort: nil)
306
463
  # GET
307
- # https://appstoreconnect.apple.com/iris/v1/betaGroups
464
+ # https://appstoreconnect.apple.com/iris/v1/preReleaseVersions
308
465
  params = build_params(filter: filter, includes: includes, limit: limit, sort: sort)
309
-
310
- response = request(:get, "betaGroups") do |req|
311
- req.options.params_encoder = Faraday::NestedParamsEncoder
312
- req.params = params
313
- end
314
- handle_response(response)
466
+ get("preReleaseVersions", params)
315
467
  end
316
468
 
317
- def add_beta_groups_to_build(build_id: nil, beta_group_ids: [])
318
- # POST
319
- # https://appstoreconnect.apple.com/iris/v1/builds/<build_id>/relationships/betaGroups
320
-
321
- body = {
322
- data: beta_group_ids.map do |id|
323
- {
324
- type: "betaGroups",
325
- id: id
326
- }
327
- end
328
- }
469
+ #
470
+ # users
471
+ #
329
472
 
330
- response = request(:post) do |req|
331
- req.url("builds/#{build_id}/relationships/betaGroups")
332
- req.body = body.to_json
333
- req.headers['Content-Type'] = 'application/json'
334
- end
335
- handle_response(response)
473
+ def get_users(filter: {}, includes: nil, limit: nil, sort: nil)
474
+ # GET
475
+ # https://appstoreconnect.apple.com/iris/v1/users
476
+ params = build_params(filter: filter, includes: includes, limit: limit, sort: sort)
477
+ get("users", params)
336
478
  end
337
479
 
338
480
  protected
339
481
 
340
- def handle_response(response, only_data: true)
482
+ def handle_response(response)
341
483
  if (200...300).cover?(response.status) && (response.body.nil? || response.body.empty?)
342
484
  return
343
485
  end
@@ -354,9 +496,7 @@ module Spaceship
354
496
 
355
497
  raise UnexpectedResponse, "Temporary App Store Connect error: #{response.body}" if response.body['statusCode'] == 'ERROR'
356
498
 
357
- return response.body['data'] if response.body['data'] && only_data
358
-
359
- return response.body
499
+ return Spaceship::ConnectAPI::Response.new(body: response.body, status: response.status)
360
500
  end
361
501
 
362
502
  def handle_errors(response)
@@ -407,4 +547,5 @@ module Spaceship
407
547
  end
408
548
  end
409
549
  end
550
+ # rubocop:enable Metrics/ClassLength
410
551
  end