fastlane 2.214.0 → 2.217.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 +98 -98
- data/deliver/lib/deliver/app_screenshot.rb +20 -10
- data/deliver/lib/deliver/runner.rb +2 -1
- data/deliver/lib/deliver/submit_for_review.rb +13 -0
- data/deliver/lib/deliver/upload_metadata.rb +58 -13
- data/fastlane/lib/fastlane/actions/docs/build_app.md +2 -2
- data/fastlane/lib/fastlane/actions/docs/capture_android_screenshots.md +8 -8
- data/fastlane/lib/fastlane/actions/docs/check_app_store_metadata.md +3 -3
- data/fastlane/lib/fastlane/actions/docs/get_push_certificate.md +2 -2
- data/fastlane/lib/fastlane/actions/docs/sync_code_signing.md +1 -1
- data/fastlane/lib/fastlane/actions/docs/upload_to_app_store.md.erb +1 -1
- data/fastlane/lib/fastlane/actions/docs/upload_to_play_store.md +6 -2
- data/fastlane/lib/fastlane/actions/docs/upload_to_testflight.md +1 -1
- data/fastlane/lib/fastlane/actions/download_universal_apk_from_google_play.rb +1 -1
- data/fastlane/lib/fastlane/actions/ensure_xcode_version.rb +4 -0
- data/fastlane/lib/fastlane/actions/git_branch.rb +1 -1
- data/fastlane/lib/fastlane/actions/install_on_device.rb +1 -1
- data/fastlane/lib/fastlane/actions/nexus_upload.rb +1 -0
- data/fastlane/lib/fastlane/actions/notarize.rb +17 -2
- data/fastlane/lib/fastlane/actions/slather.rb +17 -4
- data/fastlane/lib/fastlane/helper/git_helper.rb +3 -0
- data/fastlane/lib/fastlane/helper/xcodes_helper.rb +0 -3
- data/fastlane/lib/fastlane/lane.rb +9 -1
- data/fastlane/lib/fastlane/new_action.rb +1 -1
- data/fastlane/lib/fastlane/plugins/plugin_info_collector.rb +3 -3
- data/fastlane/lib/fastlane/plugins/template/%gem_name%.gemspec.erb +1 -2
- data/fastlane/lib/fastlane/plugins/template/.rubocop.yml +5 -1
- data/fastlane/lib/fastlane/plugins/template/lib/fastlane/plugin/%plugin_name%/helper/%plugin_name%_helper.rb.erb +1 -1
- data/fastlane/lib/fastlane/runner.rb +1 -1
- data/fastlane/lib/fastlane/version.rb +2 -2
- data/fastlane/swift/Deliverfile.swift +1 -1
- data/fastlane/swift/DeliverfileProtocol.swift +1 -1
- data/fastlane/swift/Fastlane.swift +67 -7
- 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 +17 -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/swift/formatting/Brewfile.lock.json +22 -22
- data/fastlane_core/lib/fastlane_core/cert_checker.rb +2 -2
- data/fastlane_core/lib/fastlane_core/project.rb +4 -0
- data/fastlane_core/lib/fastlane_core/queue_worker.rb +1 -1
- data/frameit/lib/frameit/device_types.rb +1 -1
- data/gym/lib/gym/module.rb +13 -2
- data/gym/lib/gym/options.rb +1 -1
- data/match/lib/match/change_password.rb +3 -9
- data/match/lib/match/commands_generator.rb +3 -6
- data/match/lib/match/encryption.rb +1 -1
- data/match/lib/match/importer.rb +3 -31
- data/match/lib/match/migrate.rb +6 -2
- data/match/lib/match/nuke.rb +3 -25
- data/match/lib/match/options.rb +20 -0
- data/match/lib/match/runner.rb +16 -37
- data/match/lib/match/setup.rb +1 -1
- data/match/lib/match/storage/git_storage.rb +9 -1
- data/match/lib/match/storage/s3_storage.rb +6 -0
- data/match/lib/match/storage.rb +56 -5
- data/precheck/lib/precheck/rules/unreachable_urls_rule.rb +1 -1
- data/snapshot/lib/assets/SnapshotHelper.swift +13 -9
- data/snapshot/lib/snapshot/reports_generator.rb +48 -7
- data/spaceship/lib/spaceship/connect_api/api_client.rb +21 -2
- data/spaceship/lib/spaceship/connect_api/models/app.rb +3 -2
- data/spaceship/lib/spaceship/connect_api/models/app_info.rb +15 -9
- data/spaceship/lib/spaceship/connect_api/models/app_screenshot_set.rb +7 -0
- data/spaceship/lib/spaceship/connect_api/models/app_store_version.rb +1 -0
- data/spaceship/lib/spaceship/connect_api/models/beta_group.rb +3 -1
- data/spaceship/lib/spaceship/connect_api/models/bundle_id.rb +4 -4
- data/spaceship/lib/spaceship/connect_api/models/certificate.rb +2 -2
- data/spaceship/lib/spaceship/connect_api/models/device.rb +2 -2
- data/spaceship/lib/spaceship/connect_api/models/profile.rb +3 -2
- data/spaceship/lib/spaceship/connect_api/provisioning/provisioning.rb +14 -8
- data/spaceship/lib/spaceship/connect_api/testflight/testflight.rb +8 -2
- data/spaceship/lib/spaceship/connect_api/tunes/tunes.rb +0 -3
- data/supply/lib/supply/client.rb +47 -21
- data/supply/lib/supply/image_listing.rb +15 -0
- data/supply/lib/supply/options.rb +5 -0
- data/supply/lib/supply/setup.rb +1 -1
- data/supply/lib/supply/uploader.rb +60 -18
- data/supply/lib/supply.rb +1 -0
- data/trainer/lib/trainer/xcresult.rb +1 -1
- metadata +282 -273
@@ -6,7 +6,7 @@ module FastlaneCore
|
|
6
6
|
# Use this when you have all the items that you'll process in advance.
|
7
7
|
# Simply enqueue them to this and call `QueueWorker#start`.
|
8
8
|
class QueueWorker
|
9
|
-
NUMBER_OF_THREADS = FastlaneCore::Helper.test? ? 1 : [
|
9
|
+
NUMBER_OF_THREADS = FastlaneCore::Helper.test? ? 1 : [ENV["DELIVER_NUMBER_OF_THREADS"], ENV["FL_NUMBER_OF_THREADS"], 10].map(&:to_i).find(&:positive?).clamp(1, ENV.fetch("FL_MAX_NUMBER_OF_THREADS", 10).to_i)
|
10
10
|
|
11
11
|
# @param concurrency (Numeric) - A number of threads to be created
|
12
12
|
# @param block (Proc) - A task you want to execute with enqueued items
|
@@ -120,7 +120,7 @@ module Frameit
|
|
120
120
|
IPHONE_8_PLUS ||= Frameit::Device.new("iphone-8-plus", "Apple iPhone 8 Plus", 6, [[1242, 2208], [2208, 1242]], 401, Color::SPACE_GRAY)
|
121
121
|
IPHONE_X ||= Frameit::Device.new("iphone-X", "Apple iPhone X", 7, [[1125, 2436], [2436, 1125]], 458, Color::SPACE_GRAY, Platform::IOS, Deliver::AppScreenshot::ScreenSize::IOS_58, :use_legacy_iphonex)
|
122
122
|
IPHONE_XS ||= Frameit::Device.new("iphone-XS", "Apple iPhone XS", 8, [[1125, 2436], [2436, 1125]], 458, Color::SPACE_GRAY, Platform::IOS, Deliver::AppScreenshot::ScreenSize::IOS_58, :use_legacy_iphonexs)
|
123
|
-
IPHONE_XR ||= Frameit::Device.new("iphone-XR", "Apple iPhone XR", 8, [[828, 1792], [1792, 828]], 326, Color::SPACE_GRAY, Platform::IOS, Deliver::AppScreenshot::ScreenSize::
|
123
|
+
IPHONE_XR ||= Frameit::Device.new("iphone-XR", "Apple iPhone XR", 8, [[828, 1792], [1792, 828]], 326, Color::SPACE_GRAY, Platform::IOS, Deliver::AppScreenshot::ScreenSize::IOS_65, :use_legacy_iphonexsmax)
|
124
124
|
IPHONE_XS_MAX ||= Frameit::Device.new("iphone-XS-Max", "Apple iPhone XS Max", 8, [[1242, 2688], [2688, 1242]], 458, Color::SPACE_GRAY, Platform::IOS, Deliver::AppScreenshot::ScreenSize::IOS_65, :use_legacy_iphonexsmax)
|
125
125
|
IPHONE_11 ||= Frameit::Device.new("iphone-11", "Apple iPhone 11", 9, [[828, 1792], [1792, 828]], 326, Color::BLACK, Platform::IOS)
|
126
126
|
IPHONE_11_PRO ||= Frameit::Device.new("iphone-11-pro", "Apple iPhone 11 Pro", 9, [[1125, 2436], [2436, 1125]], 458, Color::SPACE_GRAY, Platform::IOS)
|
data/gym/lib/gym/module.rb
CHANGED
@@ -27,8 +27,8 @@ module Gym
|
|
27
27
|
|
28
28
|
def building_for_ios?
|
29
29
|
if Gym.project.mac?
|
30
|
-
# Can be building for iOS if mac project and catalyst
|
31
|
-
return building_mac_catalyst_for_ios?
|
30
|
+
# Can be building for iOS if mac project and catalyst or multiplatform and set to iOS
|
31
|
+
return building_mac_catalyst_for_ios? || building_multiplatform_for_ios?
|
32
32
|
else
|
33
33
|
# Can be iOS project and build for mac if catalyst
|
34
34
|
return false if building_mac_catalyst_for_mac?
|
@@ -43,6 +43,9 @@ module Gym
|
|
43
43
|
# Can be a mac project and not build mac if catalyst
|
44
44
|
return building_mac_catalyst_for_mac?
|
45
45
|
else
|
46
|
+
# Can be mac project but multiplatform and building for iOS
|
47
|
+
return false if building_multiplatform_for_ios?
|
48
|
+
|
46
49
|
return Gym.project.mac?
|
47
50
|
end
|
48
51
|
end
|
@@ -55,6 +58,14 @@ module Gym
|
|
55
58
|
Gym.project.supports_mac_catalyst? && Gym.config[:catalyst_platform] == "macos"
|
56
59
|
end
|
57
60
|
|
61
|
+
def building_multiplatform_for_ios?
|
62
|
+
Gym.project.multiplatform? && Gym.project.ios? && (Gym.config[:sdk] == "iphoneos" || Gym.config[:sdk] == "iphonesimulator")
|
63
|
+
end
|
64
|
+
|
65
|
+
def building_multiplatform_for_mac?
|
66
|
+
Gym.project.multiplatform? && Gym.project.mac? && Gym.config[:sdk] == "macosx"
|
67
|
+
end
|
68
|
+
|
58
69
|
def export_destination_upload?
|
59
70
|
config_path = Gym.cache[:config_path]
|
60
71
|
return false if config_path.nil?
|
data/gym/lib/gym/options.rb
CHANGED
@@ -152,7 +152,7 @@ module Gym
|
|
152
152
|
optional: true,
|
153
153
|
verify_block: proc do |value|
|
154
154
|
av = %w(ios macos)
|
155
|
-
UI.user_error!("Unsupported
|
155
|
+
UI.user_error!("Unsupported catalyst_platform '#{value}', must be: #{av}") unless av.include?(value)
|
156
156
|
end),
|
157
157
|
FastlaneCore::ConfigItem.new(key: :installer_cert_name,
|
158
158
|
env_name: "GYM_INSTALLER_CERT_NAME",
|
@@ -19,19 +19,13 @@ module Match
|
|
19
19
|
new_password = FastlaneCore::Helper.ask_password(message: "New passphrase for Git Repo: ", confirm: true)
|
20
20
|
|
21
21
|
# Choose the right storage and encryption implementations
|
22
|
-
storage = Storage.
|
23
|
-
git_url: params[:git_url],
|
24
|
-
shallow_clone: params[:shallow_clone],
|
25
|
-
skip_docs: params[:skip_docs],
|
26
|
-
git_branch: params[:git_branch],
|
27
|
-
git_full_name: params[:git_full_name],
|
28
|
-
git_user_email: params[:git_user_email],
|
29
|
-
clone_branch_directly: params[:clone_branch_directly]
|
30
|
-
})
|
22
|
+
storage = Storage.from_params(params)
|
31
23
|
storage.download
|
32
24
|
|
33
25
|
encryption = Encryption.for_storage_mode(params[:storage_mode], {
|
34
26
|
git_url: params[:git_url],
|
27
|
+
s3_bucket: params[:s3_bucket],
|
28
|
+
s3_skip_encryption: params[:s3_skip_encryption],
|
35
29
|
working_directory: storage.working_directory
|
36
30
|
})
|
37
31
|
encryption.decrypt_files
|
@@ -118,16 +118,13 @@ module Match
|
|
118
118
|
params = FastlaneCore::Configuration.create(Match::Options.available_options, options.__hash__)
|
119
119
|
params.load_configuration_file("Matchfile")
|
120
120
|
|
121
|
-
storage = Storage.
|
122
|
-
git_url: params[:git_url],
|
123
|
-
shallow_clone: params[:shallow_clone],
|
124
|
-
git_branch: params[:git_branch],
|
125
|
-
clone_branch_directly: params[:clone_branch_directly]
|
126
|
-
})
|
121
|
+
storage = Storage.from_params(params)
|
127
122
|
storage.download
|
128
123
|
|
129
124
|
encryption = Encryption.for_storage_mode(params[:storage_mode], {
|
130
125
|
git_url: params[:git_url],
|
126
|
+
s3_bucket: params[:s3_bucket],
|
127
|
+
s3_skip_encryption: params[:s3_skip_encryption],
|
131
128
|
working_directory: storage.working_directory
|
132
129
|
})
|
133
130
|
encryption.decrypt_files if encryption
|
@@ -17,7 +17,7 @@ module Match
|
|
17
17
|
},
|
18
18
|
"s3" => lambda { |params|
|
19
19
|
params[:keychain_name] = params[:s3_bucket]
|
20
|
-
return Encryption::OpenSSL.configure(params)
|
20
|
+
return params[:s3_skip_encryption] ? nil : Encryption::OpenSSL.configure(params)
|
21
21
|
},
|
22
22
|
"gitlab_secure_files" => lambda { |params|
|
23
23
|
return nil
|
data/match/lib/match/importer.rb
CHANGED
@@ -15,42 +15,14 @@ module Match
|
|
15
15
|
profile_path = ensure_valid_file_path(profile_path, "Provisioning profile", ".mobileprovision or .provisionprofile", optional: true)
|
16
16
|
|
17
17
|
# Storage
|
18
|
-
storage = Storage.
|
19
|
-
git_url: params[:git_url],
|
20
|
-
shallow_clone: params[:shallow_clone],
|
21
|
-
skip_docs: params[:skip_docs],
|
22
|
-
git_branch: params[:git_branch],
|
23
|
-
git_full_name: params[:git_full_name],
|
24
|
-
git_user_email: params[:git_user_email],
|
25
|
-
git_private_key: params[:git_private_key],
|
26
|
-
git_basic_authorization: params[:git_basic_authorization],
|
27
|
-
git_bearer_authorization: params[:git_bearer_authorization],
|
28
|
-
clone_branch_directly: params[:clone_branch_directly],
|
29
|
-
type: params[:type].to_s,
|
30
|
-
platform: params[:platform].to_s,
|
31
|
-
google_cloud_bucket_name: params[:google_cloud_bucket_name].to_s,
|
32
|
-
google_cloud_keys_file: params[:google_cloud_keys_file].to_s,
|
33
|
-
google_cloud_project_id: params[:google_cloud_project_id].to_s,
|
34
|
-
skip_google_cloud_account_confirmation: params[:skip_google_cloud_account_confirmation],
|
35
|
-
s3_bucket: params[:s3_bucket],
|
36
|
-
s3_region: params[:s3_region],
|
37
|
-
s3_access_key: params[:s3_access_key],
|
38
|
-
s3_secret_access_key: params[:s3_secret_access_key],
|
39
|
-
s3_object_prefix: params[:s3_object_prefix],
|
40
|
-
gitlab_project: params[:gitlab_project],
|
41
|
-
gitlab_host: params[:gitlab_host],
|
42
|
-
readonly: params[:readonly],
|
43
|
-
username: params[:username],
|
44
|
-
team_id: params[:team_id],
|
45
|
-
team_name: params[:team_name],
|
46
|
-
api_key_path: params[:api_key_path],
|
47
|
-
api_key: params[:api_key]
|
48
|
-
})
|
18
|
+
storage = Storage.from_params(params)
|
49
19
|
storage.download
|
50
20
|
|
51
21
|
# Encryption
|
52
22
|
encryption = Encryption.for_storage_mode(params[:storage_mode], {
|
53
23
|
git_url: params[:git_url],
|
24
|
+
s3_bucket: params[:s3_bucket],
|
25
|
+
s3_skip_encryption: params[:s3_skip_encryption],
|
54
26
|
working_directory: storage.working_directory
|
55
27
|
})
|
56
28
|
encryption.decrypt_files if encryption
|
data/match/lib/match/migrate.rb
CHANGED
@@ -13,13 +13,15 @@ module Match
|
|
13
13
|
|
14
14
|
# We init the Google storage client before the git client
|
15
15
|
# to ask for all the missing inputs *before* cloning the git repo
|
16
|
-
google_cloud_storage = Storage.
|
16
|
+
google_cloud_storage = Storage.from_params({
|
17
|
+
storage_mode: "google_cloud",
|
17
18
|
google_cloud_bucket_name: params[:google_cloud_bucket_name],
|
18
19
|
google_cloud_keys_file: params[:google_cloud_keys_file],
|
19
20
|
google_cloud_project_id: params[:google_cloud_project_id]
|
20
21
|
})
|
21
22
|
|
22
|
-
git_storage = Storage.
|
23
|
+
git_storage = Storage.from_params({
|
24
|
+
storage_mode: "git",
|
23
25
|
git_url: params[:git_url],
|
24
26
|
shallow_clone: params[:shallow_clone],
|
25
27
|
git_branch: params[:git_branch],
|
@@ -29,6 +31,8 @@ module Match
|
|
29
31
|
|
30
32
|
encryption = Encryption.for_storage_mode(params[:storage_mode], {
|
31
33
|
git_url: params[:git_url],
|
34
|
+
s3_bucket: params[:s3_bucket],
|
35
|
+
s3_skip_encryption: params[:s3_skip_encryption],
|
32
36
|
working_directory: git_storage.working_directory
|
33
37
|
})
|
34
38
|
encryption.decrypt_files if encryption
|
data/match/lib/match/nuke.rb
CHANGED
@@ -34,36 +34,14 @@ module Match
|
|
34
34
|
|
35
35
|
spaceship_login
|
36
36
|
|
37
|
-
self.storage = Storage.
|
38
|
-
git_url: params[:git_url],
|
39
|
-
shallow_clone: params[:shallow_clone],
|
40
|
-
skip_docs: params[:skip_docs],
|
41
|
-
git_branch: params[:git_branch],
|
42
|
-
git_full_name: params[:git_full_name],
|
43
|
-
git_user_email: params[:git_user_email],
|
44
|
-
|
45
|
-
git_private_key: params[:git_private_key],
|
46
|
-
git_basic_authorization: params[:git_basic_authorization],
|
47
|
-
git_bearer_authorization: params[:git_bearer_authorization],
|
48
|
-
|
49
|
-
clone_branch_directly: params[:clone_branch_directly],
|
50
|
-
google_cloud_bucket_name: params[:google_cloud_bucket_name].to_s,
|
51
|
-
google_cloud_keys_file: params[:google_cloud_keys_file].to_s,
|
52
|
-
google_cloud_project_id: params[:google_cloud_project_id].to_s,
|
53
|
-
s3_region: params[:s3_region].to_s,
|
54
|
-
s3_access_key: params[:s3_access_key].to_s,
|
55
|
-
s3_secret_access_key: params[:s3_secret_access_key].to_s,
|
56
|
-
s3_bucket: params[:s3_bucket].to_s,
|
57
|
-
s3_object_prefix: params[:s3_object_prefix].to_s,
|
58
|
-
gitlab_project: params[:gitlab_project],
|
59
|
-
gitlab_host: params[:gitlab_host],
|
60
|
-
team_id: params[:team_id] || Spaceship::ConnectAPI.client.portal_team_id
|
61
|
-
})
|
37
|
+
self.storage = Storage.from_params(params)
|
62
38
|
self.storage.download
|
63
39
|
|
64
40
|
# After the download was complete
|
65
41
|
self.encryption = Encryption.for_storage_mode(params[:storage_mode], {
|
66
42
|
git_url: params[:git_url],
|
43
|
+
s3_bucket: params[:s3_bucket],
|
44
|
+
s3_skip_encryption: params[:s3_skip_encryption],
|
67
45
|
working_directory: storage.working_directory
|
68
46
|
})
|
69
47
|
self.encryption.decrypt_files if self.encryption
|
data/match/lib/match/options.rb
CHANGED
@@ -4,6 +4,7 @@ require 'credentials_manager/appfile_config'
|
|
4
4
|
require_relative 'module'
|
5
5
|
|
6
6
|
module Match
|
7
|
+
# rubocop:disable Metrics/ClassLength
|
7
8
|
class Options
|
8
9
|
# This is match specific, as users can append storage specific options
|
9
10
|
def self.append_option(option)
|
@@ -222,6 +223,11 @@ module Match
|
|
222
223
|
env_name: "MATCH_S3_OBJECT_PREFIX",
|
223
224
|
description: "Prefix to be used on all objects uploaded to S3",
|
224
225
|
optional: true),
|
226
|
+
FastlaneCore::ConfigItem.new(key: :s3_skip_encryption,
|
227
|
+
env_name: "MATCH_S3_SKIP_ENCRYPTION",
|
228
|
+
description: "Skip encryption of all objects uploaded to S3. WARNING: only enable this on S3 buckets with sufficiently restricted permissions and server-side encryption enabled. See https://docs.aws.amazon.com/AmazonS3/latest/userguide/UsingEncryption.html",
|
229
|
+
type: Boolean,
|
230
|
+
default_value: false),
|
225
231
|
|
226
232
|
# Storage: GitLab Secure Files
|
227
233
|
FastlaneCore::ConfigItem.new(key: :gitlab_project,
|
@@ -233,6 +239,14 @@ module Match
|
|
233
239
|
default_value: 'https://gitlab.com',
|
234
240
|
description: "GitLab Host (i.e. 'https://gitlab.com')",
|
235
241
|
optional: true),
|
242
|
+
FastlaneCore::ConfigItem.new(key: :job_token,
|
243
|
+
env_name: "CI_JOB_TOKEN",
|
244
|
+
description: "GitLab CI_JOB_TOKEN",
|
245
|
+
optional: true),
|
246
|
+
FastlaneCore::ConfigItem.new(key: :private_token,
|
247
|
+
env_name: "PRIVATE_TOKEN",
|
248
|
+
description: "GitLab Access Token",
|
249
|
+
optional: true),
|
236
250
|
|
237
251
|
# Keychain
|
238
252
|
FastlaneCore::ConfigItem.new(key: :keychain_name,
|
@@ -268,6 +282,11 @@ module Match
|
|
268
282
|
description: "Include all matching certificates in the provisioning profile. Works only for the 'development' provisioning profile type",
|
269
283
|
type: Boolean,
|
270
284
|
default_value: false),
|
285
|
+
FastlaneCore::ConfigItem.new(key: :certificate_id,
|
286
|
+
env_name: "MATCH_CERTIFICATE_ID",
|
287
|
+
description: "Select certificate by id. Useful if multiple certificates are stored in one place",
|
288
|
+
type: String,
|
289
|
+
optional: true),
|
271
290
|
FastlaneCore::ConfigItem.new(key: :force_for_new_certificates,
|
272
291
|
env_name: "MATCH_FORCE_FOR_NEW_CERTIFICATES",
|
273
292
|
description: "Renew the provisioning profiles if the certificate count on the developer portal has changed. Works only for the 'development' provisioning profile type. Requires 'include_all_certificates' option to be 'true'",
|
@@ -349,4 +368,5 @@ module Match
|
|
349
368
|
]
|
350
369
|
end
|
351
370
|
end
|
371
|
+
# rubocop:enable Metrics/ClassLength
|
352
372
|
end
|
data/match/lib/match/runner.rb
CHANGED
@@ -31,43 +31,16 @@ module Match
|
|
31
31
|
update_optional_values_depending_on_storage_type(params)
|
32
32
|
|
33
33
|
# Choose the right storage and encryption implementations
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
skip_docs: params[:skip_docs],
|
38
|
-
git_branch: params[:git_branch],
|
39
|
-
git_full_name: params[:git_full_name],
|
40
|
-
git_user_email: params[:git_user_email],
|
41
|
-
clone_branch_directly: params[:clone_branch_directly],
|
42
|
-
git_basic_authorization: params[:git_basic_authorization],
|
43
|
-
git_bearer_authorization: params[:git_bearer_authorization],
|
44
|
-
git_private_key: params[:git_private_key],
|
45
|
-
type: params[:type].to_s,
|
46
|
-
generate_apple_certs: params[:generate_apple_certs],
|
47
|
-
platform: params[:platform].to_s,
|
48
|
-
google_cloud_bucket_name: params[:google_cloud_bucket_name].to_s,
|
49
|
-
google_cloud_keys_file: params[:google_cloud_keys_file].to_s,
|
50
|
-
google_cloud_project_id: params[:google_cloud_project_id].to_s,
|
51
|
-
skip_google_cloud_account_confirmation: params[:skip_google_cloud_account_confirmation],
|
52
|
-
s3_region: params[:s3_region],
|
53
|
-
s3_access_key: params[:s3_access_key],
|
54
|
-
s3_secret_access_key: params[:s3_secret_access_key],
|
55
|
-
s3_bucket: params[:s3_bucket],
|
56
|
-
s3_object_prefix: params[:s3_object_prefix],
|
57
|
-
gitlab_project: params[:gitlab_project],
|
58
|
-
gitlab_host: params[:gitlab_host],
|
59
|
-
readonly: params[:readonly],
|
60
|
-
username: params[:readonly] ? nil : params[:username], # only pass username if not readonly
|
61
|
-
team_id: params[:team_id],
|
62
|
-
team_name: params[:team_name],
|
63
|
-
api_key_path: params[:api_key_path],
|
64
|
-
api_key: params[:api_key]
|
65
|
-
})
|
34
|
+
storage_params = params
|
35
|
+
storage_params[:username] = params[:readonly] ? nil : params[:username] # only pass username if not readonly
|
36
|
+
self.storage = Storage.from_params(storage_params)
|
66
37
|
storage.download
|
67
38
|
|
68
39
|
# Init the encryption only after the `storage.download` was called to have the right working directory
|
69
40
|
encryption = Encryption.for_storage_mode(params[:storage_mode], {
|
70
41
|
git_url: params[:git_url],
|
42
|
+
s3_bucket: params[:s3_bucket],
|
43
|
+
s3_skip_encryption: params[:s3_skip_encryption],
|
71
44
|
working_directory: storage.working_directory
|
72
45
|
})
|
73
46
|
encryption.decrypt_files if encryption
|
@@ -175,7 +148,7 @@ module Match
|
|
175
148
|
self.files_to_commit << cert_path
|
176
149
|
self.files_to_commit << private_key_path
|
177
150
|
else
|
178
|
-
cert_path = certs
|
151
|
+
cert_path = select_cert_or_key(paths: certs)
|
179
152
|
|
180
153
|
# Check validity of certificate
|
181
154
|
if Utils.is_cert_valid?(cert_path)
|
@@ -199,7 +172,7 @@ module Match
|
|
199
172
|
# Import the private key
|
200
173
|
# there seems to be no good way to check if it's already installed - so just install it
|
201
174
|
# Key will only be added to the partition list if it isn't already installed
|
202
|
-
Utils.import(keys
|
175
|
+
Utils.import(select_cert_or_key(paths: keys), params[:keychain_name], password: params[:keychain_password])
|
203
176
|
end
|
204
177
|
else
|
205
178
|
UI.message("Skipping installation of certificate as it would not work on this operating system.")
|
@@ -207,7 +180,7 @@ module Match
|
|
207
180
|
|
208
181
|
if params[:output_path]
|
209
182
|
FileUtils.cp(cert_path, params[:output_path])
|
210
|
-
FileUtils.cp(keys
|
183
|
+
FileUtils.cp(select_cert_or_key(paths: keys), params[:output_path])
|
211
184
|
end
|
212
185
|
|
213
186
|
# Get and print info of certificate
|
@@ -218,6 +191,12 @@ module Match
|
|
218
191
|
return File.basename(cert_path).gsub(".cer", "") # Certificate ID
|
219
192
|
end
|
220
193
|
|
194
|
+
# @return [String] Path to certificate or P12 key
|
195
|
+
def select_cert_or_key(paths:)
|
196
|
+
cert_id_path = ENV['MATCH_CERTIFICATE_ID'] ? paths.find { |path| path.include?(ENV['MATCH_CERTIFICATE_ID']) } : nil
|
197
|
+
cert_id_path || paths.last
|
198
|
+
end
|
199
|
+
|
221
200
|
# rubocop:disable Metrics/PerceivedComplexity
|
222
201
|
# @return [String] The UUID of the provisioning profile so we can verify it with the Apple Developer Portal
|
223
202
|
def fetch_provisioning_profile(params: nil, certificate_id: nil, app_identifier: nil, working_directory: nil)
|
@@ -358,7 +337,7 @@ module Match
|
|
358
337
|
portal_profile = all_profiles.detect { |i| i.uuid == uuid }
|
359
338
|
|
360
339
|
if portal_profile
|
361
|
-
profile_device_count = portal_profile.
|
340
|
+
profile_device_count = portal_profile.devices.count
|
362
341
|
|
363
342
|
device_classes =
|
364
343
|
case platform
|
@@ -439,7 +418,7 @@ module Match
|
|
439
418
|
# * For portal certificates, we filter out the expired one but includes a new certificate;
|
440
419
|
# * Profile still contains an expired certificate and is valid.
|
441
420
|
# Thus, we need to check the validity of profile certificates too.
|
442
|
-
profile_certs_count = portal_profile.
|
421
|
+
profile_certs_count = portal_profile.certificates.select(&:valid?).count
|
443
422
|
|
444
423
|
certificate_types =
|
445
424
|
case platform
|
data/match/lib/match/setup.rb
CHANGED
@@ -15,7 +15,7 @@ module Match
|
|
15
15
|
self.storage_options
|
16
16
|
)
|
17
17
|
|
18
|
-
storage = Storage.
|
18
|
+
storage = Storage.from_params({ storage_mode: storage_mode })
|
19
19
|
|
20
20
|
specific_content = storage.generate_matchfile_content
|
21
21
|
UI.crash!("Looks like `generate_matchfile_content` was `nil` for `#{storage_mode}`") if specific_content.nil?
|
@@ -59,12 +59,20 @@ module Match
|
|
59
59
|
self.clone_branch_directly = clone_branch_directly
|
60
60
|
self.git_basic_authorization = git_basic_authorization
|
61
61
|
self.git_bearer_authorization = git_bearer_authorization
|
62
|
-
self.git_private_key = git_private_key
|
62
|
+
self.git_private_key = convert_private_key_path_to_absolute(git_private_key)
|
63
63
|
|
64
64
|
self.type = type if type
|
65
65
|
self.platform = platform if platform
|
66
66
|
end
|
67
67
|
|
68
|
+
def convert_private_key_path_to_absolute(git_private_key)
|
69
|
+
if !git_private_key.nil? && File.file?(File.expand_path(git_private_key))
|
70
|
+
File.expand_path(git_private_key).shellescape.to_s
|
71
|
+
else
|
72
|
+
git_private_key
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
68
76
|
def prefixed_working_directory
|
69
77
|
return working_directory
|
70
78
|
end
|
@@ -102,6 +102,12 @@ module Match
|
|
102
102
|
self.working_directory = Dir.mktmpdir
|
103
103
|
|
104
104
|
s3_client.find_bucket!(s3_bucket).objects(prefix: s3_object_prefix).each do |object|
|
105
|
+
|
106
|
+
# Prevent download if the file path is a directory.
|
107
|
+
# We need to check if string ends with "/" instead of using `File.directory?` because
|
108
|
+
# the string represent a remote location, not a local file in disk.
|
109
|
+
next if object.key.end_with?("/")
|
110
|
+
|
105
111
|
file_path = strip_s3_object_prefix(object.key) # :s3_object_prefix:team_id/path/to/file
|
106
112
|
|
107
113
|
# strip s3_prefix from file_path
|
data/match/lib/match/storage.rb
CHANGED
@@ -10,16 +10,66 @@ module Match
|
|
10
10
|
def backends
|
11
11
|
@backends ||= {
|
12
12
|
"git" => lambda { |params|
|
13
|
-
return Storage::GitStorage.configure(
|
13
|
+
return Storage::GitStorage.configure({
|
14
|
+
type: params[:type],
|
15
|
+
platform: params[:platform],
|
16
|
+
git_url: params[:git_url],
|
17
|
+
shallow_clone: params[:shallow_clone],
|
18
|
+
skip_docs: params[:skip_docs],
|
19
|
+
git_branch: params[:git_branch],
|
20
|
+
git_full_name: params[:git_full_name],
|
21
|
+
git_user_email: params[:git_user_email],
|
22
|
+
clone_branch_directly: params[:clone_branch_directly],
|
23
|
+
git_basic_authorization: params[:git_basic_authorization],
|
24
|
+
git_bearer_authorization: params[:git_bearer_authorization],
|
25
|
+
git_private_key: params[:git_private_key]
|
26
|
+
})
|
14
27
|
},
|
15
28
|
"google_cloud" => lambda { |params|
|
16
|
-
return Storage::GoogleCloudStorage.configure(
|
29
|
+
return Storage::GoogleCloudStorage.configure({
|
30
|
+
type: params[:type],
|
31
|
+
platform: params[:platform],
|
32
|
+
google_cloud_bucket_name: params[:google_cloud_bucket_name],
|
33
|
+
google_cloud_keys_file: params[:google_cloud_keys_file],
|
34
|
+
google_cloud_project_id: params[:google_cloud_project_id],
|
35
|
+
readonly: params[:readonly],
|
36
|
+
username: params[:username],
|
37
|
+
team_id: params[:team_id],
|
38
|
+
team_name: params[:team_name],
|
39
|
+
api_key_path: params[:api_key_path],
|
40
|
+
api_key: params[:api_key],
|
41
|
+
skip_google_cloud_account_confirmation: params[:skip_google_cloud_account_confirmation]
|
42
|
+
})
|
17
43
|
},
|
18
44
|
"s3" => lambda { |params|
|
19
|
-
return Storage::S3Storage.configure(
|
45
|
+
return Storage::S3Storage.configure({
|
46
|
+
s3_region: params[:s3_region],
|
47
|
+
s3_access_key: params[:s3_access_key],
|
48
|
+
s3_secret_access_key: params[:s3_secret_access_key],
|
49
|
+
s3_bucket: params[:s3_bucket],
|
50
|
+
s3_object_prefix: params[:s3_object_prefix],
|
51
|
+
readonly: params[:readonly],
|
52
|
+
username: params[:username],
|
53
|
+
team_id: params[:team_id],
|
54
|
+
team_name: params[:team_name],
|
55
|
+
api_key_path: params[:api_key_path],
|
56
|
+
api_key: params[:api_key]
|
57
|
+
})
|
20
58
|
},
|
21
59
|
"gitlab_secure_files" => lambda { |params|
|
22
|
-
return Storage::GitLabSecureFiles.configure(
|
60
|
+
return Storage::GitLabSecureFiles.configure({
|
61
|
+
gitlab_host: params[:gitlab_host],
|
62
|
+
gitlab_project: params[:gitlab_project],
|
63
|
+
git_url: params[:git_url], # enables warning about unnecessary git_url
|
64
|
+
job_token: params[:job_token],
|
65
|
+
private_token: params[:private_token],
|
66
|
+
readonly: params[:readonly],
|
67
|
+
username: params[:username],
|
68
|
+
team_id: params[:team_id],
|
69
|
+
team_name: params[:team_name],
|
70
|
+
api_key_path: params[:api_key_path],
|
71
|
+
api_key: params[:api_key]
|
72
|
+
})
|
23
73
|
}
|
24
74
|
}
|
25
75
|
end
|
@@ -39,7 +89,8 @@ module Match
|
|
39
89
|
end
|
40
90
|
end
|
41
91
|
|
42
|
-
def
|
92
|
+
def from_params(params)
|
93
|
+
storage_mode = params[:storage_mode]
|
43
94
|
configurator = backends[storage_mode.to_s]
|
44
95
|
return configurator.call(params) if configurator
|
45
96
|
|
@@ -33,7 +33,7 @@ module Precheck
|
|
33
33
|
connection.use(FaradayMiddleware::FollowRedirects)
|
34
34
|
connection.adapter(:net_http)
|
35
35
|
end
|
36
|
-
return RuleReturn.new(validation_state: Precheck::VALIDATION_STATES[:failed], failure_data: url) unless request.head.status == 200
|
36
|
+
return RuleReturn.new(validation_state: Precheck::VALIDATION_STATES[:failed], failure_data: "HTTP #{request.head.status}: #{url}") unless request.head.status == 200
|
37
37
|
rescue StandardError => e
|
38
38
|
UI.verbose("URL #{url} not reachable 😵: #{e.message}")
|
39
39
|
# I can only return :fail here, but I also want to return #{url}
|
@@ -15,13 +15,12 @@
|
|
15
15
|
import Foundation
|
16
16
|
import XCTest
|
17
17
|
|
18
|
-
|
19
|
-
var locale = ""
|
20
|
-
|
18
|
+
@MainActor
|
21
19
|
func setupSnapshot(_ app: XCUIApplication, waitForAnimations: Bool = true) {
|
22
20
|
Snapshot.setupSnapshot(app, waitForAnimations: waitForAnimations)
|
23
21
|
}
|
24
22
|
|
23
|
+
@MainActor
|
25
24
|
func snapshot(_ name: String, waitForLoadingIndicator: Bool) {
|
26
25
|
if waitForLoadingIndicator {
|
27
26
|
Snapshot.snapshot(name)
|
@@ -33,6 +32,7 @@ func snapshot(_ name: String, waitForLoadingIndicator: Bool) {
|
|
33
32
|
/// - Parameters:
|
34
33
|
/// - name: The name of the snapshot
|
35
34
|
/// - timeout: Amount of seconds to wait until the network loading indicator disappears. Pass `0` if you don't want to wait.
|
35
|
+
@MainActor
|
36
36
|
func snapshot(_ name: String, timeWaitingForIdle timeout: TimeInterval = 20) {
|
37
37
|
Snapshot.snapshot(name, timeWaitingForIdle: timeout)
|
38
38
|
}
|
@@ -52,6 +52,7 @@ enum SnapshotError: Error, CustomDebugStringConvertible {
|
|
52
52
|
}
|
53
53
|
|
54
54
|
@objcMembers
|
55
|
+
@MainActor
|
55
56
|
open class Snapshot: NSObject {
|
56
57
|
static var app: XCUIApplication?
|
57
58
|
static var waitForAnimations = true
|
@@ -59,6 +60,8 @@ open class Snapshot: NSObject {
|
|
59
60
|
static var screenshotsDirectory: URL? {
|
60
61
|
return cacheDirectory?.appendingPathComponent("screenshots", isDirectory: true)
|
61
62
|
}
|
63
|
+
static var deviceLanguage = ""
|
64
|
+
static var currentLocale = ""
|
62
65
|
|
63
66
|
open class func setupSnapshot(_ app: XCUIApplication, waitForAnimations: Bool = true) {
|
64
67
|
|
@@ -103,17 +106,17 @@ open class Snapshot: NSObject {
|
|
103
106
|
|
104
107
|
do {
|
105
108
|
let trimCharacterSet = CharacterSet.whitespacesAndNewlines
|
106
|
-
|
109
|
+
currentLocale = try String(contentsOf: path, encoding: .utf8).trimmingCharacters(in: trimCharacterSet)
|
107
110
|
} catch {
|
108
111
|
NSLog("Couldn't detect/set locale...")
|
109
112
|
}
|
110
113
|
|
111
|
-
if
|
112
|
-
|
114
|
+
if currentLocale.isEmpty && !deviceLanguage.isEmpty {
|
115
|
+
currentLocale = Locale(identifier: deviceLanguage).identifier
|
113
116
|
}
|
114
117
|
|
115
|
-
if !
|
116
|
-
app.launchArguments += ["-AppleLocale", "\"\(
|
118
|
+
if !currentLocale.isEmpty {
|
119
|
+
app.launchArguments += ["-AppleLocale", "\"\(currentLocale)\""]
|
117
120
|
}
|
118
121
|
}
|
119
122
|
|
@@ -281,6 +284,7 @@ private extension XCUIElementQuery {
|
|
281
284
|
return self.containing(isNetworkLoadingIndicator)
|
282
285
|
}
|
283
286
|
|
287
|
+
@MainActor
|
284
288
|
var deviceStatusBars: XCUIElementQuery {
|
285
289
|
guard let app = Snapshot.app else {
|
286
290
|
fatalError("XCUIApplication is not set. Please call setupSnapshot(app) before snapshot().")
|
@@ -306,4 +310,4 @@ private extension CGFloat {
|
|
306
310
|
|
307
311
|
// Please don't remove the lines below
|
308
312
|
// They are used to detect outdated configuration files
|
309
|
-
// SnapshotHelperVersion [1.
|
313
|
+
// SnapshotHelperVersion [1.30]
|