fastlane 2.157.4 → 2.162.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (110) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +80 -80
  3. data/cert/lib/cert/options.rb +28 -1
  4. data/cert/lib/cert/runner.rb +50 -33
  5. data/deliver/lib/deliver/app_screenshot_iterator.rb +4 -4
  6. data/deliver/lib/deliver/options.rb +17 -1
  7. data/deliver/lib/deliver/runner.rb +36 -7
  8. data/deliver/lib/deliver/upload_metadata.rb +37 -6
  9. data/deliver/lib/deliver/upload_price_tier.rb +7 -2
  10. data/deliver/lib/deliver/upload_screenshots.rb +25 -8
  11. data/{pilot/lib/pilot/.manager.rb.swp → fastlane/lib/fastlane/.erb_template_helper.rb.swp} +0 -0
  12. data/fastlane/lib/fastlane/actions/{.ensure_git_status_clean.rb.swp → .git_commit.rb.swp} +0 -0
  13. data/fastlane/lib/fastlane/actions/actions_helper.rb +20 -1
  14. data/fastlane/lib/fastlane/actions/app_store_connect_api_key.rb +6 -1
  15. data/fastlane/lib/fastlane/actions/clean_build_artifacts.rb +1 -0
  16. data/fastlane/lib/fastlane/actions/docs/capture_android_screenshots.md +2 -2
  17. data/fastlane/lib/fastlane/actions/docs/capture_ios_screenshots.md +1 -1
  18. data/fastlane/lib/fastlane/actions/docs/create_app_online.md +1 -1
  19. data/fastlane/lib/fastlane/actions/docs/frame_screenshots.md +3 -2
  20. data/fastlane/lib/fastlane/actions/docs/run_tests.md +2 -2
  21. data/fastlane/lib/fastlane/actions/docs/sync_code_signing.md +3 -3
  22. data/fastlane/lib/fastlane/actions/docs/upload_to_play_store.md +2 -2
  23. data/fastlane/lib/fastlane/actions/docs/upload_to_testflight.md +2 -2
  24. data/fastlane/lib/fastlane/actions/download_dsyms.rb +32 -7
  25. data/fastlane/lib/fastlane/actions/ensure_git_status_clean.rb +13 -2
  26. data/fastlane/lib/fastlane/helper/git_helper.rb +2 -0
  27. data/fastlane/lib/fastlane/swift_fastlane_api_generator.rb +6 -4
  28. data/fastlane/lib/fastlane/swift_fastlane_function.rb +1 -1
  29. data/fastlane/lib/fastlane/version.rb +1 -1
  30. data/fastlane/swift/Actions.swift +2 -1
  31. data/fastlane/swift/Appfile.swift +2 -4
  32. data/fastlane/swift/ArgumentProcessor.swift +2 -6
  33. data/fastlane/swift/ControlCommand.swift +2 -5
  34. data/fastlane/swift/Deliverfile.swift +5 -2
  35. data/fastlane/swift/DeliverfileProtocol.swift +15 -4
  36. data/fastlane/swift/Fastfile.swift +5 -1
  37. data/fastlane/swift/Fastlane.swift +2333 -2240
  38. data/fastlane/swift/FastlaneSwiftRunner/FastlaneSwiftRunner.xcodeproj/project.pbxproj +5 -5
  39. data/fastlane/swift/Gymfile.swift +5 -2
  40. data/fastlane/swift/GymfileProtocol.swift +6 -3
  41. data/fastlane/swift/LaneFileProtocol.swift +42 -29
  42. data/fastlane/swift/MainProcess.swift +77 -0
  43. data/fastlane/swift/Matchfile.swift +5 -2
  44. data/fastlane/swift/MatchfileProtocol.swift +21 -6
  45. data/fastlane/swift/Plugins.swift +2 -1
  46. data/fastlane/swift/Precheckfile.swift +5 -2
  47. data/fastlane/swift/PrecheckfileProtocol.swift +18 -3
  48. data/fastlane/swift/RubyCommand.swift +2 -6
  49. data/fastlane/swift/RubyCommandable.swift +2 -6
  50. data/fastlane/swift/Runner.swift +5 -9
  51. data/fastlane/swift/RunnerArgument.swift +2 -6
  52. data/fastlane/swift/Scanfile.swift +5 -2
  53. data/fastlane/swift/ScanfileProtocol.swift +6 -3
  54. data/fastlane/swift/Screengrabfile.swift +5 -2
  55. data/fastlane/swift/ScreengrabfileProtocol.swift +6 -3
  56. data/fastlane/swift/Snapshotfile.swift +5 -2
  57. data/fastlane/swift/SnapshotfileProtocol.swift +6 -3
  58. data/fastlane/swift/SocketClient.swift +3 -7
  59. data/fastlane/swift/SocketClientDelegateProtocol.swift +2 -6
  60. data/fastlane/swift/SocketResponse.swift +2 -6
  61. data/fastlane/swift/formatting/Brewfile.lock.json +18 -10
  62. data/fastlane/swift/main.swift +4 -8
  63. data/fastlane/swift/upgrade_manifest.json +1 -1
  64. data/fastlane_core/lib/fastlane_core/analytics/analytics_session.rb +6 -7
  65. data/fastlane_core/lib/fastlane_core/keychain_importer.rb +2 -2
  66. data/frameit/lib/frameit/editor.rb +1 -0
  67. data/match/lib/match/generator.rb +6 -1
  68. data/match/lib/match/importer.rb +44 -8
  69. data/match/lib/match/migrate.rb +13 -2
  70. data/match/lib/match/nuke.rb +65 -22
  71. data/match/lib/match/options.rb +27 -2
  72. data/match/lib/match/runner.rb +38 -10
  73. data/match/lib/match/spaceship_ensure.rb +27 -21
  74. data/match/lib/match/storage/google_cloud_storage.rb +20 -3
  75. data/match/lib/match/storage/s3_storage.rb +19 -3
  76. data/pilot/lib/pilot/options.rb +2 -2
  77. data/precheck/lib/precheck/options.rb +25 -0
  78. data/precheck/lib/precheck/rule_processor.rb +94 -60
  79. data/precheck/lib/precheck/runner.rb +26 -5
  80. data/sigh/lib/sigh/options.rb +21 -0
  81. data/sigh/lib/sigh/runner.rb +80 -38
  82. data/snapshot/lib/assets/SnapshotHelper.swift +17 -2
  83. data/spaceship/README.md +1 -1
  84. data/spaceship/lib/spaceship/{connect_api/.DS_Store → .DS_Store} +0 -0
  85. data/spaceship/lib/spaceship/client.rb +2 -1
  86. data/spaceship/lib/spaceship/connect_api.rb +1 -0
  87. data/spaceship/lib/spaceship/connect_api/api_client.rb +3 -3
  88. data/spaceship/lib/spaceship/connect_api/client.rb +38 -15
  89. data/{fastlane/lib/fastlane/actions/.update_project_provisioning.rb.swp → spaceship/lib/spaceship/connect_api/models/.app_store_version_submission.rb.swp} +0 -0
  90. data/spaceship/lib/spaceship/connect_api/models/app.rb +17 -9
  91. data/spaceship/lib/spaceship/connect_api/models/app_info.rb +1 -0
  92. data/spaceship/lib/spaceship/connect_api/models/app_screenshot.rb +3 -1
  93. data/spaceship/lib/spaceship/connect_api/models/app_screenshot_set.rb +2 -2
  94. data/spaceship/lib/spaceship/connect_api/models/app_store_version.rb +3 -5
  95. data/spaceship/lib/spaceship/connect_api/models/app_store_version_localization.rb +3 -5
  96. data/spaceship/lib/spaceship/connect_api/models/app_store_version_phased_release.rb +21 -0
  97. data/spaceship/lib/spaceship/connect_api/models/beta_tester.rb +2 -1
  98. data/spaceship/lib/spaceship/connect_api/models/certificate.rb +42 -0
  99. data/spaceship/lib/spaceship/connect_api/models/profile.rb +7 -1
  100. data/spaceship/lib/spaceship/connect_api/models/user_invitation.rb +59 -0
  101. data/spaceship/lib/spaceship/connect_api/provisioning/provisioning.rb +28 -2
  102. data/spaceship/lib/spaceship/connect_api/spaceship.rb +3 -2
  103. data/spaceship/lib/spaceship/connect_api/testflight/testflight.rb +13 -0
  104. data/spaceship/lib/spaceship/connect_api/tunes/tunes.rb +29 -9
  105. data/spaceship/lib/spaceship/connect_api/users/users.rb +40 -0
  106. data/spaceship/lib/spaceship/helper/net_http_generic_request.rb +11 -5
  107. metadata +24 -25
  108. data/fastlane/lib/fastlane/actions/.hockey.rb.swp +0 -0
  109. data/fastlane/lib/fastlane/actions/.slack.rb.swp +0 -0
  110. data/fastlane/swift/FastlaneSwiftRunner/FastlaneSwiftRunner.xcodeproj/project.xcworkspace/xcuserdata/josh.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
@@ -42,9 +42,14 @@ module Match
42
42
  # while on Git we recommend using the git branch instead. As there is
43
43
  # no concept of branches in Google Cloud Storage (omg thanks), we use
44
44
  # the team id properly
45
- spaceship = SpaceshipEnsure.new(params[:username], params[:team_id], params[:team_name])
45
+ spaceship = SpaceshipEnsure.new(params[:username], params[:team_id], params[:team_name], api_token(params))
46
46
  team_id = spaceship.team_id
47
- UI.message("Detected team ID '#{team_id}' to use for Google Cloud Storage...")
47
+
48
+ if team_id.to_s.empty?
49
+ UI.user_error!("The `team_id` option is required. fastlane cannot automatically determine portal team id via the App Store Connect API (yet)")
50
+ else
51
+ UI.message("Detected team ID '#{team_id}' to use for Google Cloud Storage...")
52
+ end
48
53
 
49
54
  files_to_commit = []
50
55
  Dir.chdir(git_storage.working_directory) do
@@ -85,6 +90,12 @@ module Match
85
90
  UI.input("Please make sure to read the above and confirm with enter")
86
91
  end
87
92
 
93
+ def api_token(params)
94
+ @api_token ||= Spaceship::ConnectAPI::Token.create(params[:api_key]) if params[:api_key]
95
+ @api_token ||= Spaceship::ConnectAPI::Token.from_json_file(params[:api_key_path]) if params[:api_key_path]
96
+ return @api_token
97
+ end
98
+
88
99
  def ensure_parameters_are_valid(params)
89
100
  if params[:readonly]
90
101
  UI.user_error!("`fastlane match migrate` doesn't work in `readonly` mode")
@@ -44,7 +44,7 @@ module Match
44
44
  s3_access_key: params[:s3_access_key].to_s,
45
45
  s3_secret_access_key: params[:s3_secret_access_key].to_s,
46
46
  s3_bucket: params[:s3_bucket].to_s,
47
- team_id: params[:team_id] || Spaceship.client.team_id
47
+ team_id: params[:team_id] || Spaceship::ConnectAPI.client.portal_team_id
48
48
  })
49
49
  self.storage.download
50
50
 
@@ -97,10 +97,14 @@ module Match
97
97
  end
98
98
 
99
99
  def spaceship_login
100
- Spaceship.login(params[:username])
101
- Spaceship.select_team(team_id: params[:team_id], team_name: params[:team_name])
100
+ if api_token
101
+ UI.message("Creating authorization token for App Store Connect API")
102
+ Spaceship::ConnectAPI.token = api_token
103
+ else
104
+ Spaceship::ConnectAPI.login(params[:username], use_portal: true, use_tunes: false, portal_team_id: params[:team_id], team_name: params[:team_name])
105
+ end
102
106
 
103
- if Spaceship.client.in_house? && (type == "distribution" || type == "enterprise")
107
+ if Spaceship::ConnectAPI.client.in_house? && (type == "distribution" || type == "enterprise")
104
108
  UI.error("---")
105
109
  UI.error("⚠️ Warning: This seems to be an Enterprise account!")
106
110
  UI.error("By nuking your account's distribution, all your apps deployed via ad-hoc will stop working!") if type == "distribution"
@@ -111,6 +115,12 @@ module Match
111
115
  end
112
116
  end
113
117
 
118
+ def api_token
119
+ @api_token ||= Spaceship::ConnectAPI::Token.create(params[:api_key]) if params[:api_key]
120
+ @api_token ||= Spaceship::ConnectAPI::Token.from_json_file(params[:api_key_path]) if params[:api_key_path]
121
+ return @api_token
122
+ end
123
+
114
124
  # Collect all the certs/profiles
115
125
  def prepare_list
116
126
  UI.message("Fetching certificates and profiles...")
@@ -125,8 +135,10 @@ module Match
125
135
  # Get all iOS and macOS profile
126
136
  self.profiles = []
127
137
  prov_types.each do |prov_type|
128
- self.profiles += profile_type(prov_type).all(mac: false)
129
- self.profiles += profile_type(prov_type).all(mac: true)
138
+ types = profile_types(prov_type)
139
+ # Filtering on 'profileType' seems to be undocumented as of 2020-07-30
140
+ # but works on both web session and official API
141
+ self.profiles += Spaceship::ConnectAPI::Profile.all(filter: { profileType: types.join(",") })
130
142
  end
131
143
 
132
144
  # Gets the main and additional cert types
@@ -138,7 +150,7 @@ module Match
138
150
  self.certs = []
139
151
  self.certs += cert_types.map do |ct|
140
152
  certificate_type(ct).flat_map do |cert|
141
- cert.all(mac: false) + cert.all(mac: true)
153
+ Spaceship::ConnectAPI::Certificate.all(filter: { certificateType: cert })
142
154
  end
143
155
  end.flatten
144
156
 
@@ -165,7 +177,7 @@ module Match
165
177
  puts("")
166
178
  if self.certs.count > 0
167
179
  rows = self.certs.collect do |cert|
168
- cert_expiration = cert.expires.nil? ? "Unknown" : cert.expires.strftime("%Y-%m-%d")
180
+ cert_expiration = cert.expiration_date.nil? ? "Unknown" : Time.parse(cert.expiration_date).strftime("%Y-%m-%d")
169
181
  [cert.name, cert.id, cert.class.to_s.split("::").last, cert_expiration]
170
182
  end
171
183
  puts(Terminal::Table.new({
@@ -178,11 +190,11 @@ module Match
178
190
 
179
191
  if self.profiles.count > 0
180
192
  rows = self.profiles.collect do |p|
181
- status = p.status == 'Active' ? p.status.green : p.status.red
193
+ status = p.valid? ? p.profile_state.green : p.profile_state.red
182
194
 
183
195
  # Expires is sometimes nil
184
- expires = p.expires ? p.expires.strftime("%Y-%m-%d") : nil
185
- [p.name, p.id, status, p.type, expires]
196
+ expires = p.expiration_date ? Time.parse(p.expiration_date).strftime("%Y-%m-%d") : nil
197
+ [p.name, p.id, status, p.profile_type, expires]
186
198
  end
187
199
  puts(Terminal::Table.new({
188
200
  title: "Provisioning Profiles that are going to be revoked".green,
@@ -227,7 +239,7 @@ module Match
227
239
  self.certs.each do |cert|
228
240
  UI.message("Revoking certificate '#{cert.name}' (#{cert.id})...")
229
241
  begin
230
- cert.revoke!
242
+ cert.delete!
231
243
  rescue => ex
232
244
  UI.message(ex.to_s)
233
245
  end
@@ -274,31 +286,62 @@ module Match
274
286
  def certificate_type(type)
275
287
  case type.to_sym
276
288
  when :mac_installer_distribution
277
- return [Spaceship.certificate.mac_installer_distribution]
289
+ return [
290
+ Spaceship::ConnectAPI::Certificate::CertificateType::MAC_INSTALLER_DISTRIBUTION
291
+ ]
278
292
  when :distribution
279
- return [Spaceship.certificate.production, Spaceship.certificate.apple_distribution]
293
+ return [
294
+ Spaceship::ConnectAPI::Certificate::CertificateType::MAC_APP_DISTRIBUTION,
295
+ Spaceship::ConnectAPI::Certificate::CertificateType::IOS_DISTRIBUTION,
296
+ Spaceship::ConnectAPI::Certificate::CertificateType::DISTRIBUTION
297
+ ]
280
298
  when :development
281
- return [Spaceship.certificate.development, Spaceship.certificate.apple_development]
299
+ return [
300
+ Spaceship::ConnectAPI::Certificate::CertificateType::MAC_APP_DEVELOPMENT,
301
+ Spaceship::ConnectAPI::Certificate::CertificateType::IOS_DEVELOPMENT,
302
+ Spaceship::ConnectAPI::Certificate::CertificateType::DEVELOPMENT
303
+ ]
282
304
  when :enterprise
283
- return [Spaceship.certificate.in_house]
305
+ return [
306
+ Spaceship::ConnectAPI::Certificate::CertificateType::IOS_DISTRIBUTION
307
+ ]
284
308
  else
285
309
  raise "Unknown type '#{type}'"
286
310
  end
287
311
  end
288
312
 
289
313
  # The kind of provisioning profile we're interested in
290
- def profile_type(prov_type)
314
+ def profile_types(prov_type)
291
315
  case prov_type.to_sym
292
316
  when :appstore
293
- return Spaceship.provisioning_profile.app_store
317
+ return [
318
+ Spaceship::ConnectAPI::Profile::ProfileType::IOS_APP_STORE,
319
+ Spaceship::ConnectAPI::Profile::ProfileType::MAC_APP_STORE,
320
+ Spaceship::ConnectAPI::Profile::ProfileType::TVOS_APP_STORE,
321
+ Spaceship::ConnectAPI::Profile::ProfileType::MAC_CATALYST_APP_STORE
322
+ ]
294
323
  when :development
295
- return Spaceship.provisioning_profile.development
324
+ return [
325
+ Spaceship::ConnectAPI::Profile::ProfileType::IOS_APP_DEVELOPMENT,
326
+ Spaceship::ConnectAPI::Profile::ProfileType::MAC_APP_DEVELOPMENT,
327
+ Spaceship::ConnectAPI::Profile::ProfileType::TVOS_APP_DEVELOPMENT,
328
+ Spaceship::ConnectAPI::Profile::ProfileType::MAC_CATALYST_APP_DEVELOPMENT
329
+ ]
296
330
  when :enterprise
297
- return Spaceship.provisioning_profile.in_house
331
+ return [
332
+ Spaceship::ConnectAPI::Profile::ProfileType::IOS_APP_INHOUSE,
333
+ Spaceship::ConnectAPI::Profile::ProfileType::TVOS_APP_INHOUSE
334
+ ]
298
335
  when :adhoc
299
- return Spaceship.provisioning_profile.ad_hoc
336
+ return [
337
+ Spaceship::ConnectAPI::Profile::ProfileType::IOS_APP_ADHOC,
338
+ Spaceship::ConnectAPI::Profile::ProfileType::TVOS_APP_ADHOC
339
+ ]
300
340
  when :developer_id
301
- return Spaceship.provisioning_profile.direct
341
+ return [
342
+ Spaceship::ConnectAPI::Profile::ProfileType::MAC_APP_DIRECT,
343
+ Spaceship::ConnectAPI::Profile::ProfileType::MAC_CATALYST_APP_DIRECT
344
+ ]
302
345
  else
303
346
  raise "Unknown provisioning type '#{prov_type}'"
304
347
  end
@@ -62,7 +62,6 @@ module Match
62
62
  type: Boolean,
63
63
  default_value: false),
64
64
 
65
- # app
66
65
  FastlaneCore::ConfigItem.new(key: :app_identifier,
67
66
  short_option: "-a",
68
67
  env_name: "MATCH_APP_IDENTIFIER",
@@ -72,10 +71,30 @@ module Match
72
71
  code_gen_sensitive: true,
73
72
  default_value: CredentialsManager::AppfileConfig.try_fetch_value(:app_identifier),
74
73
  default_value_dynamic: true),
74
+
75
+ # App Store Connect API
76
+ FastlaneCore::ConfigItem.new(key: :api_key_path,
77
+ env_name: "SIGH_API_KEY_PATH",
78
+ description: "Path to your App Store Connect API Key JSON file (https://docs.fastlane.tools/app-store-connect-api/#using-fastlane-api-key-json-file)",
79
+ optional: true,
80
+ conflicting_options: [:api_key],
81
+ verify_block: proc do |value|
82
+ UI.user_error!("Couldn't find API key JSON file at path '#{value}'") unless File.exist?(value)
83
+ end),
84
+ FastlaneCore::ConfigItem.new(key: :api_key,
85
+ env_name: "SIGH_API_KEY",
86
+ description: "Your App Store Connect API Key information (https://docs.fastlane.tools/app-store-connect-api/#use-return-value-and-pass-in-as-an-option)",
87
+ type: Hash,
88
+ optional: true,
89
+ sensitive: true,
90
+ conflicting_options: [:api_key_path]),
91
+
92
+ # Apple ID
75
93
  FastlaneCore::ConfigItem.new(key: :username,
76
94
  short_option: "-u",
77
95
  env_name: "MATCH_USERNAME",
78
96
  description: "Your Apple ID Username",
97
+ optional: true,
79
98
  default_value: user,
80
99
  default_value_dynamic: true),
81
100
  FastlaneCore::ConfigItem.new(key: :team_id,
@@ -147,7 +166,7 @@ module Match
147
166
  FastlaneCore::ConfigItem.new(key: :git_bearer_authorization,
148
167
  env_name: "MATCH_GIT_BEARER_AUTHORIZATION",
149
168
  sensitive: true,
150
- description: "Use a bearer authorization header to access the git repo (e.g.: access to an Azure Devops repository), usually a string in Base64",
169
+ description: "Use a bearer authorization header to access the git repo (e.g.: access to an Azure DevOps repository), usually a string in Base64",
151
170
  conflicting_options: [:git_basic_authorization, :git_private_key],
152
171
  optional: true,
153
172
  default_value: nil),
@@ -268,6 +287,12 @@ module Match
268
287
  env_name: "MATCH_OUTPUT_PATH",
269
288
  description: "Path in which to export certificates, key and profile",
270
289
  optional: true),
290
+ FastlaneCore::ConfigItem.new(key: :skip_set_partition_list,
291
+ short_option: "-P",
292
+ env_name: "MATCH_SKIP_SET_PARTITION_LIST",
293
+ description: "Skips setting the partition list (which can sometimes take a long time). Setting the partition list is usually needed to prevent Xcode from prompting to allow a cert to be used for signing",
294
+ type: Boolean,
295
+ default_value: false),
271
296
 
272
297
  # other
273
298
  FastlaneCore::ConfigItem.new(key: :verbose,
@@ -55,7 +55,9 @@ module Match
55
55
  readonly: params[:readonly],
56
56
  username: params[:readonly] ? nil : params[:username], # only pass username if not readonly
57
57
  team_id: params[:team_id],
58
- team_name: params[:team_name]
58
+ team_name: params[:team_name],
59
+ api_key_path: params[:api_key_path],
60
+ api_key: params[:api_key]
59
61
  })
60
62
  storage.download
61
63
 
@@ -67,7 +69,7 @@ module Match
67
69
  encryption.decrypt_files if encryption
68
70
 
69
71
  unless params[:readonly]
70
- self.spaceship = SpaceshipEnsure.new(params[:username], params[:team_id], params[:team_name])
72
+ self.spaceship = SpaceshipEnsure.new(params[:username], params[:team_id], params[:team_name], api_token(params))
71
73
  if params[:type] == "enterprise" && !Spaceship.client.in_house?
72
74
  UI.user_error!("You defined the profile type 'enterprise', but your Apple account doesn't support In-House profiles")
73
75
  end
@@ -100,7 +102,7 @@ module Match
100
102
  end
101
103
 
102
104
  cert_ids << cert_id
103
- spaceship.certificates_exists(username: params[:username], certificate_ids: cert_ids, platform: params[:platform]) if spaceship
105
+ spaceship.certificates_exists(username: params[:username], certificate_ids: cert_ids) if spaceship
104
106
 
105
107
  # Provisioning Profiles
106
108
  unless params[:skip_provisioning_profiles]
@@ -136,6 +138,12 @@ module Match
136
138
  end
137
139
  # rubocop:enable Metrics/PerceivedComplexity
138
140
 
141
+ def api_token(params)
142
+ @api_token ||= Spaceship::ConnectAPI::Token.create(params[:api_key]) if params[:api_key]
143
+ @api_token ||= Spaceship::ConnectAPI::Token.from_json_file(params[:api_key_path]) if params[:api_key_path]
144
+ return @api_token
145
+ end
146
+
139
147
  # Used when creating a new certificate or profile
140
148
  def prefixed_working_directory
141
149
  return self.storage.prefixed_working_directory
@@ -316,23 +324,43 @@ module Match
316
324
 
317
325
  parsed = FastlaneCore::ProvisioningProfile.parse(profile, keychain_path)
318
326
  uuid = parsed["UUID"]
319
- portal_profile = Spaceship.provisioning_profile.all.detect { |i| i.uuid == uuid }
327
+
328
+ all_profiles = Spaceship::ConnectAPI::Profile.all(includes: "devices")
329
+ portal_profile = all_profiles.detect { |i| i.uuid == uuid }
320
330
 
321
331
  if portal_profile
322
- profile_device_count = portal_profile.devices.count
332
+ profile_device_count = portal_profile.fetch_all_devices.count
323
333
 
324
- portal_device_count =
334
+ device_classes =
325
335
  case platform
326
336
  when :ios
327
- Spaceship.device.all_ios_profile_devices.count
337
+ [
338
+ Spaceship::ConnectAPI::Device::DeviceClass::IPAD,
339
+ Spaceship::ConnectAPI::Device::DeviceClass::IPHONE,
340
+ Spaceship::ConnectAPI::Device::DeviceClass::IPOD,
341
+ Spaceship::ConnectAPI::Device::DeviceClass::APPLE_WATCH
342
+ ]
328
343
  when :tvos
329
- Spaceship.device.all_apple_tvs.count
344
+ [
345
+ Spaceship::ConnectAPI::Device::DeviceClass::APPLE_TV
346
+ ]
330
347
  when :mac, :catalyst
331
- Spaceship.device.all_macs.count
348
+ [
349
+ Spaceship::ConnectAPI::Device::DeviceClass::MAC
350
+ ]
332
351
  else
333
- Spaceship.device.all.count
352
+ []
334
353
  end
335
354
 
355
+ devices = Spaceship::ConnectAPI::Device.all
356
+ unless device_classes.empty?
357
+ devices = devices.select do |device|
358
+ device_classes.include?(device.device_class)
359
+ end
360
+ end
361
+
362
+ portal_device_count = devices.size
363
+
336
364
  return portal_device_count != profile_device_count
337
365
  end
338
366
  return false
@@ -4,28 +4,38 @@ require_relative 'module'
4
4
  module Match
5
5
  # Ensures the certificate and profiles are also available on App Store Connect
6
6
  class SpaceshipEnsure
7
- def initialize(user, team_id, team_name)
8
- # We'll try to manually fetch the password
9
- # to tell the user that a password is optional
10
- require 'credentials_manager/account_manager'
7
+ attr_accessor :team_id
11
8
 
12
- keychain_entry = CredentialsManager::AccountManager.new(user: user)
9
+ def initialize(user, team_id, team_name, api_token)
10
+ UI.message("Verifying that the certificate and profile are still valid on the Dev Portal...")
13
11
 
14
- if keychain_entry.password(ask_if_missing: false).to_s.length == 0
15
- UI.important("You can also run `fastlane match` in readonly mode to not require any access to the")
16
- UI.important("Developer Portal. This way you only share the keys and credentials")
17
- UI.command("fastlane match --readonly")
18
- UI.important("More information https://docs.fastlane.tools/actions/match/#access-control")
19
- end
12
+ if api_token
13
+ UI.message("Creating authorization token for App Store Connect API")
14
+ Spaceship::ConnectAPI.token = api_token
15
+ self.team_id = team_id
16
+ else
17
+ # We'll try to manually fetch the password
18
+ # to tell the user that a password is optional
19
+ require 'credentials_manager/account_manager'
20
20
 
21
- # Prompts select team if multiple teams and none specified
22
- UI.message("Verifying that the certificate and profile are still valid on the Dev Portal...")
23
- Spaceship::ConnectAPI.login(user, use_portal: true, use_tunes: false, portal_team_id: team_id, team_name: team_name)
21
+ keychain_entry = CredentialsManager::AccountManager.new(user: user)
22
+
23
+ if keychain_entry.password(ask_if_missing: false).to_s.length == 0
24
+ UI.important("You can also run `fastlane match` in readonly mode to not require any access to the")
25
+ UI.important("Developer Portal. This way you only share the keys and credentials")
26
+ UI.command("fastlane match --readonly")
27
+ UI.important("More information https://docs.fastlane.tools/actions/match/#access-control")
28
+ end
29
+
30
+ # Prompts select team if multiple teams and none specified
31
+ Spaceship::ConnectAPI.login(user, use_portal: true, use_tunes: false, portal_team_id: team_id, team_name: team_name)
32
+ self.team_id = Spaceship::ConnectAPI.client.portal_team_id
33
+ end
24
34
  end
25
35
 
26
36
  # The team ID of the currently logged in team
27
37
  def team_id
28
- return Spaceship::ConnectAPI.client.portal_team_id
38
+ return @team_id
29
39
  end
30
40
 
31
41
  def bundle_identifier_exists(username: nil, app_identifier: nil, platform: nil)
@@ -45,12 +55,8 @@ module Match
45
55
  UI.user_error!("Couldn't find bundle identifier '#{app_identifier}' for the user '#{username}'")
46
56
  end
47
57
 
48
- def certificates_exists(username: nil, certificate_ids: [], platform: nil)
49
- if platform == :catalyst.to_s
50
- platform = :macos.to_s
51
- end
52
-
53
- Spaceship.certificate.all(mac: platform == "macos").each do |cert|
58
+ def certificates_exists(username: nil, certificate_ids: [])
59
+ Spaceship::ConnectAPI::Certificate.all.each do |cert|
54
60
  certificate_ids.delete(cert.id)
55
61
  end
56
62
  return if certificate_ids.empty?
@@ -23,6 +23,8 @@ module Match
23
23
  attr_reader :username
24
24
  attr_reader :team_id
25
25
  attr_reader :team_name
26
+ attr_reader :api_key_path
27
+ attr_reader :api_key
26
28
 
27
29
  # Managed values
28
30
  attr_accessor :gc_storage
@@ -44,7 +46,9 @@ module Match
44
46
  readonly: params[:readonly],
45
47
  username: params[:username],
46
48
  team_id: params[:team_id],
47
- team_name: params[:team_name]
49
+ team_name: params[:team_name],
50
+ api_key_path: params[:api_key_path],
51
+ api_key: params[:api_key]
48
52
  )
49
53
  end
50
54
 
@@ -56,7 +60,9 @@ module Match
56
60
  readonly: nil,
57
61
  username: nil,
58
62
  team_id: nil,
59
- team_name: nil)
63
+ team_name: nil,
64
+ api_key_path: nil,
65
+ api_key: nil)
60
66
  @type = type if type
61
67
  @platform = platform if platform
62
68
  @google_cloud_project_id = google_cloud_project_id if google_cloud_project_id
@@ -67,6 +73,9 @@ module Match
67
73
  @team_id = team_id
68
74
  @team_name = team_name
69
75
 
76
+ @api_key_path = api_key_path
77
+ @api_key = api_key
78
+
70
79
  @google_cloud_keys_file = ensure_keys_file_exists(google_cloud_keys_file, google_cloud_project_id)
71
80
 
72
81
  if self.google_cloud_keys_file.to_s.length > 0
@@ -106,11 +115,19 @@ module Match
106
115
  # see `prefixed_working_directory` comments for more details
107
116
  return self.team_id
108
117
  else
109
- spaceship = SpaceshipEnsure.new(self.username, self.team_id, self.team_name)
118
+ UI.user_error!("The `team_id` option is required. fastlane cannot automatically determine portal team id via the App Store Connect API (yet)") if self.team_id.to_s.empty?
119
+
120
+ spaceship = SpaceshipEnsure.new(self.username, self.team_id, self.team_name, self.api_token)
110
121
  return spaceship.team_id
111
122
  end
112
123
  end
113
124
 
125
+ def api_token
126
+ api_token ||= Spaceship::ConnectAPI::Token.create(self.api_key) if self.api_key
127
+ api_token ||= Spaceship::ConnectAPI::Token.from_json_file(self.api_key_path) if self.api_key_path
128
+ return api_token
129
+ end
130
+
114
131
  def prefixed_working_directory
115
132
  # We fall back to "*", which means certificates and profiles
116
133
  # from all teams that use this bucket would be installed. This is not ideal, but