fastlane 2.202.0 → 2.212.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (184) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +98 -98
  3. data/cert/lib/cert/runner.rb +15 -7
  4. data/deliver/lib/deliver/app_screenshot.rb +18 -0
  5. data/deliver/lib/deliver/options.rb +6 -2
  6. data/deliver/lib/deliver/runner.rb +76 -29
  7. data/deliver/lib/deliver/upload_price_tier.rb +3 -1
  8. data/deliver/lib/deliver/upload_screenshots.rb +1 -1
  9. data/fastlane/lib/assets/AppfileTemplate +1 -1
  10. data/fastlane/lib/assets/AppfileTemplate.swift +1 -1
  11. data/fastlane/lib/fastlane/actions/badge.rb +1 -1
  12. data/fastlane/lib/fastlane/actions/changelog_from_git_commits.rb +1 -1
  13. data/fastlane/lib/fastlane/actions/danger.rb +14 -0
  14. data/fastlane/lib/fastlane/actions/docs/build_app.md +5 -5
  15. data/fastlane/lib/fastlane/actions/docs/capture_android_screenshots.md +19 -2
  16. data/fastlane/lib/fastlane/actions/docs/frame_screenshots.md +1 -1
  17. data/fastlane/lib/fastlane/actions/docs/run_tests.md +1 -1
  18. data/fastlane/lib/fastlane/actions/get_version_number.rb +1 -1
  19. data/fastlane/lib/fastlane/actions/git_commit.rb +4 -6
  20. data/fastlane/lib/fastlane/actions/import_certificate.rb +1 -1
  21. data/fastlane/lib/fastlane/actions/pod_lib_lint.rb +1 -1
  22. data/fastlane/lib/fastlane/actions/pod_push.rb +19 -1
  23. data/fastlane/lib/fastlane/actions/read_podspec.rb +1 -1
  24. data/fastlane/lib/fastlane/actions/run_tests.rb +11 -9
  25. data/fastlane/lib/fastlane/actions/setup_ci.rb +13 -4
  26. data/fastlane/lib/fastlane/actions/trainer.rb +2 -2
  27. data/fastlane/lib/fastlane/actions/update_code_signing_settings.rb +14 -4
  28. data/fastlane/lib/fastlane/actions/update_info_plist.rb +1 -1
  29. data/fastlane/lib/fastlane/actions/update_project_provisioning.rb +10 -1
  30. data/fastlane/lib/fastlane/actions/upload_symbols_to_sentry.rb +1 -1
  31. data/fastlane/lib/fastlane/actions/verify_build.rb +1 -1
  32. data/fastlane/lib/fastlane/actions/xcode_install.rb +5 -1
  33. data/fastlane/lib/fastlane/actions/xcode_select.rb +1 -1
  34. data/fastlane/lib/fastlane/actions/xcodebuild.rb +8 -2
  35. data/fastlane/lib/fastlane/actions/xcodes.rb +152 -0
  36. data/fastlane/lib/fastlane/actions/xcversion.rb +10 -15
  37. data/fastlane/lib/fastlane/cli_tools_distributor.rb +5 -0
  38. data/fastlane/lib/fastlane/commands_generator.rb +2 -1
  39. data/fastlane/lib/fastlane/fast_file.rb +18 -5
  40. data/fastlane/lib/fastlane/features.rb +3 -0
  41. data/fastlane/lib/fastlane/helper/xcodes_helper.rb +28 -0
  42. data/fastlane/lib/fastlane/helper/xcversion_helper.rb +0 -9
  43. data/fastlane/lib/fastlane/lane_manager.rb +1 -1
  44. data/fastlane/lib/fastlane/plugins/template/%gem_name%.gemspec.erb +1 -1
  45. data/fastlane/lib/fastlane/plugins/template/.rubocop.yml +5 -1
  46. data/fastlane/lib/fastlane/setup/setup_ios.rb +1 -1
  47. data/fastlane/lib/fastlane/swift_fastlane_api_generator.rb +1 -1
  48. data/fastlane/lib/fastlane/swift_lane_manager.rb +11 -3
  49. data/fastlane/lib/fastlane/swift_runner_upgrader.rb +54 -1
  50. data/fastlane/lib/fastlane/tools.rb +16 -0
  51. data/fastlane/lib/fastlane/version.rb +1 -1
  52. data/fastlane/swift/Actions.swift +1 -1
  53. data/fastlane/swift/Appfile.swift +2 -2
  54. data/fastlane/swift/ArgumentProcessor.swift +1 -1
  55. data/fastlane/swift/Atomic.swift +150 -0
  56. data/fastlane/swift/ControlCommand.swift +1 -1
  57. data/fastlane/swift/Deliverfile.swift +2 -2
  58. data/fastlane/swift/DeliverfileProtocol.swift +8 -4
  59. data/fastlane/swift/Fastlane.swift +363 -184
  60. data/fastlane/swift/FastlaneSwiftRunner/FastlaneSwiftRunner.xcodeproj/project.pbxproj +30 -20
  61. data/fastlane/swift/FastlaneSwiftRunner/FastlaneSwiftRunner.xcodeproj/xcshareddata/xcschemes/FastlaneRunner.xcscheme +1 -1
  62. data/fastlane/swift/Gymfile.swift +2 -2
  63. data/fastlane/swift/GymfileProtocol.swift +7 -3
  64. data/fastlane/swift/LaneFileProtocol.swift +2 -2
  65. data/fastlane/swift/MainProcess.swift +3 -3
  66. data/fastlane/swift/Matchfile.swift +2 -2
  67. data/fastlane/swift/MatchfileProtocol.swift +21 -5
  68. data/fastlane/swift/OptionalConfigValue.swift +1 -1
  69. data/fastlane/swift/Plugins.swift +1 -1
  70. data/fastlane/swift/Precheckfile.swift +2 -2
  71. data/fastlane/swift/PrecheckfileProtocol.swift +3 -3
  72. data/fastlane/swift/RubyCommand.swift +1 -1
  73. data/fastlane/swift/RubyCommandable.swift +1 -1
  74. data/fastlane/swift/Runner.swift +10 -2
  75. data/fastlane/swift/RunnerArgument.swift +1 -1
  76. data/fastlane/swift/Scanfile.swift +2 -2
  77. data/fastlane/swift/ScanfileProtocol.swift +11 -3
  78. data/fastlane/swift/Screengrabfile.swift +2 -2
  79. data/fastlane/swift/ScreengrabfileProtocol.swift +3 -3
  80. data/fastlane/swift/Snapshotfile.swift +2 -2
  81. data/fastlane/swift/SnapshotfileProtocol.swift +4 -4
  82. data/fastlane/swift/SocketClient.swift +9 -5
  83. data/fastlane/swift/SocketClientDelegateProtocol.swift +2 -2
  84. data/fastlane/swift/SocketResponse.swift +1 -1
  85. data/fastlane/swift/formatting/Brewfile.lock.json +42 -24
  86. data/fastlane/swift/main.swift +1 -1
  87. data/fastlane/swift/upgrade_manifest.json +1 -1
  88. data/fastlane_core/README.md +1 -0
  89. data/fastlane_core/lib/fastlane_core/cert_checker.rb +79 -17
  90. data/fastlane_core/lib/fastlane_core/device_manager.rb +5 -1
  91. data/fastlane_core/lib/fastlane_core/itunes_transporter.rb +335 -20
  92. data/fastlane_core/lib/fastlane_core/keychain_importer.rb +1 -0
  93. data/fastlane_core/lib/fastlane_core/project.rb +19 -2
  94. data/fastlane_core/lib/fastlane_core/ui/implementations/shell.rb +4 -2
  95. data/frameit/lib/frameit/device.rb +1 -1
  96. data/frameit/lib/frameit/device_types.rb +9 -0
  97. data/frameit/lib/frameit/frame_downloader.rb +1 -1
  98. data/gym/lib/gym/generators/build_command_generator.rb +1 -0
  99. data/gym/lib/gym/options.rb +7 -0
  100. data/match/lib/match/change_password.rb +2 -0
  101. data/match/lib/match/commands_generator.rb +2 -1
  102. data/match/lib/match/encryption/openssl.rb +1 -1
  103. data/match/lib/match/encryption.rb +3 -0
  104. data/match/lib/match/generator.rb +1 -0
  105. data/match/lib/match/importer.rb +10 -1
  106. data/match/lib/match/migrate.rb +4 -3
  107. data/match/lib/match/module.rb +54 -2
  108. data/match/lib/match/nuke.rb +36 -47
  109. data/match/lib/match/options.rb +22 -1
  110. data/match/lib/match/runner.rb +25 -6
  111. data/match/lib/match/setup.rb +1 -1
  112. data/match/lib/match/spaceship_ensure.rb +4 -2
  113. data/match/lib/match/storage/gitlab/client.rb +102 -0
  114. data/match/lib/match/storage/gitlab/secure_file.rb +65 -0
  115. data/match/lib/match/storage/gitlab_secure_files.rb +182 -0
  116. data/match/lib/match/storage/google_cloud_storage.rb +7 -6
  117. data/match/lib/match/storage/s3_storage.rb +3 -3
  118. data/match/lib/match/storage.rb +4 -0
  119. data/match/lib/match/table_printer.rb +2 -1
  120. data/match/lib/match/utils.rb +15 -2
  121. data/pem/lib/pem/manager.rb +1 -1
  122. data/pilot/lib/pilot/build_manager.rb +33 -13
  123. data/pilot/lib/pilot/options.rb +6 -1
  124. data/scan/lib/scan/detect_values.rb +6 -0
  125. data/scan/lib/scan/options.rb +16 -1
  126. data/scan/lib/scan/runner.rb +33 -14
  127. data/scan/lib/scan/test_command_generator.rb +7 -1
  128. data/sigh/lib/sigh/download_all.rb +14 -2
  129. data/sigh/lib/sigh/module.rb +3 -1
  130. data/sigh/lib/sigh/options.rb +5 -0
  131. data/sigh/lib/sigh/runner.rb +12 -2
  132. data/snapshot/lib/assets/SnapshotHelper.swift +3 -3
  133. data/snapshot/lib/snapshot/options.rb +1 -1
  134. data/snapshot/lib/snapshot/reports_generator.rb +1 -0
  135. data/snapshot/lib/snapshot/simulator_launchers/simulator_launcher_base.rb +9 -2
  136. data/spaceship/lib/spaceship/client.rb +36 -25
  137. data/spaceship/lib/spaceship/connect_api/api_client.rb +10 -5
  138. data/spaceship/lib/spaceship/connect_api/models/actor.rb +26 -0
  139. data/spaceship/lib/spaceship/connect_api/models/app.rb +7 -5
  140. data/spaceship/lib/spaceship/connect_api/models/app_info_localization.rb +5 -0
  141. data/spaceship/lib/spaceship/connect_api/models/app_screenshot_set.rb +5 -0
  142. data/spaceship/lib/spaceship/connect_api/models/app_store_version.rb +1 -1
  143. data/spaceship/lib/spaceship/connect_api/models/app_store_version_localization.rb +27 -10
  144. data/spaceship/lib/spaceship/connect_api/models/build_bundle.rb +9 -0
  145. data/spaceship/lib/spaceship/connect_api/models/build_bundle_file_sizes.rb +34 -0
  146. data/spaceship/lib/spaceship/connect_api/models/build_delivery.rb +2 -1
  147. data/spaceship/lib/spaceship/connect_api/models/certificate.rb +1 -0
  148. data/spaceship/lib/spaceship/connect_api/models/device.rb +47 -4
  149. data/spaceship/lib/spaceship/connect_api/models/profile.rb +4 -0
  150. data/spaceship/lib/spaceship/connect_api/models/resolution_center_message.rb +29 -0
  151. data/spaceship/lib/spaceship/connect_api/models/resolution_center_thread.rb +67 -0
  152. data/spaceship/lib/spaceship/connect_api/models/review_rejection.rb +19 -0
  153. data/spaceship/lib/spaceship/connect_api/models/review_submission.rb +13 -0
  154. data/spaceship/lib/spaceship/connect_api/models/user.rb +5 -0
  155. data/spaceship/lib/spaceship/connect_api/provisioning/provisioning.rb +19 -0
  156. data/spaceship/lib/spaceship/connect_api/response.rb +10 -6
  157. data/spaceship/lib/spaceship/connect_api/testflight/testflight.rb +33 -2
  158. data/spaceship/lib/spaceship/connect_api/token.rb +5 -2
  159. data/spaceship/lib/spaceship/connect_api/tunes/tunes.rb +41 -8
  160. data/spaceship/lib/spaceship/connect_api.rb +6 -0
  161. data/spaceship/lib/spaceship/errors.rb +34 -0
  162. data/spaceship/lib/spaceship/hashcash.rb +52 -0
  163. data/spaceship/lib/spaceship/portal/certificate.rb +4 -3
  164. data/spaceship/lib/spaceship/tunes/app_ratings.rb +6 -6
  165. data/spaceship/lib/spaceship/tunes/iap_families.rb +1 -1
  166. data/spaceship/lib/spaceship/tunes/tunes.rb +0 -1
  167. data/spaceship/lib/spaceship/tunes/tunes_client.rb +79 -21
  168. data/spaceship/lib/spaceship/two_step_or_factor_client.rb +11 -3
  169. data/spaceship/lib/spaceship.rb +1 -0
  170. data/supply/lib/supply/client.rb +2 -7
  171. data/trainer/lib/assets/junit.xml.erb +9 -1
  172. data/trainer/lib/trainer/junit_generator.rb +2 -2
  173. data/trainer/lib/trainer/options.rb +1 -1
  174. data/trainer/lib/trainer/test_parser.rb +25 -3
  175. metadata +36 -33
  176. data/deliver/lib/deliver/.runner.rb.swp +0 -0
  177. data/deliver/lib/deliver/.submit_for_review.rb.swp +0 -0
  178. data/fastlane/lib/.DS_Store +0 -0
  179. data/fastlane/lib/fastlane/.DS_Store +0 -0
  180. data/fastlane/lib/fastlane/actions/.DS_Store +0 -0
  181. data/spaceship/lib/spaceship/connect_api/models/.app.rb.swp +0 -0
  182. data/spaceship/lib/spaceship/connect_api/testflight/.testflight.rb.swp +0 -0
  183. data/spaceship/lib/spaceship/tunes/user_detail.rb +0 -15
  184. data/trainer/lib/.DS_Store +0 -0
@@ -29,6 +29,9 @@ module Spaceship
29
29
  IPOD = "IPOD"
30
30
  APPLE_TV = "APPLE_TV"
31
31
  MAC = "MAC"
32
+
33
+ # As of 2022-11-12, this is not officially supported by App Store Connect API
34
+ APPLE_SILICON_MAC = "APPLE_SILICON_MAC"
32
35
  end
33
36
 
34
37
  module Status
@@ -58,7 +61,7 @@ module Spaceship
58
61
  # @param platform [String] The platform of the device.
59
62
  # @param include_disabled [Bool] Whether to include disable devices. false by default.
60
63
  # @return (Device) Find a device based on the UDID of the device. nil if no device was found.
61
- def self.find_by_udid(device_udid, client: nil, platform: nil, include_disabled: false)
64
+ def self.find_by_udid(device_udid, client: nil, include_disabled: false)
62
65
  self.all(client: client).find do |device|
63
66
  device.udid.casecmp(device_udid) == 0 && (include_disabled ? true : device.enabled?)
64
67
  end
@@ -67,10 +70,9 @@ module Spaceship
67
70
  # @param client [ConnectAPI] ConnectAPI client.
68
71
  # @param name [String] The name to be assigned to the device, if it needs to be created.
69
72
  # @param platform [String] The platform of the device.
70
- # @param include_disabled [Bool] Whether to include disable devices. false by default.
71
73
  # @return (Device) Find a device based on the UDID of the device. If no device was found, nil if no device was found.
72
- def self.find_or_create(device_udid, client: nil, name: nil, platform: nil, include_disabled: false)
73
- existing = self.find_by_udid(device_udid, client: client, platform: platform)
74
+ def self.find_or_create(device_udid, client: nil, name: nil, platform: nil)
75
+ existing = self.find_by_udid(device_udid, client: client)
74
76
  return existing if existing
75
77
  return self.create(client: client, name: name, platform: platform, udid: device_udid)
76
78
  end
@@ -85,6 +87,47 @@ module Spaceship
85
87
  resp = client.post_device(name: name, platform: platform, udid: udid)
86
88
  return resp.to_models.first
87
89
  end
90
+
91
+ # @param device_udid [String] Device Provisioning UDID that needs to be modified.
92
+ # @param client [ConnectAPI] ConnectAPI client.
93
+ # @param enabled [Boolean] New enabled value. true - if device must be enabled, `false` - to disable device. nil if no status change needed.
94
+ # @param new_name [String] A new name for the device. nil if no name change needed.
95
+ # @return (Device) Modified device based on the UDID of the device. nil if no device was found.
96
+ def self.modify(device_udid, client: nil, enabled: nil, new_name: nil)
97
+ client ||= Spaceship::ConnectAPI
98
+ existing = self.find_by_udid(device_udid, client: client, include_disabled: true)
99
+ return nil if existing.nil?
100
+
101
+ enabled = existing.enabled? if enabled.nil?
102
+ new_name ||= existing.name
103
+ return existing if existing.name == new_name && existing.enabled? == enabled
104
+ new_status = enabled ? Status::ENABLED : Status::DISABLED
105
+
106
+ resp = client.patch_device(id: existing.id, new_name: new_name, status: new_status)
107
+ return resp.to_models.first
108
+ end
109
+
110
+ # @param device_udid [String] Device Provisioning UDID that needs to be enabled.
111
+ # @param client [ConnectAPI] ConnectAPI client.
112
+ # @return (Device) Modified device based on the UDID of the device. nil if no device was found.
113
+ def self.enable(device_udid, client: nil)
114
+ self.modify(device_udid, client: client, enabled: true)
115
+ end
116
+
117
+ # @param device_udid [String] Device Provisioning UDID that needs to be disabled.
118
+ # @param client [ConnectAPI] ConnectAPI client.
119
+ # @return (Device) Modified device based on the UDID of the device. nil if no device was found.
120
+ def self.disable(device_udid, client: nil)
121
+ self.modify(device_udid, client: client, enabled: false)
122
+ end
123
+
124
+ # @param device_udid [String] Device Provisioning UDID that needs to be renamed.
125
+ # @param new_name [String] A new name for the device.
126
+ # @param client [ConnectAPI] ConnectAPI client.
127
+ # @return (Device) Modified device based on the UDID of the device. nil if no device was found.
128
+ def self.rename(device_udid, new_name, client: nil)
129
+ self.modify(device_udid, client: client, new_name: new_name)
130
+ end
88
131
  end
89
132
  end
90
133
  end
@@ -51,6 +51,10 @@ module Spaceship
51
51
  MAC_CATALYST_APP_DEVELOPMENT = "MAC_CATALYST_APP_DEVELOPMENT"
52
52
  MAC_CATALYST_APP_STORE = "MAC_CATALYST_APP_STORE"
53
53
  MAC_CATALYST_APP_DIRECT = "MAC_CATALYST_APP_DIRECT"
54
+
55
+ # As of 2022-06-25, only available with Apple ID auth
56
+ MAC_APP_INHOUSE = "MAC_APP_INHOUSE"
57
+ MAC_CATALYST_APP_INHOUSE = "MAC_CATALYST_APP_INHOUSE"
54
58
  end
55
59
 
56
60
  def self.type
@@ -0,0 +1,29 @@
1
+ require_relative '../model'
2
+ require_relative './actor'
3
+ require_relative './review_rejection'
4
+
5
+ module Spaceship
6
+ class ConnectAPI
7
+ class ResolutionCenterMessage
8
+ include Spaceship::ConnectAPI::Model
9
+
10
+ attr_accessor :message_body
11
+ attr_accessor :created_date
12
+ attr_accessor :rejections
13
+ attr_accessor :from_actor
14
+
15
+ attr_mapping({
16
+ messageBody: 'message_body',
17
+ createdDate: 'created_date',
18
+
19
+ # includes
20
+ rejections: 'rejections',
21
+ fromActor: 'from_actor'
22
+ })
23
+
24
+ def self.type
25
+ return 'resolutionCenterMessages'
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,67 @@
1
+ require_relative '../model'
2
+
3
+ module Spaceship
4
+ class ConnectAPI
5
+ class ResolutionCenterThread
6
+ include Spaceship::ConnectAPI::Model
7
+
8
+ attr_accessor :state
9
+ attr_accessor :can_developer_add_node
10
+ attr_accessor :objectionable_content
11
+ attr_accessor :thread_type
12
+ attr_accessor :created_date
13
+ attr_accessor :last_message_response_date
14
+
15
+ attr_accessor :resolution_center_messages
16
+ attr_accessor :app_store_version
17
+
18
+ module ThreadType
19
+ REJECTION_BINARY = 'REJECTION_BINARY'
20
+ REJECTION_METADATA = 'REJECTION_METADATA'
21
+ REJECTION_REVIEW_SUBMISSION = 'REJECTION_REVIEW_SUBMISSION'
22
+ APP_MESSAGE_ARC = 'APP_MESSAGE_ARC'
23
+ APP_MESSAGE_ARB = 'APP_MESSAGE_ARB'
24
+ APP_MESSAGE_COMM = 'APP_MESSAGE_COMM'
25
+ end
26
+
27
+ attr_mapping({
28
+ state: 'state',
29
+ canDeveloperAddNote: 'can_developer_add_node',
30
+ objectionableContent: 'objectionable_content',
31
+ threadType: 'thread_type',
32
+ createdDate: 'created_date',
33
+ lastMessageResponseDate: 'last_message_response_date',
34
+
35
+ # includes
36
+ resolutionCenterMessages: 'resolution_center_messages',
37
+ appStoreVersion: 'app_store_version'
38
+ })
39
+
40
+ def self.type
41
+ return "resolutionCenterThreads"
42
+ end
43
+
44
+ #
45
+ # API
46
+ #
47
+
48
+ def self.all(client: nil, filter:, includes: nil)
49
+ client ||= Spaceship::ConnectAPI
50
+ resps = client.get_resolution_center_threads(filter: filter, includes: includes).all_pages
51
+ return resps.flat_map(&:to_models)
52
+ end
53
+
54
+ def fetch_messages(client: nil, filter: {}, includes: nil)
55
+ client ||= Spaceship::ConnectAPI
56
+ resps = client.get_resolution_center_messages(thread_id: id, filter: filter, includes: includes).all_pages
57
+ return resps.flat_map(&:to_models)
58
+ end
59
+
60
+ def fetch_rejection_reasons(client: nil, includes: nil)
61
+ client ||= Spaceship::ConnectAPI
62
+ resp = client.get_review_rejection(filter: { 'resolutionCenterMessage.resolutionCenterThread': id }, includes: includes)
63
+ return resp.to_models
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,19 @@
1
+ require_relative '../model'
2
+
3
+ module Spaceship
4
+ class ConnectAPI
5
+ class ReviewRejection
6
+ include Spaceship::ConnectAPI::Model
7
+
8
+ attr_accessor :reasons
9
+
10
+ attr_mapping({
11
+ reasons: 'reasons'
12
+ })
13
+
14
+ def self.type
15
+ return 'reviewRejections'
16
+ end
17
+ end
18
+ end
19
+ end
@@ -20,6 +20,7 @@ module Spaceship
20
20
  COMPLETE = "COMPLETE"
21
21
  IN_REVIEW = "IN_REVIEW"
22
22
  READY_FOR_REVIEW = "READY_FOR_REVIEW"
23
+ UNRESOLVED_ISSUES = "UNRESOLVED_ISSUES"
23
24
  WAITING_FOR_REVIEW = "WAITING_FOR_REVIEW"
24
25
  end
25
26
 
@@ -68,6 +69,18 @@ module Spaceship
68
69
  resp = client.post_review_submission_item(review_submission_id: id, app_store_version_id: app_store_version_id)
69
70
  return resp.to_models.first
70
71
  end
72
+
73
+ def fetch_resolution_center_threads(client: nil)
74
+ client ||= Spaceship::ConnectAPI
75
+ resp = client.get_resolution_center_threads(filter: { reviewSubmission: id }, includes: 'reviewSubmission')
76
+ return resp.to_models
77
+ end
78
+
79
+ def latest_resolution_center_messages(client: nil)
80
+ client ||= Spaceship::ConnectAPI
81
+ threads = fetch_resolution_center_threads(client: client)
82
+ threads.first.fetch_messages(client: client)
83
+ end
71
84
  end
72
85
  end
73
86
  end
@@ -57,6 +57,11 @@ module Spaceship
57
57
  return all(client: client, filter: { email: email }, includes: includes)
58
58
  end
59
59
 
60
+ def delete!(client: nil)
61
+ client ||= Spaceship::ConnectAPI
62
+ client.delete_user(user_id: id)
63
+ end
64
+
60
65
  def get_visible_apps(client: nil, limit: nil)
61
66
  client ||= Spaceship::ConnectAPI
62
67
  resp = client.get_user_visible_apps(user_id: id, limit: limit)
@@ -190,6 +190,25 @@ module Spaceship
190
190
  provisioning_request_client.post("devices", body)
191
191
  end
192
192
 
193
+ def patch_device(id: nil, status: nil, new_name: nil)
194
+ raise "Device id is nil" if id.nil?
195
+
196
+ attributes = {
197
+ name: new_name,
198
+ status: status
199
+ }
200
+
201
+ body = {
202
+ data: {
203
+ attributes: attributes,
204
+ id: id,
205
+ type: "devices"
206
+ }
207
+ }
208
+
209
+ provisioning_request_client.patch("devices/#{id}", body)
210
+ end
211
+
193
212
  #
194
213
  # profiles
195
214
  #
@@ -22,13 +22,17 @@ module Spaceship
22
22
  return links["next"]
23
23
  end
24
24
 
25
- def next_page
25
+ def next_page(&block)
26
26
  url = next_url
27
27
  return nil if url.nil?
28
- return client.get(url)
28
+ if block_given?
29
+ return yield(url)
30
+ else
31
+ return client.get(url)
32
+ end
29
33
  end
30
34
 
31
- def next_pages(count: 1)
35
+ def next_pages(count: 1, &block)
32
36
  if !count.nil? && count < 0
33
37
  count = 0
34
38
  end
@@ -38,7 +42,7 @@ module Spaceship
38
42
 
39
43
  resp = self
40
44
  loop do
41
- resp = resp.next_page
45
+ resp = resp.next_page(&block)
42
46
  break if resp.nil?
43
47
  responses << resp
44
48
  counter += 1
@@ -49,8 +53,8 @@ module Spaceship
49
53
  return responses
50
54
  end
51
55
 
52
- def all_pages
53
- return next_pages(count: nil)
56
+ def all_pages(&block)
57
+ return next_pages(count: nil, &block)
54
58
  end
55
59
 
56
60
  def to_models
@@ -290,6 +290,28 @@ module Spaceship
290
290
  test_flight_request_client.post("bulkBetaTesterAssignments", body)
291
291
  end
292
292
 
293
+ # attributes - {email: "", firstName: "", lastName: ""}
294
+ def post_beta_tester_assignment(beta_group_ids: [], attributes: {})
295
+ body = {
296
+ data: {
297
+ attributes: attributes,
298
+ relationships: {
299
+ betaGroups: {
300
+ data: beta_group_ids.map do |id|
301
+ {
302
+ type: "betaGroups",
303
+ id: id
304
+ }
305
+ end
306
+ }
307
+ },
308
+ type: "betaTesters"
309
+ }
310
+ }
311
+
312
+ test_flight_request_client.post("betaTesters", body)
313
+ end
314
+
293
315
  def add_beta_tester_to_group(beta_group_id: nil, beta_tester_ids: nil)
294
316
  beta_tester_ids || []
295
317
  body = {
@@ -390,6 +412,15 @@ module Spaceship
390
412
  test_flight_request_client.get("betaTesterMetrics", params)
391
413
  end
392
414
 
415
+ #
416
+ # buildBundles
417
+ #
418
+
419
+ def get_build_bundles_build_bundle_file_sizes(build_bundle_id:, limit: nil)
420
+ params = test_flight_request_client.build_params(filter: nil, includes: nil, limit: limit, sort: nil, cursor: nil)
421
+ test_flight_request_client.get("buildBundles/#{build_bundle_id}/buildBundleFileSizes", params)
422
+ end
423
+
393
424
  #
394
425
  # builds
395
426
  #
@@ -448,9 +479,9 @@ module Spaceship
448
479
  # buildDeliveries
449
480
  #
450
481
 
451
- def get_build_deliveries(filter: {}, includes: nil, limit: nil, sort: nil)
482
+ def get_build_deliveries(app_id:, filter: {}, includes: nil, limit: nil, sort: nil)
452
483
  params = test_flight_request_client.build_params(filter: filter, includes: includes, limit: limit, sort: sort)
453
- test_flight_request_client.get("buildDeliveries", params)
484
+ test_flight_request_client.get("apps/#{app_id}/buildDeliveries", params)
454
485
  end
455
486
 
456
487
  #
@@ -90,14 +90,17 @@ module Spaceship
90
90
  end
91
91
 
92
92
  def refresh!
93
- @expiration = Time.now + @duration
93
+ now = Time.now
94
+ @expiration = now + @duration
94
95
 
95
96
  header = {
96
- kid: key_id
97
+ kid: key_id,
98
+ typ: 'JWT'
97
99
  }
98
100
 
99
101
  payload = {
100
102
  iss: issuer_id,
103
+ iat: now.to_i,
101
104
  exp: @expiration.to_i,
102
105
  aud: 'appstoreconnect-v1'
103
106
  }
@@ -134,7 +134,15 @@ module Spaceship
134
134
  tunes_request_client.post("apps", body)
135
135
  end
136
136
 
137
- def patch_app(app_id: nil, attributes: {}, app_price_tier_id: nil, territory_ids: nil)
137
+ # Updates app attributes, price tier, visibility in regions or countries.
138
+ # Use territory_ids with allow_removing_from_sale to remove app from sale
139
+ # @param territory_ids updates app visibility in regions or countries.
140
+ # Possible values:
141
+ # empty array will remove app from sale if allow_removing_from_sale is true,
142
+ # array with territory ids will set availability to territories with those ids,
143
+ # nil will leave app availability on AppStore as is
144
+ # @param allow_removing_from_sale allows for removing app from sale when territory_ids is an empty array
145
+ def patch_app(app_id: nil, attributes: {}, app_price_tier_id: nil, territory_ids: nil, allow_removing_from_sale: false)
138
146
  relationships = {}
139
147
  included = []
140
148
 
@@ -173,13 +181,15 @@ module Spaceship
173
181
  end
174
182
 
175
183
  # Territories
176
- territories_data = (territory_ids || []).map do |id|
177
- { type: "territories", id: id }
178
- end
179
- unless territories_data.empty?
180
- relationships[:availableTerritories] = {
181
- data: territories_data
182
- }
184
+ unless territory_ids.nil?
185
+ territories_data = territory_ids.map do |id|
186
+ { type: "territories", id: id }
187
+ end
188
+ if !territories_data.empty? || allow_removing_from_sale
189
+ relationships[:availableTerritories] = {
190
+ data: territories_data
191
+ }
192
+ end
183
193
  end
184
194
 
185
195
  # Data
@@ -1242,6 +1252,29 @@ module Spaceship
1242
1252
  params = tunes_request_client.build_params(filter: nil, includes: nil, limit: nil, sort: nil)
1243
1253
  tunes_request_client.get("territories", params)
1244
1254
  end
1255
+
1256
+ #
1257
+ # resolutionCenter
1258
+ #
1259
+ # As of 2022-11-11:
1260
+ # This is not official available throught the App Store Connect API using an API Key.
1261
+ # This is only works with Apple ID auth.
1262
+ #
1263
+
1264
+ def get_resolution_center_threads(filter: {}, includes: nil)
1265
+ params = tunes_request_client.build_params(filter: filter, includes: includes)
1266
+ tunes_request_client.get('resolutionCenterThreads', params)
1267
+ end
1268
+
1269
+ def get_resolution_center_messages(thread_id:, filter: {}, includes: nil)
1270
+ params = tunes_request_client.build_params(filter: filter, includes: includes)
1271
+ tunes_request_client.get("resolutionCenterThreads/#{thread_id}/resolutionCenterMessages", params)
1272
+ end
1273
+
1274
+ def get_review_rejection(filter: {}, includes: nil)
1275
+ params = tunes_request_client.build_params(filter: filter, includes: includes)
1276
+ tunes_request_client.get("reviewRejections", params)
1277
+ end
1245
1278
  end
1246
1279
  end
1247
1280
  end
@@ -33,6 +33,7 @@ require 'spaceship/connect_api/models/build'
33
33
  require 'spaceship/connect_api/models/build_delivery'
34
34
  require 'spaceship/connect_api/models/build_beta_detail'
35
35
  require 'spaceship/connect_api/models/build_bundle'
36
+ require 'spaceship/connect_api/models/build_bundle_file_sizes'
36
37
  require 'spaceship/connect_api/models/custom_app_organization'
37
38
  require 'spaceship/connect_api/models/custom_app_user'
38
39
  require 'spaceship/connect_api/models/pre_release_version'
@@ -68,6 +69,11 @@ require 'spaceship/connect_api/models/reset_ratings_request'
68
69
  require 'spaceship/connect_api/models/sandbox_tester'
69
70
  require 'spaceship/connect_api/models/territory'
70
71
 
72
+ require 'spaceship/connect_api/models/resolution_center_message'
73
+ require 'spaceship/connect_api/models/resolution_center_thread'
74
+ require 'spaceship/connect_api/models/review_rejection'
75
+ require 'spaceship/connect_api/models/actor'
76
+
71
77
  module Spaceship
72
78
  class ConnectAPI
73
79
  # Defined in the App Store Connect API docs:
@@ -98,4 +98,38 @@ module Spaceship
98
98
 
99
99
  # Raised when 403 is received from portal request
100
100
  class AccessForbiddenError < BasicPreferredInfoError; end
101
+
102
+ # Base class for errors coming from App Store Connect locale changes
103
+ class AppStoreLocaleError < BasicPreferredInfoError
104
+ def initialize(msg)
105
+ @message = (msg ? "An exception occurred for locale: #{msg}." : nil)
106
+ super
107
+ end
108
+
109
+ # no need to search github issues since the error is specific
110
+ def show_github_issues
111
+ false
112
+ end
113
+ end
114
+
115
+ # Raised for localized text errors from App Store Connect
116
+ class AppStoreLocalizationError < AppStoreLocaleError
117
+ def preferred_error_info
118
+ "#{@message} Check the localization requirements here: https://help.apple.com/app-store-connect/en.lproj/static.html#dev354659071"
119
+ end
120
+ end
121
+
122
+ # Raised for localized screenshots errors from App Store Connect
123
+ class AppStoreScreenshotError < AppStoreLocaleError
124
+ def preferred_error_info
125
+ "#{@message} Check the screenshot requirements here: https://help.apple.com/app-store-connect/en.lproj/static.html#devd274dd925"
126
+ end
127
+ end
128
+
129
+ # Raised for localized app preview errors from App Store Connect
130
+ class AppStoreAppPreviewError < AppStoreLocaleError
131
+ def preferred_error_info
132
+ "#{@message} Check the app preview requirements here: https://help.apple.com/app-store-connect/en.lproj/static.html#dev4e413fcb8"
133
+ end
134
+ end
101
135
  end
@@ -0,0 +1,52 @@
1
+ require 'digest'
2
+
3
+ module Spaceship
4
+ module Hashcash
5
+ # This App Store Connect hashcash spec was generously donated by...
6
+ #
7
+ # __ _
8
+ # __ _ _ __ _ __ / _|(_) __ _ _ _ _ __ ___ ___
9
+ # / _` || '_ \ | '_ \ | |_ | | / _` || | | || '__|/ _ \/ __|
10
+ # | (_| || |_) || |_) || _|| || (_| || |_| || | | __/\__ \
11
+ # \__,_|| .__/ | .__/ |_| |_| \__, | \__,_||_| \___||___/
12
+ # |_| |_| |___/
13
+ #
14
+ #
15
+ # <summary>
16
+ # 1:11:20230223170600:4d74fb15eb23f465f1f6fcbf534e5877::6373
17
+ # X-APPLE-HC: 1:11:20230223170600:4d74fb15eb23f465f1f6fcbf534e5877::6373
18
+ # ^ ^ ^ ^ ^
19
+ # | | | | +-- Counter
20
+ # | | | +-- Resource
21
+ # | | +-- Date YYMMDD[hhmm[ss]]
22
+ # | +-- Bits (number of leading zeros)
23
+ # +-- Version
24
+ #
25
+ # We can't use an off-the-shelf Hashcash because Apple's implementation is not quite the same as the spec/convention.
26
+ # 1. The spec calls for a nonce called "Rand" to be inserted between the Ext and Counter. They don't do that at all.
27
+ # 2. The Counter conventionally encoded as base-64 but Apple just uses the decimal number's string representation.
28
+ #
29
+ # Iterate from Counter=0 to Counter=N finding an N that makes the SHA1(X-APPLE-HC) lead with Bits leading zero bits
30
+ #
31
+ #
32
+ # We get the "Resource" from the X-Apple-HC-Challenge header and Bits from X-Apple-HC-Bits
33
+ #
34
+ # </summary>
35
+ def self.make(bits:, challenge:)
36
+ version = 1
37
+ date = Time.now.strftime("%Y%m%d%H%M%S")
38
+
39
+ counter = 0
40
+ loop do
41
+ hc = [
42
+ version, bits, date, challenge, ":#{counter}"
43
+ ].join(":")
44
+
45
+ if Digest::SHA1.digest(hc).unpack1('B*')[0, bits.to_i].to_i == 0
46
+ return hc
47
+ end
48
+ counter += 1
49
+ end
50
+ end
51
+ end
52
+ end
@@ -168,7 +168,7 @@ module Spaceship
168
168
  "R58UK2EWSO" => Production,
169
169
  "9RQEK7MSXA" => InHouse,
170
170
  "LA30L5BJEU" => Certificate,
171
- "BKLRAVXMGM" => DevelopmentPush,
171
+ "JKG5JZ54H7" => DevelopmentPush,
172
172
  "UPV3DW712I" => ProductionPush,
173
173
  "Y3B2F3TYSI" => Passbook,
174
174
  "3T2ZP62QW8" => WebsitePush,
@@ -178,12 +178,13 @@ module Spaceship
178
178
  }
179
179
 
180
180
  OLDER_IOS_CERTIFICATE_TYPES = [
181
- # those are also sent by the browser, but not sure what they represent
181
+ "3BQKVH9I2X", # old ProductionPush
182
+ "BKLRAVXMGM", # old DevelopmentPush
183
+ # those are also sent by the browser, but not sure what they represent:
182
184
  "T44PTHVNID",
183
185
  "DZQUP8189Y",
184
186
  "FGQUP4785Z",
185
187
  "S5WE21TULA",
186
- "3BQKVH9I2X", # ProductionPush,
187
188
  "FUOY7LWJET"
188
189
  ]
189
190
 
@@ -8,22 +8,22 @@ module Spaceship
8
8
  # this version is for
9
9
  attr_accessor :application
10
10
 
11
- # @return (Integer) total number of ratings recevied
11
+ # @return (Integer) total number of ratings received
12
12
  attr_accessor :rating_count
13
13
 
14
- # @return (Integer) total number of one star ratings recevied
14
+ # @return (Integer) total number of one star ratings received
15
15
  attr_accessor :one_star_rating_count
16
16
 
17
- # @return (Integer) total number of two star ratings recevied
17
+ # @return (Integer) total number of two star ratings received
18
18
  attr_accessor :two_star_rating_count
19
19
 
20
- # @return (Integer) total number of three star ratings recevied
20
+ # @return (Integer) total number of three star ratings received
21
21
  attr_accessor :three_star_rating_count
22
22
 
23
- # @return (Integer) total number of four star ratings recevied
23
+ # @return (Integer) total number of four star ratings received
24
24
  attr_accessor :four_star_rating_count
25
25
 
26
- # @return (Integer) total number of five star ratings recevied
26
+ # @return (Integer) total number of five star ratings received
27
27
  attr_accessor :five_star_rating_count
28
28
 
29
29
  attr_mapping({
@@ -7,7 +7,7 @@ module Spaceship
7
7
  attr_accessor :application
8
8
 
9
9
  # Create a new Purchase Family
10
- # a freshly created family has to have atleast one product.
10
+ # a freshly created family has to have at least one product.
11
11
  # the product will be created, and versions/pricing_intervals and so on
12
12
  # should be set by subsequent edit.
13
13
  # @param name (String) Familyname
@@ -14,7 +14,6 @@ require_relative 'app_version_ref'
14
14
  require_relative 'app_version_history'
15
15
  require_relative 'app_version_states_history'
16
16
  require_relative 'transit_app_file'
17
- require_relative 'user_detail'
18
17
  require_relative 'app_screenshot'
19
18
  require_relative 'language_converter'
20
19
  require_relative 'build'