fastlane 2.232.1 → 2.233.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/credentials_manager/lib/credentials_manager/appfile_config.rb +4 -0
- data/deliver/lib/deliver/detect_values.rb +2 -0
- data/deliver/lib/deliver/options.rb +23 -0
- data/deliver/lib/deliver/runner.rb +17 -12
- data/deliver/lib/deliver/sync_app_previews.rb +204 -0
- data/fastlane/lib/fastlane/actions/app_store_connect_api_key.rb +5 -1
- data/fastlane/lib/fastlane/actions/docs/upload_to_app_store.md.erb +20 -4
- data/fastlane/lib/fastlane/actions/docs/upload_to_testflight.md +3 -0
- data/fastlane/lib/fastlane/actions/resign.rb +13 -2
- data/fastlane/lib/fastlane/actions/swiftlint.rb +8 -1
- data/fastlane/lib/fastlane/actions/upload_to_app_store.rb +1 -1
- data/fastlane/lib/fastlane/cli_tools_distributor.rb +10 -1
- data/fastlane/lib/fastlane/console.rb +2 -2
- data/fastlane/lib/fastlane/helper/s3_client_helper.rb +5 -2
- data/fastlane/lib/fastlane/version.rb +1 -1
- data/fastlane/swift/Deliverfile.swift +1 -1
- data/fastlane/swift/DeliverfileProtocol.swift +29 -1
- data/fastlane/swift/Fastlane.swift +105 -9
- data/fastlane/swift/Gymfile.swift +1 -1
- data/fastlane/swift/GymfileProtocol.swift +8 -1
- data/fastlane/swift/LaneFileProtocol.swift +3 -3
- data/fastlane/swift/Matchfile.swift +1 -1
- data/fastlane/swift/MatchfileProtocol.swift +8 -1
- 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_core/lib/fastlane_core/itunes_transporter.rb +48 -17
- data/fastlane_core/lib/fastlane_core/video_utils.rb +202 -0
- data/frameit/lib/frameit/device_types.rb +2 -2
- data/gym/lib/gym/generators/build_command_generator.rb +2 -1
- data/gym/lib/gym/options.rb +5 -0
- data/match/lib/match/generator.rb +3 -1
- data/match/lib/match/options.rb +5 -0
- data/match/lib/match/runner.rb +12 -7
- data/match/lib/match/storage/s3_storage.rb +4 -1
- data/match/lib/match/storage.rb +1 -0
- data/pilot/lib/pilot/build_manager.rb +4 -12
- data/pilot/lib/pilot/options.rb +4 -0
- data/precheck/lib/precheck/rules/rules_data/curse_word_hashes/README.md +54 -0
- data/precheck/lib/precheck/rules/rules_data/curse_word_hashes/en_us.txt +2 -1
- data/scan/lib/scan/detect_values.rb +11 -3
- data/sigh/lib/assets/resign.sh +18 -5
- data/sigh/lib/sigh/commands_generator.rb +1 -0
- data/sigh/lib/sigh/manager.rb +6 -6
- data/sigh/lib/sigh/resign.rb +9 -6
- data/spaceship/lib/spaceship/connect_api/models/app_preview_set.rb +54 -17
- data/spaceship/lib/spaceship/connect_api/models/app_store_version_localization.rb +1 -2
- data/spaceship/lib/spaceship/connect_api/tunes/tunes.rb +2 -2
- data/trainer/lib/trainer/legacy_xcresult.rb +27 -20
- data/trainer/lib/trainer/xcresult/test_suite.rb +4 -1
- metadata +27 -25
data/match/lib/match/storage.rb
CHANGED
|
@@ -46,6 +46,7 @@ module Match
|
|
|
46
46
|
s3_region: params[:s3_region],
|
|
47
47
|
s3_access_key: params[:s3_access_key],
|
|
48
48
|
s3_secret_access_key: params[:s3_secret_access_key],
|
|
49
|
+
s3_session_token: params[:s3_session_token],
|
|
49
50
|
s3_bucket: params[:s3_bucket],
|
|
50
51
|
s3_object_prefix: params[:s3_object_prefix],
|
|
51
52
|
readonly: params[:readonly],
|
|
@@ -398,7 +398,7 @@ module Pilot
|
|
|
398
398
|
|
|
399
399
|
# If App Store Connect API token, use token.
|
|
400
400
|
# If api_key is specified and it is an Individual API Key, don't use token but use username.
|
|
401
|
-
# If itc_provider was explicitly specified, use it.
|
|
401
|
+
# If itc_provider or provider_public_id was explicitly specified, use it.
|
|
402
402
|
# If there are multiple teams, infer the provider from the selected team name.
|
|
403
403
|
# If there are fewer than two teams, don't infer the provider.
|
|
404
404
|
def transporter_for_selected_team(options)
|
|
@@ -414,24 +414,16 @@ module Pilot
|
|
|
414
414
|
api_key
|
|
415
415
|
end
|
|
416
416
|
|
|
417
|
-
# Currently no kind of transporters accept an Individual API Key. Use username and app-specific password instead.
|
|
418
|
-
# See https://github.com/fastlane/fastlane/issues/22115
|
|
419
|
-
is_individual_key = !api_key.nil? && api_key[:issuer_id].nil?
|
|
420
|
-
if is_individual_key
|
|
421
|
-
api_key = nil
|
|
422
|
-
api_token = nil
|
|
423
|
-
end
|
|
424
|
-
|
|
425
417
|
unless api_token.nil?
|
|
426
418
|
api_token.refresh! if api_token.expired?
|
|
427
|
-
return FastlaneCore::ItunesTransporter.new(nil, nil, false, nil, api_token.text, altool_compatible_command: true, api_key: api_key)
|
|
419
|
+
return FastlaneCore::ItunesTransporter.new(nil, nil, false, nil, api_token.text, altool_compatible_command: true, api_key: api_key, provider_public_id: nil)
|
|
428
420
|
end
|
|
429
421
|
|
|
430
422
|
# Otherwise use username and password
|
|
431
423
|
tunes_client = Spaceship::ConnectAPI.client ? Spaceship::ConnectAPI.client.tunes_client : nil
|
|
432
424
|
|
|
433
|
-
generic_transporter = FastlaneCore::ItunesTransporter.new(options[:username], nil, false, options[:itc_provider], altool_compatible_command: true, api_key: api_key)
|
|
434
|
-
return generic_transporter if options[:itc_provider] || tunes_client.nil?
|
|
425
|
+
generic_transporter = FastlaneCore::ItunesTransporter.new(options[:username], nil, false, options[:itc_provider], altool_compatible_command: true, api_key: api_key, provider_public_id: options[:provider_public_id])
|
|
426
|
+
return generic_transporter if options[:itc_provider] || options[:provider_public_id] || tunes_client.nil?
|
|
435
427
|
return generic_transporter unless tunes_client.teams.count > 1
|
|
436
428
|
|
|
437
429
|
begin
|
data/pilot/lib/pilot/options.rb
CHANGED
|
@@ -293,6 +293,10 @@ module Pilot
|
|
|
293
293
|
env_name: "PILOT_ITC_PROVIDER",
|
|
294
294
|
description: "The provider short name to be used with the iTMSTransporter to identify your team. This value will override the automatically detected provider short name. To get provider short name run `pathToXcode.app/Contents/Applications/Application\\ Loader.app/Contents/itms/bin/iTMSTransporter -m provider -u 'USERNAME' -p 'PASSWORD' -account_type itunes_connect -v off`. The short names of providers should be listed in the second column",
|
|
295
295
|
optional: true),
|
|
296
|
+
FastlaneCore::ConfigItem.new(key: :provider_public_id,
|
|
297
|
+
env_name: "PILOT_PROVIDER_PUBLIC_ID",
|
|
298
|
+
description: "The provider public ID to be used with altool (--provider-public-id). This value will override the automatically detected provider value for altool uploads. Required after Xcode 26 when your account is associated with multiple providers and using username/app-password authentication",
|
|
299
|
+
optional: true),
|
|
296
300
|
# rubocop:enable Layout/LineLength
|
|
297
301
|
|
|
298
302
|
# waiting and uploaded build
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# Updating Curse Word Hashes for `fastlane precheck`
|
|
2
|
+
|
|
3
|
+
## What does `precheck/rules/curse_words_rule` do?
|
|
4
|
+
|
|
5
|
+
It uses the metadata fetched from the App Store by _precheck_ and reviews it word by word, failing if it matches one of the committed terms.
|
|
6
|
+
|
|
7
|
+
## What Terms to Hash
|
|
8
|
+
|
|
9
|
+
According to "Want to improve precheck's rules?" in [precheck's docs](https://docs.fastlane.tools/actions/precheck/), phrases flagged by a reviewer in your recent App Store Rejection.
|
|
10
|
+
|
|
11
|
+
## Format
|
|
12
|
+
|
|
13
|
+
These phrases are committed in repo under https://github.com/fastlane/fastlane/tree/master/precheck/lib/precheck/rules/rules_data/curse_word_hashes as sha 256 digest (one way hash).
|
|
14
|
+
|
|
15
|
+
### Before Generating
|
|
16
|
+
|
|
17
|
+
Make sure the term you are adding is:
|
|
18
|
+
1. A single word phrase
|
|
19
|
+
2. In all lowercase letters
|
|
20
|
+
3. Void of punctuation
|
|
21
|
+
|
|
22
|
+
This criteria mimics the transformations performed on the input data that is getting checked in https://github.com/fastlane/fastlane/tree/master/precheck/lib/precheck/rules/curse_words_rule.rb
|
|
23
|
+
|
|
24
|
+
### Generating a New Hash
|
|
25
|
+
|
|
26
|
+
```rb
|
|
27
|
+
irb(main):001:0> require 'digest'
|
|
28
|
+
=> true
|
|
29
|
+
irb(main):002:0> new_term_to_add = "oneword"
|
|
30
|
+
=> "oneword"
|
|
31
|
+
irb(main):003:0> Digest::SHA256.hexdigest(new_term_to_add)
|
|
32
|
+
=> "31be3624bc03aa68bc050cce316dc80cfe1ace3d0f58fa5f5b20c9e781c44a07"
|
|
33
|
+
irb(main):004:0>
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Append this to the end of the file (with a newline afterward).
|
|
37
|
+
|
|
38
|
+
## How to Test Your Newly Added Term
|
|
39
|
+
|
|
40
|
+
### Hack at the unit tests to include your phrase
|
|
41
|
+
|
|
42
|
+
Update the tests in https://github.com/fastlane/fastlane/blob/master/precheck/spec/rules/curse_words_rule_spec.rb to include your new phrase.
|
|
43
|
+
|
|
44
|
+
```diff
|
|
45
|
+
let(:happy_item) { TextItemToCheck.new("tacos are really delicious, seriously, I can't even", :description, "description") }
|
|
46
|
+
- let(:curse_item) { TextItemToCheck.new("please excuse the use of 'shit' in this description", :description, "description") }
|
|
47
|
+
+ let(:curse_item) { TextItemToCheck.new("please excuse the use of 'oneword' in this description", :description, "description") }
|
|
48
|
+
|
|
49
|
+
it "passes for non-curse item" do
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### Update your App's listing and run pre-check
|
|
53
|
+
|
|
54
|
+
Add your term to your App's description or keywords and run `bundle exec fastlane precheck` to ensure that it fails the check.
|
|
@@ -346,4 +346,5 @@ bc8059fe9118fcf7b2c20a0bf9fdd8111942f2cb4754b45fc0b16916ab679ddb
|
|
|
346
346
|
9f02f229004cc97cbe3e41ad839a73dab5f68d4c296dd64055317cf90dd11a1a
|
|
347
347
|
dab70d211b90bf5e931b5626bc558850752e107daf995bf9e8cb1a08ca7309bf
|
|
348
348
|
4efb200187aa257858d45bc72b8e590bac33db176aba6576cdd6623655a5a74f
|
|
349
|
-
0be9b885f4a35a18f6af6b1ac0acd7fa4b19993999c3fbf66dd1e3e0c4c753c8
|
|
349
|
+
0be9b885f4a35a18f6af6b1ac0acd7fa4b19993999c3fbf66dd1e3e0c4c753c8
|
|
350
|
+
c6603565c5159fbe846a53e991829d452a1546d41150c0d3c73ddbd7f476ee0d
|
|
@@ -111,7 +111,9 @@ module Scan
|
|
|
111
111
|
|
|
112
112
|
def self.default_os_version(os_type)
|
|
113
113
|
@os_versions ||= {}
|
|
114
|
-
@os_versions[os_type]
|
|
114
|
+
return @os_versions[os_type] if @os_versions.key?(os_type)
|
|
115
|
+
|
|
116
|
+
@os_versions[os_type] = begin
|
|
115
117
|
UI.crash!("Unknown platform: #{os_type}") unless PLATFORMS.key?(os_type)
|
|
116
118
|
platform = PLATFORMS[os_type]
|
|
117
119
|
|
|
@@ -128,7 +130,8 @@ module Scan
|
|
|
128
130
|
sdks_output, status = Open3.capture2('xcodebuild -showsdks -json')
|
|
129
131
|
sdk_version = begin
|
|
130
132
|
raise status unless status.success?
|
|
131
|
-
JSON.parse(sdks_output).find { |e| e['platform'] == platform[:simulator] }
|
|
133
|
+
entry = JSON.parse(sdks_output).find { |e| e['platform'] == platform[:simulator] }
|
|
134
|
+
entry['productVersion'] || entry['sdkVersion']
|
|
132
135
|
rescue StandardError => e
|
|
133
136
|
UI.error(e)
|
|
134
137
|
UI.error("xcodebuild CLI broken, please run `xcodebuild` and make sure it works")
|
|
@@ -147,7 +150,12 @@ module Scan
|
|
|
147
150
|
end
|
|
148
151
|
|
|
149
152
|
# Get OS version corresponding to build
|
|
150
|
-
|
|
153
|
+
os_version = FastlaneCore::DeviceManager.runtime_build_os_versions[runtime_build]
|
|
154
|
+
unless os_version
|
|
155
|
+
UI.important("Runtime build '#{runtime_build}' not found in installed runtimes, falling back to SDK version '#{sdk_version}'")
|
|
156
|
+
os_version = sdk_version
|
|
157
|
+
end
|
|
158
|
+
Gem::Version.new(os_version)
|
|
151
159
|
end
|
|
152
160
|
end
|
|
153
161
|
end
|
data/sigh/lib/assets/resign.sh
CHANGED
|
@@ -152,6 +152,7 @@ usage() {
|
|
|
152
152
|
echo -e "\t --use-app-entitlements\t\tExtract app bundle codesigning entitlements and combine with entitlements from new provisioning profile." >&2
|
|
153
153
|
echo -e "\t\t\t\t\t\t\tCan't use together with '-e, --entitlements' option." >&2
|
|
154
154
|
echo -e "\t--keychain-path path\t\t\tSpecify the path to a keychain that /usr/bin/codesign should use." >&2
|
|
155
|
+
echo -e "\t--pagesize size\t\t\t\tSpecify the page size (in bytes) for codesign. Must be a power of two." >&2
|
|
155
156
|
echo -e "\t-v, --verbose\t\t\t\tVerbose output." >&2
|
|
156
157
|
echo -e "\t-h, --help\t\t\t\tDisplay help message." >&2
|
|
157
158
|
exit 2
|
|
@@ -171,11 +172,13 @@ VERSION_NUMBER=""
|
|
|
171
172
|
SHORT_VERSION=
|
|
172
173
|
BUNDLE_VERSION=
|
|
173
174
|
KEYCHAIN_PATH=
|
|
175
|
+
PAGESIZE=
|
|
174
176
|
RAW_PROVISIONS=()
|
|
175
177
|
PROVISIONS_BY_ID=()
|
|
176
178
|
DEFAULT_PROVISION=""
|
|
177
179
|
TEMP_DIR="_floatsignTemp"
|
|
178
180
|
USE_APP_ENTITLEMENTS=""
|
|
181
|
+
VERBOSE=""
|
|
179
182
|
XCODE_VERSION="$(xcodebuild -version | grep "Xcode" | /usr/bin/cut -f 2 -d ' ')"
|
|
180
183
|
|
|
181
184
|
# List of plist keys used for reference to and from nested apps and extensions
|
|
@@ -226,6 +229,10 @@ while [ "$1" != "" ]; do
|
|
|
226
229
|
shift
|
|
227
230
|
KEYCHAIN_PATH="$1"
|
|
228
231
|
;;
|
|
232
|
+
--pagesize )
|
|
233
|
+
shift
|
|
234
|
+
PAGESIZE="$1"
|
|
235
|
+
;;
|
|
229
236
|
-v | --verbose )
|
|
230
237
|
VERBOSE="--verbose"
|
|
231
238
|
;;
|
|
@@ -247,6 +254,11 @@ if [ -n "$KEYCHAIN_PATH" ]; then
|
|
|
247
254
|
KEYCHAIN_FLAG="--keychain $KEYCHAIN_PATH"
|
|
248
255
|
fi
|
|
249
256
|
|
|
257
|
+
PAGESIZE_ARGS=()
|
|
258
|
+
if [ -n "$PAGESIZE" ]; then
|
|
259
|
+
PAGESIZE_ARGS=(--pagesize "$PAGESIZE")
|
|
260
|
+
fi
|
|
261
|
+
|
|
250
262
|
# Log the options
|
|
251
263
|
for provision in "${RAW_PROVISIONS[@]}"; do
|
|
252
264
|
if [[ "$provision" =~ .+=.+ ]]; then
|
|
@@ -266,6 +278,7 @@ log "Certificate: '$CERTIFICATE'"
|
|
|
266
278
|
[[ -n "${SHORT_VERSION}" ]] && log "Specified short version to use: '$SHORT_VERSION'"
|
|
267
279
|
[[ -n "${BUNDLE_VERSION}" ]] && log "Specified bundle version to use: '$BUNDLE_VERSION'"
|
|
268
280
|
[[ -n "${KEYCHAIN_FLAG}" ]] && log "Specified keychain to use: '$KEYCHAIN_PATH'"
|
|
281
|
+
[[ -n "${PAGESIZE}" ]] && log "Specified page size: '$PAGESIZE'"
|
|
269
282
|
[[ -n "${NEW_FILE}" ]] && log "Output file name: '$NEW_FILE'"
|
|
270
283
|
[[ -n "${USE_APP_ENTITLEMENTS}" ]] && log "Extract app entitlements: YES"
|
|
271
284
|
|
|
@@ -549,7 +562,7 @@ function resign {
|
|
|
549
562
|
do
|
|
550
563
|
if [[ "$assetpack" == *.assetpack ]]; then
|
|
551
564
|
rm -rf "$assetpack"/_CodeSignature
|
|
552
|
-
/usr/bin/codesign
|
|
565
|
+
/usr/bin/codesign ${VERBOSE} "${PAGESIZE_ARGS[@]}" --generate-entitlement-der "${KEYCHAIN_FLAG}" -f -s "$CERTIFICATE" "$assetpack"
|
|
553
566
|
checkStatus
|
|
554
567
|
else
|
|
555
568
|
log "Ignoring non-assetpack: $assetpack"
|
|
@@ -571,7 +584,7 @@ function resign {
|
|
|
571
584
|
log "Resigning '$framework'"
|
|
572
585
|
# Must not quote KEYCHAIN_FLAG because it needs to be unwrapped and passed to codesign with spaces
|
|
573
586
|
# shellcheck disable=SC2086
|
|
574
|
-
/usr/bin/codesign ${VERBOSE} --generate-entitlement-der ${KEYCHAIN_FLAG} -f -s "$CERTIFICATE" "$framework"
|
|
587
|
+
/usr/bin/codesign ${VERBOSE} "${PAGESIZE_ARGS[@]}" --generate-entitlement-der ${KEYCHAIN_FLAG} -f -s "$CERTIFICATE" "$framework"
|
|
575
588
|
checkStatus
|
|
576
589
|
else
|
|
577
590
|
log "Ignoring non-framework: $framework"
|
|
@@ -625,7 +638,7 @@ function resign {
|
|
|
625
638
|
log "Creating an archived-expanded-entitlements.xcent file for Xcode 9 builds or earlier"
|
|
626
639
|
cp -f "$ENTITLEMENTS" "$APP_PATH/archived-expanded-entitlements.xcent"
|
|
627
640
|
fi
|
|
628
|
-
/usr/bin/codesign
|
|
641
|
+
/usr/bin/codesign ${VERBOSE} "${PAGESIZE_ARGS[@]}" --generate-entitlement-der -f -s "$CERTIFICATE" --entitlements "$ENTITLEMENTS" "$APP_PATH"
|
|
629
642
|
checkStatus
|
|
630
643
|
elif [[ -n "${USE_APP_ENTITLEMENTS}" ]]; then
|
|
631
644
|
# Extract entitlements from provisioning profile and from the app binary
|
|
@@ -870,7 +883,7 @@ function resign {
|
|
|
870
883
|
log "Creating an archived-expanded-entitlements.xcent file for Xcode 9 builds or earlier"
|
|
871
884
|
cp -f "$PATCHED_ENTITLEMENTS" "$APP_PATH/archived-expanded-entitlements.xcent"
|
|
872
885
|
fi
|
|
873
|
-
/usr/bin/codesign
|
|
886
|
+
/usr/bin/codesign ${VERBOSE} "${PAGESIZE_ARGS[@]}" --generate-entitlement-der -f -s "$CERTIFICATE" --entitlements "$PATCHED_ENTITLEMENTS" "$APP_PATH"
|
|
874
887
|
checkStatus
|
|
875
888
|
else
|
|
876
889
|
log "Extracting entitlements from provisioning profile"
|
|
@@ -884,7 +897,7 @@ function resign {
|
|
|
884
897
|
fi
|
|
885
898
|
# Must not quote KEYCHAIN_FLAG because it needs to be unwrapped and passed to codesign with spaces
|
|
886
899
|
# shellcheck disable=SC2086
|
|
887
|
-
/usr/bin/codesign ${VERBOSE} --generate-entitlement-der ${KEYCHAIN_FLAG} -f -s "$CERTIFICATE" --entitlements "$TEMP_DIR/newEntitlements" "$APP_PATH"
|
|
900
|
+
/usr/bin/codesign ${VERBOSE} "${PAGESIZE_ARGS[@]}" --generate-entitlement-der ${KEYCHAIN_FLAG} -f -s "$CERTIFICATE" --entitlements "$TEMP_DIR/newEntitlements" "$APP_PATH"
|
|
888
901
|
checkStatus
|
|
889
902
|
fi
|
|
890
903
|
|
|
@@ -114,6 +114,7 @@ module Sigh
|
|
|
114
114
|
c.option('--use_app_entitlements', 'Extract app bundle codesigning entitlements and combine with entitlements from new provisioning profile.')
|
|
115
115
|
c.option('-g', '--new_bundle_id STRING', String, 'New application bundle ID (CFBundleIdentifier)')
|
|
116
116
|
c.option('--keychain_path STRING', String, 'Path to the keychain that /usr/bin/codesign should use')
|
|
117
|
+
c.option('--page_size STRING', String, 'Page size in bytes for codesign --pagesize (power of two)')
|
|
117
118
|
|
|
118
119
|
c.action do |args, options|
|
|
119
120
|
Sigh::Resign.new.run(options, args)
|
data/sigh/lib/sigh/manager.rb
CHANGED
|
@@ -4,7 +4,7 @@ require_relative 'runner'
|
|
|
4
4
|
|
|
5
5
|
module Sigh
|
|
6
6
|
class Manager
|
|
7
|
-
def self.start
|
|
7
|
+
def self.start(keychain_path: nil)
|
|
8
8
|
path = Sigh::Runner.new.run
|
|
9
9
|
|
|
10
10
|
return nil unless path
|
|
@@ -23,7 +23,7 @@ module Sigh
|
|
|
23
23
|
# in case it already exists
|
|
24
24
|
end
|
|
25
25
|
|
|
26
|
-
install_profile(output) unless Sigh.config[:skip_install]
|
|
26
|
+
install_profile(output, keychain_path) unless Sigh.config[:skip_install]
|
|
27
27
|
|
|
28
28
|
puts(output.green)
|
|
29
29
|
|
|
@@ -35,13 +35,13 @@ module Sigh
|
|
|
35
35
|
DownloadAll.new.download_all(download_xcode_profiles: download_xcode_profiles)
|
|
36
36
|
end
|
|
37
37
|
|
|
38
|
-
def self.install_profile(profile)
|
|
39
|
-
uuid = FastlaneCore::ProvisioningProfile.uuid(profile)
|
|
40
|
-
name = FastlaneCore::ProvisioningProfile.name(profile)
|
|
38
|
+
def self.install_profile(profile, keychain_path = nil)
|
|
39
|
+
uuid = FastlaneCore::ProvisioningProfile.uuid(profile, keychain_path)
|
|
40
|
+
name = FastlaneCore::ProvisioningProfile.name(profile, keychain_path)
|
|
41
41
|
ENV["SIGH_UDID"] = ENV["SIGH_UUID"] = uuid if uuid
|
|
42
42
|
ENV["SIGH_NAME"] = name if name
|
|
43
43
|
|
|
44
|
-
FastlaneCore::ProvisioningProfile.install(profile)
|
|
44
|
+
FastlaneCore::ProvisioningProfile.install(profile, keychain_path)
|
|
45
45
|
end
|
|
46
46
|
end
|
|
47
47
|
end
|
data/sigh/lib/sigh/resign.rb
CHANGED
|
@@ -8,18 +8,18 @@ module Sigh
|
|
|
8
8
|
class Resign
|
|
9
9
|
def run(options, args)
|
|
10
10
|
# get the command line inputs and parse those into the vars we need...
|
|
11
|
-
ipa, signing_identity, provisioning_profiles, entitlements, version, display_name, short_version, bundle_version, new_bundle_id, use_app_entitlements, keychain_path = get_inputs(options, args)
|
|
11
|
+
ipa, signing_identity, provisioning_profiles, entitlements, version, display_name, short_version, bundle_version, new_bundle_id, use_app_entitlements, keychain_path, page_size = get_inputs(options, args)
|
|
12
12
|
# ... then invoke our programmatic interface with these vars
|
|
13
|
-
unless resign(ipa, signing_identity, provisioning_profiles, entitlements, version, display_name, short_version, bundle_version, new_bundle_id, use_app_entitlements, keychain_path)
|
|
13
|
+
unless resign(ipa, signing_identity, provisioning_profiles, entitlements, version, display_name, short_version, bundle_version, new_bundle_id, use_app_entitlements, keychain_path, page_size)
|
|
14
14
|
UI.user_error!("Failed to re-sign .ipa")
|
|
15
15
|
end
|
|
16
16
|
end
|
|
17
17
|
|
|
18
|
-
def self.resign(ipa, signing_identity, provisioning_profiles, entitlements, version, display_name, short_version, bundle_version, new_bundle_id, use_app_entitlements, keychain_path)
|
|
19
|
-
self.new.resign(ipa, signing_identity, provisioning_profiles, entitlements, version, display_name, short_version, bundle_version, new_bundle_id, use_app_entitlements, keychain_path)
|
|
18
|
+
def self.resign(ipa, signing_identity, provisioning_profiles, entitlements, version, display_name, short_version, bundle_version, new_bundle_id, use_app_entitlements, keychain_path, pagesize = nil)
|
|
19
|
+
self.new.resign(ipa, signing_identity, provisioning_profiles, entitlements, version, display_name, short_version, bundle_version, new_bundle_id, use_app_entitlements, keychain_path, pagesize)
|
|
20
20
|
end
|
|
21
21
|
|
|
22
|
-
def resign(ipa, signing_identity, provisioning_profiles, entitlements, version, display_name, short_version, bundle_version, new_bundle_id, use_app_entitlements, keychain_path)
|
|
22
|
+
def resign(ipa, signing_identity, provisioning_profiles, entitlements, version, display_name, short_version, bundle_version, new_bundle_id, use_app_entitlements, keychain_path, pagesize = nil)
|
|
23
23
|
resign_path = find_resign_path
|
|
24
24
|
|
|
25
25
|
if keychain_path
|
|
@@ -53,6 +53,7 @@ module Sigh
|
|
|
53
53
|
bundle_id = "-b '#{new_bundle_id}'" if new_bundle_id
|
|
54
54
|
use_app_entitlements_flag = "--use-app-entitlements" if use_app_entitlements
|
|
55
55
|
specific_keychain = "--keychain-path #{keychain_path.shellescape}" if keychain_path
|
|
56
|
+
pagesize_option = "--pagesize #{pagesize}" if pagesize
|
|
56
57
|
|
|
57
58
|
command = [
|
|
58
59
|
resign_path.shellescape,
|
|
@@ -68,6 +69,7 @@ module Sigh
|
|
|
68
69
|
verbose,
|
|
69
70
|
bundle_id,
|
|
70
71
|
specific_keychain,
|
|
72
|
+
pagesize_option,
|
|
71
73
|
ipa.shellescape # Output path must always be last argument
|
|
72
74
|
].join(' ')
|
|
73
75
|
|
|
@@ -97,12 +99,13 @@ module Sigh
|
|
|
97
99
|
new_bundle_id = options.new_bundle_id || nil
|
|
98
100
|
use_app_entitlements = options.use_app_entitlements || nil
|
|
99
101
|
keychain_path = options.keychain_path || nil
|
|
102
|
+
page_size = options.page_size || nil
|
|
100
103
|
|
|
101
104
|
if options.provisioning_name
|
|
102
105
|
UI.important("The provisioning_name (-n) option is not applicable to resign. You should use provisioning_profile (-p) instead")
|
|
103
106
|
end
|
|
104
107
|
|
|
105
|
-
return ipa, signing_identity, provisioning_profiles, entitlements, version, display_name, short_version, bundle_version, new_bundle_id, use_app_entitlements, keychain_path
|
|
108
|
+
return ipa, signing_identity, provisioning_profiles, entitlements, version, display_name, short_version, bundle_version, new_bundle_id, use_app_entitlements, keychain_path, page_size
|
|
106
109
|
end
|
|
107
110
|
|
|
108
111
|
def find_resign_path
|
|
@@ -11,35 +11,37 @@ module Spaceship
|
|
|
11
11
|
attr_accessor :app_previews
|
|
12
12
|
|
|
13
13
|
module PreviewType
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
14
|
+
# https://developer.apple.com/documentation/appstoreconnectapi/previewtype
|
|
15
|
+
IPHONE_35 = "IPHONE_35" # not supported anymore
|
|
16
|
+
IPHONE_40 = "IPHONE_40" # 4"
|
|
17
|
+
IPHONE_47 = "IPHONE_47" # 4.7"
|
|
18
|
+
IPHONE_55 = "IPHONE_55" # 5.5"
|
|
19
|
+
IPHONE_58 = "IPHONE_58" # 6.1"
|
|
20
|
+
IPHONE_61 = "IPHONE_61" # 6.3"
|
|
21
|
+
IPHONE_65 = "IPHONE_65" # 6.5"
|
|
22
|
+
IPHONE_67 = "IPHONE_67" # 6.9"
|
|
23
|
+
|
|
24
|
+
IPAD_97 = "IPAD_97" # 9.7"
|
|
25
|
+
IPAD_105 = "IPAD_105" # 10.5"
|
|
26
|
+
IPAD_PRO_129 = "IPAD_PRO_129" # 12.9"
|
|
27
|
+
IPAD_PRO_3GEN_11 = "IPAD_PRO_3GEN_11" # 11"
|
|
28
|
+
IPAD_PRO_3GEN_129 = "IPAD_PRO_3GEN_129" # 13"
|
|
27
29
|
|
|
28
30
|
DESKTOP = "DESKTOP"
|
|
29
31
|
|
|
30
32
|
ALL = [
|
|
31
|
-
IPHONE_35,
|
|
32
33
|
IPHONE_40,
|
|
33
34
|
IPHONE_47,
|
|
34
35
|
IPHONE_55,
|
|
35
36
|
IPHONE_58,
|
|
37
|
+
IPHONE_61,
|
|
36
38
|
IPHONE_65,
|
|
37
39
|
IPHONE_67,
|
|
38
40
|
|
|
39
41
|
IPAD_97,
|
|
40
42
|
IPAD_105,
|
|
41
|
-
IPAD_PRO_3GEN_11,
|
|
42
43
|
IPAD_PRO_129,
|
|
44
|
+
IPAD_PRO_3GEN_11,
|
|
43
45
|
IPAD_PRO_3GEN_129,
|
|
44
46
|
|
|
45
47
|
DESKTOP
|
|
@@ -60,9 +62,9 @@ module Spaceship
|
|
|
60
62
|
# API
|
|
61
63
|
#
|
|
62
64
|
|
|
63
|
-
def self.all(client: nil, filter: {}, includes: nil, limit: nil, sort: nil)
|
|
65
|
+
def self.all(client: nil, app_store_version_localization_id: nil, filter: {}, includes: nil, limit: nil, sort: nil)
|
|
64
66
|
client ||= Spaceship::ConnectAPI
|
|
65
|
-
resp = client.get_app_preview_sets(filter: filter, includes: includes, limit: limit, sort: sort)
|
|
67
|
+
resp = client.get_app_preview_sets(app_store_version_localization_id: app_store_version_localization_id, filter: filter, includes: includes, limit: limit, sort: sort)
|
|
66
68
|
return resp.to_models
|
|
67
69
|
end
|
|
68
70
|
|
|
@@ -106,6 +108,41 @@ module Spaceship
|
|
|
106
108
|
|
|
107
109
|
return client.get_app_preview_set(app_preview_set_id: id, includes: "appPreviews").first
|
|
108
110
|
end
|
|
111
|
+
|
|
112
|
+
# Validate video resolution (portrait canonical sizes) for provided preview_type.
|
|
113
|
+
# Returns true if the resolution matches any accepted pair.
|
|
114
|
+
def self.validate_video_resolution(width, height, preview_type)
|
|
115
|
+
return false unless width && height
|
|
116
|
+
if width > height
|
|
117
|
+
width, height = height, width
|
|
118
|
+
end
|
|
119
|
+
# for a list of valid resolutions, look for "Accepted resolutions" at https://developer.apple.com/help/app-store-connect/reference/app-information/app-preview-specifications
|
|
120
|
+
# resolutions below are sorted by display inch from biggest to smallest (see top of the module)
|
|
121
|
+
canonical = {
|
|
122
|
+
# iPhone
|
|
123
|
+
PreviewType::IPHONE_67 => [[886, 1920]],
|
|
124
|
+
PreviewType::IPHONE_65 => [[886, 1920]],
|
|
125
|
+
PreviewType::IPHONE_61 => [[886, 1920]],
|
|
126
|
+
PreviewType::IPHONE_58 => [[886, 1920]],
|
|
127
|
+
PreviewType::IPHONE_55 => [[1080, 1920]],
|
|
128
|
+
PreviewType::IPHONE_47 => [[750, 1334]],
|
|
129
|
+
PreviewType::IPHONE_40 => [[1080, 1920]],
|
|
130
|
+
|
|
131
|
+
# iPad
|
|
132
|
+
PreviewType::IPAD_PRO_3GEN_129 => [[1200, 1600]],
|
|
133
|
+
PreviewType::IPAD_PRO_3GEN_11 => [[1200, 1600]],
|
|
134
|
+
PreviewType::IPAD_PRO_129 => [[1200, 1600], [900, 1200]],
|
|
135
|
+
PreviewType::IPAD_105 => [[1200, 1600]],
|
|
136
|
+
PreviewType::IPAD_97 => [[900, 1200]],
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
pairs = canonical[preview_type] || []
|
|
140
|
+
pairs.any? { |(canon_width, canon_height)| width == canon_width && height == canon_height }
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def self.preview_type_from_filename(name, preview_types = PreviewType::ALL)
|
|
144
|
+
preview_types.find { |type| name.to_s.upcase.include?(type) }
|
|
145
|
+
end
|
|
109
146
|
end
|
|
110
147
|
end
|
|
111
148
|
end
|
|
@@ -78,8 +78,7 @@ module Spaceship
|
|
|
78
78
|
def get_app_preview_sets(client: nil, filter: {}, includes: "appPreviews", limit: nil, sort: nil)
|
|
79
79
|
client ||= Spaceship::ConnectAPI
|
|
80
80
|
filter ||= {}
|
|
81
|
-
filter
|
|
82
|
-
return Spaceship::ConnectAPI::AppPreviewSet.all(client: client, filter: filter, includes: includes, limit: limit, sort: sort)
|
|
81
|
+
return Spaceship::ConnectAPI::AppPreviewSet.all(client: client, app_store_version_localization_id: id, filter: filter, includes: includes, limit: limit, sort: sort)
|
|
83
82
|
rescue => error
|
|
84
83
|
raise Spaceship::AppStoreAppPreviewError.new(@locale, error)
|
|
85
84
|
end
|
|
@@ -367,9 +367,9 @@ module Spaceship
|
|
|
367
367
|
# appPreviewSets
|
|
368
368
|
#
|
|
369
369
|
|
|
370
|
-
def get_app_preview_sets(filter: {}, includes: nil, limit: nil, sort: nil)
|
|
370
|
+
def get_app_preview_sets(app_store_version_localization_id: nil, filter: {}, includes: nil, limit: nil, sort: nil)
|
|
371
371
|
params = tunes_request_client.build_params(filter: filter, includes: includes, limit: limit, sort: sort)
|
|
372
|
-
tunes_request_client.get("#{Version::V1}/appPreviewSets", params)
|
|
372
|
+
tunes_request_client.get("#{Version::V1}/appStoreVersionLocalizations/#{app_store_version_localization_id}/appPreviewSets", params)
|
|
373
373
|
end
|
|
374
374
|
|
|
375
375
|
def get_app_preview_set(app_preview_set_id: nil, filter: {}, includes: nil, limit: nil, sort: nil)
|
|
@@ -502,26 +502,7 @@ module Trainer
|
|
|
502
502
|
|
|
503
503
|
# Remove retry attempts from the count and test rows
|
|
504
504
|
if output_remove_retry_attempts
|
|
505
|
-
test_rows = test_rows
|
|
506
|
-
remove = false
|
|
507
|
-
|
|
508
|
-
identifier = test_row[:identifier]
|
|
509
|
-
info = tests_by_identifier[identifier]
|
|
510
|
-
|
|
511
|
-
# Remove if this row is a retry and is a failure
|
|
512
|
-
if info[:retry_count] > 0
|
|
513
|
-
remove = !(test_row[:failures] || []).empty?
|
|
514
|
-
end
|
|
515
|
-
|
|
516
|
-
# Remove all failure and retry count if test did eventually pass
|
|
517
|
-
if remove
|
|
518
|
-
info[:failure_count] -= 1
|
|
519
|
-
info[:retry_count] -= 1
|
|
520
|
-
tests_by_identifier[identifier] = info
|
|
521
|
-
end
|
|
522
|
-
|
|
523
|
-
remove
|
|
524
|
-
end
|
|
505
|
+
test_rows, tests_by_identifier = remove_retry_attempts(test_rows, tests_by_identifier)
|
|
525
506
|
end
|
|
526
507
|
|
|
527
508
|
row = {
|
|
@@ -549,6 +530,32 @@ module Trainer
|
|
|
549
530
|
rows
|
|
550
531
|
end
|
|
551
532
|
|
|
533
|
+
def remove_retry_attempts(test_rows, tests_by_identifier)
|
|
534
|
+
# Group test rows by identifier and keep only the last one for each identifier
|
|
535
|
+
test_rows_by_identifier = test_rows.group_by { |row| row[:identifier] }
|
|
536
|
+
|
|
537
|
+
# Update counts for removed retry attempts
|
|
538
|
+
test_rows_by_identifier.each do |identifier, rows|
|
|
539
|
+
rows_to_remove = rows[0...-1]
|
|
540
|
+
|
|
541
|
+
info = tests_by_identifier[identifier]
|
|
542
|
+
rows_to_remove.each do |row|
|
|
543
|
+
if !(row[:failures] || []).empty?
|
|
544
|
+
info[:failure_count] -= 1
|
|
545
|
+
elsif row[:skipped] == true
|
|
546
|
+
info[:skip_count] -= 1
|
|
547
|
+
end
|
|
548
|
+
info[:retry_count] -= 1
|
|
549
|
+
end
|
|
550
|
+
tests_by_identifier[identifier] = info
|
|
551
|
+
end
|
|
552
|
+
|
|
553
|
+
# Keep only the last row for each identifier
|
|
554
|
+
filtered_test_rows = test_rows_by_identifier.values.map(&:last)
|
|
555
|
+
|
|
556
|
+
[filtered_test_rows, tests_by_identifier]
|
|
557
|
+
end
|
|
558
|
+
|
|
552
559
|
def test_summaries_to_configuration_names(test_summaries)
|
|
553
560
|
summary_to_name = {}
|
|
554
561
|
test_summaries.each do |summary|
|
|
@@ -106,7 +106,10 @@ module Trainer
|
|
|
106
106
|
# Add test cases
|
|
107
107
|
@test_cases.each do |test_case|
|
|
108
108
|
runs = test_case.to_xml_nodes
|
|
109
|
-
|
|
109
|
+
# Remove retry attempts: keep only the final run (whether it passes, fails, or is skipped)
|
|
110
|
+
if output_remove_retry_attempts
|
|
111
|
+
runs = runs.last(1)
|
|
112
|
+
end
|
|
110
113
|
runs.each { |node| testsuite.add_element(node) }
|
|
111
114
|
end
|
|
112
115
|
|