fastlane 2.151.2 → 2.155.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 +82 -82
- data/deliver/lib/deliver/app_screenshot.rb +1 -1
- data/deliver/lib/deliver/commands_generator.rb +7 -4
- data/deliver/lib/deliver/detect_values.rb +9 -3
- data/deliver/lib/deliver/download_screenshots.rb +1 -3
- data/deliver/lib/deliver/html_generator.rb +8 -1
- data/deliver/lib/deliver/options.rb +1 -1
- data/deliver/lib/deliver/runner.rb +5 -10
- data/deliver/lib/deliver/setup.rb +92 -3
- data/deliver/lib/deliver/submit_for_review.rb +4 -6
- data/deliver/lib/deliver/upload_metadata.rb +51 -30
- data/deliver/lib/deliver/upload_price_tier.rb +1 -3
- data/deliver/lib/deliver/upload_screenshots.rb +75 -44
- data/fastlane/lib/fastlane/{helper/.s3_client_helper.rb.swp → .erb_template_helper.rb.swp} +0 -0
- data/{deliver/lib/deliver/.commands_generator.rb.swp → fastlane/lib/fastlane/actions/.git_commit.rb.swp} +0 -0
- data/fastlane/lib/fastlane/actions/carthage.rb +7 -0
- data/fastlane/lib/fastlane/actions/create_keychain.rb +5 -1
- data/fastlane/lib/fastlane/actions/docs/frame_screenshots.md +3 -1
- data/fastlane/lib/fastlane/actions/docs/sync_code_signing.md +21 -2
- data/fastlane/lib/fastlane/actions/docs/upload_to_app_store.md.erb +4 -4
- data/fastlane/lib/fastlane/actions/download_dsyms.rb +4 -2
- data/fastlane/lib/fastlane/actions/erb.rb +10 -2
- data/fastlane/lib/fastlane/actions/git_branch.rb +4 -1
- data/fastlane/lib/fastlane/actions/git_pull.rb +13 -2
- data/fastlane/lib/fastlane/actions/sync_code_signing.rb +5 -0
- data/fastlane/lib/fastlane/actions/upload_to_testflight.rb +11 -3
- data/fastlane/lib/fastlane/runner.rb +3 -1
- data/fastlane/lib/fastlane/version.rb +1 -1
- data/fastlane/swift/Deliverfile.swift +1 -1
- data/fastlane/swift/DeliverfileProtocol.swift +3 -3
- data/fastlane/swift/Fastlane.swift +419 -192
- data/fastlane/swift/Gymfile.swift +1 -1
- data/fastlane/swift/GymfileProtocol.swift +1 -1
- data/fastlane/swift/Matchfile.swift +1 -1
- data/fastlane/swift/MatchfileProtocol.swift +10 -2
- 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 +9 -1
- data/fastlane_core/lib/fastlane_core/device_manager.rb +25 -6
- data/frameit/lib/frameit/editor.rb +11 -6
- data/gym/lib/gym/detect_values.rb +6 -3
- data/gym/lib/gym/module.rb +30 -0
- data/gym/lib/gym/runner.rb +23 -18
- data/match/lib/match/generator.rb +6 -0
- data/match/lib/match/options.rb +16 -4
- data/match/lib/match/runner.rb +13 -5
- data/match/lib/match/spaceship_ensure.rb +7 -9
- data/match/lib/match/storage/git_storage.rb +16 -2
- data/match/lib/match/storage/google_cloud_storage.rb +1 -1
- data/pilot/lib/pilot/build_manager.rb +9 -0
- data/pilot/lib/pilot/options.rb +7 -1
- data/scan/lib/scan/runner.rb +19 -6
- data/sigh/lib/sigh/download_all.rb +42 -27
- data/sigh/lib/sigh/module.rb +26 -0
- data/sigh/lib/sigh/options.rb +2 -2
- data/sigh/lib/sigh/runner.rb +74 -33
- data/snapshot/lib/snapshot/options.rb +10 -0
- data/snapshot/lib/snapshot/simulator_launchers/launcher_configuration.rb +2 -0
- data/snapshot/lib/snapshot/simulator_launchers/simulator_launcher_base.rb +5 -0
- data/snapshot/lib/snapshot/test_command_generator.rb +3 -2
- data/snapshot/lib/snapshot/test_command_generator_xcode_8.rb +4 -1
- data/spaceship/lib/spaceship/connect_api.rb +1 -0
- data/spaceship/lib/spaceship/connect_api/client.rb +5 -3
- data/spaceship/lib/spaceship/connect_api/model.rb +15 -1
- data/spaceship/lib/spaceship/connect_api/models/age_rating_declaration.rb +1 -0
- data/spaceship/lib/spaceship/connect_api/models/app.rb +61 -3
- data/spaceship/lib/spaceship/connect_api/models/app_info_localization.rb +1 -0
- data/spaceship/lib/spaceship/connect_api/models/app_preview.rb +1 -0
- data/spaceship/lib/spaceship/connect_api/models/app_screenshot.rb +44 -5
- data/spaceship/lib/spaceship/connect_api/models/app_store_review_detail.rb +1 -0
- data/spaceship/lib/spaceship/connect_api/models/app_store_version.rb +12 -0
- data/spaceship/lib/spaceship/connect_api/models/app_store_version_localization.rb +1 -0
- data/spaceship/lib/spaceship/connect_api/models/app_store_version_release_request.rb +12 -0
- data/spaceship/lib/spaceship/connect_api/models/build.rb +1 -0
- data/spaceship/lib/spaceship/connect_api/models/bundle_id.rb +17 -5
- data/spaceship/lib/spaceship/connect_api/models/bundle_id_capability.rb +41 -7
- data/spaceship/lib/spaceship/connect_api/models/idfa_declaration.rb +1 -0
- data/spaceship/lib/spaceship/connect_api/models/profile.rb +31 -1
- data/spaceship/lib/spaceship/connect_api/provisioning/client.rb +46 -4
- data/spaceship/lib/spaceship/connect_api/provisioning/provisioning.rb +41 -0
- data/spaceship/lib/spaceship/connect_api/tunes/tunes.rb +32 -1
- data/supply/lib/supply/client.rb +2 -1
- data/supply/lib/supply/options.rb +8 -1
- metadata +34 -61
- data/deliver/lib/deliver/.submit_for_review.rb.swp +0 -0
- data/frameit/lib/frameit/.editor.rb.swp +0 -0
data/match/lib/match/runner.rb
CHANGED
@@ -40,6 +40,7 @@ module Match
|
|
40
40
|
clone_branch_directly: params[:clone_branch_directly],
|
41
41
|
git_basic_authorization: params[:git_basic_authorization],
|
42
42
|
git_bearer_authorization: params[:git_bearer_authorization],
|
43
|
+
git_private_key: params[:git_private_key],
|
43
44
|
type: params[:type].to_s,
|
44
45
|
generate_apple_certs: params[:generate_apple_certs],
|
45
46
|
platform: params[:platform].to_s,
|
@@ -206,20 +207,26 @@ module Match
|
|
206
207
|
return File.basename(cert_path).gsub(".cer", "") # Certificate ID
|
207
208
|
end
|
208
209
|
|
210
|
+
# rubocop:disable Metrics/PerceivedComplexity
|
209
211
|
# @return [String] The UUID of the provisioning profile so we can verify it with the Apple Developer Portal
|
210
212
|
def fetch_provisioning_profile(params: nil, certificate_id: nil, app_identifier: nil, working_directory: nil)
|
211
213
|
prov_type = Match.profile_type_sym(params[:type])
|
212
214
|
|
213
215
|
names = [Match::Generator.profile_type_name(prov_type), app_identifier]
|
214
|
-
if params[:platform].to_s == :tvos.to_s
|
216
|
+
if params[:platform].to_s == :tvos.to_s || params[:platform].to_s == :catalyst.to_s
|
215
217
|
names.push(params[:platform])
|
216
218
|
end
|
217
219
|
|
218
220
|
profile_name = names.join("_").gsub("*", '\*') # this is important, as it shouldn't be a wildcard
|
219
221
|
base_dir = File.join(prefixed_working_directory, "profiles", prov_type.to_s)
|
220
222
|
|
221
|
-
extension =
|
222
|
-
|
223
|
+
extension = ".mobileprovision"
|
224
|
+
if [:macos.to_s, :catalyst.to_s].include?(params[:platform].to_s)
|
225
|
+
extension = ".provisionprofile"
|
226
|
+
end
|
227
|
+
|
228
|
+
profile_file = "#{profile_name}#{extension}"
|
229
|
+
profiles = Dir[File.join(base_dir, profile_file)]
|
223
230
|
if Helper.mac?
|
224
231
|
keychain_path = FastlaneCore::Helper.keychain_path(params[:keychain_name]) unless params[:keychain_name].nil?
|
225
232
|
end
|
@@ -241,7 +248,7 @@ module Match
|
|
241
248
|
|
242
249
|
if profile.nil? || force
|
243
250
|
if params[:readonly]
|
244
|
-
UI.error("No matching provisioning profiles found for '#{
|
251
|
+
UI.error("No matching provisioning profiles found for '#{profile_file}'")
|
245
252
|
UI.error("A new one cannot be created because you enabled `readonly`")
|
246
253
|
if Dir.exist?(base_dir) # folder for `prov_type` does not exist on first match use for that type
|
247
254
|
all_profiles = Dir.entries(base_dir).reject { |f| f.start_with?(".") }
|
@@ -302,6 +309,7 @@ module Match
|
|
302
309
|
|
303
310
|
return uuid
|
304
311
|
end
|
312
|
+
# rubocop:enable Metrics/PerceivedComplexity
|
305
313
|
|
306
314
|
def device_count_different?(profile: nil, keychain_path: nil, platform: nil)
|
307
315
|
return false unless profile
|
@@ -319,7 +327,7 @@ module Match
|
|
319
327
|
Spaceship.device.all_ios_profile_devices.count
|
320
328
|
when :tvos
|
321
329
|
Spaceship.device.all_apple_tvs.count
|
322
|
-
when :mac
|
330
|
+
when :mac, :catalyst
|
323
331
|
Spaceship.device.all_macs.count
|
324
332
|
else
|
325
333
|
Spaceship.device.all.count
|
@@ -46,6 +46,10 @@ module Match
|
|
46
46
|
end
|
47
47
|
|
48
48
|
def certificates_exists(username: nil, certificate_ids: [], platform: nil)
|
49
|
+
if platform == :catalyst.to_s
|
50
|
+
platform = :macos.to_s
|
51
|
+
end
|
52
|
+
|
49
53
|
Spaceship.certificate.all(mac: platform == "macos").each do |cert|
|
50
54
|
certificate_ids.delete(cert.id)
|
51
55
|
end
|
@@ -61,18 +65,12 @@ module Match
|
|
61
65
|
end
|
62
66
|
|
63
67
|
def profile_exists(username: nil, uuid: nil, platform: nil)
|
64
|
-
|
65
|
-
|
68
|
+
# App Store Connect API does not allow filter of profile by platform or uuid (as of 2020-07-30)
|
69
|
+
# Need to fetch all profiles and search for uuid on client side
|
70
|
+
found = Spaceship::ConnectAPI::Profile.all.find do |profile|
|
66
71
|
profile.uuid == uuid
|
67
72
|
end
|
68
73
|
|
69
|
-
# Look for iOS after looking for macOS (needed for Catalyst apps)
|
70
|
-
if !found && is_mac
|
71
|
-
found = Spaceship.provisioning_profile.all(mac: false).find do |profile|
|
72
|
-
profile.uuid == uuid
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
74
|
unless found
|
77
75
|
UI.error("Provisioning profile '#{uuid}' is not available on the Developer Portal for the user #{username}, fixing this now for you 🔨")
|
78
76
|
return false
|
@@ -19,6 +19,7 @@ module Match
|
|
19
19
|
attr_accessor :platform
|
20
20
|
attr_accessor :git_basic_authorization
|
21
21
|
attr_accessor :git_bearer_authorization
|
22
|
+
attr_accessor :git_private_key
|
22
23
|
|
23
24
|
def self.configure(params)
|
24
25
|
return self.new(
|
@@ -32,7 +33,8 @@ module Match
|
|
32
33
|
git_user_email: params[:git_user_email],
|
33
34
|
clone_branch_directly: params[:clone_branch_directly],
|
34
35
|
git_basic_authorization: params[:git_basic_authorization],
|
35
|
-
git_bearer_authorization: params[:git_bearer_authorization]
|
36
|
+
git_bearer_authorization: params[:git_bearer_authorization],
|
37
|
+
git_private_key: params[:git_private_key]
|
36
38
|
)
|
37
39
|
end
|
38
40
|
|
@@ -46,7 +48,8 @@ module Match
|
|
46
48
|
git_user_email: nil,
|
47
49
|
clone_branch_directly: false,
|
48
50
|
git_basic_authorization: nil,
|
49
|
-
git_bearer_authorization: nil
|
51
|
+
git_bearer_authorization: nil,
|
52
|
+
git_private_key: nil)
|
50
53
|
self.git_url = git_url
|
51
54
|
self.shallow_clone = shallow_clone
|
52
55
|
self.skip_docs = skip_docs
|
@@ -56,6 +59,7 @@ module Match
|
|
56
59
|
self.clone_branch_directly = clone_branch_directly
|
57
60
|
self.git_basic_authorization = git_basic_authorization
|
58
61
|
self.git_bearer_authorization = git_bearer_authorization
|
62
|
+
self.git_private_key = git_private_key
|
59
63
|
|
60
64
|
self.type = type if type
|
61
65
|
self.platform = platform if platform
|
@@ -85,6 +89,16 @@ module Match
|
|
85
89
|
command += " -b #{self.branch.shellescape} --single-branch"
|
86
90
|
end
|
87
91
|
|
92
|
+
unless self.git_private_key.nil?
|
93
|
+
if File.file?(self.git_private_key)
|
94
|
+
ssh_add = File.expand_path(self.git_private_key).shellescape.to_s
|
95
|
+
else
|
96
|
+
UI.message("Private key file does not exist, will continue by using it as a raw key.")
|
97
|
+
ssh_add = "- <<< \"#{self.git_private_key}\""
|
98
|
+
end
|
99
|
+
command = "ssh-agent bash -c 'ssh-add #{ssh_add}; #{command}'"
|
100
|
+
end
|
101
|
+
|
88
102
|
UI.message("Cloning remote git repo...")
|
89
103
|
if self.branch && !self.clone_branch_directly
|
90
104
|
UI.message("If cloning the repo takes too long, you can use the `clone_branch_directly` option in match.")
|
@@ -213,7 +213,7 @@ module Match
|
|
213
213
|
|
214
214
|
return DEFAULT_KEYS_FILE_NAME if File.exist?(DEFAULT_KEYS_FILE_NAME)
|
215
215
|
|
216
|
-
fastlane_folder_gc_keys_path = File.join(FastlaneCore::FastlaneFolder.path, DEFAULT_KEYS_FILE_NAME)
|
216
|
+
fastlane_folder_gc_keys_path = File.join(FastlaneCore::FastlaneFolder.path || Dir.pwd, DEFAULT_KEYS_FILE_NAME)
|
217
217
|
return fastlane_folder_gc_keys_path if File.exist?(fastlane_folder_gc_keys_path)
|
218
218
|
|
219
219
|
if google_cloud_project_id.to_s.length > 0
|
@@ -281,8 +281,17 @@ module Pilot
|
|
281
281
|
changelog
|
282
282
|
end
|
283
283
|
|
284
|
+
def self.strip_less_than_sign(changelog)
|
285
|
+
if changelog && changelog.include?("<")
|
286
|
+
changelog.delete!("<")
|
287
|
+
UI.important("Less than signs (<) have been removed from the changelog, since they're not allowed by Apple.")
|
288
|
+
end
|
289
|
+
changelog
|
290
|
+
end
|
291
|
+
|
284
292
|
def self.sanitize_changelog(changelog)
|
285
293
|
changelog = strip_emoji(changelog)
|
294
|
+
changelog = strip_less_than_sign(changelog)
|
286
295
|
truncate_changelog(changelog)
|
287
296
|
end
|
288
297
|
|
data/pilot/lib/pilot/options.rb
CHANGED
@@ -122,7 +122,7 @@ module Pilot
|
|
122
122
|
short_option: "-w",
|
123
123
|
optional: true,
|
124
124
|
env_name: "PILOT_CHANGELOG",
|
125
|
-
description: "Provide the 'What to Test' text when uploading a new build
|
125
|
+
description: "Provide the 'What to Test' text when uploading a new build"),
|
126
126
|
FastlaneCore::ConfigItem.new(key: :skip_submission,
|
127
127
|
short_option: "-s",
|
128
128
|
env_name: "PILOT_SKIP_SUBMISSION",
|
@@ -146,6 +146,12 @@ module Pilot
|
|
146
146
|
default_value: false),
|
147
147
|
|
148
148
|
# distribution
|
149
|
+
FastlaneCore::ConfigItem.new(key: :distribute_only,
|
150
|
+
short_option: "-D",
|
151
|
+
env_name: "PILOT_DISTRIBUTE_ONLY",
|
152
|
+
description: "Distribute a previously uploaded build (equivalent to the `fastlane pilot distribute` command)",
|
153
|
+
default_value: false,
|
154
|
+
type: Boolean),
|
149
155
|
FastlaneCore::ConfigItem.new(key: :uses_non_exempt_encryption,
|
150
156
|
short_option: "-X",
|
151
157
|
env_name: "PILOT_USES_NON_EXEMPT_ENCRYPTION",
|
data/scan/lib/scan/runner.rb
CHANGED
@@ -39,12 +39,7 @@ module Scan
|
|
39
39
|
end
|
40
40
|
end
|
41
41
|
|
42
|
-
|
43
|
-
# And a correct one is freshly launched. Switching between multiple simulator
|
44
|
-
# in case the user specified multiple targets works with no issues
|
45
|
-
# This way it's okay to just call it for the first simulator we're using for
|
46
|
-
# the first test run
|
47
|
-
FastlaneCore::Simulator.launch(Scan.devices.first) if Scan.devices && Scan.config[:prelaunch_simulator]
|
42
|
+
prelaunch_simulators
|
48
43
|
|
49
44
|
if Scan.config[:reinstall_app]
|
50
45
|
app_identifier = Scan.config[:app_identifier]
|
@@ -165,6 +160,24 @@ module Scan
|
|
165
160
|
File.read(Scan.cache[:temp_junit_report])
|
166
161
|
end
|
167
162
|
|
163
|
+
def prelaunch_simulators
|
164
|
+
return unless Scan.devices.to_a.size > 0 # no devices selected, no sims to launch
|
165
|
+
|
166
|
+
# Return early unless the user wants to prelaunch simulators. Or if the user wants simulator logs
|
167
|
+
# then we must prelaunch simulators because Xcode's headless
|
168
|
+
# mode launches and shutsdown the simulators before we can collect the logs.
|
169
|
+
return unless Scan.config[:prelaunch_simulator] || Scan.config[:include_simulator_logs]
|
170
|
+
|
171
|
+
devices_to_shutdown = []
|
172
|
+
Scan.devices.each do |device|
|
173
|
+
devices_to_shutdown << device if device.state == "Shutdown"
|
174
|
+
device.boot
|
175
|
+
end
|
176
|
+
at_exit do
|
177
|
+
devices_to_shutdown.each(&:shutdown)
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
168
181
|
def copy_simulator_logs
|
169
182
|
return unless Scan.config[:include_simulator_logs]
|
170
183
|
|
@@ -1,5 +1,7 @@
|
|
1
1
|
require 'spaceship'
|
2
2
|
|
3
|
+
require 'base64'
|
4
|
+
|
3
5
|
require_relative 'manager'
|
4
6
|
require_relative 'module'
|
5
7
|
|
@@ -12,35 +14,43 @@ module Sigh
|
|
12
14
|
Spaceship.select_team
|
13
15
|
UI.message("Successfully logged in")
|
14
16
|
|
17
|
+
if download_xcode_profiles
|
18
|
+
UI.deprecated("The App Store Connect API does not support querying for Xcode managed profiles: --download_code_profiles is deprecated")
|
19
|
+
end
|
20
|
+
|
15
21
|
case Sigh.config[:platform].to_s
|
16
22
|
when 'ios'
|
17
|
-
|
18
|
-
|
23
|
+
profile_types = [
|
24
|
+
Spaceship::ConnectAPI::Profile::ProfileType::IOS_APP_STORE,
|
25
|
+
Spaceship::ConnectAPI::Profile::ProfileType::IOS_APP_INHOUSE,
|
26
|
+
Spaceship::ConnectAPI::Profile::ProfileType::IOS_APP_ADHOC,
|
27
|
+
Spaceship::ConnectAPI::Profile::ProfileType::IOS_APP_DEVELOPMENT
|
28
|
+
]
|
19
29
|
when 'macos'
|
20
|
-
|
21
|
-
|
30
|
+
profile_types = [
|
31
|
+
Spaceship::ConnectAPI::Profile::ProfileType::MAC_APP_STORE,
|
32
|
+
Spaceship::ConnectAPI::Profile::ProfileType::MAC_APP_DEVELOPMENT,
|
33
|
+
Spaceship::ConnectAPI::Profile::ProfileType::MAC_APP_DIRECT
|
34
|
+
]
|
35
|
+
when 'catalyst'
|
36
|
+
profile_types = [
|
37
|
+
Spaceship::ConnectAPI::Profile::ProfileType::MAC_CATALYST_APP_STORE,
|
38
|
+
Spaceship::ConnectAPI::Profile::ProfileType::MAC_CATALYST_APP_DEVELOPMENT,
|
39
|
+
Spaceship::ConnectAPI::Profile::ProfileType::MAC_CATALYST_APP_DIRECT
|
40
|
+
]
|
22
41
|
when 'tvos'
|
23
|
-
|
24
|
-
|
42
|
+
profile_types = [
|
43
|
+
Spaceship::ConnectAPI::Profile::ProfileType::TVOS_APP_STORE,
|
44
|
+
Spaceship::ConnectAPI::Profile::ProfileType::TVOS_APP_INHOUSE,
|
45
|
+
Spaceship::ConnectAPI::Profile::ProfileType::TVOS_APP_ADHOC,
|
46
|
+
Spaceship::ConnectAPI::Profile::ProfileType::TVOS_APP_DEVELOPMENT
|
47
|
+
]
|
25
48
|
end
|
26
|
-
end
|
27
|
-
|
28
|
-
# @param xcode [Bool] Whether or not the user passed the download_xcode_profiles flag
|
29
|
-
# @param supported [Bool] Whether or not this platform supports downloading xcode profiles at all
|
30
|
-
def xcode_profiles_downloaded?(xcode: false, supported: false)
|
31
|
-
if supported
|
32
|
-
if xcode
|
33
|
-
UI.message("This run also included all Xcode managed provisioning profiles, as you used the `--download_xcode_profiles` flag")
|
34
|
-
elsif !xcode
|
35
|
-
UI.message("All Xcode managed provisioning profiles were ignored on this, to include them use the `--download_xcode_profiles` flag")
|
36
|
-
end
|
37
49
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
end
|
43
|
-
end
|
50
|
+
# Filtering on 'profileType' seems to be undocumented as of 2020-07-30
|
51
|
+
# but works on both web session and official API
|
52
|
+
profiles = Spaceship::ConnectAPI::Profile.all(filter: { profileType: profile_types.join(",") }, includes: "bundleId")
|
53
|
+
download_profiles(profiles)
|
44
54
|
end
|
45
55
|
|
46
56
|
# @param profiles [Array] Array of all the provisioning profiles we want to download
|
@@ -57,18 +67,22 @@ module Sigh
|
|
57
67
|
end
|
58
68
|
end
|
59
69
|
|
70
|
+
def pretty_type(profile_type)
|
71
|
+
return Sigh.profile_pretty_type(profile_type)
|
72
|
+
end
|
73
|
+
|
60
74
|
# @param profile [ProvisioningProfile] A profile we plan to download and store
|
61
75
|
def download_profile(profile)
|
62
76
|
FileUtils.mkdir_p(Sigh.config[:output_path])
|
63
77
|
|
64
|
-
type_name = profile.
|
65
|
-
profile_name = "#{type_name}_#{profile.uuid}_#{profile.
|
78
|
+
type_name = pretty_type(profile.profile_type)
|
79
|
+
profile_name = "#{type_name}_#{profile.uuid}_#{profile.bundle_id.identifier}"
|
66
80
|
|
67
81
|
if Sigh.config[:platform].to_s == 'tvos'
|
68
82
|
profile_name += "_tvos"
|
69
83
|
end
|
70
84
|
|
71
|
-
if Sigh.config[:platform].to_s
|
85
|
+
if ['macos', 'catalyst'].include?(Sigh.config[:platform].to_s)
|
72
86
|
profile_name += '.provisionprofile'
|
73
87
|
else
|
74
88
|
profile_name += '.mobileprovision'
|
@@ -76,7 +90,8 @@ module Sigh
|
|
76
90
|
|
77
91
|
output_path = File.join(Sigh.config[:output_path], profile_name)
|
78
92
|
File.open(output_path, "wb") do |f|
|
79
|
-
|
93
|
+
content = Base64.decode64(profile.profile_content)
|
94
|
+
f.write(content)
|
80
95
|
end
|
81
96
|
|
82
97
|
Manager.install_profile(output_path) unless Sigh.config[:skip_install]
|
data/sigh/lib/sigh/module.rb
CHANGED
@@ -5,6 +5,32 @@ module Sigh
|
|
5
5
|
# Use this to just setup the configuration attribute and set it later somewhere else
|
6
6
|
class << self
|
7
7
|
attr_accessor :config
|
8
|
+
|
9
|
+
def profile_pretty_type(profile_type)
|
10
|
+
require 'spaceship'
|
11
|
+
|
12
|
+
case profile_type
|
13
|
+
when Spaceship::ConnectAPI::Profile::ProfileType::IOS_APP_DEVELOPMENT,
|
14
|
+
Spaceship::ConnectAPI::Profile::ProfileType::MAC_APP_DEVELOPMENT,
|
15
|
+
Spaceship::ConnectAPI::Profile::ProfileType::TVOS_APP_DEVELOPMENT,
|
16
|
+
Spaceship::ConnectAPI::Profile::ProfileType::MAC_CATALYST_APP_DEVELOPMENT
|
17
|
+
"Development"
|
18
|
+
when Spaceship::ConnectAPI::Profile::ProfileType::IOS_APP_STORE,
|
19
|
+
Spaceship::ConnectAPI::Profile::ProfileType::MAC_APP_STORE,
|
20
|
+
Spaceship::ConnectAPI::Profile::ProfileType::TVOS_APP_STORE,
|
21
|
+
Spaceship::ConnectAPI::Profile::ProfileType::MAC_CATALYST_APP_STORE
|
22
|
+
"AppStore"
|
23
|
+
when Spaceship::ConnectAPI::Profile::ProfileType::IOS_APP_ADHOC,
|
24
|
+
Spaceship::ConnectAPI::Profile::ProfileType::TVOS_APP_ADHOC
|
25
|
+
"AdHoc"
|
26
|
+
when Spaceship::ConnectAPI::Profile::ProfileType::IOS_APP_INHOUSE,
|
27
|
+
Spaceship::ConnectAPI::Profile::ProfileType::TVOS_APP_INHOUSE
|
28
|
+
"InHouse"
|
29
|
+
when Spaceship::ConnectAPI::Profile::ProfileType::MAC_APP_DIRECT,
|
30
|
+
Spaceship::ConnectAPI::Profile::ProfileType::MAC_CATALYST_APP_DIRECT
|
31
|
+
"Direct"
|
32
|
+
end
|
33
|
+
end
|
8
34
|
end
|
9
35
|
|
10
36
|
Helper = FastlaneCore::Helper # you gotta love Ruby: Helper.* should use the Helper class contained in FastlaneCore
|
data/sigh/lib/sigh/options.rb
CHANGED
@@ -131,12 +131,12 @@ module Sigh
|
|
131
131
|
FastlaneCore::ConfigItem.new(key: :platform,
|
132
132
|
short_option: '-p',
|
133
133
|
env_name: "SIGH_PLATFORM",
|
134
|
-
description: "Set the provisioning profile's platform (i.e. ios, tvos)",
|
134
|
+
description: "Set the provisioning profile's platform (i.e. ios, tvos, macos, catalyst)",
|
135
135
|
is_string: false,
|
136
136
|
default_value: "ios",
|
137
137
|
verify_block: proc do |value|
|
138
138
|
value = value.to_s
|
139
|
-
pt = %w(macos tvos ios)
|
139
|
+
pt = %w(macos tvos ios catalyst)
|
140
140
|
UI.user_error!("Unsupported platform, must be: #{pt}") unless pt.include?(value)
|
141
141
|
end),
|
142
142
|
FastlaneCore::ConfigItem.new(key: :readonly,
|
data/sigh/lib/sigh/runner.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
require 'spaceship'
|
2
2
|
|
3
|
+
require 'base64'
|
4
|
+
|
3
5
|
require 'fastlane_core/print_table'
|
4
6
|
require 'fastlane_core/cert_checker'
|
5
7
|
require_relative 'module'
|
@@ -42,7 +44,7 @@ module Sigh
|
|
42
44
|
|
43
45
|
UI.user_error!("Something went wrong fetching the latest profile") unless profile
|
44
46
|
|
45
|
-
if
|
47
|
+
if [Spaceship::ConnectAPI::Profile::ProfileType::IOS_APP_INHOUSE, Spaceship::ConnectAPI::Profile::ProfileType::TVOS_APP_INHOUSE].include?(profile_type)
|
46
48
|
ENV["SIGH_PROFILE_ENTERPRISE"] = "1"
|
47
49
|
else
|
48
50
|
ENV.delete("SIGH_PROFILE_ENTERPRISE")
|
@@ -55,11 +57,26 @@ module Sigh
|
|
55
57
|
def profile_type
|
56
58
|
return @profile_type if @profile_type
|
57
59
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
60
|
+
case Sigh.config[:platform]
|
61
|
+
when "ios"
|
62
|
+
@profile_type = Spaceship::ConnectAPI::Profile::ProfileType::IOS_APP_STORE
|
63
|
+
@profile_type = Spaceship::ConnectAPI::Profile::ProfileType::IOS_APP_INHOUSE if Spaceship.client.in_house?
|
64
|
+
@profile_type = Spaceship::ConnectAPI::Profile::ProfileType::IOS_APP_ADHOC if Sigh.config[:adhoc]
|
65
|
+
@profile_type = Spaceship::ConnectAPI::Profile::ProfileType::IOS_APP_DEVELOPMENT if Sigh.config[:development]
|
66
|
+
when "tvos"
|
67
|
+
@profile_type = Spaceship::ConnectAPI::Profile::ProfileType::TVOS_APP_STORE
|
68
|
+
@profile_type = Spaceship::ConnectAPI::Profile::ProfileType::TVOS_APP_INHOUSE if Spaceship.client.in_house?
|
69
|
+
@profile_type = Spaceship::ConnectAPI::Profile::ProfileType::TVOS_APP_ADHOC if Sigh.config[:adhoc]
|
70
|
+
@profile_type = Spaceship::ConnectAPI::Profile::ProfileType::TVOS_APP_DEVELOPMENT if Sigh.config[:development]
|
71
|
+
when "macos"
|
72
|
+
@profile_type = Spaceship::ConnectAPI::Profile::ProfileType::MAC_APP_STORE
|
73
|
+
@profile_type = Spaceship::ConnectAPI::Profile::ProfileType::MAC_APP_DEVELOPMENT if Sigh.config[:development]
|
74
|
+
@profile_type = Spaceship::ConnectAPI::Profile::ProfileType::MAC_APP_DIRECT if Sigh.config[:developer_id]
|
75
|
+
when "catalyst"
|
76
|
+
@profile_type = Spaceship::ConnectAPI::Profile::ProfileType::MAC_CATALYST_APP_STORE
|
77
|
+
@profile_type = Spaceship::ConnectAPI::Profile::ProfileType::MAC_CATALYST_APP_DEVELOPMENT if Sigh.config[:development]
|
78
|
+
@profile_type = Spaceship::ConnectAPI::Profile::ProfileType::MAC_CATALYST_APP_DIRECT if Sigh.config[:developer_id]
|
79
|
+
end
|
63
80
|
|
64
81
|
@profile_type
|
65
82
|
end
|
@@ -67,9 +84,13 @@ module Sigh
|
|
67
84
|
# Fetches a profile matching the user's search requirements
|
68
85
|
def fetch_profiles
|
69
86
|
UI.message("Fetching profiles...")
|
70
|
-
|
71
|
-
|
72
|
-
|
87
|
+
|
88
|
+
# Filtering on 'profileType' seems to be undocumented as of 2020-07-30
|
89
|
+
# but works on both web session and official API
|
90
|
+
results = Spaceship::ConnectAPI::Profile.all(filter: { profileType: profile_type }, includes: "bundleId,certificates").select do |profile|
|
91
|
+
profile.bundle_id.identifier == Sigh.config[:app_identifier]
|
92
|
+
end
|
93
|
+
|
73
94
|
results = results.find_all do |current_profile|
|
74
95
|
if current_profile.valid? || Sigh.config[:force]
|
75
96
|
true
|
@@ -93,7 +114,7 @@ module Sigh
|
|
93
114
|
# "member" and not an a "admin"
|
94
115
|
raw_certs = current_profile.certificates.map do |cert|
|
95
116
|
begin
|
96
|
-
raw_cert = cert.
|
117
|
+
raw_cert = Base64.decode64(cert.certificate_content)
|
97
118
|
rescue => error
|
98
119
|
UI.important("Cannot download cert #{cert.id} - #{error.message}")
|
99
120
|
raw_cert = nil
|
@@ -114,31 +135,45 @@ module Sigh
|
|
114
135
|
UI.message("Certificate for Provisioning Profile '#{current_profile.name}' not available locally: #{current_cert[:cert].id}, skipping this one...")
|
115
136
|
end
|
116
137
|
end
|
117
|
-
|
138
|
+
|
139
|
+
# Don't need to check if certificate is valid because it comes with the
|
140
|
+
# profile in the response
|
141
|
+
installed
|
118
142
|
end
|
119
143
|
end
|
120
144
|
|
145
|
+
def profile_type_pretty_type
|
146
|
+
return Sigh.profile_pretty_type(profile_type)
|
147
|
+
end
|
148
|
+
|
121
149
|
# Create a new profile and return it
|
122
150
|
def create_profile!
|
123
|
-
|
124
|
-
|
125
|
-
name = Sigh.config[:provisioning_name] || [bundle_id, profile_type.pretty_type].join(' ')
|
151
|
+
app_identifier = Sigh.config[:app_identifier]
|
152
|
+
name = Sigh.config[:provisioning_name] || [app_identifier, profile_type_pretty_type].join(' ')
|
126
153
|
|
127
154
|
unless Sigh.config[:skip_fetch_profiles]
|
128
|
-
|
155
|
+
profile = Spaceship::ConnectAPI::Profile.all.find { |p| p.name == name }
|
156
|
+
if profile
|
129
157
|
UI.user_error!("The name '#{name}' is already taken, and fail_on_name_taken is true") if Sigh.config[:fail_on_name_taken]
|
130
158
|
UI.error("The name '#{name}' is already taken, using another one.")
|
131
159
|
name += " #{Time.now.to_i}"
|
132
160
|
end
|
133
161
|
end
|
134
162
|
|
163
|
+
bundle_id = Spaceship::ConnectAPI::BundleId.find(app_identifier)
|
164
|
+
unless bundle_id
|
165
|
+
UI.user_error!("Could not find App with App Identifier '#{Sigh.config[:app_identifier]}'")
|
166
|
+
end
|
167
|
+
|
135
168
|
UI.important("Creating new provisioning profile for '#{Sigh.config[:app_identifier]}' with name '#{name}' for '#{Sigh.config[:platform]}' platform")
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
169
|
+
|
170
|
+
profile = Spaceship::ConnectAPI::Profile.create(
|
171
|
+
name: name,
|
172
|
+
profile_type: profile_type,
|
173
|
+
bundle_id_id: bundle_id.id,
|
174
|
+
certificate_ids: [certificate_to_use.id]
|
175
|
+
)
|
176
|
+
|
142
177
|
profile
|
143
178
|
end
|
144
179
|
|
@@ -155,16 +190,16 @@ module Sigh
|
|
155
190
|
def certificates_for_profile_and_platform
|
156
191
|
case Sigh.config[:platform].to_s
|
157
192
|
when 'ios', 'tvos'
|
158
|
-
if profile_type == Spaceship
|
193
|
+
if profile_type == Spaceship::ConnectAPI::Profile::ProfileType::IOS_APP_DEVELOPMENT || profile_type == Spaceship::ConnectAPI::Profile::ProfileType::TVOS_APP_DEVELOPMENT
|
159
194
|
certificates = Spaceship.certificate.development.all +
|
160
195
|
Spaceship.certificate.apple_development.all
|
161
|
-
elsif profile_type == Spaceship
|
196
|
+
elsif profile_type == Spaceship::ConnectAPI::Profile::ProfileType::IOS_APP_INHOUSE || profile_type == Spaceship::ConnectAPI::Profile::ProfileType::TVOS_APP_INHOUSE
|
162
197
|
# Enterprise accounts don't have access to Apple Distribution certificates
|
163
198
|
certificates = Spaceship.certificate.in_house.all
|
164
199
|
# handles case where the desired certificate type is adhoc but the account is an enterprise account
|
165
200
|
# the apple dev portal api has a weird quirk in it where if you query for distribution certificates
|
166
201
|
# for enterprise accounts, you get nothing back even if they exist.
|
167
|
-
elsif profile_type == Spaceship
|
202
|
+
elsif (profile_type == Spaceship::ConnectAPI::Profile::ProfileType::IOS_APP_ADHOC || profile_type == Spaceship::ConnectAPI::Profile::ProfileType::TVOS_APP_ADHOC) && Spaceship.client && Spaceship.client.in_house?
|
168
203
|
# Enterprise accounts don't have access to Apple Distribution certificates
|
169
204
|
certificates = Spaceship.certificate.in_house.all
|
170
205
|
else
|
@@ -173,14 +208,14 @@ module Sigh
|
|
173
208
|
Spaceship.certificate.apple_distribution.all
|
174
209
|
end
|
175
210
|
|
176
|
-
when 'macos'
|
177
|
-
if profile_type == Spaceship
|
211
|
+
when 'macos', 'catalyst'
|
212
|
+
if profile_type == Spaceship::ConnectAPI::Profile::ProfileType::MAC_APP_DEVELOPMENT || profile_type == Spaceship::ConnectAPI::Profile::ProfileType::MAC_CATALYST_APP_DEVELOPMENT
|
178
213
|
certificates = Spaceship.certificate.mac_development.all +
|
179
214
|
Spaceship.certificate.apple_development.all
|
180
|
-
elsif profile_type == Spaceship
|
215
|
+
elsif profile_type == Spaceship::ConnectAPI::Profile::ProfileType::MAC_APP_STORE || profile_type == Spaceship::ConnectAPI::Profile::ProfileType::MAC_CATALYST_APP_STORE
|
181
216
|
certificates = Spaceship.certificate.mac_app_distribution.all +
|
182
217
|
Spaceship.certificate.apple_distribution.all
|
183
|
-
elsif profile_type == Spaceship
|
218
|
+
elsif profile_type == Spaceship::ConnectAPI::Profile::ProfileType::MAC_APP_DIRECT || profile_type == Spaceship::ConnectAPI::Profile::ProfileType::MAC_CATALYST_APP_DIRECT
|
184
219
|
certificates = Spaceship.certificate.developer_id_application.all
|
185
220
|
else
|
186
221
|
certificates = Spaceship.certificate.mac_app_distribution.all +
|
@@ -235,7 +270,7 @@ module Sigh
|
|
235
270
|
filters << "Owner Name: '#{Sigh.config[:cert_owner_name]}' " if Sigh.config[:cert_owner_name]
|
236
271
|
filters << "Certificate ID: '#{Sigh.config[:cert_id]}' " if Sigh.config[:cert_id]
|
237
272
|
UI.important("No certificates for filter: #{filters}") if filters.length > 0
|
238
|
-
message = "Could not find a matching code signing identity for type '#{
|
273
|
+
message = "Could not find a matching code signing identity for type '#{profile_type_pretty_type}'. "
|
239
274
|
message += "It is recommended to use match to manage code signing for you, more information on https://codesigning.guide. "
|
240
275
|
message += "If you don't want to do so, you can also use cert to generate a new one: https://fastlane.tools/cert"
|
241
276
|
UI.user_error!(message)
|
@@ -248,13 +283,15 @@ module Sigh
|
|
248
283
|
# Downloads and stores the provisioning profile
|
249
284
|
def download_profile(profile)
|
250
285
|
UI.important("Downloading provisioning profile...")
|
251
|
-
profile_name ||= "#{
|
286
|
+
profile_name ||= "#{profile_type_pretty_type}_#{Sigh.config[:app_identifier]}"
|
252
287
|
|
253
288
|
if Sigh.config[:platform].to_s == 'tvos'
|
254
289
|
profile_name += "_tvos"
|
290
|
+
elsif Sigh.config[:platform].to_s == 'catalyst'
|
291
|
+
profile_name += "_catalyst"
|
255
292
|
end
|
256
293
|
|
257
|
-
if Sigh.config[:platform].to_s
|
294
|
+
if ['macos', 'catalyst'].include?(Sigh.config[:platform].to_s)
|
258
295
|
profile_name += '.provisionprofile'
|
259
296
|
else
|
260
297
|
profile_name += '.mobileprovision'
|
@@ -263,7 +300,8 @@ module Sigh
|
|
263
300
|
tmp_path = Dir.mktmpdir("profile_download")
|
264
301
|
output_path = File.join(tmp_path, profile_name)
|
265
302
|
File.open(output_path, "wb") do |f|
|
266
|
-
|
303
|
+
content = Base64.decode64(profile.profile_content)
|
304
|
+
f.write(content)
|
267
305
|
end
|
268
306
|
|
269
307
|
UI.success("Successfully downloaded provisioning profile...")
|
@@ -272,7 +310,10 @@ module Sigh
|
|
272
310
|
|
273
311
|
# Makes sure the current App ID exists. If not, it will show an appropriate error message
|
274
312
|
def ensure_app_exists!
|
275
|
-
|
313
|
+
# Only ensuring by app identifier
|
314
|
+
# We used to ensure by platform (IOS and MAC_OS) but now apps are
|
315
|
+
# always UNIVERSAL as of 2020-07-30
|
316
|
+
return if Spaceship::ConnectAPI::BundleId.find(Sigh.config[:app_identifier])
|
276
317
|
print_produce_command(Sigh.config)
|
277
318
|
UI.user_error!("Could not find App with App Identifier '#{Sigh.config[:app_identifier]}'")
|
278
319
|
end
|