fastlane 2.109.1 → 2.110.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 +66 -66
- data/deliver/lib/deliver/.options.rb.swp +0 -0
- data/fastlane/lib/fastlane/actions/download.rb +1 -0
- data/fastlane/lib/fastlane/actions/install_on_device.rb +2 -2
- data/fastlane/lib/fastlane/actions/resign.rb +5 -17
- data/fastlane/lib/fastlane/helper/adb_helper.rb +1 -1
- data/fastlane/lib/fastlane/swift_fastlane_api_generator.rb +3 -3
- data/fastlane/lib/fastlane/version.rb +1 -1
- data/fastlane/swift/Deliverfile.swift +1 -1
- data/fastlane/swift/Fastlane.swift +73 -65
- data/fastlane/swift/Gymfile.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/Scanfile.swift +1 -1
- data/fastlane/swift/ScanfileProtocol.swift +29 -29
- data/fastlane/swift/Screengrabfile.swift +1 -1
- data/fastlane/swift/Snapshotfile.swift +1 -1
- data/fastlane_core/lib/fastlane_core/itunes_transporter.rb +18 -16
- data/frameit/lib/frameit/options.rb +1 -1
- data/match/lib/match.rb +1 -0
- data/match/lib/match/change_password.rb +7 -0
- data/match/lib/match/commands_generator.rb +15 -2
- data/match/lib/match/encryption.rb +3 -0
- data/match/lib/match/encryption/openssl.rb +2 -2
- data/match/lib/match/migrate.rb +97 -0
- data/match/lib/match/module.rb +1 -1
- data/match/lib/match/nuke.rb +22 -6
- data/match/lib/match/options.rb +19 -1
- data/match/lib/match/runner.rb +58 -15
- data/match/lib/match/spaceship_ensure.rb +6 -1
- data/match/lib/match/storage.rb +4 -0
- data/match/lib/match/storage/git_storage.rb +1 -10
- data/match/lib/match/storage/google_cloud_storage.rb +227 -0
- data/match/lib/match/storage/interface.rb +9 -3
- data/scan/lib/scan/options.rb +105 -86
- data/spaceship/README.md +20 -42
- metadata +38 -17
- data/fastlane_core/lib/fastlane_core/configuration/.config_item.rb.swp +0 -0
- data/pilot/lib/pilot/.options.rb.swp +0 -0
@@ -21,6 +21,8 @@ protocol MatchfileProtocol: class {
|
|
21
21
|
var skipDocs: Bool { get }
|
22
22
|
var platform: String { get }
|
23
23
|
var templateName: String? { get }
|
24
|
+
var googleCloudBucketName: String? { get }
|
25
|
+
var googleCloudKeysFile: String? { get }
|
24
26
|
}
|
25
27
|
|
26
28
|
extension MatchfileProtocol {
|
@@ -46,8 +48,10 @@ extension MatchfileProtocol {
|
|
46
48
|
var skipDocs: Bool { return false }
|
47
49
|
var platform: String { return "ios" }
|
48
50
|
var templateName: String? { return nil }
|
51
|
+
var googleCloudBucketName: String? { return nil }
|
52
|
+
var googleCloudKeysFile: String? { return nil }
|
49
53
|
}
|
50
54
|
|
51
55
|
// Please don't remove the lines below
|
52
56
|
// They are used to detect outdated files
|
53
|
-
// FastlaneRunnerAPIVersion [0.9.
|
57
|
+
// FastlaneRunnerAPIVersion [0.9.3]
|
@@ -1,16 +1,21 @@
|
|
1
1
|
protocol ScanfileProtocol: class {
|
2
2
|
var workspace: String? { get }
|
3
3
|
var project: String? { get }
|
4
|
+
var scheme: String? { get }
|
4
5
|
var device: String? { get }
|
5
|
-
var toolchain: String? { get }
|
6
6
|
var devices: [String]? { get }
|
7
7
|
var skipDetectDevices: Bool { get }
|
8
|
-
var
|
8
|
+
var reinstallApp: Bool { get }
|
9
|
+
var appIdentifier: String? { get }
|
10
|
+
var onlyTesting: String? { get }
|
11
|
+
var skipTesting: String? { get }
|
12
|
+
var xctestrun: String? { get }
|
13
|
+
var toolchain: String? { get }
|
9
14
|
var clean: Bool { get }
|
10
15
|
var codeCoverage: Bool? { get }
|
11
16
|
var addressSanitizer: Bool? { get }
|
12
17
|
var threadSanitizer: Bool? { get }
|
13
|
-
var
|
18
|
+
var openReport: Bool { get }
|
14
19
|
var outputDirectory: String { get }
|
15
20
|
var outputStyle: String? { get }
|
16
21
|
var outputTypes: String { get }
|
@@ -20,47 +25,47 @@ protocol ScanfileProtocol: class {
|
|
20
25
|
var suppressXcodeOutput: String? { get }
|
21
26
|
var formatter: String? { get }
|
22
27
|
var xcprettyArgs: String? { get }
|
28
|
+
var derivedDataPath: String? { get }
|
29
|
+
var shouldZipBuildProducts: Bool { get }
|
30
|
+
var resultBundle: Bool { get }
|
31
|
+
var useClangReportName: Bool { get }
|
23
32
|
var maxConcurrentSimulators: Int? { get }
|
24
33
|
var disableConcurrentTesting: Bool { get }
|
34
|
+
var skipBuild: Bool { get }
|
25
35
|
var testWithoutBuilding: Bool? { get }
|
26
36
|
var buildForTesting: Bool? { get }
|
27
|
-
var xctestrun: String? { get }
|
28
|
-
var derivedDataPath: String? { get }
|
29
|
-
var shouldZipBuildProducts: Bool { get }
|
30
|
-
var resultBundle: Bool { get }
|
31
37
|
var sdk: String? { get }
|
32
|
-
var openReport: Bool { get }
|
33
38
|
var configuration: String? { get }
|
34
|
-
var destination: String? { get }
|
35
39
|
var xcargs: String? { get }
|
36
40
|
var xcconfig: String? { get }
|
37
|
-
var onlyTesting: String? { get }
|
38
|
-
var skipTesting: String? { get }
|
39
41
|
var slackUrl: String? { get }
|
40
42
|
var slackChannel: String? { get }
|
41
43
|
var slackMessage: String? { get }
|
42
44
|
var skipSlack: Bool { get }
|
43
45
|
var slackOnlyOnFailure: Bool { get }
|
44
|
-
var
|
46
|
+
var destination: String? { get }
|
45
47
|
var customReportFileName: String? { get }
|
46
|
-
var appIdentifier: String? { get }
|
47
|
-
var reinstallApp: Bool { get }
|
48
48
|
var failBuild: Bool { get }
|
49
49
|
}
|
50
50
|
|
51
51
|
extension ScanfileProtocol {
|
52
52
|
var workspace: String? { return nil }
|
53
53
|
var project: String? { return nil }
|
54
|
+
var scheme: String? { return nil }
|
54
55
|
var device: String? { return nil }
|
55
|
-
var toolchain: String? { return nil }
|
56
56
|
var devices: [String]? { return nil }
|
57
57
|
var skipDetectDevices: Bool { return false }
|
58
|
-
var
|
58
|
+
var reinstallApp: Bool { return false }
|
59
|
+
var appIdentifier: String? { return nil }
|
60
|
+
var onlyTesting: String? { return nil }
|
61
|
+
var skipTesting: String? { return nil }
|
62
|
+
var xctestrun: String? { return nil }
|
63
|
+
var toolchain: String? { return nil }
|
59
64
|
var clean: Bool { return false }
|
60
65
|
var codeCoverage: Bool? { return nil }
|
61
66
|
var addressSanitizer: Bool? { return nil }
|
62
67
|
var threadSanitizer: Bool? { return nil }
|
63
|
-
var
|
68
|
+
var openReport: Bool { return false }
|
64
69
|
var outputDirectory: String { return "./test_output" }
|
65
70
|
var outputStyle: String? { return nil }
|
66
71
|
var outputTypes: String { return "html,junit" }
|
@@ -70,34 +75,29 @@ extension ScanfileProtocol {
|
|
70
75
|
var suppressXcodeOutput: String? { return nil }
|
71
76
|
var formatter: String? { return nil }
|
72
77
|
var xcprettyArgs: String? { return nil }
|
78
|
+
var derivedDataPath: String? { return nil }
|
79
|
+
var shouldZipBuildProducts: Bool { return false }
|
80
|
+
var resultBundle: Bool { return false }
|
81
|
+
var useClangReportName: Bool { return false }
|
73
82
|
var maxConcurrentSimulators: Int? { return nil }
|
74
83
|
var disableConcurrentTesting: Bool { return false }
|
84
|
+
var skipBuild: Bool { return false }
|
75
85
|
var testWithoutBuilding: Bool? { return nil }
|
76
86
|
var buildForTesting: Bool? { return nil }
|
77
|
-
var xctestrun: String? { return nil }
|
78
|
-
var derivedDataPath: String? { return nil }
|
79
|
-
var shouldZipBuildProducts: Bool { return false }
|
80
|
-
var resultBundle: Bool { return false }
|
81
87
|
var sdk: String? { return nil }
|
82
|
-
var openReport: Bool { return false }
|
83
88
|
var configuration: String? { return nil }
|
84
|
-
var destination: String? { return nil }
|
85
89
|
var xcargs: String? { return nil }
|
86
90
|
var xcconfig: String? { return nil }
|
87
|
-
var onlyTesting: String? { return nil }
|
88
|
-
var skipTesting: String? { return nil }
|
89
91
|
var slackUrl: String? { return nil }
|
90
92
|
var slackChannel: String? { return nil }
|
91
93
|
var slackMessage: String? { return nil }
|
92
94
|
var skipSlack: Bool { return false }
|
93
95
|
var slackOnlyOnFailure: Bool { return false }
|
94
|
-
var
|
96
|
+
var destination: String? { return nil }
|
95
97
|
var customReportFileName: String? { return nil }
|
96
|
-
var appIdentifier: String? { return nil }
|
97
|
-
var reinstallApp: Bool { return false }
|
98
98
|
var failBuild: Bool { return true }
|
99
99
|
}
|
100
100
|
|
101
101
|
// Please don't remove the lines below
|
102
102
|
// They are used to detect outdated files
|
103
|
-
// FastlaneRunnerAPIVersion [0.9.
|
103
|
+
// FastlaneRunnerAPIVersion [0.9.7]
|
@@ -162,7 +162,7 @@ module FastlaneCore
|
|
162
162
|
[
|
163
163
|
'"' + Helper.transporter_path + '"',
|
164
164
|
"-m upload",
|
165
|
-
"-u
|
165
|
+
"-u #{username.shellescape}",
|
166
166
|
"-p #{shell_escaped_password(password)}",
|
167
167
|
"-f \"#{source}\"",
|
168
168
|
additional_upload_parameters, # that's here, because the user might overwrite the -t option
|
@@ -177,7 +177,7 @@ module FastlaneCore
|
|
177
177
|
[
|
178
178
|
'"' + Helper.transporter_path + '"',
|
179
179
|
"-m lookupMetadata",
|
180
|
-
"-u
|
180
|
+
"-u #{username.shellescape}",
|
181
181
|
"-p #{shell_escaped_password(password)}",
|
182
182
|
"-apple_id #{apple_id}",
|
183
183
|
"-destination '#{destination}'",
|
@@ -203,21 +203,23 @@ module FastlaneCore
|
|
203
203
|
private
|
204
204
|
|
205
205
|
def shell_escaped_password(password)
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
password = "'" + password + "'" unless Helper.windows?
|
206
|
+
password = password.shellescape
|
207
|
+
unless Helper.windows?
|
208
|
+
# because the shell handles passwords with single-quotes incorrectly, use `gsub` to replace `shellescape`'d single-quotes of this form:
|
209
|
+
# \'
|
210
|
+
# with a sequence that wraps the escaped single-quote in double-quotes:
|
211
|
+
# '"\'"'
|
212
|
+
# this allows us to properly handle passwords with single-quotes in them
|
213
|
+
# background: https://stackoverflow.com/questions/1250079/how-to-escape-single-quotes-within-single-quoted-strings/1250098#1250098
|
214
|
+
password = password.gsub("\\'") do
|
215
|
+
# we use the 'do' version of gsub, because two-param version interprets the replace text as a pattern and does the wrong thing
|
216
|
+
"'\"\\'\"'"
|
217
|
+
end
|
219
218
|
|
220
|
-
|
219
|
+
# wrap the fully-escaped password in single quotes, since the transporter expects a escaped password string (which must be single-quoted for the shell's benefit)
|
220
|
+
password = "'" + password + "'"
|
221
|
+
end
|
222
|
+
return password
|
221
223
|
end
|
222
224
|
end
|
223
225
|
|
@@ -46,7 +46,7 @@ module Frameit
|
|
46
46
|
default_value: false),
|
47
47
|
FastlaneCore::ConfigItem.new(key: :force_orientation_block,
|
48
48
|
type: :string_callback,
|
49
|
-
description: "[Advanced] A block to customize your
|
49
|
+
description: "[Advanced] A block to customize your screenshots' device orientation",
|
50
50
|
display_in_shell: false,
|
51
51
|
optional: true,
|
52
52
|
default_value: proc do |filename|
|
data/match/lib/match.rb
CHANGED
@@ -7,6 +7,7 @@ require_relative 'match/generator'
|
|
7
7
|
require_relative 'match/setup'
|
8
8
|
require_relative 'match/spaceship_ensure'
|
9
9
|
require_relative 'match/change_password'
|
10
|
+
require_relative 'match/migrate'
|
10
11
|
require_relative 'match/storage'
|
11
12
|
require_relative 'match/encryption'
|
12
13
|
require_relative 'match/module'
|
@@ -7,6 +7,13 @@ module Match
|
|
7
7
|
# These functions should only be used while in (UI.) interactive mode
|
8
8
|
class ChangePassword
|
9
9
|
def self.update(params: nil)
|
10
|
+
if params[:storage_mode] != "git"
|
11
|
+
# Only git supports changing the password
|
12
|
+
# All other storage options will most likely use more advanced
|
13
|
+
# ways to encrypt files
|
14
|
+
UI.user_error!("Only git-based match allows you to change your password, current `storage_mode` is #{params[:storage_mode]}")
|
15
|
+
end
|
16
|
+
|
10
17
|
ensure_ui_interactive
|
11
18
|
|
12
19
|
to = ChangePassword.ask_password(message: "New passphrase for Git Repo: ", confirm: true)
|
@@ -1,17 +1,19 @@
|
|
1
1
|
require 'commander'
|
2
2
|
|
3
3
|
require 'fastlane_core/configuration/configuration'
|
4
|
-
require_relative 'module'
|
5
4
|
|
6
5
|
require_relative 'nuke'
|
7
6
|
require_relative 'change_password'
|
8
7
|
require_relative 'setup'
|
9
8
|
require_relative 'runner'
|
10
9
|
require_relative 'options'
|
10
|
+
require_relative 'migrate'
|
11
11
|
|
12
12
|
require_relative 'storage'
|
13
13
|
require_relative 'encryption'
|
14
14
|
|
15
|
+
require_relative 'module'
|
16
|
+
|
15
17
|
HighLine.track_eof = false
|
16
18
|
|
17
19
|
module Match
|
@@ -125,11 +127,22 @@ module Match
|
|
125
127
|
git_url: params[:git_url],
|
126
128
|
working_directory: storage.working_directory
|
127
129
|
})
|
128
|
-
encryption.decrypt_files
|
130
|
+
encryption.decrypt_files if encryption
|
129
131
|
UI.success("Repo is at: '#{storage.working_directory}'")
|
130
132
|
end
|
131
133
|
end
|
132
134
|
|
135
|
+
command :migrate do |c|
|
136
|
+
c.syntax = "fastlane match migrate"
|
137
|
+
c.description = "Migrate from one storage backend to another one"
|
138
|
+
|
139
|
+
FastlaneCore::CommanderGenerator.new.generate(Match::Options.available_options, command: c)
|
140
|
+
|
141
|
+
c.action do |args, options|
|
142
|
+
Match::Migrate.new.migrate(args, options)
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
133
146
|
command "nuke" do |c|
|
134
147
|
# We have this empty command here, since otherwise the normal `match` command will be executed
|
135
148
|
c.syntax = "fastlane match nuke"
|
@@ -4,8 +4,8 @@ require 'securerandom'
|
|
4
4
|
require 'security'
|
5
5
|
require 'shellwords'
|
6
6
|
|
7
|
-
require_relative '../module'
|
8
7
|
require_relative '../change_password'
|
8
|
+
require_relative '../module'
|
9
9
|
|
10
10
|
module Match
|
11
11
|
module Encryption
|
@@ -144,7 +144,7 @@ module Match
|
|
144
144
|
rescue => error
|
145
145
|
fallback_hash_algorithm = "SHA256"
|
146
146
|
if hash_algorithm != fallback_hash_algorithm
|
147
|
-
decrypt_specific_file(path, password, fallback_hash_algorithm)
|
147
|
+
decrypt_specific_file(path: path, password: password, hash_algorithm: fallback_hash_algorithm)
|
148
148
|
else
|
149
149
|
UI.error(error.to_s)
|
150
150
|
UI.crash!("Error decrypting '#{path}'")
|
@@ -0,0 +1,97 @@
|
|
1
|
+
require_relative 'options'
|
2
|
+
require_relative 'spaceship_ensure'
|
3
|
+
require_relative 'encryption'
|
4
|
+
require_relative 'storage'
|
5
|
+
require_relative 'module'
|
6
|
+
require 'fileutils'
|
7
|
+
|
8
|
+
module Match
|
9
|
+
class Migrate
|
10
|
+
def migrate(args, options)
|
11
|
+
params = FastlaneCore::Configuration.create(Match::Options.available_options, options.__hash__)
|
12
|
+
loaded_matchfile = params.load_configuration_file("Matchfile")
|
13
|
+
|
14
|
+
ensure_parameters_are_valid(params)
|
15
|
+
|
16
|
+
# We init the Google storage client before the git client
|
17
|
+
# to ask for all the missing inputs *before* cloning the git repo
|
18
|
+
google_cloud_storage = Storage.for_mode("google_cloud", {
|
19
|
+
google_cloud_bucket_name: params[:google_cloud_bucket_name],
|
20
|
+
google_cloud_keys_file: params[:google_cloud_keys_file]
|
21
|
+
})
|
22
|
+
|
23
|
+
git_storage = Storage.for_mode("git", {
|
24
|
+
git_url: params[:git_url],
|
25
|
+
shallow_clone: params[:shallow_clone],
|
26
|
+
git_branch: params[:git_branch],
|
27
|
+
clone_branch_directly: params[:clone_branch_directly]
|
28
|
+
})
|
29
|
+
git_storage.download
|
30
|
+
|
31
|
+
encryption = Encryption.for_storage_mode(params[:storage_mode], {
|
32
|
+
git_url: params[:git_url],
|
33
|
+
working_directory: git_storage.working_directory
|
34
|
+
})
|
35
|
+
encryption.decrypt_files if encryption
|
36
|
+
UI.success("Decrypted the git repo to '#{git_storage.working_directory}'")
|
37
|
+
|
38
|
+
google_cloud_storage.download
|
39
|
+
|
40
|
+
# Note how we always prefix the path in Google Cloud with the Team ID
|
41
|
+
# while on Git we recommend using the git branch instead. As there is
|
42
|
+
# no concept of branches in Google Cloud Storage (omg thanks), we use
|
43
|
+
# the team id properly
|
44
|
+
spaceship = SpaceshipEnsure.new(params[:username], params[:team_id], params[:team_name])
|
45
|
+
team_id = spaceship.team_id
|
46
|
+
UI.message("Detected team ID '#{team_id}' to use for Google Cloud Storage...")
|
47
|
+
|
48
|
+
files_to_commit = []
|
49
|
+
Dir.chdir(git_storage.working_directory) do
|
50
|
+
Dir[File.join("**", "*")].each do |current_file|
|
51
|
+
next if File.directory?(current_file)
|
52
|
+
|
53
|
+
to_path = File.join(google_cloud_storage.working_directory, team_id, current_file)
|
54
|
+
FileUtils.mkdir_p(File.expand_path("..", to_path))
|
55
|
+
|
56
|
+
if File.exist?(to_path)
|
57
|
+
UI.user_error!("Looks like file already exists on Google Cloud Storage at path '#{to_path}', stopping the migration process. Please make sure the bucket is empty, or at least doesn't contain any files related to the same Team ID")
|
58
|
+
end
|
59
|
+
FileUtils.cp(current_file, to_path)
|
60
|
+
|
61
|
+
files_to_commit << to_path
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
google_cloud_storage.save_changes!(files_to_commit: files_to_commit)
|
66
|
+
|
67
|
+
UI.success("Successfully migrated your code signing certificates and provisioning profiles to Google Cloud Storage")
|
68
|
+
UI.success("Make sure to update your configuration to specify the `storage_mode`, as well as the bucket to use.")
|
69
|
+
UI.message("")
|
70
|
+
if loaded_matchfile
|
71
|
+
UI.message("Update your Matchfile at path '#{loaded_matchfile.configfile_path}':")
|
72
|
+
UI.message("")
|
73
|
+
UI.command_output("\t\tstorage_mode \"google_cloud\"")
|
74
|
+
UI.command_output("\t\tgoogle_cloud_bucket_name \"#{google_cloud_storage.bucket_name}\"")
|
75
|
+
else
|
76
|
+
UI.message("Update your Fastfile `match` call to include")
|
77
|
+
UI.message("")
|
78
|
+
UI.command_output("\t\tstorage_mode: \"google_cloud\",")
|
79
|
+
UI.command_output("\t\tgoogle_cloud_bucket_name: \"#{google_cloud_storage.bucket_name}\",")
|
80
|
+
end
|
81
|
+
UI.message("")
|
82
|
+
UI.success("You can also remove the `git_url`, as well as any other git related configurations from your Fastfile and Matchfile")
|
83
|
+
UI.message("")
|
84
|
+
UI.input("Please make sure to read the above and confirm with enter")
|
85
|
+
end
|
86
|
+
|
87
|
+
def ensure_parameters_are_valid(params)
|
88
|
+
if params[:readonly]
|
89
|
+
UI.user_error!("`fastlane match migrate` doesn't work in `readonly` mode")
|
90
|
+
end
|
91
|
+
|
92
|
+
if params[:storage_mode] != "git"
|
93
|
+
UI.user_error!("`fastlane match migrate` only allows migration from `git` to `google_cloud` right now, looks like your currently selected `storage_mode` is '#{params[:storage_mode]}'")
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|