fastlane 2.212.1 → 2.219.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (227) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +100 -100
  3. data/deliver/lib/deliver/app_screenshot.rb +22 -12
  4. data/deliver/lib/deliver/app_screenshot_iterator.rb +2 -2
  5. data/deliver/lib/deliver/detect_values.rb +1 -1
  6. data/deliver/lib/deliver/languages.rb +1 -1
  7. data/deliver/lib/deliver/loader.rb +2 -2
  8. data/deliver/lib/deliver/options.rb +4 -4
  9. data/deliver/lib/deliver/runner.rb +10 -9
  10. data/deliver/lib/deliver/submit_for_review.rb +13 -0
  11. data/deliver/lib/deliver/sync_screenshots.rb +2 -2
  12. data/deliver/lib/deliver/upload_metadata.rb +60 -15
  13. data/deliver/lib/deliver/upload_price_tier.rb +2 -2
  14. data/deliver/lib/deliver/upload_screenshots.rb +3 -3
  15. data/fastlane/lib/assets/custom_action_template.rb +18 -12
  16. data/fastlane/lib/fastlane/action.rb +1 -1
  17. data/fastlane/lib/fastlane/actions/appledoc.rb +1 -1
  18. data/fastlane/lib/fastlane/actions/apteligent.rb +1 -1
  19. data/fastlane/lib/fastlane/actions/backup_xcarchive.rb +1 -1
  20. data/fastlane/lib/fastlane/actions/commit_github_file.rb +2 -2
  21. data/fastlane/lib/fastlane/actions/copy_artifacts.rb +1 -1
  22. data/fastlane/lib/fastlane/actions/create_app_online.rb +1 -1
  23. data/fastlane/lib/fastlane/actions/create_pull_request.rb +1 -1
  24. data/fastlane/lib/fastlane/actions/docs/build_app.md +2 -2
  25. data/fastlane/lib/fastlane/actions/docs/capture_android_screenshots.md +8 -8
  26. data/fastlane/lib/fastlane/actions/docs/check_app_store_metadata.md +3 -3
  27. data/fastlane/lib/fastlane/actions/docs/get_push_certificate.md +2 -2
  28. data/fastlane/lib/fastlane/actions/docs/sync_code_signing.md +6 -4
  29. data/fastlane/lib/fastlane/actions/docs/upload_to_app_store.md.erb +1 -1
  30. data/fastlane/lib/fastlane/actions/docs/upload_to_play_store.md +6 -2
  31. data/fastlane/lib/fastlane/actions/docs/upload_to_testflight.md +1 -1
  32. data/fastlane/lib/fastlane/actions/download_universal_apk_from_google_play.rb +124 -0
  33. data/fastlane/lib/fastlane/actions/ensure_git_status_clean.rb +44 -5
  34. data/fastlane/lib/fastlane/actions/ensure_xcode_version.rb +4 -0
  35. data/fastlane/lib/fastlane/actions/get_certificates.rb +1 -1
  36. data/fastlane/lib/fastlane/actions/get_github_release.rb +1 -1
  37. data/fastlane/lib/fastlane/actions/get_provisioning_profile.rb +1 -1
  38. data/fastlane/lib/fastlane/actions/git_branch.rb +1 -1
  39. data/fastlane/lib/fastlane/actions/github_api.rb +1 -1
  40. data/fastlane/lib/fastlane/actions/gradle.rb +1 -1
  41. data/fastlane/lib/fastlane/actions/install_on_device.rb +2 -2
  42. data/fastlane/lib/fastlane/actions/ipa.rb +1 -1
  43. data/fastlane/lib/fastlane/actions/jazzy.rb +1 -1
  44. data/fastlane/lib/fastlane/actions/nexus_upload.rb +1 -0
  45. data/fastlane/lib/fastlane/actions/notarize.rb +17 -2
  46. data/fastlane/lib/fastlane/actions/oclint.rb +3 -3
  47. data/fastlane/lib/fastlane/actions/opt_out_crash_reporting.rb +2 -2
  48. data/fastlane/lib/fastlane/actions/restore_file.rb +1 -1
  49. data/fastlane/lib/fastlane/actions/set_github_release.rb +1 -1
  50. data/fastlane/lib/fastlane/actions/slather.rb +18 -5
  51. data/fastlane/lib/fastlane/actions/sonar.rb +12 -3
  52. data/fastlane/lib/fastlane/actions/splunkmint.rb +1 -1
  53. data/fastlane/lib/fastlane/actions/spm.rb +76 -2
  54. data/fastlane/lib/fastlane/actions/update_info_plist.rb +1 -1
  55. data/fastlane/lib/fastlane/actions/update_urban_airship_configuration.rb +1 -1
  56. data/fastlane/lib/fastlane/actions/upload_symbols_to_crashlytics.rb +1 -0
  57. data/fastlane/lib/fastlane/actions/upload_symbols_to_sentry.rb +1 -1
  58. data/fastlane/lib/fastlane/actions/upload_to_testflight.rb +2 -2
  59. data/fastlane/lib/fastlane/actions/verify_build.rb +7 -4
  60. data/fastlane/lib/fastlane/actions/xcov.rb +1 -1
  61. data/fastlane/lib/fastlane/cli_tools_distributor.rb +1 -1
  62. data/fastlane/lib/fastlane/command_line_handler.rb +2 -4
  63. data/fastlane/lib/fastlane/commands_generator.rb +2 -2
  64. data/fastlane/lib/fastlane/fast_file.rb +1 -1
  65. data/fastlane/lib/fastlane/helper/dotenv_helper.rb +1 -1
  66. data/fastlane/lib/fastlane/helper/git_helper.rb +3 -0
  67. data/fastlane/lib/fastlane/helper/xcodes_helper.rb +0 -3
  68. data/fastlane/lib/fastlane/junit_generator.rb +1 -1
  69. data/fastlane/lib/fastlane/lane.rb +9 -1
  70. data/fastlane/lib/fastlane/lane_manager.rb +1 -2
  71. data/fastlane/lib/fastlane/new_action.rb +1 -1
  72. data/fastlane/lib/fastlane/plugins/plugin_info_collector.rb +3 -3
  73. data/fastlane/lib/fastlane/plugins/template/%gem_name%.gemspec.erb +1 -13
  74. data/fastlane/lib/fastlane/plugins/template/.rubocop.yml +9 -1
  75. data/fastlane/lib/fastlane/plugins/template/Gemfile.erb +27 -0
  76. data/fastlane/lib/fastlane/plugins/template/lib/fastlane/plugin/%plugin_name%/helper/%plugin_name%_helper.rb.erb +1 -1
  77. data/fastlane/lib/fastlane/runner.rb +2 -2
  78. data/fastlane/lib/fastlane/setup/setup.rb +1 -1
  79. data/fastlane/lib/fastlane/swift_lane_manager.rb +2 -5
  80. data/fastlane/lib/fastlane/swift_runner_upgrader.rb +7 -4
  81. data/fastlane/lib/fastlane/version.rb +2 -2
  82. data/fastlane/swift/Actions.swift +1 -1
  83. data/fastlane/swift/Appfile.swift +1 -1
  84. data/fastlane/swift/ArgumentProcessor.swift +1 -1
  85. data/fastlane/swift/Atomic.swift +1 -1
  86. data/fastlane/swift/ControlCommand.swift +1 -1
  87. data/fastlane/swift/Deliverfile.swift +2 -2
  88. data/fastlane/swift/DeliverfileProtocol.swift +4 -4
  89. data/fastlane/swift/Fastlane.swift +227 -36
  90. data/fastlane/swift/Gymfile.swift +2 -2
  91. data/fastlane/swift/GymfileProtocol.swift +2 -2
  92. data/fastlane/swift/LaneFileProtocol.swift +5 -5
  93. data/fastlane/swift/MainProcess.swift +1 -1
  94. data/fastlane/swift/Matchfile.swift +2 -2
  95. data/fastlane/swift/MatchfileProtocol.swift +22 -2
  96. data/fastlane/swift/OptionalConfigValue.swift +1 -1
  97. data/fastlane/swift/Plugins.swift +1 -1
  98. data/fastlane/swift/Precheckfile.swift +2 -2
  99. data/fastlane/swift/PrecheckfileProtocol.swift +2 -2
  100. data/fastlane/swift/RubyCommand.swift +1 -1
  101. data/fastlane/swift/RubyCommandable.swift +1 -1
  102. data/fastlane/swift/Runner.swift +1 -1
  103. data/fastlane/swift/RunnerArgument.swift +1 -1
  104. data/fastlane/swift/Scanfile.swift +2 -2
  105. data/fastlane/swift/ScanfileProtocol.swift +6 -2
  106. data/fastlane/swift/Screengrabfile.swift +2 -2
  107. data/fastlane/swift/ScreengrabfileProtocol.swift +2 -2
  108. data/fastlane/swift/Snapshotfile.swift +2 -2
  109. data/fastlane/swift/SnapshotfileProtocol.swift +2 -2
  110. data/fastlane/swift/SocketClient.swift +1 -1
  111. data/fastlane/swift/SocketClientDelegateProtocol.swift +1 -1
  112. data/fastlane/swift/SocketResponse.swift +1 -1
  113. data/fastlane/swift/formatting/Brewfile.lock.json +31 -23
  114. data/fastlane/swift/main.swift +1 -1
  115. data/fastlane_core/lib/fastlane_core/build_watcher.rb +1 -1
  116. data/fastlane_core/lib/fastlane_core/cert_checker.rb +4 -9
  117. data/fastlane_core/lib/fastlane_core/configuration/configuration_file.rb +1 -1
  118. data/fastlane_core/lib/fastlane_core/device_manager.rb +17 -15
  119. data/fastlane_core/lib/fastlane_core/fastlane_pty.rb +34 -12
  120. data/fastlane_core/lib/fastlane_core/helper.rb +1 -1
  121. data/fastlane_core/lib/fastlane_core/itunes_transporter.rb +53 -16
  122. data/fastlane_core/lib/fastlane_core/project.rb +7 -2
  123. data/fastlane_core/lib/fastlane_core/queue_worker.rb +2 -2
  124. data/fastlane_core/lib/fastlane_core/string_filters.rb +6 -6
  125. data/fastlane_core/lib/fastlane_core/ui/fastlane_runner.rb +2 -2
  126. data/frameit/lib/frameit/device_types.rb +1 -1
  127. data/frameit/lib/frameit/editor.rb +4 -4
  128. data/frameit/lib/frameit/trim_box.rb +1 -1
  129. data/gym/lib/gym/error_handler.rb +1 -1
  130. data/gym/lib/gym/generators/build_command_generator.rb +1 -1
  131. data/gym/lib/gym/generators/package_command_generator_xcode7.rb +3 -3
  132. data/gym/lib/gym/module.rb +13 -2
  133. data/gym/lib/gym/options.rb +1 -1
  134. data/gym/lib/gym/runner.rb +1 -1
  135. data/gym/lib/gym/xcodebuild_fixes/README.md +1 -1
  136. data/match/lib/match/change_password.rb +3 -9
  137. data/match/lib/match/commands_generator.rb +3 -6
  138. data/match/lib/match/encryption.rb +1 -1
  139. data/match/lib/match/generator.rb +9 -1
  140. data/match/lib/match/importer.rb +3 -30
  141. data/match/lib/match/migrate.rb +6 -2
  142. data/match/lib/match/module.rb +2 -1
  143. data/match/lib/match/nuke.rb +3 -24
  144. data/match/lib/match/options.rb +25 -0
  145. data/match/lib/match/portal_cache.rb +106 -0
  146. data/match/lib/match/portal_fetcher.rb +72 -0
  147. data/match/lib/match/profile_includes.rb +120 -0
  148. data/match/lib/match/runner.rb +93 -209
  149. data/match/lib/match/setup.rb +1 -1
  150. data/match/lib/match/spaceship_ensure.rb +15 -11
  151. data/match/lib/match/storage/git_storage.rb +17 -4
  152. data/match/lib/match/storage/gitlab/client.rb +40 -14
  153. data/match/lib/match/storage/gitlab_secure_files.rb +18 -7
  154. data/match/lib/match/storage/interface.rb +1 -1
  155. data/match/lib/match/storage/s3_storage.rb +7 -1
  156. data/match/lib/match/storage.rb +56 -5
  157. data/match/lib/match.rb +3 -0
  158. data/pilot/lib/pilot/build_manager.rb +4 -4
  159. data/precheck/lib/precheck/rules/unreachable_urls_rule.rb +1 -1
  160. data/produce/lib/produce/itunes_connect.rb +1 -1
  161. data/scan/lib/scan/detect_values.rb +86 -21
  162. data/scan/lib/scan/options.rb +6 -1
  163. data/scan/lib/scan/runner.rb +1 -1
  164. data/scan/lib/scan/test_command_generator.rb +1 -1
  165. data/screengrab/lib/screengrab/runner.rb +1 -1
  166. data/sigh/lib/assets/resign.sh +10 -10
  167. data/sigh/lib/sigh/commands_generator.rb +1 -1
  168. data/sigh/lib/sigh/module.rb +98 -0
  169. data/sigh/lib/sigh/options.rb +55 -1
  170. data/sigh/lib/sigh/resign.rb +1 -1
  171. data/sigh/lib/sigh/runner.rb +36 -112
  172. data/snapshot/lib/assets/SnapshotHelper.swift +13 -9
  173. data/snapshot/lib/snapshot/latest_os_version.rb +2 -5
  174. data/snapshot/lib/snapshot/reports_generator.rb +48 -7
  175. data/snapshot/lib/snapshot/setup.rb +2 -2
  176. data/snapshot/lib/snapshot/simulator_launchers/simulator_launcher.rb +23 -22
  177. data/snapshot/lib/snapshot/simulator_launchers/simulator_launcher_base.rb +2 -2
  178. data/snapshot/lib/snapshot/test_command_generator.rb +1 -1
  179. data/spaceship/lib/spaceship/client.rb +1 -2
  180. data/spaceship/lib/spaceship/connect_api/api_client.rb +22 -3
  181. data/spaceship/lib/spaceship/connect_api/client.rb +4 -4
  182. data/spaceship/lib/spaceship/connect_api/models/app.rb +5 -4
  183. data/spaceship/lib/spaceship/connect_api/models/app_info.rb +15 -9
  184. data/spaceship/lib/spaceship/connect_api/models/app_preview_set.rb +2 -0
  185. data/spaceship/lib/spaceship/connect_api/models/app_screenshot.rb +2 -2
  186. data/spaceship/lib/spaceship/connect_api/models/app_screenshot_set.rb +7 -0
  187. data/spaceship/lib/spaceship/connect_api/models/app_store_version.rb +1 -0
  188. data/spaceship/lib/spaceship/connect_api/models/beta_group.rb +3 -1
  189. data/spaceship/lib/spaceship/connect_api/models/bundle_id.rb +5 -5
  190. data/spaceship/lib/spaceship/connect_api/models/certificate.rb +3 -3
  191. data/spaceship/lib/spaceship/connect_api/models/device.rb +83 -4
  192. data/spaceship/lib/spaceship/connect_api/models/profile.rb +5 -3
  193. data/spaceship/lib/spaceship/connect_api/models/user.rb +38 -0
  194. data/spaceship/lib/spaceship/connect_api/models/user_invitation.rb +5 -15
  195. data/spaceship/lib/spaceship/connect_api/provisioning/provisioning.rb +14 -8
  196. data/spaceship/lib/spaceship/connect_api/testflight/testflight.rb +8 -2
  197. data/spaceship/lib/spaceship/connect_api/tunes/tunes.rb +3 -6
  198. data/spaceship/lib/spaceship/connect_api/users/users.rb +34 -0
  199. data/spaceship/lib/spaceship/connect_api.rb +2 -0
  200. data/spaceship/lib/spaceship/portal/app.rb +1 -1
  201. data/spaceship/lib/spaceship/portal/app_group.rb +1 -1
  202. data/spaceship/lib/spaceship/test_flight/client.rb +1 -1
  203. data/spaceship/lib/spaceship/test_flight/tester.rb +1 -1
  204. data/spaceship/lib/spaceship/tunes/app_details.rb +2 -2
  205. data/spaceship/lib/spaceship/tunes/app_image.rb +1 -1
  206. data/spaceship/lib/spaceship/tunes/app_review_attachment.rb +1 -1
  207. data/spaceship/lib/spaceship/tunes/app_submission.rb +1 -1
  208. data/spaceship/lib/spaceship/tunes/app_version.rb +5 -5
  209. data/spaceship/lib/spaceship/tunes/build_details.rb +1 -1
  210. data/spaceship/lib/spaceship/tunes/iap.rb +3 -3
  211. data/spaceship/lib/spaceship/tunes/iap_detail.rb +2 -2
  212. data/spaceship/lib/spaceship/tunes/iap_families.rb +1 -1
  213. data/spaceship/lib/spaceship/tunes/iap_family_details.rb +2 -2
  214. data/spaceship/lib/spaceship/tunes/iap_family_list.rb +1 -1
  215. data/spaceship/lib/spaceship/tunes/tunes_client.rb +3 -3
  216. data/supply/lib/supply/client.rb +80 -21
  217. data/supply/lib/supply/generated_universal_apk.rb +24 -0
  218. data/supply/lib/supply/image_listing.rb +15 -0
  219. data/supply/lib/supply/options.rb +5 -0
  220. data/supply/lib/supply/setup.rb +2 -2
  221. data/supply/lib/supply/uploader.rb +60 -18
  222. data/supply/lib/supply.rb +2 -0
  223. data/trainer/lib/trainer/junit_generator.rb +1 -1
  224. data/trainer/lib/trainer/test_parser.rb +1 -1
  225. data/trainer/lib/trainer/xcresult.rb +1 -1
  226. metadata +205 -431
  227. data/fastlane/lib/fastlane/plugins/template/Gemfile +0 -6
@@ -17,8 +17,8 @@ module Spaceship
17
17
  # bundleIds
18
18
  #
19
19
 
20
- def get_bundle_ids(filter: {}, includes: nil, limit: nil, sort: nil)
21
- params = provisioning_request_client.build_params(filter: filter, includes: includes, limit: limit, sort: sort)
20
+ def get_bundle_ids(filter: {}, includes: nil, fields: nil, limit: nil, sort: nil)
21
+ params = provisioning_request_client.build_params(filter: filter, includes: includes, fields: fields, limit: limit, sort: sort)
22
22
  provisioning_request_client.get("bundleIds", params)
23
23
  end
24
24
 
@@ -129,8 +129,8 @@ module Spaceship
129
129
  # certificates
130
130
  #
131
131
 
132
- def get_certificates(profile_id: nil, filter: {}, includes: nil, limit: nil, sort: nil)
133
- params = provisioning_request_client.build_params(filter: filter, includes: includes, limit: limit, sort: sort)
132
+ def get_certificates(profile_id: nil, filter: {}, includes: nil, fields: nil, limit: nil, sort: nil)
133
+ params = provisioning_request_client.build_params(filter: filter, includes: includes, fields: fields, limit: limit, sort: sort)
134
134
  if profile_id.nil?
135
135
  provisioning_request_client.get("certificates", params)
136
136
  else
@@ -164,8 +164,8 @@ module Spaceship
164
164
  # devices
165
165
  #
166
166
 
167
- def get_devices(profile_id: nil, filter: {}, includes: nil, limit: nil, sort: nil)
168
- params = provisioning_request_client.build_params(filter: filter, includes: includes, limit: limit, sort: sort)
167
+ def get_devices(profile_id: nil, filter: {}, includes: nil, fields: nil, limit: nil, sort: nil)
168
+ params = provisioning_request_client.build_params(filter: filter, includes: includes, fields: fields, limit: limit, sort: sort)
169
169
  if profile_id.nil?
170
170
  provisioning_request_client.get("devices", params)
171
171
  else
@@ -213,8 +213,8 @@ module Spaceship
213
213
  # profiles
214
214
  #
215
215
 
216
- def get_profiles(filter: {}, includes: nil, limit: nil, sort: nil)
217
- params = provisioning_request_client.build_params(filter: filter, includes: includes, limit: limit, sort: sort)
216
+ def get_profiles(filter: {}, includes: nil, fields: nil, limit: nil, sort: nil)
217
+ params = provisioning_request_client.build_params(filter: filter, includes: includes, fields: fields, limit: limit, sort: sort)
218
218
  provisioning_request_client.get("profiles", params)
219
219
  end
220
220
 
@@ -253,6 +253,12 @@ module Spaceship
253
253
  provisioning_request_client.post("profiles", body)
254
254
  end
255
255
 
256
+ def get_profile_bundle_id(profile_id: nil)
257
+ raise "Profile id is nil" if profile_id.nil?
258
+
259
+ provisioning_request_client.get("profiles/#{profile_id}/bundleId")
260
+ end
261
+
256
262
  def delete_profile(profile_id: nil)
257
263
  raise "Profile id is nil" if profile_id.nil?
258
264
 
@@ -204,13 +204,19 @@ module Spaceship
204
204
  test_flight_request_client.delete("builds/#{build_id}/relationships/betaGroups", nil, body)
205
205
  end
206
206
 
207
- def create_beta_group(app_id: nil, group_name: nil, is_internal_group: false, public_link_enabled: false, public_link_limit: 10_000, public_link_limit_enabled: false)
207
+ def create_beta_group(app_id: nil, group_name: nil, is_internal_group: false, public_link_enabled: false, public_link_limit: 10_000, public_link_limit_enabled: false, has_access_to_all_builds: nil)
208
+ if is_internal_group
209
+ has_access_to_all_builds = true if has_access_to_all_builds.nil?
210
+ else
211
+ # Access to all builds is only for internal groups
212
+ has_access_to_all_builds = nil
213
+ end
208
214
  body = {
209
215
  data: {
210
216
  attributes: {
211
217
  name: group_name,
212
218
  isInternalGroup: is_internal_group,
213
- hasAccessToAllBuilds: is_internal_group ? true : false, # Undocumented of 2021-08-02 in ASC API docs and ASC Open API spec. This is the default behavior on App Store Connect and does work with both Apple ID and API Token
219
+ hasAccessToAllBuilds: has_access_to_all_builds, # Undocumented of 2021-08-02 in ASC API docs and ASC Open API spec. This is the default behavior on App Store Connect and does work with both Apple ID and API Token
214
220
  publicLinkEnabled: public_link_enabled,
215
221
  publicLinkLimit: public_link_limit,
216
222
  publicLinkLimitEnabled: public_link_limit_enabled
@@ -94,7 +94,7 @@ module Spaceship
94
94
  }
95
95
  end
96
96
 
97
- app_store_verions_data = platforms.map do |platform|
97
+ data_for_app_store_versions = platforms.map do |platform|
98
98
  {
99
99
  type: "appStoreVersions",
100
100
  id: "${store-version-#{platform}}"
@@ -103,7 +103,7 @@ module Spaceship
103
103
 
104
104
  relationships = {
105
105
  appStoreVersions: {
106
- data: app_store_verions_data
106
+ data: data_for_app_store_versions
107
107
  },
108
108
  appInfos: {
109
109
  data: [
@@ -160,9 +160,6 @@ module Spaceship
160
160
  included << {
161
161
  type: "appPrices",
162
162
  id: "${price1}",
163
- attributes: {
164
- startDate: nil
165
- },
166
163
  relationships: {
167
164
  app: {
168
165
  data: {
@@ -1257,7 +1254,7 @@ module Spaceship
1257
1254
  # resolutionCenter
1258
1255
  #
1259
1256
  # As of 2022-11-11:
1260
- # This is not official available throught the App Store Connect API using an API Key.
1257
+ # This is not official available through the App Store Connect API using an API Key.
1261
1258
  # This is only works with Apple ID auth.
1262
1259
  #
1263
1260
 
@@ -28,6 +28,36 @@ module Spaceship
28
28
  users_request_client.delete("users/#{user_id}")
29
29
  end
30
30
 
31
+ # Update existing user
32
+ def patch_user(user_id:, all_apps_visible:, provisioning_allowed:, roles:, visible_app_ids:)
33
+ body = {
34
+ data: {
35
+ type: 'users',
36
+ id: user_id,
37
+ attributes: {
38
+ allAppsVisible: all_apps_visible,
39
+ provisioningAllowed: provisioning_allowed,
40
+ roles: roles
41
+ },
42
+ relationships: {
43
+ visibleApps: {
44
+ data: visible_app_ids.map do |app_id|
45
+ {
46
+ type: "apps",
47
+ id: app_id
48
+ }
49
+ end
50
+ }
51
+ }
52
+ }
53
+ }
54
+
55
+ # Avoid API error: You cannot set visible apps for this user because the user's roles give them access to all apps.
56
+ body[:data].delete(:relationships) if all_apps_visible
57
+
58
+ users_request_client.patch("users/#{user_id}", body)
59
+ end
60
+
31
61
  # Add app permissions for user
32
62
  # @deprecated Use {#post_user_visible_apps} instead.
33
63
  def add_user_visible_apps(user_id: nil, app_ids: nil)
@@ -116,6 +146,10 @@ module Spaceship
116
146
  }
117
147
  }
118
148
  }
149
+
150
+ # Avoid API error: You cannot set visible apps for this user because the user's roles give them access to all apps.
151
+ body[:data].delete(:relationships) if all_apps_visible
152
+
119
153
  users_request_client.post("userInvitations", body)
120
154
  end
121
155
 
@@ -76,6 +76,8 @@ require 'spaceship/connect_api/models/actor'
76
76
 
77
77
  module Spaceship
78
78
  class ConnectAPI
79
+ MAX_OBJECTS_PER_PAGE_LIMIT = 200
80
+
79
81
  # Defined in the App Store Connect API docs:
80
82
  # https://developer.apple.com/documentation/appstoreconnectapi/platform
81
83
  #
@@ -141,7 +141,7 @@ module Spaceship
141
141
 
142
142
  # Delete this App ID. This action will most likely fail if the App ID is already in the store
143
143
  # or there are active profiles
144
- # @return (App) The app you just deletd
144
+ # @return (App) The app you just deleted
145
145
  def delete!
146
146
  client.delete_app!(app_id, mac: mac?)
147
147
  self
@@ -63,7 +63,7 @@ module Spaceship
63
63
  end
64
64
 
65
65
  # Delete this app group
66
- # @return (AppGroup) The app group you just deletd
66
+ # @return (AppGroup) The app group you just deleted
67
67
  def delete!
68
68
  client.delete_app_group!(app_group_id)
69
69
  self
@@ -8,7 +8,7 @@ module Spaceship
8
8
  #
9
9
  # This client is solely responsible for the making HTTP requests and
10
10
  # parsing their responses. Parameters should be either named parameters, or
11
- # for large request data bodies, pass in anything that can resond to
11
+ # for large request data bodies, pass in anything that can respond to
12
12
  # `to_json`.
13
13
  #
14
14
  # 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.
@@ -94,7 +94,7 @@ module Spaceship
94
94
 
95
95
  # @return (Spaceship::TestFlight::Tester) Returns the testers matching the parameter.
96
96
  # ITC searches all fields, and is full text. The search results are the union of all words in the search text
97
- # @param text (String) (required): Value used to filter the tester, case insensitive
97
+ # @param text (String) (required): Value used to filter the tester, case-insensitive
98
98
  def self.search(app_id: nil, text: nil, is_email_exact_match: false)
99
99
  text = text.strip
100
100
  testers_matching_text = client.search_for_tester_in_app(app_id: app_id, text: text).map { |data| self.new(data) }
@@ -11,7 +11,7 @@ module Spaceship
11
11
  # Localized values
12
12
  ####
13
13
 
14
- # @return (Array) Raw access the all available languages. You shouldn't use it probbaly
14
+ # @return (Array) Raw access the all available languages. You shouldn't use it probably
15
15
  attr_accessor :languages
16
16
 
17
17
  # @return (Hash) A hash representing the app name in all languages
@@ -23,7 +23,7 @@ module Spaceship
23
23
  # @return (Hash) A hash representing the privacy URL in all languages
24
24
  attr_reader :privacy_url
25
25
 
26
- # @return (Hash) A hash prepresenting the privacy URL in all languages for Apple TV
26
+ # @return (Hash) A hash representing the privacy URL in all languages for Apple TV
27
27
  attr_reader :apple_tv_privacy_policy
28
28
 
29
29
  # Categories (e.g. MZGenre.Business)
@@ -35,7 +35,7 @@ module Spaceship
35
35
  end
36
36
 
37
37
  def setup
38
- # Since September 2015 we don't get the url any more, so we have to manually build it
38
+ # Since September 2015 we don't get the url anymore, so we have to manually build it
39
39
  self.url = "#{HOST_URL}/#{self.asset_token}/0x0ss.jpg"
40
40
  end
41
41
 
@@ -33,7 +33,7 @@ module Spaceship
33
33
  end
34
34
 
35
35
  def setup
36
- # Since September 2015 we don't get the url any more, so we have to manually build it
36
+ # Since September 2015 we don't get the url anymore, so we have to manually build it
37
37
  self.url = "#{HOST_URL}/#{self.asset_token}"
38
38
  end
39
39
 
@@ -22,7 +22,7 @@ module Spaceship
22
22
 
23
23
  # To pass from the user
24
24
 
25
- # @deprecated Setted automatically by <tt>add_id_info_uses_idfa</tt> usage
25
+ # @deprecated Set automatically by <tt>add_id_info_uses_idfa</tt> usage
26
26
  # @return (Boolean) Ad ID Info - Limits ads tracking
27
27
  # <b>DEPRECATED:</b> Use <tt>add_id_info_uses_idfa</tt> instead.
28
28
  attr_accessor :add_id_info_limits_tracking
@@ -78,7 +78,7 @@ module Spaceship
78
78
  # @return (Spaceship::Tunes::AppImage) the structure containing information about the large watch icon (1024x1024)
79
79
  attr_accessor :watch_app_icon
80
80
 
81
- # @return (Integer) a unqiue ID for this version generated by App Store Connect
81
+ # @return (Integer) a unique ID for this version generated by App Store Connect
82
82
  attr_accessor :version_id
83
83
 
84
84
  # @return (Spaceship::Tunes::AppReviewAttachment) the structure containing information about the review attachment file
@@ -147,7 +147,7 @@ module Spaceship
147
147
  # @return (String) App Review Information Email Address
148
148
  attr_accessor :review_email
149
149
 
150
- # @return (Boolean) The checkbox that indiciates if a demo account
150
+ # @return (Boolean) The checkbox that indicates if a demo account
151
151
  # is needed. Is set automatically depending on if a user and pass
152
152
  # are set
153
153
  attr_reader :review_user_needed
@@ -546,7 +546,7 @@ module Spaceship
546
546
  device_lang_screenshots << new_screenshot
547
547
  end
548
548
  else # removing
549
- raise "cannot remove screenshot with non existing sort_order" unless existing_sort_orders.include?(sort_order)
549
+ raise "cannot remove screenshot with nonexistent sort_order" unless existing_sort_orders.include?(sort_order)
550
550
  device_lang_screenshots.delete_at(existing_sort_orders.index(sort_order))
551
551
  end
552
552
  setup_screenshots
@@ -624,7 +624,7 @@ module Spaceship
624
624
  device_lang_trailers << new_trailer
625
625
  end
626
626
  else # removing trailer
627
- raise "cannot remove trailer with non existing sort_order" unless existing_sort_orders.include?(sort_order)
627
+ raise "cannot remove trailer with nonexistent sort_order" unless existing_sort_orders.include?(sort_order)
628
628
  device_lang_trailers.delete_at(existing_sort_orders.index(sort_order))
629
629
  end
630
630
  setup_trailers
@@ -754,7 +754,7 @@ module Spaceship
754
754
  raise "#{device} isn't a valid device name" unless DisplayFamily.find(device)
755
755
 
756
756
  languages = raw_data_details.select { |d| d["language"] == language }
757
- # IDEA: better error for non existing language
757
+ # IDEA: better error for nonexistent language
758
758
  raise "#{language} isn't an activated language" unless languages.count > 0
759
759
  lang_details = languages[0]
760
760
  display_families = lang_details["displayFamilies"]["value"]
@@ -59,7 +59,7 @@ module Spaceship
59
59
 
60
60
  # @return (String) Platform of the app
61
61
  # @example 'ios'
62
- attr_accessor :app_plattform
62
+ attr_accessor :app_platform
63
63
 
64
64
  # @return (String) Device Requirements / Device Protocols
65
65
  attr_accessor :device_protocols
@@ -15,14 +15,14 @@ module Spaceship
15
15
  # @return (Spaceship::Tunes::Application) A reference to the application
16
16
  attr_accessor :application
17
17
 
18
- # @return (Spaceship::Tunes::IAPFamilies) A reference to the familie list
18
+ # @return (Spaceship::Tunes::IAPFamilies) A reference to the family list
19
19
  def families
20
20
  attrs = {}
21
21
  attrs[:application] = self.application
22
22
  Tunes::IAPFamilies.new(attrs)
23
23
  end
24
24
 
25
- # Creates a new In-App-Purchese on App Store Connect
25
+ # Creates a new In-App-Purchase on App Store Connect
26
26
  # if the In-App-Purchase already exists an exception is raised. Spaceship::TunesClient::ITunesConnectError
27
27
  # @param type (String): The Type of the in-app-purchase (Spaceship::Tunes::IAPType::CONSUMABLE,Spaceship::Tunes::IAPType::NON_CONSUMABLE,Spaceship::Tunes::IAPType::RECURRING,Spaceship::Tunes::IAPType::NON_RENEW_SUBSCRIPTION)
28
28
  # @param versions (Hash): a Hash of the languages
@@ -49,7 +49,7 @@ module Spaceship
49
49
  # tier: 1
50
50
  # }
51
51
  # ]
52
- # @param family_id (String) Only used on RECURRING purchases, assigns the In-App-Purchase to a specific familie
52
+ # @param family_id (String) Only used on RECURRING purchases, assigns the In-App-Purchase to a specific family
53
53
  # @param subscription_free_trial (String) Free Trial duration (1w,1m,3m....)
54
54
  # @param subscription_duration (String) 1w,1m.....
55
55
  # @param subscription_price_target (Hash) Only used on RECURRING purchases, used to set the
@@ -220,7 +220,7 @@ module Spaceship
220
220
  # if the iap is not yet cleared for sale
221
221
  # @return ([Spaceship::Tunes::PricingInfo]) An array of pricing infos from the same pricing tier
222
222
  # if the iap uses world wide pricing
223
- # @return ([Spaceship::Tunes::IAPSubscriptionPricingInfo]) An array of pricing infos from multple subscription pricing tiers
223
+ # @return ([Spaceship::Tunes::IAPSubscriptionPricingInfo]) An array of pricing infos from multiple subscription pricing tiers
224
224
  # if the iap uses territorial pricing
225
225
  def pricing_info
226
226
  return [] unless cleared_for_sale
@@ -230,7 +230,7 @@ module Spaceship
230
230
 
231
231
  private
232
232
 
233
- # Checks wheather an iap uses world wide or territorial pricing.
233
+ # Checks whether an iap uses world wide or territorial pricing.
234
234
  #
235
235
  # @return (true, false)
236
236
  def world_wide_pricing?
@@ -13,7 +13,7 @@ module Spaceship
13
13
  # @param name (String) Familyname
14
14
  # @param product_id (String) New Product's id
15
15
  # @param reference_name (String) Reference name of the new product
16
- # @param versions (Hash) Localized Familie names
16
+ # @param versions (Hash) Localized Family names
17
17
  # @example
18
18
  # versions: {
19
19
  # 'de-DE': {
@@ -9,13 +9,13 @@ module Spaceship
9
9
  # @return (String) the family name
10
10
  attr_accessor :name
11
11
 
12
- # @return (Intger) the family id
12
+ # @return (Integer) the family id
13
13
  attr_accessor :family_id
14
14
 
15
15
  # @return (Array) all linked in-app purchases of this family
16
16
  attr_accessor :linked_iaps
17
17
 
18
- # @return (Intger) amount of linked in-app purchases of this family (read-only)
18
+ # @return (Integer) amount of linked in-app purchases of this family (read-only)
19
19
  attr_accessor :iap_count
20
20
 
21
21
  # @return (Array) of all in-app purchase family details
@@ -9,7 +9,7 @@ module Spaceship
9
9
  # @return (String) the family name
10
10
  attr_accessor :name
11
11
 
12
- # @return (Intger) the Family Id
12
+ # @return (Integer) the Family Id
13
13
  attr_accessor :family_id
14
14
 
15
15
  attr_mapping({
@@ -272,7 +272,7 @@ module Spaceship
272
272
  # if it needs to
273
273
  #
274
274
  # https://github.com/fastlane/fastlane/pull/20480
275
- r = request(:get, "https://appstoreconnect.apple.com/iris/v1/apps?include=appStoreVersions,prices")
275
+ r = request(:get, "https://appstoreconnect.apple.com/iris/v1/apps?include=appStoreVersions")
276
276
  response = Spaceship::ConnectAPI::Response.new(
277
277
  body: r.body,
278
278
  status: r.status,
@@ -659,7 +659,7 @@ module Spaceship
659
659
  r = request(:get, "ra/apps/#{app_id}/pricing/intervals")
660
660
  data = parse_response(r, 'data')
661
661
 
662
- # preOrder isn't needed for for the request and has some
662
+ # preOrder isn't needed for the request and has some
663
663
  # values that can cause a failure (invalid dates) so we are removing it
664
664
  data.delete('preOrder')
665
665
 
@@ -1011,7 +1011,7 @@ module Spaceship
1011
1011
  end
1012
1012
 
1013
1013
  #####################################################
1014
- # @!group CandiateBuilds
1014
+ # @!group CandidateBuilds
1015
1015
  #####################################################
1016
1016
 
1017
1017
  def candidate_builds(app_id, version_id)
@@ -78,6 +78,7 @@ module Supply
78
78
  private
79
79
 
80
80
  def call_google_api
81
+ tries_left ||= (ENV["SUPPLY_UPLOAD_MAX_RETRIES"] || 0).to_i
81
82
  yield if block_given?
82
83
  rescue Google::Apis::Error => e
83
84
  error = begin
@@ -92,7 +93,13 @@ module Supply
92
93
  message = e.body
93
94
  end
94
95
 
95
- UI.user_error!("Google Api Error: #{e.message} - #{message}")
96
+ if tries_left.positive?
97
+ UI.error("Google Api Error: #{e.message} - #{message} - Retrying...")
98
+ tries_left -= 1
99
+ retry
100
+ else
101
+ UI.user_error!("Google Api Error: #{e.message} - #{message}")
102
+ end
96
103
  end
97
104
  end
98
105
 
@@ -305,6 +312,39 @@ module Supply
305
312
  return latest_version
306
313
  end
307
314
 
315
+ # Get the list of Universal APKs generated by Google from the AAB for a particular version code
316
+ #
317
+ # @param [Fixnum] version_code
318
+ # Version code of the app bundle.
319
+ # @raise [FastlaneError] (Google Api Error) If no APK was found for the provided `package_name` and `version_code`
320
+ # @return [Array<GeneratedUniversalApk>]
321
+ #
322
+ def list_generated_universal_apks(package_name:, version_code:)
323
+ result = call_google_api { client.list_generatedapks(package_name, version_code) }
324
+
325
+ result.generated_apks.map do |row|
326
+ GeneratedUniversalApk.new(package_name, version_code, row.certificate_sha256_hash, row.generated_universal_apk.download_id)
327
+ end
328
+ end
329
+
330
+ # Download a Universal APK generated by Google for a particular version code
331
+ #
332
+ # @param [Supply::GeneratedUniversalApk] generated_universal_apk
333
+ # The GeneratedUniversalApk object retrieved from a call to `list_generated_universal_apks`
334
+ # @param [IO, String] destination
335
+ # IO stream or filename to receive content download
336
+ #
337
+ def download_generated_universal_apk(generated_universal_apk:, destination:)
338
+ call_google_api {
339
+ client.download_generatedapk(
340
+ generated_universal_apk.package_name,
341
+ generated_universal_apk.version_code,
342
+ generated_universal_apk.download_id,
343
+ download_dest: destination
344
+ )
345
+ }
346
+ end
347
+
308
348
  #####################################################
309
349
  # @!group Modifying data
310
350
  #####################################################
@@ -499,6 +539,12 @@ module Supply
499
539
  # @!group Screenshots
500
540
  #####################################################
501
541
 
542
+ # Fetch all the images of a given type and for a given language of your store listing
543
+ #
544
+ # @param [String] image_type Typically one of the elements of either Supply::IMAGES_TYPES or Supply::SCREENSHOT_TYPES
545
+ # @param [String] language Localization code (a BCP-47 language tag; for example, "de-AT" for Austrian German).
546
+ # @return [Array<ImageListing>] A list of ImageListing instances describing each image with its id, sha256 and url
547
+ #
502
548
  def fetch_images(image_type: nil, language: nil)
503
549
  ensure_active_edit!
504
550
 
@@ -511,29 +557,17 @@ module Supply
511
557
  )
512
558
  end
513
559
 
514
- urls = (result.images || []).map(&:url)
515
- images = urls.map do |url|
516
- uri = URI.parse(url)
517
- clean_url = [
518
- uri.scheme,
519
- uri.userinfo,
520
- uri.host,
521
- uri.port,
522
- uri.path
523
- ].join
524
-
525
- UI.verbose("Initial URL received: '#{url}'")
526
- UI.verbose("Removed params ('#{uri.query}') from the URL")
527
- UI.verbose("URL after removing params: '#{clean_url}'")
528
-
529
- full_url = "#{url}=s0" # '=s0' param ensures full image size is returned (https://github.com/fastlane/fastlane/pull/14322#issuecomment-473012462)
530
- full_url
560
+ (result.images || []).map do |row|
561
+ full_url = "#{row.url}=s0" # '=s0' param ensures full image size is returned (https://github.com/fastlane/fastlane/pull/14322#issuecomment-473012462)
562
+ ImageListing.new(row.id, row.sha1, row.sha256, full_url)
531
563
  end
532
-
533
- return images
534
564
  end
535
565
 
536
- # @param image_type (e.g. phoneScreenshots, sevenInchScreenshots, ...)
566
+ # Upload an image or screenshot of a specific type for a given language to your store listing
567
+ #
568
+ # @param [String] image_type (e.g. phoneScreenshots, sevenInchScreenshots, ...)
569
+ # @param [String] language localization code (i.e. BCP-47 language tag as in `pt-BR`)
570
+ #
537
571
  def upload_image(image_path: nil, image_type: nil, language: nil)
538
572
  ensure_active_edit!
539
573
 
@@ -549,6 +583,11 @@ module Supply
549
583
  end
550
584
  end
551
585
 
586
+ # Remove all screenshots of a given image_type and language from the store listing
587
+ #
588
+ # @param [String] image_type (e.g. phoneScreenshots, sevenInchScreenshots, ...)
589
+ # @param [String] language localization code (i.e. BCP-47 language tag as in `pt-BR`)
590
+ #
552
591
  def clear_screenshots(image_type: nil, language: nil)
553
592
  ensure_active_edit!
554
593
 
@@ -562,6 +601,26 @@ module Supply
562
601
  end
563
602
  end
564
603
 
604
+ # Remove a specific screenshot of a given image_type and language from the store listing
605
+ #
606
+ # @param [String] image_type (e.g. phoneScreenshots, sevenInchScreenshots, ...)
607
+ # @param [String] language localization code (i.e. BCP-47 language tag as in `pt-BR`)
608
+ # @param [String] image_id The id of the screenshot to remove (as per `ImageListing#id`)
609
+ #
610
+ def clear_screenshot(image_type: nil, language: nil, image_id: nil)
611
+ ensure_active_edit!
612
+
613
+ call_google_api do
614
+ client.delete_edit_image(
615
+ current_package_name,
616
+ current_edit.id,
617
+ language,
618
+ image_type,
619
+ image_id
620
+ )
621
+ end
622
+ end
623
+
565
624
  def upload_obb(obb_file_path: nil, apk_version_code: nil, expansion_file_type: nil)
566
625
  ensure_active_edit!
567
626
 
@@ -0,0 +1,24 @@
1
+ module Supply
2
+ # A model representing the returned values from a call to Client#list_generated_universal_apks
3
+ class GeneratedUniversalApk
4
+ attr_accessor :package_name
5
+ attr_accessor :version_code
6
+ attr_accessor :certificate_sha256_hash
7
+ attr_accessor :download_id
8
+
9
+ # Initializes the Generated Universal APK model
10
+ def initialize(package_name, version_code, certificate_sha256_hash, download_id)
11
+ self.package_name = package_name
12
+ self.version_code = version_code
13
+ self.certificate_sha256_hash = certificate_sha256_hash
14
+ self.download_id = download_id
15
+ end
16
+
17
+ def ==(other)
18
+ self.package_name == other.package_name \
19
+ && self.version_code == other.version_code \
20
+ && self.certificate_sha256_hash == other.certificate_sha256_hash \
21
+ && self.download_id == other.download_id
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,15 @@
1
+ module Supply
2
+ class ImageListing
3
+ attr_reader :id
4
+ attr_reader :sha1
5
+ attr_reader :sha256
6
+ attr_reader :url
7
+
8
+ def initialize(id, sha1, sha256, url)
9
+ @id = id
10
+ @sha1 = sha1
11
+ @sha256 = sha256
12
+ @url = url
13
+ end
14
+ end
15
+ end
@@ -210,6 +210,11 @@ module Supply
210
210
  description: "Whether to skip uploading SCREENSHOTS",
211
211
  type: Boolean,
212
212
  default_value: false),
213
+ FastlaneCore::ConfigItem.new(key: :sync_image_upload,
214
+ env_name: "SUPPLY_SYNC_IMAGE_UPLOAD",
215
+ description: "Whether to use sha256 comparison to skip upload of images and screenshots that are already in Play Store",
216
+ type: Boolean,
217
+ default_value: false),
213
218
  FastlaneCore::ConfigItem.new(key: :track_promote_to,
214
219
  env_name: "SUPPLY_TRACK_PROMOTE_TO",
215
220
  optional: true,
@@ -66,14 +66,14 @@ module Supply
66
66
 
67
67
  UI.message("Downloading `#{image_type}` for #{listing.language}...")
68
68
 
69
- urls = client.fetch_images(image_type: image_type, language: listing.language)
69
+ urls = client.fetch_images(image_type: image_type, language: listing.language).map(&:url)
70
70
  next if urls.nil? || urls.empty?
71
71
 
72
72
  image_counter = 1 # Used to prefix the downloaded files, so order is preserved.
73
73
  urls.each do |url|
74
74
  if IMAGES_TYPES.include?(image_type) # IMAGE_TYPES are stored in locale/images
75
75
  file_path = "#{path}.#{FastImage.type(url)}"
76
- else # SCREENSHOT_TYPES are stored in locale/images/<screensho_types>
76
+ else # SCREENSHOT_TYPES are stored in locale/images/<screenshot_types>
77
77
  file_path = File.join(path, "#{image_counter}_#{listing.language}.#{FastImage.type(url)}")
78
78
  end
79
79