fastlane 2.157.4 → 2.162.0

Sign up to get free protection for your applications and to get access to all the features.
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