fastlane 2.213.0 → 2.215.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 +94 -94
- data/deliver/lib/deliver/app_screenshot.rb +13 -10
- data/deliver/lib/deliver/submit_for_review.rb +13 -0
- data/deliver/lib/deliver/upload_price_tier.rb +1 -1
- data/fastlane/lib/assets/custom_action_template.rb +18 -12
- 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 +6 -4
- data/fastlane/lib/fastlane/actions/docs/upload_to_testflight.md +1 -1
- data/fastlane/lib/fastlane/actions/download_universal_apk_from_google_play.rb +124 -0
- data/fastlane/lib/fastlane/actions/ensure_xcode_version.rb +4 -0
- data/fastlane/lib/fastlane/helper/xcodes_helper.rb +0 -3
- 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/version.rb +2 -2
- data/fastlane/swift/Deliverfile.swift +1 -1
- data/fastlane/swift/DeliverfileProtocol.swift +1 -1
- data/fastlane/swift/Fastlane.swift +79 -4
- 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 +5 -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 +28 -18
- data/fastlane_core/lib/fastlane_core/cert_checker.rb +1 -1
- data/frameit/lib/frameit/device_types.rb +1 -1
- data/gym/lib/gym/generators/build_command_generator.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 +7 -0
- data/match/lib/match/runner.rb +5 -32
- data/match/lib/match/setup.rb +1 -1
- data/match/lib/match/storage/gitlab/client.rb +40 -14
- data/match/lib/match/storage/gitlab_secure_files.rb +7 -2
- data/match/lib/match/storage/s3_storage.rb +6 -0
- data/match/lib/match/storage.rb +56 -5
- data/scan/lib/scan/test_command_generator.rb +1 -1
- data/snapshot/lib/snapshot/test_command_generator.rb +1 -1
- data/spaceship/lib/spaceship/client.rb +0 -1
- data/spaceship/lib/spaceship/connect_api/api_client.rb +19 -1
- 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 +5 -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/user.rb +38 -0
- data/spaceship/lib/spaceship/connect_api/models/user_invitation.rb +5 -15
- data/spaceship/lib/spaceship/connect_api/testflight/testflight.rb +8 -2
- data/spaceship/lib/spaceship/connect_api/users/users.rb +34 -0
- data/supply/lib/supply/client.rb +72 -20
- data/supply/lib/supply/generated_universal_apk.rb +24 -0
- 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 +32 -5
- data/supply/lib/supply.rb +2 -0
- metadata +285 -274
@@ -2,45 +2,55 @@
|
|
2
2
|
"entries": {
|
3
3
|
"brew": {
|
4
4
|
"swiftformat": {
|
5
|
-
"version": "0.
|
5
|
+
"version": "0.52.3",
|
6
6
|
"bottle": {
|
7
7
|
"rebuild": 0,
|
8
8
|
"root_url": "https://ghcr.io/v2/homebrew/core",
|
9
9
|
"files": {
|
10
|
+
"arm64_sonoma": {
|
11
|
+
"cellar": ":any_skip_relocation",
|
12
|
+
"url": "https://ghcr.io/v2/homebrew/core/swiftformat/blobs/sha256:a5ea23d7a08c20b20981a23f1ebc3221ca5796408934c412c2518598e00eb50f",
|
13
|
+
"sha256": "a5ea23d7a08c20b20981a23f1ebc3221ca5796408934c412c2518598e00eb50f"
|
14
|
+
},
|
10
15
|
"arm64_ventura": {
|
11
16
|
"cellar": ":any_skip_relocation",
|
12
|
-
"url": "https://ghcr.io/v2/homebrew/core/swiftformat/blobs/sha256:
|
13
|
-
"sha256": "
|
17
|
+
"url": "https://ghcr.io/v2/homebrew/core/swiftformat/blobs/sha256:4c60e18bc44c0781d97a96c536aa8bb6e762b79008927c5e7307dcf2c69b6058",
|
18
|
+
"sha256": "4c60e18bc44c0781d97a96c536aa8bb6e762b79008927c5e7307dcf2c69b6058"
|
14
19
|
},
|
15
20
|
"arm64_monterey": {
|
16
21
|
"cellar": ":any_skip_relocation",
|
17
|
-
"url": "https://ghcr.io/v2/homebrew/core/swiftformat/blobs/sha256:
|
18
|
-
"sha256": "
|
22
|
+
"url": "https://ghcr.io/v2/homebrew/core/swiftformat/blobs/sha256:d63d1affcfba1ea8b6bf035d4abd834bf2effe0c0cf385ba608f98341da1c837",
|
23
|
+
"sha256": "d63d1affcfba1ea8b6bf035d4abd834bf2effe0c0cf385ba608f98341da1c837"
|
19
24
|
},
|
20
25
|
"arm64_big_sur": {
|
21
26
|
"cellar": ":any_skip_relocation",
|
22
|
-
"url": "https://ghcr.io/v2/homebrew/core/swiftformat/blobs/sha256:
|
23
|
-
"sha256": "
|
27
|
+
"url": "https://ghcr.io/v2/homebrew/core/swiftformat/blobs/sha256:d80ec81a9140159181b77145d2dfdcd38488b23b262ef1bd74ab7163d0cbebae",
|
28
|
+
"sha256": "d80ec81a9140159181b77145d2dfdcd38488b23b262ef1bd74ab7163d0cbebae"
|
29
|
+
},
|
30
|
+
"sonoma": {
|
31
|
+
"cellar": ":any_skip_relocation",
|
32
|
+
"url": "https://ghcr.io/v2/homebrew/core/swiftformat/blobs/sha256:1aa6efde9ecda9e98c1b852192e0230b2e84055861382660e93c50e59a80487f",
|
33
|
+
"sha256": "1aa6efde9ecda9e98c1b852192e0230b2e84055861382660e93c50e59a80487f"
|
24
34
|
},
|
25
35
|
"ventura": {
|
26
36
|
"cellar": ":any_skip_relocation",
|
27
|
-
"url": "https://ghcr.io/v2/homebrew/core/swiftformat/blobs/sha256:
|
28
|
-
"sha256": "
|
37
|
+
"url": "https://ghcr.io/v2/homebrew/core/swiftformat/blobs/sha256:274da364741558f1f52780e9a92354db212a803cf5d84c2ca9ff632d94ada47d",
|
38
|
+
"sha256": "274da364741558f1f52780e9a92354db212a803cf5d84c2ca9ff632d94ada47d"
|
29
39
|
},
|
30
40
|
"monterey": {
|
31
41
|
"cellar": ":any_skip_relocation",
|
32
|
-
"url": "https://ghcr.io/v2/homebrew/core/swiftformat/blobs/sha256:
|
33
|
-
"sha256": "
|
42
|
+
"url": "https://ghcr.io/v2/homebrew/core/swiftformat/blobs/sha256:b53d82e6f2d42bf1e6fa799983fdfae934b483bc916c34436184fcb7e407f896",
|
43
|
+
"sha256": "b53d82e6f2d42bf1e6fa799983fdfae934b483bc916c34436184fcb7e407f896"
|
34
44
|
},
|
35
45
|
"big_sur": {
|
36
46
|
"cellar": ":any_skip_relocation",
|
37
|
-
"url": "https://ghcr.io/v2/homebrew/core/swiftformat/blobs/sha256:
|
38
|
-
"sha256": "
|
47
|
+
"url": "https://ghcr.io/v2/homebrew/core/swiftformat/blobs/sha256:9bd117c9e2f92bde0f59a4106748a56e57687a1716627ef601e63b15a383ea35",
|
48
|
+
"sha256": "9bd117c9e2f92bde0f59a4106748a56e57687a1716627ef601e63b15a383ea35"
|
39
49
|
},
|
40
50
|
"x86_64_linux": {
|
41
51
|
"cellar": "/home/linuxbrew/.linuxbrew/Cellar",
|
42
|
-
"url": "https://ghcr.io/v2/homebrew/core/swiftformat/blobs/sha256:
|
43
|
-
"sha256": "
|
52
|
+
"url": "https://ghcr.io/v2/homebrew/core/swiftformat/blobs/sha256:384fee82f88b4bf8b30cfe9cec946ebd9127a4741b28e06cec42fc0d9b70c0f6",
|
53
|
+
"sha256": "384fee82f88b4bf8b30cfe9cec946ebd9127a4741b28e06cec42fc0d9b70c0f6"
|
44
54
|
}
|
45
55
|
}
|
46
56
|
}
|
@@ -74,12 +84,12 @@
|
|
74
84
|
"macOS": "12.5"
|
75
85
|
},
|
76
86
|
"ventura": {
|
77
|
-
"HOMEBREW_VERSION": "4.
|
87
|
+
"HOMEBREW_VERSION": "4.1.11-36-g184efd9",
|
78
88
|
"HOMEBREW_PREFIX": "/opt/homebrew",
|
79
89
|
"Homebrew/homebrew-core": "api",
|
80
90
|
"CLT": "",
|
81
|
-
"Xcode": "14.
|
82
|
-
"macOS": "13.
|
91
|
+
"Xcode": "14.3",
|
92
|
+
"macOS": "13.4"
|
83
93
|
}
|
84
94
|
}
|
85
95
|
}
|
@@ -146,7 +146,7 @@ module FastlaneCore
|
|
146
146
|
|
147
147
|
def self.install_wwdr_certificate(cert_alias)
|
148
148
|
url = WWDRCA_CERTIFICATES.find { |c| c[:alias] == cert_alias }.fetch(:url)
|
149
|
-
file = Tempfile.new(File.basename(url))
|
149
|
+
file = Tempfile.new([File.basename(url, ".cer"), ".cer"])
|
150
150
|
filename = file.path
|
151
151
|
keychain = wwdr_keychain
|
152
152
|
keychain = "-k #{keychain.shellescape}" unless keychain.empty?
|
@@ -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)
|
@@ -80,7 +80,7 @@ module Gym
|
|
80
80
|
if Gym.config[:disable_xcpretty] || formatter == ''
|
81
81
|
UI.verbose("Not using an xcodebuild formatter")
|
82
82
|
elsif !options.empty?
|
83
|
-
UI.important("Detected legacy xcpretty being used so formatting
|
83
|
+
UI.important("Detected legacy xcpretty being used, so formatting with xcpretty")
|
84
84
|
UI.important("Option(s) used: #{options.join(', ')}")
|
85
85
|
pipe += pipe_xcpretty
|
86
86
|
elsif formatter == 'xcpretty'
|
@@ -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,
|
@@ -349,4 +355,5 @@ module Match
|
|
349
355
|
]
|
350
356
|
end
|
351
357
|
end
|
358
|
+
# rubocop:enable Metrics/ClassLength
|
352
359
|
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
|
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?
|
@@ -40,6 +40,8 @@ module Match
|
|
40
40
|
def files
|
41
41
|
@files ||= begin
|
42
42
|
url = URI.parse(base_url)
|
43
|
+
# 100 is maximum number of Secure files available on Gitlab https://docs.gitlab.com/ee/api/secure_files.html
|
44
|
+
url.query = [url.query, "per_page=100"].compact.join('&')
|
43
45
|
|
44
46
|
request = Net::HTTP::Get.new(url.request_uri)
|
45
47
|
|
@@ -69,32 +71,56 @@ module Match
|
|
69
71
|
"name" => target_file
|
70
72
|
)
|
71
73
|
|
72
|
-
|
74
|
+
execute_request(url, request, target_file)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def execute_request(url, request, target_file = nil)
|
79
|
+
request[authentication_key] = authentication_value
|
80
|
+
|
81
|
+
http = Net::HTTP.new(url.host, url.port)
|
82
|
+
http.use_ssl = url.instance_of?(URI::HTTPS)
|
83
|
+
|
84
|
+
begin
|
85
|
+
response = http.request(request)
|
86
|
+
rescue Errno::ECONNREFUSED, SocketError => message
|
87
|
+
UI.user_error!("GitLab connection error: #{message}")
|
88
|
+
end
|
73
89
|
|
74
|
-
|
90
|
+
unless response.kind_of?(Net::HTTPSuccess)
|
91
|
+
handle_response_error(response, target_file)
|
75
92
|
end
|
93
|
+
|
94
|
+
response
|
76
95
|
end
|
77
96
|
|
78
|
-
def
|
97
|
+
def handle_response_error(response, target_file = nil)
|
98
|
+
error_prefix = "GitLab storage error:"
|
99
|
+
file_debug_string = "File: #{target_file}" unless target_file.nil?
|
100
|
+
api_debug_string = "API: #{@api_v4_url}"
|
101
|
+
debug_info = "(#{[file_debug_string, api_debug_string].compact.join(', ')})"
|
102
|
+
|
79
103
|
begin
|
80
|
-
|
104
|
+
parsed = JSON.parse(response.body)
|
81
105
|
rescue JSON::ParserError
|
82
|
-
response_body = response.body
|
83
106
|
end
|
84
107
|
|
85
|
-
if
|
86
|
-
|
108
|
+
if parsed && parsed["message"] && (parsed["message"]["name"] == ["has already been taken"])
|
109
|
+
error_handler = :error
|
110
|
+
error = "#{target_file} already exists in GitLab project #{@project_id}, file not uploaded"
|
87
111
|
else
|
88
|
-
|
112
|
+
error_handler = :user_error!
|
113
|
+
error = "#{response.code}: #{response.body}"
|
89
114
|
end
|
90
|
-
|
115
|
+
error_message = [error_prefix, error, debug_info].join(' ')
|
91
116
|
|
92
|
-
|
93
|
-
|
117
|
+
UI.send(error_handler, error_message)
|
118
|
+
end
|
94
119
|
|
95
|
-
|
96
|
-
|
97
|
-
|
120
|
+
def prompt_for_access_token
|
121
|
+
unless authentication_key
|
122
|
+
@private_token = UI.input("Please supply a GitLab personal or project access token: ")
|
123
|
+
end
|
98
124
|
end
|
99
125
|
end
|
100
126
|
end
|
@@ -47,7 +47,8 @@ module Match
|
|
47
47
|
team_id: params[:team_id],
|
48
48
|
team_name: params[:team_name],
|
49
49
|
api_key_path: params[:api_key_path],
|
50
|
-
api_key: params[:api_key]
|
50
|
+
api_key: params[:api_key],
|
51
|
+
gitlab_host: params[:gitlab_host]
|
51
52
|
)
|
52
53
|
end
|
53
54
|
|
@@ -60,7 +61,8 @@ module Match
|
|
60
61
|
team_id: nil,
|
61
62
|
team_name: nil,
|
62
63
|
api_key_path: nil,
|
63
|
-
api_key: nil
|
64
|
+
api_key: nil,
|
65
|
+
gitlab_host: nil)
|
64
66
|
|
65
67
|
@readonly = readonly
|
66
68
|
@username = username
|
@@ -68,6 +70,7 @@ module Match
|
|
68
70
|
@team_name = team_name
|
69
71
|
@api_key_path = api_key_path
|
70
72
|
@api_key = api_key
|
73
|
+
@gitlab_host = gitlab_host
|
71
74
|
|
72
75
|
@job_token = job_token
|
73
76
|
@private_token = private_token
|
@@ -95,6 +98,8 @@ module Match
|
|
95
98
|
end
|
96
99
|
|
97
100
|
def download
|
101
|
+
gitlab_client.prompt_for_access_token
|
102
|
+
|
98
103
|
# Check if we already have a functional working_directory
|
99
104
|
return if @working_directory
|
100
105
|
|
@@ -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
|
|
@@ -132,7 +132,7 @@ module Scan
|
|
132
132
|
if formatter == ''
|
133
133
|
UI.verbose("Not using an xcodebuild formatter")
|
134
134
|
elsif !options.empty?
|
135
|
-
UI.important("Detected legacy xcpretty being used so formatting
|
135
|
+
UI.important("Detected legacy xcpretty being used, so formatting with xcpretty")
|
136
136
|
UI.important("Option(s) used: #{options.join(', ')}")
|
137
137
|
pipe << pipe_xcpretty
|
138
138
|
elsif formatter == 'xcpretty'
|
@@ -34,7 +34,7 @@ module Snapshot
|
|
34
34
|
if Snapshot.config[:disable_xcpretty] || formatter == ''
|
35
35
|
UI.verbose("Not using an xcodebuild formatter")
|
36
36
|
elsif !options.empty?
|
37
|
-
UI.important("Detected legacy xcpretty being used so formatting
|
37
|
+
UI.important("Detected legacy xcpretty being used, so formatting with xcpretty")
|
38
38
|
UI.important("Option(s) used: #{options.join(', ')}")
|
39
39
|
pipe += pipe_xcpretty
|
40
40
|
elsif formatter == 'xcpretty'
|