fastlane 2.160.0 → 2.165.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +78 -78
- data/cert/lib/cert/options.rb +28 -1
- data/cert/lib/cert/runner.rb +51 -34
- data/deliver/lib/deliver/app_screenshot_iterator.rb +4 -4
- data/deliver/lib/deliver/module.rb +2 -0
- data/deliver/lib/deliver/options.rb +5 -5
- data/deliver/lib/deliver/queue_worker.rb +14 -29
- data/deliver/lib/deliver/upload_metadata.rb +20 -5
- data/deliver/lib/deliver/upload_screenshots.rb +28 -13
- data/fastlane/lib/fastlane/actions/.download_dsyms.rb.swp +0 -0
- data/fastlane/lib/fastlane/actions/actions_helper.rb +20 -1
- data/fastlane/lib/fastlane/actions/app_store_build_number.rb +39 -3
- data/fastlane/lib/fastlane/actions/app_store_connect_api_key.rb +15 -1
- data/fastlane/lib/fastlane/actions/check_app_store_metadata.rb +1 -0
- data/fastlane/lib/fastlane/actions/docs/capture_android_screenshots.md +2 -2
- data/fastlane/lib/fastlane/actions/docs/capture_ios_screenshots.md +2 -2
- data/fastlane/lib/fastlane/actions/docs/create_app_online.md +1 -1
- data/fastlane/lib/fastlane/actions/docs/frame_screenshots.md +2 -2
- data/fastlane/lib/fastlane/actions/docs/run_tests.md +2 -2
- data/fastlane/lib/fastlane/actions/docs/sync_code_signing.md +12 -3
- data/fastlane/lib/fastlane/actions/docs/upload_to_play_store.md +2 -2
- data/fastlane/lib/fastlane/actions/docs/upload_to_testflight.md +1 -1
- data/fastlane/lib/fastlane/actions/download_dsyms.rb +1 -0
- data/fastlane/lib/fastlane/actions/ensure_git_status_clean.rb +13 -2
- data/fastlane/lib/fastlane/actions/get_certificates.rb +1 -0
- data/fastlane/lib/fastlane/actions/get_provisioning_profile.rb +1 -0
- data/fastlane/lib/fastlane/actions/import_from_git.rb +9 -1
- data/fastlane/lib/fastlane/actions/is_ci.rb +1 -1
- data/fastlane/lib/fastlane/actions/latest_testflight_build_number.rb +15 -0
- data/fastlane/lib/fastlane/actions/register_device.rb +46 -5
- data/fastlane/lib/fastlane/actions/register_devices.rb +50 -16
- data/fastlane/lib/fastlane/actions/set_changelog.rb +31 -3
- data/fastlane/lib/fastlane/actions/sync_code_signing.rb +1 -0
- data/fastlane/lib/fastlane/actions/upload_to_app_store.rb +3 -2
- data/fastlane/lib/fastlane/fast_file.rb +74 -23
- data/fastlane/lib/fastlane/plugins/template/.rubocop.yml +1 -0
- data/fastlane/lib/fastlane/version.rb +1 -1
- data/fastlane/swift/Deliverfile.swift +1 -1
- data/fastlane/swift/DeliverfileProtocol.swift +4 -4
- data/fastlane/swift/Fastlane.swift +120 -27
- data/fastlane/swift/Gymfile.swift +1 -1
- data/fastlane/swift/GymfileProtocol.swift +1 -1
- data/fastlane/swift/LaneFileProtocol.swift +28 -36
- data/fastlane/swift/MainProcess.swift +1 -1
- data/fastlane/swift/Matchfile.swift +1 -1
- data/fastlane/swift/MatchfileProtocol.swift +21 -5
- data/fastlane/swift/Precheckfile.swift +1 -1
- data/fastlane/swift/PrecheckfileProtocol.swift +1 -1
- data/fastlane/swift/Scanfile.swift +1 -1
- data/fastlane/swift/ScanfileProtocol.swift +1 -1
- data/fastlane/swift/Screengrabfile.swift +1 -1
- data/fastlane/swift/ScreengrabfileProtocol.swift +1 -1
- data/fastlane/swift/Snapshotfile.swift +1 -1
- data/fastlane/swift/SnapshotfileProtocol.swift +1 -1
- data/fastlane/swift/main.swift +1 -1
- data/fastlane_core/lib/fastlane_core/analytics/analytics_session.rb +6 -7
- data/fastlane_core/lib/fastlane_core/device_manager.rb +8 -4
- data/fastlane_core/lib/fastlane_core/helper.rb +1 -1
- data/fastlane_core/lib/fastlane_core/keychain_importer.rb +3 -3
- data/gym/lib/gym/generators/package_command_generator_xcode7.rb +2 -2
- data/match/lib/match/generator.rb +6 -1
- data/match/lib/match/importer.rb +63 -18
- data/match/lib/match/migrate.rb +13 -2
- data/match/lib/match/nuke.rb +65 -22
- data/match/lib/match/options.rb +34 -3
- data/match/lib/match/runner.rb +38 -10
- data/match/lib/match/spaceship_ensure.rb +27 -21
- data/match/lib/match/storage/google_cloud_storage.rb +20 -3
- data/match/lib/match/storage/s3_storage.rb +19 -3
- data/scan/lib/scan/detect_values.rb +5 -8
- data/scan/lib/scan/runner.rb +2 -1
- data/sigh/lib/assets/resign.sh +1 -1
- data/sigh/lib/sigh/download_all.rb +16 -4
- data/sigh/lib/sigh/options.rb +21 -0
- data/sigh/lib/sigh/runner.rb +83 -41
- data/snapshot/lib/assets/SnapshotHelper.swift +4 -0
- data/snapshot/lib/snapshot/simulator_launchers/simulator_launcher_base.rb +2 -1
- data/spaceship/README.md +1 -1
- data/spaceship/lib/spaceship/client.rb +9 -4
- data/spaceship/lib/spaceship/connect_api.rb +27 -0
- data/spaceship/lib/spaceship/connect_api/api_client.rb +12 -3
- data/spaceship/lib/spaceship/connect_api/client.rb +20 -7
- data/spaceship/lib/spaceship/connect_api/models/app.rb +51 -0
- data/spaceship/lib/spaceship/connect_api/models/app_screenshot.rb +3 -1
- data/spaceship/lib/spaceship/connect_api/models/beta_tester.rb +2 -1
- data/spaceship/lib/spaceship/connect_api/models/certificate.rb +42 -0
- data/spaceship/lib/spaceship/connect_api/models/custom_app_organization.rb +43 -0
- data/spaceship/lib/spaceship/connect_api/models/custom_app_user.rb +41 -0
- data/spaceship/lib/spaceship/connect_api/models/device.rb +5 -0
- data/spaceship/lib/spaceship/connect_api/models/profile.rb +7 -1
- data/spaceship/lib/spaceship/connect_api/models/user_invitation.rb +59 -0
- data/spaceship/lib/spaceship/connect_api/provisioning/provisioning.rb +45 -2
- data/spaceship/lib/spaceship/connect_api/spaceship.rb +7 -4
- data/spaceship/lib/spaceship/connect_api/testflight/testflight.rb +13 -0
- data/spaceship/lib/spaceship/connect_api/token.rb +6 -1
- data/spaceship/lib/spaceship/connect_api/tunes/tunes.rb +75 -1
- data/spaceship/lib/spaceship/connect_api/users/users.rb +40 -0
- data/spaceship/lib/spaceship/helper/net_http_generic_request.rb +11 -5
- data/supply/lib/supply/uploader.rb +1 -1
- metadata +19 -15
data/match/lib/match/migrate.rb
CHANGED
@@ -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
|
-
|
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")
|
data/match/lib/match/nuke.rb
CHANGED
@@ -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.
|
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
|
-
|
101
|
-
|
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
|
-
|
129
|
-
|
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
|
-
|
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.
|
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.
|
193
|
+
status = p.valid? ? p.profile_state.green : p.profile_state.red
|
182
194
|
|
183
195
|
# Expires is sometimes nil
|
184
|
-
expires = p.
|
185
|
-
[p.name, p.id, status, p.
|
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.
|
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 [
|
289
|
+
return [
|
290
|
+
Spaceship::ConnectAPI::Certificate::CertificateType::MAC_INSTALLER_DISTRIBUTION
|
291
|
+
]
|
278
292
|
when :distribution
|
279
|
-
return [
|
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 [
|
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 [
|
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
|
314
|
+
def profile_types(prov_type)
|
291
315
|
case prov_type.to_sym
|
292
316
|
when :appstore
|
293
|
-
return
|
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
|
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
|
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
|
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
|
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
|
data/match/lib/match/options.rb
CHANGED
@@ -62,20 +62,39 @@ 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",
|
69
|
-
description: "The bundle identifier(s) of your app (comma-separated)",
|
68
|
+
description: "The bundle identifier(s) of your app (comma-separated string or array of strings)",
|
70
69
|
type: Array, # we actually allow String and Array here
|
71
70
|
skip_type_validation: true,
|
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
|
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),
|
@@ -264,10 +283,22 @@ module Match
|
|
264
283
|
optional: true,
|
265
284
|
type: Boolean,
|
266
285
|
default_value: false),
|
286
|
+
FastlaneCore::ConfigItem.new(key: :skip_certificate_matching,
|
287
|
+
env_name: "MATCH_SKIP_CERTIFICATE_MATCHING",
|
288
|
+
description: "Set to true if there is no access to Apple developer portal but there are certificates, keys and profiles provided. Only works with match import action",
|
289
|
+
optional: true,
|
290
|
+
type: Boolean,
|
291
|
+
default_value: false),
|
267
292
|
FastlaneCore::ConfigItem.new(key: :output_path,
|
268
293
|
env_name: "MATCH_OUTPUT_PATH",
|
269
294
|
description: "Path in which to export certificates, key and profile",
|
270
295
|
optional: true),
|
296
|
+
FastlaneCore::ConfigItem.new(key: :skip_set_partition_list,
|
297
|
+
short_option: "-P",
|
298
|
+
env_name: "MATCH_SKIP_SET_PARTITION_LIST",
|
299
|
+
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",
|
300
|
+
type: Boolean,
|
301
|
+
default_value: false),
|
271
302
|
|
272
303
|
# other
|
273
304
|
FastlaneCore::ConfigItem.new(key: :verbose,
|
data/match/lib/match/runner.rb
CHANGED
@@ -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
|
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
|
-
|
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.
|
332
|
+
profile_device_count = portal_profile.fetch_all_devices.count
|
323
333
|
|
324
|
-
|
334
|
+
device_classes =
|
325
335
|
case platform
|
326
336
|
when :ios
|
327
|
-
|
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
|
-
|
344
|
+
[
|
345
|
+
Spaceship::ConnectAPI::Device::DeviceClass::APPLE_TV
|
346
|
+
]
|
330
347
|
when :mac, :catalyst
|
331
|
-
|
348
|
+
[
|
349
|
+
Spaceship::ConnectAPI::Device::DeviceClass::MAC
|
350
|
+
]
|
332
351
|
else
|
333
|
-
|
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
|
-
|
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
|
-
|
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
|
15
|
-
UI.
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
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
|
-
|
22
|
-
|
23
|
-
|
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
|
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: []
|
49
|
-
|
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
|
-
|
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
|