fastlane 2.196.0 → 2.199.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.
- checksums.yaml +4 -4
- data/README.md +94 -94
- data/cert/lib/cert/runner.rb +5 -2
- data/deliver/lib/assets/ScreenshotsHelp +29 -6
- data/deliver/lib/deliver/app_screenshot.rb +5 -4
- data/deliver/lib/deliver/app_screenshot_iterator.rb +1 -1
- data/deliver/lib/deliver/runner.rb +1 -1
- data/deliver/lib/deliver/upload_screenshots.rb +1 -1
- data/fastlane/lib/.DS_Store +0 -0
- data/fastlane/lib/fastlane/.DS_Store +0 -0
- data/fastlane/lib/fastlane/actions/.DS_Store +0 -0
- data/fastlane/lib/fastlane/actions/docs/upload_to_app_store.md.erb +1 -1
- data/fastlane/lib/fastlane/actions/download_dsyms.rb +61 -45
- data/fastlane/lib/fastlane/actions/ensure_xcode_version.rb +1 -1
- data/fastlane/lib/fastlane/actions/get_push_certificate.rb +1 -1
- data/fastlane/lib/fastlane/actions/get_version_number.rb +6 -2
- data/fastlane/lib/fastlane/actions/notarize.rb +29 -11
- data/fastlane/lib/fastlane/actions/set_github_release.rb +11 -5
- data/fastlane/lib/fastlane/actions/update_code_signing_settings.rb +18 -1
- data/fastlane/lib/fastlane/actions/xcversion.rb +18 -3
- data/fastlane/lib/fastlane/documentation/docs_generator.rb +17 -12
- data/fastlane/lib/fastlane/version.rb +1 -1
- data/fastlane/swift/Deliverfile.swift +1 -1
- data/fastlane/swift/DeliverfileProtocol.swift +1 -1
- data/fastlane/swift/Fastlane.swift +66 -21
- data/fastlane/swift/Gymfile.swift +1 -1
- data/fastlane/swift/GymfileProtocol.swift +5 -1
- data/fastlane/swift/Matchfile.swift +1 -1
- data/fastlane/swift/MatchfileProtocol.swift +1 -1
- data/fastlane/swift/Precheckfile.swift +1 -1
- data/fastlane/swift/PrecheckfileProtocol.swift +1 -1
- data/fastlane/swift/Runner.swift +3 -7
- data/fastlane/swift/Scanfile.swift +1 -1
- data/fastlane/swift/ScanfileProtocol.swift +3 -3
- 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/formatting/Brewfile.lock.json +26 -21
- data/fastlane_core/lib/fastlane_core/itunes_transporter.rb +38 -7
- data/frameit/lib/frameit/editor.rb +16 -18
- data/frameit/lib/frameit/trim_box.rb +6 -0
- data/gym/lib/gym/generators/build_command_generator.rb +1 -1
- data/gym/lib/gym/options.rb +6 -0
- data/match/lib/match/nuke.rb +79 -1
- data/match/lib/match/spaceship_ensure.rb +1 -0
- data/pem/lib/pem/manager.rb +29 -6
- data/pem/lib/pem/options.rb +9 -0
- data/pilot/lib/pilot/build_manager.rb +1 -1
- data/scan/lib/scan/options.rb +2 -2
- data/scan/lib/scan/runner.rb +1 -1
- data/snapshot/lib/snapshot/simulator_launchers/simulator_launcher_base.rb +1 -1
- data/spaceship/lib/spaceship/client.rb +35 -15
- data/spaceship/lib/spaceship/commands_generator.rb +1 -1
- data/spaceship/lib/spaceship/connect_api/models/build.rb +4 -2
- data/spaceship/lib/spaceship/connect_api/models/build_bundle.rb +59 -0
- data/spaceship/lib/spaceship/connect_api/models/certificate.rb +3 -0
- data/spaceship/lib/spaceship/connect_api/response.rb +13 -0
- data/spaceship/lib/spaceship/connect_api.rb +1 -0
- data/spaceship/lib/spaceship/globals.rb +9 -0
- data/spaceship/lib/spaceship/spaceauth_runner.rb +1 -1
- data/trainer/lib/.DS_Store +0 -0
- metadata +24 -18
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'shellwords'
|
2
|
+
require 'tmpdir'
|
2
3
|
require 'fileutils'
|
3
4
|
require 'credentials_manager/account_manager'
|
4
5
|
|
@@ -148,6 +149,17 @@ module FastlaneCore
|
|
148
149
|
end
|
149
150
|
end
|
150
151
|
|
152
|
+
def file_upload_option(source)
|
153
|
+
ext = File.extname(source).downcase
|
154
|
+
is_asset_file_type = !File.directory?(source) && [".ipa", ".pkg", ".dmg", ".zip"].include?(ext)
|
155
|
+
|
156
|
+
if is_asset_file_type
|
157
|
+
return "-assetFile #{source.shellescape}"
|
158
|
+
else
|
159
|
+
return "-f #{source.shellescape}"
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
151
163
|
def additional_upload_parameters
|
152
164
|
# As Apple recommends in Transporter User Guide we shouldn't specify the -t transport parameter
|
153
165
|
# and instead allow Transporter to use automatic transport discovery
|
@@ -177,7 +189,7 @@ module FastlaneCore
|
|
177
189
|
("-u #{username.shellescape}" unless use_jwt),
|
178
190
|
("-p #{shell_escaped_password(password)}" unless use_jwt),
|
179
191
|
("-jwt #{jwt}" if use_jwt),
|
180
|
-
|
192
|
+
file_upload_option(source),
|
181
193
|
additional_upload_parameters, # that's here, because the user might overwrite the -t option
|
182
194
|
"-k 100000",
|
183
195
|
("-WONoPause true" if Helper.windows?), # Windows only: process instantly returns instead of waiting for key press
|
@@ -261,7 +273,7 @@ module FastlaneCore
|
|
261
273
|
("-u #{username.shellescape}" unless use_jwt),
|
262
274
|
("-p @env:ITMS_TRANSPORTER_PASSWORD" unless use_jwt),
|
263
275
|
("-jwt #{jwt}" if use_jwt),
|
264
|
-
|
276
|
+
file_upload_option(source),
|
265
277
|
additional_upload_parameters, # that's here, because the user might overwrite the -t option
|
266
278
|
'-k 100000',
|
267
279
|
("-itc_provider #{provider_short_name}" if jwt.nil? && !provider_short_name.to_s.empty?),
|
@@ -282,7 +294,7 @@ module FastlaneCore
|
|
282
294
|
("-u #{username.shellescape}" unless use_jwt),
|
283
295
|
("-p #{password.shellescape}" unless use_jwt),
|
284
296
|
("-jwt #{jwt}" if use_jwt),
|
285
|
-
|
297
|
+
file_upload_option(source),
|
286
298
|
additional_upload_parameters, # that's here, because the user might overwrite the -t option
|
287
299
|
'-k 100000',
|
288
300
|
("-itc_provider #{provider_short_name}" if jwt.nil? && !provider_short_name.to_s.empty?),
|
@@ -472,12 +484,31 @@ module FastlaneCore
|
|
472
484
|
# @param app_id [Integer] The unique App ID
|
473
485
|
# @param dir [String] the path in which the package file is located
|
474
486
|
# @param package_path [String] the path to the package file (used instead of app_id and dir)
|
487
|
+
# @param asset_path [String] the path to the ipa/dmg/pkg file (used instead of package_path if running on macOS)
|
475
488
|
# @return (Bool) True if everything worked fine
|
476
489
|
# @raise [Deliver::TransporterTransferError] when something went wrong
|
477
490
|
# when transferring
|
478
|
-
def upload(app_id = nil, dir = nil, package_path: nil)
|
479
|
-
raise "app_id and dir are required or package_path is required" if (app_id.nil? || dir.nil?) && package_path.nil?
|
480
|
-
|
491
|
+
def upload(app_id = nil, dir = nil, package_path: nil, asset_path: nil)
|
492
|
+
raise "app_id and dir are required or package_path or asset_path is required" if (app_id.nil? || dir.nil?) && package_path.nil? && asset_path.nil?
|
493
|
+
|
494
|
+
# Transport can upload .ipa, .dmg, and .pkg files directly with -assetFile
|
495
|
+
# However, -assetFile requires -assetDescription if Linux or Windows
|
496
|
+
# This will give the asset directly if macOS and asset_path exists
|
497
|
+
# otherwise it will use the .itmsp package
|
498
|
+
|
499
|
+
force_itmsp = FastlaneCore::Env.truthy?("ITMSTRANSPORTER_FORCE_ITMS_PACKAGE_UPLOAD")
|
500
|
+
can_use_asset_path = Helper.is_mac? && asset_path
|
501
|
+
|
502
|
+
actual_dir = if can_use_asset_path && !force_itmsp
|
503
|
+
# The asset gets deleted upon completion so copying to a temp directory
|
504
|
+
tmp_asset_path = File.join(Dir.tmpdir, File.basename(asset_path))
|
505
|
+
FileUtils.cp(asset_path, tmp_asset_path)
|
506
|
+
tmp_asset_path
|
507
|
+
elsif package_path
|
508
|
+
package_path
|
509
|
+
else
|
510
|
+
File.join(dir, "#{app_id}.itmsp")
|
511
|
+
end
|
481
512
|
|
482
513
|
UI.message("Going to upload updated app to App Store Connect")
|
483
514
|
UI.success("This might take a few minutes. Please don't interrupt the script.")
|
@@ -492,7 +523,7 @@ module FastlaneCore
|
|
492
523
|
result = @transporter_executor.execute(command, ItunesTransporter.hide_transporter_output?)
|
493
524
|
rescue TransporterRequiresApplicationSpecificPasswordError => ex
|
494
525
|
handle_two_step_failure(ex)
|
495
|
-
return upload(app_id, dir, package_path: package_path)
|
526
|
+
return upload(app_id, dir, package_path: package_path, asset_path: asset_path)
|
496
527
|
end
|
497
528
|
|
498
529
|
if result
|
@@ -467,26 +467,24 @@ module Frameit
|
|
467
467
|
# Get matching trim box:
|
468
468
|
trim_box = trim_boxes[key]
|
469
469
|
|
470
|
-
#
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
|
481
|
-
end
|
470
|
+
# Adjust the trim box based on top_vertical_trim_offset and bottom_vertical_trim_offset to maintain the text baseline:
|
471
|
+
# Determine the trim area by maintaining the same vertical top offset based on the smallest value from all trim boxes (top_vertical_trim_offset).
|
472
|
+
# When the vertical top offset is larger than the smallest vertical top offset, the trim box needs to be adjusted:
|
473
|
+
if trim_box.offset_y > top_vertical_trim_offset
|
474
|
+
# Increase the height of the trim box with the difference in vertical top offset:
|
475
|
+
trim_box.height += trim_box.offset_y - top_vertical_trim_offset
|
476
|
+
# Change the vertical top offset to match that of the others:
|
477
|
+
trim_box.offset_y = top_vertical_trim_offset
|
478
|
+
|
479
|
+
UI.verbose("Trim box for key \"#{key}\" is adjusted to align top: #{trim_box.json_string_format}")
|
480
|
+
end
|
482
481
|
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
|
482
|
+
# Check if the height needs to be adjusted to reach the bottom offset:
|
483
|
+
if (trim_box.offset_y + trim_box.height) < bottom_vertical_trim_offset
|
484
|
+
# Set the height of the trim box to the difference between vertical bottom and top offset:
|
485
|
+
trim_box.height = bottom_vertical_trim_offset - trim_box.offset_y
|
487
486
|
|
488
|
-
|
489
|
-
end
|
487
|
+
UI.verbose("Trim box for key \"#{key}\" is adjusted to align bottom: #{trim_box.json_string_format}")
|
490
488
|
end
|
491
489
|
|
492
490
|
# Crop image with (adjusted) trim box parameters in MiniMagick string format:
|
@@ -31,5 +31,11 @@ module Frameit
|
|
31
31
|
# Convert trim box parameters to string with syntax: "<width>x<height>+<offset_x>+<offset_y>":
|
32
32
|
return "#{@width}x#{@height}+#{@offset_x}+#{@offset_y}"
|
33
33
|
end
|
34
|
+
|
35
|
+
# Get the trimbox parameters in a human readable JSON string format
|
36
|
+
def json_string_format
|
37
|
+
# Create a JSON string from the trim box parameters:
|
38
|
+
return "{\"width\" : #{@width}, \"height\" : #{@height} , \"offset_x\" : #{@offset_x}, \"offset_y\" : #{@offset_y}}"
|
39
|
+
end
|
34
40
|
end
|
35
41
|
end
|
data/gym/lib/gym/options.rb
CHANGED
@@ -275,6 +275,12 @@ module Gym
|
|
275
275
|
optional: true,
|
276
276
|
type: Boolean,
|
277
277
|
default_value: false),
|
278
|
+
FastlaneCore::ConfigItem.new(key: :xcodebuild_command,
|
279
|
+
env_name: "GYM_XCODE_BUILD_COMMAND",
|
280
|
+
description: "Allows for override of the default `xcodebuild` command",
|
281
|
+
type: String,
|
282
|
+
optional: true,
|
283
|
+
default_value: "xcodebuild"),
|
278
284
|
FastlaneCore::ConfigItem.new(key: :cloned_source_packages_path,
|
279
285
|
env_name: "GYM_CLONED_SOURCE_PACKAGES_PATH",
|
280
286
|
description: "Sets a custom path for Swift Package Manager dependencies",
|
data/match/lib/match/nuke.rb
CHANGED
@@ -9,7 +9,11 @@ require_relative 'module'
|
|
9
9
|
require_relative 'storage'
|
10
10
|
require_relative 'encryption'
|
11
11
|
|
12
|
+
require 'tempfile'
|
13
|
+
require 'base64'
|
14
|
+
|
12
15
|
module Match
|
16
|
+
# rubocop:disable Metrics/ClassLength
|
13
17
|
class Nuke
|
14
18
|
attr_accessor :params
|
15
19
|
attr_accessor :type
|
@@ -67,6 +71,7 @@ module Match
|
|
67
71
|
title: "Summary for match nuke #{Fastlane::VERSION}")
|
68
72
|
|
69
73
|
prepare_list
|
74
|
+
filter_by_cert
|
70
75
|
print_tables
|
71
76
|
|
72
77
|
if params[:readonly]
|
@@ -139,7 +144,7 @@ module Match
|
|
139
144
|
types = profile_types(prov_type)
|
140
145
|
# Filtering on 'profileType' seems to be undocumented as of 2020-07-30
|
141
146
|
# but works on both web session and official API
|
142
|
-
self.profiles += Spaceship::ConnectAPI::Profile.all(filter: { profileType: types.join(",") })
|
147
|
+
self.profiles += Spaceship::ConnectAPI::Profile.all(filter: { profileType: types.join(",") }, includes: "certificates")
|
143
148
|
end
|
144
149
|
|
145
150
|
# Gets the main and additional cert types
|
@@ -173,6 +178,78 @@ module Match
|
|
173
178
|
self.files = certs + keys + profiles
|
174
179
|
end
|
175
180
|
|
181
|
+
def filter_by_cert
|
182
|
+
# Force will continue to revoke and delete all certificates and profiles
|
183
|
+
return if self.params[:force] || !UI.interactive?
|
184
|
+
return if self.certs.count < 2
|
185
|
+
|
186
|
+
# Print table showing certificates that can be revoked
|
187
|
+
puts("")
|
188
|
+
rows = self.certs.each_with_index.collect do |cert, i|
|
189
|
+
cert_expiration = cert.expiration_date.nil? ? "Unknown" : Time.parse(cert.expiration_date).strftime("%Y-%m-%d")
|
190
|
+
[i + 1, cert.name, cert.id, cert.class.to_s.split("::").last, cert_expiration]
|
191
|
+
end
|
192
|
+
puts(Terminal::Table.new({
|
193
|
+
title: "Certificates that can be revoked".green,
|
194
|
+
headings: ["Option", "Name", "ID", "Type", "Expires"],
|
195
|
+
rows: FastlaneCore::PrintTable.transform_output(rows)
|
196
|
+
}))
|
197
|
+
puts("")
|
198
|
+
|
199
|
+
UI.important("By default, all listed certificates and profiles will be nuked")
|
200
|
+
if UI.confirm("Do you want to only nuke specific certificates and their associated profiles?")
|
201
|
+
input_indexes = UI.input("Enter the \"Option\" number(s) from the table above? (comma-separated)").split(',')
|
202
|
+
|
203
|
+
# Get certificates from option indexes
|
204
|
+
self.certs = input_indexes.map do |index|
|
205
|
+
self.certs[index.to_i - 1]
|
206
|
+
end.compact
|
207
|
+
|
208
|
+
if self.certs.empty?
|
209
|
+
UI.user_error!("No certificates were selected based on option number(s) entered")
|
210
|
+
end
|
211
|
+
|
212
|
+
# Do profile selection logic
|
213
|
+
cert_ids = self.certs.map(&:id)
|
214
|
+
self.profiles = self.profiles.select do |profile|
|
215
|
+
profile_cert_ids = profile.certificates.map(&:id)
|
216
|
+
(cert_ids & profile_cert_ids).any?
|
217
|
+
end
|
218
|
+
|
219
|
+
# Do file selection logic
|
220
|
+
self.files = self.files.select do |f|
|
221
|
+
found = false
|
222
|
+
|
223
|
+
ext = File.extname(f)
|
224
|
+
filename = File.basename(f, ".*")
|
225
|
+
|
226
|
+
# Attempt to find cert based on filename
|
227
|
+
if ext == ".cer" || ext == ".p12"
|
228
|
+
found ||= self.certs.any? do |cert|
|
229
|
+
filename == cert.id.to_s
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
233
|
+
# Attempt to find profile matched on UUIDs in profile
|
234
|
+
if ext == ".mobileprovision" || ext == ".provisionprofile"
|
235
|
+
storage_uuid = FastlaneCore::ProvisioningProfile.uuid(f)
|
236
|
+
|
237
|
+
found ||= self.profiles.any? do |profile|
|
238
|
+
tmp_file = Tempfile.new
|
239
|
+
tmp_file.write(Base64.decode64(profile.profile_content))
|
240
|
+
tmp_file.close
|
241
|
+
|
242
|
+
# Compare profile uuid in storage to profile uuid on developer portal
|
243
|
+
portal_uuid = FastlaneCore::ProvisioningProfile.uuid(tmp_file.path)
|
244
|
+
storage_uuid == portal_uuid
|
245
|
+
end
|
246
|
+
end
|
247
|
+
|
248
|
+
found
|
249
|
+
end
|
250
|
+
end
|
251
|
+
end
|
252
|
+
|
176
253
|
# Print tables to ask the user
|
177
254
|
def print_tables
|
178
255
|
puts("")
|
@@ -351,4 +428,5 @@ module Match
|
|
351
428
|
end
|
352
429
|
end
|
353
430
|
end
|
431
|
+
# rubocop:disable Metrics/ClassLength
|
354
432
|
end
|
@@ -70,6 +70,7 @@ module Match
|
|
70
70
|
UI.error("for the user #{username}")
|
71
71
|
UI.error("Make sure to use the same user and team every time you run 'match' for this")
|
72
72
|
UI.error("Git repository. This might be caused by revoking the certificate on the Dev Portal")
|
73
|
+
UI.error("If missing certificate is a Developer ID Installer, you may need to auth with Apple ID instead of App Store API Key")
|
73
74
|
UI.user_error!("To reset the certificates of your Apple account, you can use the `fastlane match nuke` feature, more information on https://docs.fastlane.tools/actions/match/")
|
74
75
|
end
|
75
76
|
|
data/pem/lib/pem/manager.rb
CHANGED
@@ -18,7 +18,13 @@ module PEM
|
|
18
18
|
|
19
19
|
if existing_certificate
|
20
20
|
remaining_days = (existing_certificate.expires - Time.now) / 60 / 60 / 24
|
21
|
-
|
21
|
+
|
22
|
+
display_platform = ''
|
23
|
+
unless PEM.config[:website_push]
|
24
|
+
display_platform = "#{PEM.config[:platform]} "
|
25
|
+
end
|
26
|
+
|
27
|
+
UI.message("Existing #{display_platform}push notification profile for '#{existing_certificate.owner_name}' is valid for #{remaining_days.round} more days.")
|
22
28
|
if remaining_days > PEM.config[:active_days_limit]
|
23
29
|
if PEM.config[:force]
|
24
30
|
UI.success("You already have an existing push certificate, but a new one will be created since the --force option has been set.")
|
@@ -59,7 +65,7 @@ module PEM
|
|
59
65
|
|
60
66
|
x509_certificate = cert.download
|
61
67
|
|
62
|
-
filename_base = PEM.config[:pem_name] || "#{certificate_type}_#{PEM.config[:app_identifier]}"
|
68
|
+
filename_base = PEM.config[:pem_name] || "#{certificate_type}_#{PEM.config[:app_identifier]}_#{PEM.config[:platform]}"
|
63
69
|
filename_base = File.basename(filename_base, ".pem") # strip off the .pem if it was provided.
|
64
70
|
|
65
71
|
output_path = File.expand_path(PEM.config[:output_path])
|
@@ -86,12 +92,29 @@ module PEM
|
|
86
92
|
end
|
87
93
|
|
88
94
|
def certificate
|
89
|
-
if PEM.config[:
|
90
|
-
Spaceship.certificate.development_push
|
91
|
-
elsif PEM.config[:website_push]
|
95
|
+
if PEM.config[:website_push]
|
92
96
|
Spaceship.certificate.website_push
|
93
97
|
else
|
94
|
-
|
98
|
+
platform = PEM.config[:platform]
|
99
|
+
UI.user_error!('platform parameter is unspecified.') unless platform
|
100
|
+
|
101
|
+
case platform
|
102
|
+
when 'ios'
|
103
|
+
if PEM.config[:development]
|
104
|
+
Spaceship.certificate.development_push
|
105
|
+
else
|
106
|
+
Spaceship.certificate.production_push
|
107
|
+
end
|
108
|
+
when 'macos'
|
109
|
+
if PEM.config[:development]
|
110
|
+
Spaceship.certificate.mac_development_push
|
111
|
+
else
|
112
|
+
Spaceship.certificate.mac_production_push
|
113
|
+
end
|
114
|
+
else
|
115
|
+
UI.user_error!("Unsupported platform '#{platform}'. Supported platforms for development and production certificates are 'ios' & 'macos'")
|
116
|
+
end
|
117
|
+
|
95
118
|
end
|
96
119
|
end
|
97
120
|
|
data/pem/lib/pem/options.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'fastlane_core/configuration/config_item'
|
2
2
|
require 'credentials_manager/appfile_config'
|
3
|
+
require 'fastlane/helper/lane_helper'
|
3
4
|
|
4
5
|
require_relative 'module'
|
5
6
|
|
@@ -10,6 +11,14 @@ module PEM
|
|
10
11
|
user ||= CredentialsManager::AppfileConfig.try_fetch_value(:apple_id)
|
11
12
|
|
12
13
|
[
|
14
|
+
FastlaneCore::ConfigItem.new(key: :platform,
|
15
|
+
description: "Set certificate's platform. Used for creation of production & development certificates. Supported platforms: ios, macos",
|
16
|
+
short_option: "-m",
|
17
|
+
env_name: "PEM_PLATFORM",
|
18
|
+
default_value: "ios",
|
19
|
+
verify_block: proc do |value|
|
20
|
+
UI.user_error!("The platform can only be ios or macos") unless ['ios', 'macos'].include?(value)
|
21
|
+
end),
|
13
22
|
FastlaneCore::ConfigItem.new(key: :development,
|
14
23
|
env_name: "PEM_DEVELOPMENT",
|
15
24
|
description: "Renew the development push certificate instead of the production one",
|
@@ -38,7 +38,7 @@ module Pilot
|
|
38
38
|
end
|
39
39
|
|
40
40
|
transporter = transporter_for_selected_team(options)
|
41
|
-
result = transporter.upload(package_path: package_path)
|
41
|
+
result = transporter.upload(package_path: package_path, asset_path: options[:ipa] || options[:pkg])
|
42
42
|
|
43
43
|
unless result
|
44
44
|
transporter_errors = transporter.displayable_errors
|
data/scan/lib/scan/options.rb
CHANGED
@@ -60,7 +60,7 @@ module Scan
|
|
60
60
|
optional: true,
|
61
61
|
is_string: true,
|
62
62
|
env_name: "SCAN_DEVICE",
|
63
|
-
description: "The name of the simulator type you want to run tests on (e.g. 'iPhone 6')",
|
63
|
+
description: "The name of the simulator type you want to run tests on (e.g. 'iPhone 6' or 'iPhone SE (2nd generation) (14.5)')",
|
64
64
|
conflicting_options: [:devices],
|
65
65
|
conflict_block: proc do |value|
|
66
66
|
UI.user_error!("You can't use 'device' and 'devices' options in one run")
|
@@ -70,7 +70,7 @@ module Scan
|
|
70
70
|
is_string: false,
|
71
71
|
env_name: "SCAN_DEVICES",
|
72
72
|
type: Array,
|
73
|
-
description: "Array of devices to run the tests on (e.g. ['iPhone 6', 'iPad Air'])",
|
73
|
+
description: "Array of devices to run the tests on (e.g. ['iPhone 6', 'iPad Air', 'iPhone SE (2nd generation) (14.5)'])",
|
74
74
|
conflicting_options: [:device],
|
75
75
|
conflict_block: proc do |value|
|
76
76
|
UI.user_error!("You can't use 'device' and 'devices' options in one run")
|
data/scan/lib/scan/runner.rb
CHANGED
@@ -226,7 +226,7 @@ module Scan
|
|
226
226
|
FileUtils.cp(xctestrun_file, output_path)
|
227
227
|
UI.message("Successfully copied xctestrun file: #{output_path}")
|
228
228
|
else
|
229
|
-
UI.user_error!("Could not find .
|
229
|
+
UI.user_error!("Could not find .xctestrun file to copy")
|
230
230
|
end
|
231
231
|
end
|
232
232
|
|
@@ -123,7 +123,7 @@ module Snapshot
|
|
123
123
|
# Simulator could stil be booting with Apple logo
|
124
124
|
# Need to wait "some amount of time" until home screen shows
|
125
125
|
boot_sleep = ENV["SNAPSHOT_SIMULATOR_WAIT_FOR_BOOT_TIMEOUT"].to_i || 10
|
126
|
-
UI.message("Waiting #{boot_sleep} seconds for device to fully boot before overriding status bar... Set 'SNAPSHOT_SIMULATOR_WAIT_FOR_BOOT_TIMEOUT'
|
126
|
+
UI.message("Waiting #{boot_sleep} seconds for device to fully boot before overriding status bar... Set 'SNAPSHOT_SIMULATOR_WAIT_FOR_BOOT_TIMEOUT' environment variable to adjust timeout")
|
127
127
|
sleep(boot_sleep) if boot_sleep > 0
|
128
128
|
|
129
129
|
UI.message("Overriding Status Bar")
|
@@ -391,10 +391,11 @@ module Spaceship
|
|
391
391
|
|
392
392
|
keychain_entry = CredentialsManager::AccountManager.new(user: user, password: password)
|
393
393
|
user ||= keychain_entry.user
|
394
|
-
password = keychain_entry.password
|
394
|
+
password = keychain_entry.password(ask_if_missing: !Spaceship::Globals.check_session)
|
395
395
|
end
|
396
396
|
|
397
397
|
if user.to_s.strip.empty? || password.to_s.strip.empty?
|
398
|
+
exit_with_session_state(user, false) if Spaceship::Globals.check_session
|
398
399
|
raise NoUserCredentialsError.new, "No login data provided"
|
399
400
|
end
|
400
401
|
|
@@ -413,21 +414,16 @@ module Spaceship
|
|
413
414
|
end
|
414
415
|
end
|
415
416
|
|
416
|
-
#
|
417
|
-
# This will also handle 2 step verification and 2 factor authentication
|
417
|
+
# Check if we have a cached/valid session
|
418
418
|
#
|
419
|
-
#
|
420
|
-
#
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
# lane (e.g. call match 5 times), this would lock you out of the account for a while.
|
428
|
-
# By loading existing sessions and checking if they're valid, we're sending less login requests.
|
429
|
-
# More context on why this change was necessary https://github.com/fastlane/fastlane/pull/11108
|
430
|
-
#
|
419
|
+
# Background:
|
420
|
+
# December 4th 2017 Apple introduced a rate limit - which is of course fine by itself -
|
421
|
+
# but unfortunately also rate limits successful logins. If you call multiple tools in a
|
422
|
+
# lane (e.g. call match 5 times), this would lock you out of the account for a while.
|
423
|
+
# By loading existing sessions and checking if they're valid, we're sending less login requests.
|
424
|
+
# More context on why this change was necessary https://github.com/fastlane/fastlane/pull/11108
|
425
|
+
#
|
426
|
+
def has_valid_session
|
431
427
|
# If there was a successful manual login before, we have a session on disk
|
432
428
|
if load_session_from_file
|
433
429
|
# Check if the session is still valid here
|
@@ -462,6 +458,23 @@ module Spaceship
|
|
462
458
|
#
|
463
459
|
# After this point, we sure have no valid session any more and have to create a new one
|
464
460
|
#
|
461
|
+
return false
|
462
|
+
end
|
463
|
+
|
464
|
+
# This method is used for both the Apple Dev Portal and App Store Connect
|
465
|
+
# This will also handle 2 step verification and 2 factor authentication
|
466
|
+
#
|
467
|
+
# It is called in `send_login_request` of sub classes (which the method `login`, above, transferred over to via `do_login`)
|
468
|
+
# rubocop:disable Metrics/PerceivedComplexity
|
469
|
+
def send_shared_login_request(user, password)
|
470
|
+
# Check if the cache or FASTLANE_SESSION is still valid
|
471
|
+
has_valid_session = self.has_valid_session
|
472
|
+
|
473
|
+
# Exit if `--check_session` flag was passed
|
474
|
+
exit_with_session_state(user, has_valid_session) if Spaceship::Globals.check_session
|
475
|
+
|
476
|
+
# If the session is valid no need to attempt to generate a new one.
|
477
|
+
return true if has_valid_session
|
465
478
|
|
466
479
|
data = {
|
467
480
|
accountName: user,
|
@@ -566,6 +579,13 @@ module Spaceship
|
|
566
579
|
return false
|
567
580
|
end
|
568
581
|
|
582
|
+
# This method is used to log if the session is valid or not and then exit
|
583
|
+
# It is called when the `--check_session` flag is passed
|
584
|
+
def exit_with_session_state(user, has_valid_session)
|
585
|
+
puts("#{has_valid_session ? 'Valid' : 'No valid'} session found (#{user}). Exiting.")
|
586
|
+
exit(has_valid_session)
|
587
|
+
end
|
588
|
+
|
569
589
|
def itc_service_key
|
570
590
|
return @service_key if @service_key
|
571
591
|
|
@@ -41,7 +41,7 @@ module Spaceship
|
|
41
41
|
c.syntax = 'fastlane spaceship spaceauth'
|
42
42
|
c.description = 'Authentication helper for spaceship/fastlane to work with Apple 2-Step/2FA'
|
43
43
|
c.option('--copy_to_clipboard', 'Whether the session string should be copied to clipboard. For more info see https://docs.fastlane.tools/best-practices/continuous-integration/#storing-a-manually-verified-session-using-spaceauth`')
|
44
|
-
|
44
|
+
c.option('--check_session', 'Check to see if there is a valid session (either in the cache or via FASTLANE_SESSION). Sets the exit code to 0 if the session is valid or 1 if not.') { Spaceship::Globals.check_session = true }
|
45
45
|
c.action do |args, options|
|
46
46
|
Spaceship::SpaceauthRunner.new(username: options.user, copy_to_clipboard: options.copy_to_clipboard).run
|
47
47
|
end
|
@@ -19,6 +19,7 @@ module Spaceship
|
|
19
19
|
attr_accessor :beta_build_metrics
|
20
20
|
attr_accessor :beta_build_localizations
|
21
21
|
attr_accessor :build_beta_detail
|
22
|
+
attr_accessor :build_bundles
|
22
23
|
attr_accessor :pre_release_version
|
23
24
|
attr_accessor :individual_testers
|
24
25
|
|
@@ -38,10 +39,11 @@ module Spaceship
|
|
38
39
|
"betaBuildLocalizations" => "beta_build_localizations",
|
39
40
|
"buildBetaDetail" => "build_beta_detail",
|
40
41
|
"preReleaseVersion" => "pre_release_version",
|
41
|
-
"individualTesters" => "individual_testers"
|
42
|
+
"individualTesters" => "individual_testers",
|
43
|
+
"buildBundles" => "build_bundles"
|
42
44
|
})
|
43
45
|
|
44
|
-
ESSENTIAL_INCLUDES = "app,buildBetaDetail,preReleaseVersion"
|
46
|
+
ESSENTIAL_INCLUDES = "app,buildBetaDetail,preReleaseVersion,buildBundles"
|
45
47
|
|
46
48
|
module ProcessingState
|
47
49
|
PROCESSING = "PROCESSING"
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require_relative '../model'
|
2
|
+
module Spaceship
|
3
|
+
class ConnectAPI
|
4
|
+
class BuildBundle
|
5
|
+
include Spaceship::ConnectAPI::Model
|
6
|
+
|
7
|
+
attr_accessor :bundle_id
|
8
|
+
attr_accessor :bundle_type
|
9
|
+
attr_accessor :sdk_build
|
10
|
+
attr_accessor :platform_build
|
11
|
+
attr_accessor :file_name
|
12
|
+
attr_accessor :has_siri_kit
|
13
|
+
attr_accessor :has_on_demand_resources
|
14
|
+
attr_accessor :is_newsstand
|
15
|
+
attr_accessor :has_prerendered_icon
|
16
|
+
attr_accessor :uses_location_services
|
17
|
+
attr_accessor :is_ios_build_mac_app_store_compatible
|
18
|
+
attr_accessor :includes_symbols
|
19
|
+
attr_accessor :dsym_url
|
20
|
+
attr_accessor :supported_architectures
|
21
|
+
attr_accessor :required_capabilities
|
22
|
+
attr_accessor :device_protocols
|
23
|
+
attr_accessor :locales
|
24
|
+
attr_accessor :entitlements
|
25
|
+
attr_accessor :tracks_users
|
26
|
+
|
27
|
+
module BundleType
|
28
|
+
APP = "APP"
|
29
|
+
# APP_CLIP might be in here as well
|
30
|
+
end
|
31
|
+
|
32
|
+
attr_mapping({
|
33
|
+
"bundleId" => "bundle_id",
|
34
|
+
"bundleType" => "bundle_type",
|
35
|
+
"sdkBuild" => "sdk_build",
|
36
|
+
"platformBuild" => "platform_build",
|
37
|
+
"fileName" => "file_name",
|
38
|
+
"hasSirikit" => "has_siri_kit",
|
39
|
+
"hasOnDemandResources" => "has_on_demand_resources",
|
40
|
+
"isNewsstand" => "is_newsstand",
|
41
|
+
"hasPrerenderedIcon" => "has_prerendered_icon",
|
42
|
+
"usesLocationServices" => "uses_location_services",
|
43
|
+
"isIosBuildMacAppStoreCompatible" => "is_ios_build_mac_app_store_compatible",
|
44
|
+
"includesSymbols" => "includes_symbols",
|
45
|
+
"dSYMUrl" => "dsym_url",
|
46
|
+
"supportedArchitectures" => "supported_architectures",
|
47
|
+
"requiredCapabilities" => "required_capabilities",
|
48
|
+
"deviceProtocols" => "device_protocols",
|
49
|
+
"locales" => "locales",
|
50
|
+
"entitlements" => "entitlements",
|
51
|
+
"tracksUsers" => "tracks_users"
|
52
|
+
})
|
53
|
+
|
54
|
+
def self.type
|
55
|
+
return "buildBundles"
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -41,6 +41,9 @@ module Spaceship
|
|
41
41
|
MAC_APP_DEVELOPMENT = "MAC_APP_DEVELOPMENT"
|
42
42
|
DEVELOPER_ID_KEXT = "DEVELOPER_ID_KEXT"
|
43
43
|
DEVELOPER_ID_APPLICATION = "DEVELOPER_ID_APPLICATION"
|
44
|
+
|
45
|
+
# As of 2021-11-09, this is only available with Apple ID auth
|
46
|
+
DEVELOPER_ID_INSTALLER = "DEVELOPER_ID_INSTALLER"
|
44
47
|
end
|
45
48
|
|
46
49
|
def self.type
|
@@ -64,6 +64,19 @@ module Spaceship
|
|
64
64
|
yield(model)
|
65
65
|
end
|
66
66
|
end
|
67
|
+
|
68
|
+
def all_pages_each(&block)
|
69
|
+
to_models.each do |model|
|
70
|
+
yield(model)
|
71
|
+
end
|
72
|
+
|
73
|
+
resp = self
|
74
|
+
loop do
|
75
|
+
resp = resp.next_page
|
76
|
+
break if resp.nil?
|
77
|
+
resp.each(&block)
|
78
|
+
end
|
79
|
+
end
|
67
80
|
end
|
68
81
|
end
|
69
82
|
end
|
@@ -32,6 +32,7 @@ require 'spaceship/connect_api/models/beta_tester_metric'
|
|
32
32
|
require 'spaceship/connect_api/models/build'
|
33
33
|
require 'spaceship/connect_api/models/build_delivery'
|
34
34
|
require 'spaceship/connect_api/models/build_beta_detail'
|
35
|
+
require 'spaceship/connect_api/models/build_bundle'
|
35
36
|
require 'spaceship/connect_api/models/custom_app_organization'
|
36
37
|
require 'spaceship/connect_api/models/custom_app_user'
|
37
38
|
require 'spaceship/connect_api/models/pre_release_version'
|