escalator_ios 1.2.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.
@@ -0,0 +1,271 @@
1
+ module Escalator
2
+
3
+ class Resign
4
+
5
+ class << self
6
+
7
+ def run command
8
+ @command = command
9
+ prepareContext
10
+ applyCertificates
11
+ command.ipaPaths.map { |path|
12
+ resignIPA handleIPA path
13
+ }
14
+ end
15
+
16
+ private
17
+
18
+ attr_accessor :command
19
+
20
+ attr_accessor :tmpdir
21
+
22
+ attr_accessor :keyInfo_path
23
+
24
+ attr_accessor :bundle_version
25
+
26
+ attr_accessor :assets_path
27
+
28
+ attr_accessor :iconInfo_path
29
+
30
+ attr_accessor :cerIdentifier
31
+
32
+ def prepareContext
33
+ Throw.note "Prepare resign context ..."
34
+ @tmpdir = ENV["TMPDIR"] + "escalator/resign"
35
+ if File.exist? tmpdir
36
+ FileUtils.rm_rf Dir["#{tmpdir}/*"]
37
+ else
38
+ FileUtils.mkdir_p tmpdir
39
+ end
40
+ @keyInfo_path = tmpdir + "/keyInfo.json"
41
+ keyInfo = Hash.new
42
+ keyInfo[:in_house] = false
43
+ keyInfo[:key_id] = command.key_id
44
+ keyInfo[:issuer_id] = command.issuer_id
45
+ keyInfo[:key_filepath] = command.keyfile_path
46
+ keyInfo[:key] = File.read command.keyfile_path
47
+ file = File.new keyInfo_path, "w"
48
+ file.write JSON.generate keyInfo
49
+ file.close
50
+ @bundle_version = command.bundle_version.to_i
51
+ @assets_path = tmpdir + "/assets"
52
+ FileUtils.mkdir_p assets_path
53
+ info_path = File.expand_path "../../../resources/IconInfo.plist", __FILE__
54
+ FileUtils.cp info_path, tmpdir
55
+ @iconInfo_path = tmpdir + "/IconInfo.plist"
56
+ end
57
+
58
+ def applyCertificates
59
+ Throw.note "begin apply certificates ..."
60
+ cmd = "fastlane cert create --api_key_path #{keyInfo_path}"
61
+ cmd += " --generate_apple_certs true -p #{command.user_password} -o #{tmpdir}"
62
+ system cmd
63
+ if !$?.success?
64
+ Throw.error "Apply .cer file faild!"
65
+ end
66
+ cer = File.read Dir.glob("#{tmpdir}/*.cer").first
67
+ @cerIdentifier = OpenSSL::Digest.hexdigest("SHA1", cer).upcase
68
+ cmd = "fastlane sigh renew --api_key_path #{keyInfo_path} -a #{command.bundle_identifier}"
69
+ cmd += " -q embedded.mobileprovision -o #{tmpdir}"
70
+ system cmd
71
+ if !$?.success?
72
+ Throw.error "Apply embedded.mobileprovision file faild!"
73
+ end
74
+ end
75
+
76
+ def handleIPA ipaPath
77
+ basePath = File.dirname(ipaPath)
78
+ coverInfoPath = basePath + "/CoverInfo.plist"
79
+ coverData = Hash.new
80
+ coverData["CFBundleVersion"] = ""
81
+ coverData["CFBundleName"] = ""
82
+ coverData["CFBundleExecutable"] = ""
83
+ coverData["CFBundleDisplayName"] = ""
84
+ if File.exist? coverInfoPath
85
+ coverPlist = CFPropertyList::List.new :file => coverInfoPath
86
+ CFPropertyList.native_types(coverPlist.value).each { |key, value|
87
+ coverData[key] = value
88
+ }
89
+ end
90
+ bundleVersion = coverData["CFBundleVersion"]
91
+ if bundleVersion.empty?
92
+ bundleVersion = bundle_version.to_s
93
+ @bundle_version += 1
94
+ end
95
+ displayName = coverData["CFBundleDisplayName"]
96
+ if displayName.empty?
97
+ displayName = command.display_name
98
+ end
99
+ bundleName = coverData["CFBundleName"]
100
+ if bundleName.empty?
101
+ bundleName = command.bundle_name
102
+ end
103
+ executableName = coverData["CFBundleExecutable"]
104
+ if executableName.empty?
105
+ executableName = command.executable_name
106
+ end
107
+ if (command.iconAssets_path.empty? &&
108
+ bundleName.empty? &&
109
+ executableName.empty?)
110
+ return OpenStruct.new(:path => ipaPath, :displayName => displayName)
111
+ end
112
+ Throw.note "begin handle #{File.basename ipaPath} ..."
113
+ content_path = tmpdir + "/content"
114
+ FileUtils.mkdir_p content_path
115
+ system "unzip -o -q #{ipaPath} -d #{content_path}"
116
+ if !$?.success?
117
+ Throw.error "Unzip ipa faild!"
118
+ end
119
+ appPath = Dir.glob("#{content_path}/**/*.app").first
120
+ if !command.iconAssets_path.empty?
121
+ handleAssets appPath, basePath
122
+ end
123
+ pluginsProvisions = []
124
+ pluginsPath = "#{appPath}/PlugIns"
125
+ if File.exist? pluginsPath
126
+ pluginsProvisions = handlePlugins pluginsPath
127
+ end
128
+ if !(bundleName.empty? && executableName.empty?)
129
+ handleBundle appPath, bundleName, executableName
130
+ end
131
+ FileUtils.rm_rf ipaPath
132
+ newIpaPath = ipaPath
133
+ if !bundleName.empty?
134
+ newIpaPath = File.expand_path "../#{bundleName}.ipa", ipaPath
135
+ end
136
+ system "cd #{content_path} && zip -q -r -D #{newIpaPath} ./*"
137
+ if !$?.success?
138
+ Throw.error "Zip payload faild!"
139
+ end
140
+ FileUtils.rm_rf content_path
141
+ OpenStruct.new(
142
+ :path => newIpaPath,
143
+ :bundleVersion => bundleVersion,
144
+ :displayName => displayName,
145
+ :pluginsProvisions => pluginsProvisions
146
+ )
147
+ end
148
+
149
+ def handleAssets appPath, assetsPath
150
+ Throw.note "begin handle assets ..."
151
+ cmd = "actool --compile #{assets_path} --minimum-deployment-target 11.0 --platform iphoneos"
152
+ cmd += " --app-icon AppIcon --output-partial-info-plist #{iconInfo_path}"
153
+ cmd += " --compress-pngs #{command.iconAssets_path}"
154
+ Dir.glob("#{assetsPath}/*.xcassets") { |file|
155
+ cmd += " #{file}"
156
+ icon_path = "#{file}/AppIcon.appiconset"
157
+ if File.exist? icon_path
158
+ FileUtils.rm_rf icon_path
159
+ end
160
+ }
161
+ system cmd
162
+ if !$?.success?
163
+ Throw.error "Generate new Assets.car faild!"
164
+ end
165
+ FileUtils.mv Dir["#{assets_path}/*"], appPath, force: true
166
+ end
167
+
168
+ def handlePlugins path
169
+ appleIdField = command.apple_id.empty? ? "" : "-u #{command.apple_id}"
170
+ parts = (command.bundle_identifier.split ".").sort_by { |p| p.length }
171
+ groupName = parts.last
172
+ groupIdentifier = "group.#{command.bundle_identifier}"
173
+ system "fastlane produce group #{appleIdField} -g #{groupIdentifier} -n '#{groupName} App Group'"
174
+ if !$?.success?
175
+ Throw.error "Create #{groupName} app group faild!"
176
+ end
177
+ infos = Dir.glob("#{path}/*.appex/Info.plist").map { |infoPath|
178
+ plist = CFPropertyList::List.new :file => infoPath
179
+ CFPropertyList.native_types plist.value
180
+ }
181
+ enableNetworkExtension = false
182
+ infos.each { |info|
183
+ enableNetworkExtension |= info["NSExtension"]["NSExtensionPointIdentifier"].include? "com.apple.networkextension"
184
+ }
185
+ networkExtensionField = enableNetworkExtension ? "--network-extension" : ""
186
+ system "fastlane produce enable_services #{appleIdField} --app-group #{networkExtensionField} -j ios -a #{command.bundle_identifier}"
187
+ if !$?.success?
188
+ Throw.error "#{command.bundle_identifier} enable services faild!"
189
+ end
190
+ system "fastlane produce associate_group #{appleIdField} #{groupIdentifier} -a #{command.bundle_identifier}"
191
+ if !$?.success?
192
+ Throw.error "#{command.bundle_identifier} associate group faild!"
193
+ end
194
+ system "fastlane sigh renew --api_key_path #{keyInfo_path} -f -a #{command.bundle_identifier} -q embedded.mobileprovision -o #{tmpdir}"
195
+ if !$?.success?
196
+ Throw.error "Apply embedded.mobileprovision file faild!"
197
+ end
198
+ infos.map { |info|
199
+ originalIdentifier = info["CFBundleIdentifier"]
200
+ name = info["CFBundleExecutable"]
201
+ provisionName = "#{name}.mobileprovision"
202
+ identifier = "#{command.bundle_identifier}.#{name}"
203
+ system "fastlane produce create #{appleIdField} -i -j ios -a #{identifier} -q #{name}"
204
+ if !$?.success?
205
+ Throw.error "Create #{identifier} faild!"
206
+ end
207
+ system "fastlane produce enable_services #{appleIdField} --app-group #{networkExtensionField} -j ios -a #{identifier}"
208
+ if !$?.success?
209
+ Throw.error "#{identifier} enable services faild!"
210
+ end
211
+ system "fastlane produce associate_group #{appleIdField} #{groupIdentifier} -a #{identifier}"
212
+ if !$?.success?
213
+ Throw.error "#{identifier} associate group faild!"
214
+ end
215
+ system "fastlane sigh renew --api_key_path #{keyInfo_path} -a #{identifier} -q #{provisionName} -o #{tmpdir}"
216
+ if !$?.success?
217
+ Throw.error "Apply #{provisionName} file faild!"
218
+ end
219
+ "#{originalIdentifier}=#{tmpdir}/#{provisionName}"
220
+ }
221
+ end
222
+
223
+ def handleBundle appPath, newBundleName, newExecutableName
224
+ Throw.note "begin handle bundle ..."
225
+ plistPath = appPath + "/Info.plist"
226
+ plist = CFPropertyList::List.new :file => plistPath
227
+ data = CFPropertyList.native_types plist.value
228
+ if !newExecutableName.empty?
229
+ executableName = data["CFBundleExecutable"]
230
+ FileUtils.mv "#{appPath}/#{executableName}", "#{appPath}/#{newExecutableName}", force: true
231
+ data["CFBundleExecutable"] = newExecutableName
232
+ end
233
+ if !newBundleName.empty?
234
+ data["CFBundleName"] = newBundleName
235
+ end
236
+ plist.value = CFPropertyList::guess data
237
+ plist.save plistPath
238
+ if !newBundleName.empty?
239
+ newAppPath = File.dirname(appPath) + "/#{newBundleName}.app"
240
+ FileUtils.mv appPath, newAppPath, force: true
241
+ end
242
+ end
243
+
244
+ def resignIPA ipaInfo
245
+ path = File.dirname ipaInfo.path
246
+ ipaName = File.basename ipaInfo.path
247
+ Throw.note "begin resign #{ipaName} ..."
248
+ cmd = "fastlane sigh resign --short_version #{command.short_version}"
249
+ cmd += " --bundle_version #{ipaInfo.bundleVersion}"
250
+ if !ipaInfo.displayName.empty?
251
+ cmd += " -d #{ipaInfo.displayName}"
252
+ end
253
+ cmd += " --use_app_entitlements -p #{tmpdir}/embedded.mobileprovision"
254
+ ipaInfo.pluginsProvisions.each { |provision|
255
+ cmd += " -p #{provision}"
256
+ }
257
+ cmd += " -i #{cerIdentifier} #{ipaInfo.path}"
258
+ system cmd
259
+ if !$?.success?
260
+ Throw.error "Resign ipa faild!"
261
+ end
262
+ newPath = path + "_build_#{ipaInfo.bundleVersion}"
263
+ FileUtils.mv path, newPath, force: true
264
+ "#{newPath}/#{ipaName}"
265
+ end
266
+
267
+ end
268
+
269
+ end
270
+
271
+ end
@@ -0,0 +1,79 @@
1
+ module Escalator
2
+
3
+ class Setup
4
+
5
+ class << self
6
+
7
+ def run command
8
+ @command = command
9
+ if command.set_zshcompletion
10
+ pluginPath = File.expand_path "../../../resources/zsh_plugin/escalator", __FILE__
11
+ FileUtils.cp_r pluginPath, command.custom_plugins
12
+ return
13
+ end
14
+ prepareContext
15
+ exportPlist
16
+ end
17
+
18
+ private
19
+
20
+ attr_accessor :command
21
+
22
+ attr_accessor :config_data
23
+
24
+ attr_accessor :cover_data
25
+
26
+ def prepareContext
27
+ @config_data = Hash.new
28
+ @cover_data = Hash.new
29
+ if command.commands.include? "confuse"
30
+ config_data["keywords"] = ["混淆词1", "混淆词2"]
31
+ end
32
+ if command.commands.include? "archive"
33
+ config_data["method"] = "app-store 或者 ad-hoc"
34
+ end
35
+ if command.commands.include? "resign"
36
+ config_data["key_id"] = "AppStore Connect 拷贝"
37
+ config_data["issuer_id"] = "AppStore Connect 拷贝"
38
+ config_data["keyfile_path"] = "AppStore Connect 下载的 .p8 文件的绝对路径"
39
+ config_data["user_password"] = "当前电脑用户密码"
40
+ config_data["CFBundleIdentifier"] = "新的唯一标识符"
41
+ config_data["CFBundleShortVersionString"] = "版本号"
42
+ config_data["CFBundleVersion"] = "初始 Build 号"
43
+ config_data["apple_id"] = "可缺省: 对应的苹果开发者账户, 如果含有 APP GROUP 推荐添加此字段"
44
+ config_data["CFBundleName"] = "可缺省: 新包名"
45
+ config_data["CFBundleExecutable"] = "可缺省: 新的二进制名"
46
+ config_data["CFBundleDisplayName"] = "可缺省: 新的 APP 名称"
47
+ config_data["iconAssets_path"] = "可缺省: 包含新 AppIcon 的 .xcassets 文件的绝对路径"
48
+
49
+ cover_data["CFBundleVersion"] = "可缺省: 覆盖全局配置中的 Build 号规则"
50
+ cover_data["CFBundleName"] = "可缺省: 覆盖全局配置中的 新包名"
51
+ cover_data["CFBundleExecutable"] = "可缺省: 覆盖全局配置中的 新的二进制名"
52
+ cover_data["CFBundleDisplayName"] = "可缺省: 覆盖全局配置中的 新的 APP 名称"
53
+ end
54
+ if command.commands.include? "upload"
55
+ config_data["key_id"] = "AppStore Connect 拷贝"
56
+ config_data["issuer_id"] = "AppStore Connect 拷贝"
57
+ config_data["keyfile_path"] = "AppStore Connect 下载的 .p8 文件的绝对路径"
58
+ config_data["CFBundleIdentifier"] = "新的唯一标识符"
59
+ end
60
+ end
61
+
62
+ def exportPlist
63
+ configPlist = CFPropertyList::List.new
64
+ configPlist.format = CFPropertyList::List::FORMAT_XML
65
+ configPlist.value = CFPropertyList.guess config_data
66
+ configPlist.save command.output_path + "/ConfigInfo.plist"
67
+ if command.commands.include? "resign"
68
+ coverPlist = CFPropertyList::List.new
69
+ coverPlist.format = CFPropertyList::List::FORMAT_XML
70
+ coverPlist.value = CFPropertyList.guess cover_data
71
+ coverPlist.save command.output_path + "/CoverInfo.plist"
72
+ end
73
+ end
74
+
75
+ end
76
+
77
+ end
78
+
79
+ end
@@ -0,0 +1,23 @@
1
+ module Escalator
2
+
3
+ class Throw
4
+
5
+ class << self
6
+
7
+ def error message
8
+ puts
9
+ puts message.ansi.red
10
+ puts
11
+ exit -1
12
+ end
13
+
14
+ def note message
15
+ puts
16
+ puts message.ansi.green
17
+ end
18
+
19
+ end
20
+
21
+ end
22
+
23
+ end
@@ -0,0 +1,57 @@
1
+ module Escalator
2
+
3
+ class Upload
4
+
5
+ class << self
6
+
7
+ def run command
8
+ @command = command
9
+ prepareContext
10
+ command.ipaPaths.each { |path|
11
+ uploadIPA path
12
+ }
13
+ end
14
+
15
+ private
16
+
17
+ attr_accessor :command
18
+
19
+ attr_accessor :tmpdir
20
+
21
+ attr_accessor :keyInfo_path
22
+
23
+ def prepareContext
24
+ Throw.note "Prepare upload context ..."
25
+ @tmpdir = ENV["TMPDIR"] + "escalator/upload"
26
+ if File.exist? tmpdir
27
+ FileUtils.rm_rf Dir["#{tmpdir}/*"]
28
+ else
29
+ FileUtils.mkdir_p tmpdir
30
+ end
31
+ @keyInfo_path = tmpdir + "/keyInfo.json"
32
+ keyInfo = Hash.new
33
+ keyInfo[:in_house] = false
34
+ keyInfo[:key_id] = command.key_id
35
+ keyInfo[:issuer_id] = command.issuer_id
36
+ keyInfo[:key_filepath] = command.keyfile_path
37
+ keyInfo[:key] = File.read command.keyfile_path
38
+ file = File.new keyInfo_path, "w"
39
+ file.write JSON.generate keyInfo
40
+ file.close
41
+ end
42
+
43
+ def uploadIPA path
44
+ Throw.note "Begin upload #{path} ..."
45
+ cmd = "fastlane pilot upload --api_key_path #{keyInfo_path}"
46
+ cmd += " -i #{path} -a #{command.bundle_identifier} -z true"
47
+ system(cmd)
48
+ if !$?.success?
49
+ Throw.error "Upload ipa faild!"
50
+ end
51
+ end
52
+
53
+ end
54
+
55
+ end
56
+
57
+ end
data/lib/escalator.rb ADDED
@@ -0,0 +1,25 @@
1
+ module Escalator
2
+
3
+ VERSION = "1.2.0".freeze
4
+
5
+ require "json"
6
+ require "openssl"
7
+ require "ostruct"
8
+ require "fileutils"
9
+ require "cfpropertylist"
10
+ require "xcodeproj"
11
+ require "fastlane"
12
+ require "colored2"
13
+ require "claide"
14
+
15
+ require "escalator/group+"
16
+ require "escalator/throw"
17
+ require "escalator/command"
18
+ require "escalator/confuse"
19
+ require "escalator/archive"
20
+ require "escalator/resign"
21
+ require "escalator/upload"
22
+ require "escalator/combine"
23
+ require "escalator/setup"
24
+
25
+ end
@@ -0,0 +1,20 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+ <plist version="1.0">
4
+ <dict>
5
+ <key>destination</key>
6
+ <string>export</string>
7
+ <key>manageAppVersionAndBuildNumber</key>
8
+ <false/>
9
+ <key>method</key>
10
+ <string>app-store</string>
11
+ <key>signingStyle</key>
12
+ <string>automatic</string>
13
+ <key>stripSwiftSymbols</key>
14
+ <true/>
15
+ <key>uploadBitcode</key>
16
+ <false/>
17
+ <key>uploadSymbols</key>
18
+ <false/>
19
+ </dict>
20
+ </plist>
@@ -0,0 +1,31 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+ <plist version="1.0">
4
+ <dict>
5
+ <key>CFBundleIcons</key>
6
+ <dict>
7
+ <key>CFBundlePrimaryIcon</key>
8
+ <dict>
9
+ <key>CFBundleIconFiles</key>
10
+ <array>
11
+ <string>AppIcon60x60</string>
12
+ </array>
13
+ <key>CFBundleIconName</key>
14
+ <string>AppIcon</string>
15
+ </dict>
16
+ </dict>
17
+ <key>CFBundleIcons~ipad</key>
18
+ <dict>
19
+ <key>CFBundlePrimaryIcon</key>
20
+ <dict>
21
+ <key>CFBundleIconFiles</key>
22
+ <array>
23
+ <string>AppIcon60x60</string>
24
+ <string>AppIcon76x76</string>
25
+ </array>
26
+ <key>CFBundleIconName</key>
27
+ <string>AppIcon</string>
28
+ </dict>
29
+ </dict>
30
+ </dict>
31
+ </plist>
@@ -0,0 +1,127 @@
1
+ #compdef escalator
2
+ #autoload
3
+
4
+ local -a _subcommands
5
+ local -a _arguments
6
+ local -a _options
7
+
8
+ case "$words[2]" in
9
+ confuse )
10
+ _options=(
11
+ "--project-path=path:path 为 .xcodeproj 源路径"
12
+ "--output-path=path:path 为混淆工程存放路径"
13
+ "--show-output:文件管理中展示输出文件夹, 默认: 否"
14
+ "--verbose:输出更多调试信息, 默认: 否"
15
+ "--no-ansi:关闭高亮输出模式, 默认: 否"
16
+ "--help:仅输出指定命令的帮助文档, 默认: 否"
17
+ )
18
+ _describe -t options "escalator confuse options" _options
19
+ ;;
20
+ archive )
21
+ case "$words[3]" in
22
+ app-store | ad-hoc )
23
+ _options=(
24
+ "--project-path=path:path 为 .xcproject 源路径"
25
+ "--output-path=path:path 为 .ipa 以及部分重签资源的存放路径"
26
+ "--show-output:文件管理中展示输出文件夹, 默认: 否"
27
+ "--verbose:输出更多调试信息, 默认: 否"
28
+ "--no-ansi:关闭高亮输出模式, 默认: 否"
29
+ "--help:仅输出指定命令的帮助文档, 默认: 否"
30
+ )
31
+ _describe -t options "escalator archive options" _options
32
+ ;;
33
+ * )
34
+ _arguments=(
35
+ "app-store:发布商店类型"
36
+ "ad-hoc:发布测试类型"
37
+ )
38
+ _describe -t arguments "escalator archive arguments" _arguments
39
+ ;;
40
+ esac
41
+ ;;
42
+ resign )
43
+ _options=(
44
+ "--key-id=id:id 为 Appstore Connect 用户访问密钥的 keyId"
45
+ "--issuer-id=id:id 为 Appstore Connect 用户访问密钥的 issuerId"
46
+ "--keyfile-path=path:path 为 Appstore Connect 用户访问密钥的 .p8 文件保存路径"
47
+ "--user-password=password:password 为当前电脑用户的访问密码"
48
+ "--bundle-identifier=identifier:identifier 为新的唯一标识符"
49
+ "--short-version=version:version 为新的版本号"
50
+ "--bundle-version=version:version 为新的 BuildID, 同一账号下处理多 IPA, 会自动叠加"
51
+ "--apple-id=id:id 为对应的苹果开发者账户, 如果含有 APP GROUP 推荐添加此字段, 默认: 无"
52
+ "--bundle-name=name:name 为新的包名, 默认: 不变"
53
+ "--display-name=name:name 为新的 APP 名称, 默认: 不变"
54
+ "--executable-name=name:name 为新的二进制文件名, 默认: 不变"
55
+ "--iconAssets-path=path:path 为包含新 AppIcon 的 .xcassets 资源文件路径, 默认: 无"
56
+ "--verbose:输出更多调试信息, 默认: 否"
57
+ "--no-ansi:关闭高亮输出模式, 默认: 否"
58
+ "--help:仅输出指定命令的帮助文档, 默认: 否"
59
+ )
60
+ _describe -t options "escalator resign options" _options
61
+ ;;
62
+ upload )
63
+ _options=(
64
+ "--key-id=id:id 为 Appstore Connect 用户访问密钥的 keyId"
65
+ "--issuer-id=id:id 为 Appstore Connect 用户访问密钥的 issuerId"
66
+ "--keyfile-path=path:path 为 Appstore Connect 用户访问密钥的 .p8 文件保存路径"
67
+ "--bundle-identifier=identifier:identifier 为上传账户下对应唯一标识符"
68
+ "--verbose:输出更多调试信息, 默认: 否"
69
+ "--no-ansi:关闭高亮输出模式, 默认: 否"
70
+ "--help:仅输出指定命令的帮助文档, 默认: 否"
71
+ )
72
+ _describe -t options "escalator upload options" _options
73
+ ;;
74
+ setup )
75
+ _arguments=(
76
+ "confuse:混淆命令"
77
+ "archive:打包命令"
78
+ "resign:重签命令"
79
+ "upload:上传命令"
80
+ )
81
+ _describe -t arguments "escalator setup arguments" _arguments
82
+ _options=(
83
+ "--output-path=path:path 为参数模版导出路径"
84
+ "--set-zshcompletion:会忽略其他参数, 只设置 oh-my-zsh 的命令补全插件到 custom/plugins 中, zshrc 配置插件, 请自己手动更新, 默认: 否"
85
+ "--verbose:输出更多调试信息, 默认: 否"
86
+ "--no-ansi:关闭高亮输出模式, 默认: 否"
87
+ "--help:仅输出指定命令的帮助文档, 默认: 否"
88
+ )
89
+ _describe -t options "escalator setup options" _options
90
+ ;;
91
+ combine )
92
+ _arguments=(
93
+ "confuse:混淆命令"
94
+ "archive:打包命令"
95
+ "resign:重签命令"
96
+ "upload:上传命令"
97
+ )
98
+ _describe -t arguments "escalator setup arguments" _arguments
99
+ _options=(
100
+ "--config-path=path:path 为任务流需要的配置参数 ConfigInfo.plist 文件路径"
101
+ "--input-path=path:path 为初始命令需要的输入根目录, 会自动检测需要的输入文件"
102
+ "--work-path=path:path 为脚本工作的根目录"
103
+ "--verbose:输出更多调试信息, 默认: 否"
104
+ "--no-ansi:关闭高亮输出模式, 默认: 否"
105
+ "--help:仅输出指定命令的帮助文档, 默认: 否"
106
+ )
107
+ _describe -t options "escalator combine options" _options
108
+ ;;
109
+ *)
110
+ _subcommands=(
111
+ "confuse:混淆 Xcode 工程"
112
+ "archive:打包 Xcode 工程"
113
+ "resign:重签 IPA 安装包"
114
+ "upload:上传 IPA 安装包"
115
+ "setup:生成 组合命令执行需要的参数模版"
116
+ "combine:组合 命令: confuse archive resign upload"
117
+ )
118
+ _describe -t commands "escalator subcommands" _subcommands
119
+ _options=(
120
+ "--help:仅输出指定命令的帮助文档, 默认: 否"
121
+ "--version:仅输出工具版本号, 默认: 否"
122
+ "--verbose:输出更多调试信息, 默认: 否"
123
+ "--no-ansi:关闭高亮输出模式, 默认: 否"
124
+ )
125
+ _describe -t options "escalator options" _options
126
+ ;;
127
+ esac