pindo 5.19.3 → 5.19.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/pindo/base/git_handler.rb +5 -5
- data/lib/pindo/command/appstore/iap.rb +2 -2
- data/lib/pindo/command/appstore/updateid.rb +1 -1
- data/lib/pindo/command/ios/autoresign.rb +70 -29
- data/lib/pindo/command/ios/podpush.rb +1 -1
- data/lib/pindo/command/unity/packbuild.rb +1 -1
- data/lib/pindo/command/utils/copyconfig.rb +1 -1
- data/lib/pindo/command/utils/renewbundleid.rb +1 -1
- data/lib/pindo/config/build_info_manager.rb +2 -2
- data/lib/pindo/module/appstore/itcapp_helper.rb +1 -1
- data/lib/pindo/module/build/swark_helper.rb +1 -1
- data/lib/pindo/module/cert/cert_helper.rb +1 -1
- data/lib/pindo/module/cert/pem_helper.rb +1 -1
- data/lib/pindo/module/pgyer/pgyerhelper.rb +24 -21
- data/lib/pindo/module/resign/ipa_resign_adapter.rb +14 -0
- data/lib/pindo/module/resign/mac_app_resign_adapter.rb +16 -0
- data/lib/pindo/module/task/model/build/ios_build_adhoc_task.rb +1 -1
- data/lib/pindo/module/task/model/build/ios_build_appstore_task.rb +1 -1
- data/lib/pindo/module/task/model/git/git_commit_task.rb +2 -2
- data/lib/pindo/module/task/model/resign/ipa_local_resign_task.rb +44 -10
- data/lib/pindo/module/utils/git_repo_helper.rb +2 -2
- data/lib/pindo/module/xcode/applovin_xcode_helper.rb +1 -1
- data/lib/pindo/module/xcode/cocoapods_helper.rb +2 -2
- data/lib/pindo/module/xcode/mac_app_resign_helper.rb +243 -0
- data/lib/pindo/module/xcode/xcode_build_helper.rb +3 -3
- data/lib/pindo/module/xcode/xcode_swark_helper.rb +1 -1
- data/lib/pindo/options/core/option_value_parser.rb +12 -2
- data/lib/pindo/options/groups/jps_options.rb +2 -1
- data/lib/pindo/options/groups/tool_options.rb +18 -0
- data/lib/pindo/version.rb +17 -10
- data/lib/pindo.rb +12 -0
- metadata +8 -5
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: b7cccaa492d62d373f89fd3af414f3536ca43d47a840cc916b2629445cb581e3
|
|
4
|
+
data.tar.gz: 70f7ad8f931126af81fb7bceae2f54b35d1adc4d34b3991cde6b3a6c6422b950
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 9ac4563509d172649298ca22c6f1459b2805521c2c0aa226f6ba9dacdb95b287814d92c70b5b747ac0be9f783c929f180d430dc72c179b76b764e65922ce30c2
|
|
7
|
+
data.tar.gz: 8383a7f60e3970a37e7e3311a6f930dfc9fb68ca49fc56c48ba868678739ed6215ea63d5f326b86ee690afb747a98bede384378e163229094c0e9a2b972c7be9
|
|
@@ -443,7 +443,7 @@ module Pindo
|
|
|
443
443
|
return config_repo_dir
|
|
444
444
|
end
|
|
445
445
|
|
|
446
|
-
def git_addpush_repo(path:nil, message:"
|
|
446
|
+
def git_addpush_repo(path:nil, message:"chore(config): 提交配置变更", commit_file_params:nil)
|
|
447
447
|
# gitee.com 仓库自动去除代理;is_gitee_repo? 命令已带 -C,无需 chdir
|
|
448
448
|
if is_gitee_repo?(local_repo_dir: path)
|
|
449
449
|
return without_proxy { git_addpush_repo_impl(path: path, message: message, commit_file_params: commit_file_params) }
|
|
@@ -452,7 +452,7 @@ module Pindo
|
|
|
452
452
|
git_addpush_repo_impl(path: path, message: message, commit_file_params: commit_file_params)
|
|
453
453
|
end
|
|
454
454
|
|
|
455
|
-
def git_addpush_repo_impl(path:nil, message:"
|
|
455
|
+
def git_addpush_repo_impl(path:nil, message:"chore(config): 提交配置变更", commit_file_params:nil)
|
|
456
456
|
current=Dir.pwd
|
|
457
457
|
Dir.chdir(path)
|
|
458
458
|
begin
|
|
@@ -467,7 +467,7 @@ module Pindo
|
|
|
467
467
|
end
|
|
468
468
|
end
|
|
469
469
|
if need_commit
|
|
470
|
-
git! ['commit', '-m
|
|
470
|
+
git! ['commit', '-m', message]
|
|
471
471
|
git! ['push']
|
|
472
472
|
else
|
|
473
473
|
# puts "\n#{path}\n!!!仓库中文件未发生变化,无需提交!!!\n"
|
|
@@ -478,7 +478,7 @@ module Pindo
|
|
|
478
478
|
# puts files_list
|
|
479
479
|
if !files_list.nil? && files_list.size > 0
|
|
480
480
|
git! ['add', '-A']
|
|
481
|
-
git! ['commit', '-m
|
|
481
|
+
git! ['commit', '-m', message]
|
|
482
482
|
git! ['push']
|
|
483
483
|
else
|
|
484
484
|
puts "\n#{path}\n!!!仓库中文件未发生变化,无需提交!!!\n"
|
|
@@ -620,7 +620,7 @@ module Pindo
|
|
|
620
620
|
|
|
621
621
|
def handle_commit_all(project_dir, branch, commit_message = nil)
|
|
622
622
|
# 使用传入的 commit_message,如果没有则使用默认值
|
|
623
|
-
message = commit_message || "build: 构建产生提交"
|
|
623
|
+
message = commit_message || "chore(build): 构建产生提交"
|
|
624
624
|
|
|
625
625
|
Funlog.instance.fancyinfo_start("开始提交文件...")
|
|
626
626
|
git! ['add', '-A']
|
|
@@ -150,7 +150,7 @@ module Pindo
|
|
|
150
150
|
|
|
151
151
|
pindo_dir = File.expand_path(pindo_single_config.pindo_dir)
|
|
152
152
|
config_repo_dir = File.join(pindo_dir, @bundle_id)
|
|
153
|
-
Pindo::GitHandler.git_addpush_repo(path: config_repo_dir, message: "
|
|
153
|
+
Pindo::GitHandler.git_addpush_repo(path: config_repo_dir, message: "chore(config): 下载应用 iap 配置", commit_file_params: ["fastlane/iap/iap_appstore_download.json"])
|
|
154
154
|
|
|
155
155
|
update_app_share_secrets(app_id: app_id, need_create: false)
|
|
156
156
|
end
|
|
@@ -295,7 +295,7 @@ module Pindo
|
|
|
295
295
|
file.close
|
|
296
296
|
end
|
|
297
297
|
|
|
298
|
-
Pindo::GitHandler.git_addpush_repo(path: config_repo_dir, message: "
|
|
298
|
+
Pindo::GitHandler.git_addpush_repo(path: config_repo_dir, message: "chore(config): 更新应用 shared secret", commit_file_params: ["config.json"])
|
|
299
299
|
|
|
300
300
|
end
|
|
301
301
|
|
|
@@ -211,7 +211,7 @@ module Pindo
|
|
|
211
211
|
# 只提交 config.json 到 Git 仓库
|
|
212
212
|
Pindo::GitHandler.git_addpush_repo(
|
|
213
213
|
path: app_config_dir,
|
|
214
|
-
message: "
|
|
214
|
+
message: "chore(config): 同步 Apple Developer Portal 的 capabilities",
|
|
215
215
|
commit_file_params: ["config.json"]
|
|
216
216
|
)
|
|
217
217
|
|
|
@@ -17,7 +17,7 @@ module Pindo
|
|
|
17
17
|
class Autoresign < Ios
|
|
18
18
|
|
|
19
19
|
include Appselect
|
|
20
|
-
self.summary = 'IPA
|
|
20
|
+
self.summary = 'iOS IPA / macOS App 重签名工具'
|
|
21
21
|
|
|
22
22
|
# 启用缓存机制
|
|
23
23
|
def self.use_cache?
|
|
@@ -25,7 +25,7 @@ module Pindo
|
|
|
25
25
|
end
|
|
26
26
|
|
|
27
27
|
self.description = <<-DESC
|
|
28
|
-
使用最新的证书重签名IPA
|
|
28
|
+
使用最新的证书重签名 iOS IPA 或 macOS App。
|
|
29
29
|
|
|
30
30
|
支持功能:
|
|
31
31
|
|
|
@@ -35,6 +35,8 @@ module Pindo
|
|
|
35
35
|
|
|
36
36
|
* 支持指定IPA路径
|
|
37
37
|
|
|
38
|
+
* 使用 --macos 对 macOS .app 目录进行 Developer ID / Development 重签名
|
|
39
|
+
|
|
38
40
|
* 支持上传到JPS测试平台
|
|
39
41
|
|
|
40
42
|
* 支持发送测试通知
|
|
@@ -47,6 +49,10 @@ module Pindo
|
|
|
47
49
|
|
|
48
50
|
$ pindo ios autoresign demo.ipa # 重签名指定IPA文件
|
|
49
51
|
|
|
52
|
+
$ pindo ios autoresign Demo.app --macos # 重签名指定 macOS App
|
|
53
|
+
|
|
54
|
+
$ pindo ios autoresign --app=Demo.app --macos # 使用选项指定 macOS App
|
|
55
|
+
|
|
50
56
|
$ pindo ios autoresign --adhoc # 使用adhoc证书重签名
|
|
51
57
|
|
|
52
58
|
$ pindo ios autoresign --deploy # 使用发布bundle id
|
|
@@ -65,7 +71,7 @@ module Pindo
|
|
|
65
71
|
DESC
|
|
66
72
|
|
|
67
73
|
self.arguments = [
|
|
68
|
-
CLAide::Argument.new('path/to/demo.ipa', true),
|
|
74
|
+
CLAide::Argument.new('path/to/demo.ipa|path/to/Demo.app', true),
|
|
69
75
|
]
|
|
70
76
|
|
|
71
77
|
def self.option_items
|
|
@@ -73,11 +79,11 @@ module Pindo
|
|
|
73
79
|
items = []
|
|
74
80
|
|
|
75
81
|
# 添加工具参数(ToolOptions)
|
|
76
|
-
items.concat(Pindo::Options::ToolOptions.select(:ipa, :deploy))
|
|
82
|
+
items.concat(Pindo::Options::ToolOptions.select(:ipa, :app, :deploy))
|
|
77
83
|
|
|
78
84
|
# 添加构建类型参数(BuildOptions)
|
|
79
85
|
items.concat(Pindo::Options::BuildOptions.select(
|
|
80
|
-
:dev, :adhoc, :develop_id, :build_type
|
|
86
|
+
:bundleid, :dev, :adhoc, :develop_id, :build_type
|
|
81
87
|
))
|
|
82
88
|
|
|
83
89
|
# 添加证书相关参数(CertOptions)
|
|
@@ -106,9 +112,10 @@ module Pindo
|
|
|
106
112
|
@options = initialize_options(argv)
|
|
107
113
|
|
|
108
114
|
# 优先使用选项参数,如果没有则使用位置参数
|
|
109
|
-
@args_ipa_file = @options[:ipa] || positional_ipa
|
|
115
|
+
@args_ipa_file = @options[:app] || @options[:ipa] || positional_ipa
|
|
110
116
|
|
|
111
117
|
@args_deploy_flag = @options[:deploy]
|
|
118
|
+
@args_bundle_id = @options[:bundleid]
|
|
112
119
|
|
|
113
120
|
# JPS 参数(从 options 中获取)
|
|
114
121
|
@args_upload_flag = @options[:upload]
|
|
@@ -154,7 +161,8 @@ module Pindo
|
|
|
154
161
|
|
|
155
162
|
# 处理平台类型
|
|
156
163
|
@platform_type = @options[:platform]
|
|
157
|
-
|
|
164
|
+
# --app 只用于 macOS,指定即隐含 macOS 平台,无需再显式加 --macos
|
|
165
|
+
if @args_macos_flag || @options[:app]
|
|
158
166
|
@platform_type = 'macos'
|
|
159
167
|
end
|
|
160
168
|
|
|
@@ -165,15 +173,18 @@ module Pindo
|
|
|
165
173
|
|
|
166
174
|
super
|
|
167
175
|
@additional_args = argv.remainder!
|
|
176
|
+
unless @additional_args.empty?
|
|
177
|
+
raise Informative, "只允许指定一个安装包路径,多余参数: #{@additional_args.join(' ')}"
|
|
178
|
+
end
|
|
168
179
|
end
|
|
169
180
|
|
|
170
181
|
|
|
171
182
|
def run
|
|
172
183
|
begin
|
|
173
|
-
# 1.
|
|
184
|
+
# 1. 查找待签名包(iOS 为 IPA,macOS 为 .app)
|
|
174
185
|
ipa_file_path = find_ipa_file()
|
|
175
186
|
unless ipa_file_path && File.exist?(ipa_file_path)
|
|
176
|
-
raise Informative, "
|
|
187
|
+
raise Informative, "未找到需要重签名的安装包"
|
|
177
188
|
end
|
|
178
189
|
|
|
179
190
|
# 2. 选择 Bundle ID
|
|
@@ -187,7 +198,7 @@ module Pindo
|
|
|
187
198
|
app_info_obj, workflow_info = prepare_jps_config()
|
|
188
199
|
|
|
189
200
|
# 5. 计算重签名后的 IPA 文件名
|
|
190
|
-
resigned_ipa_file = ipa_file_path
|
|
201
|
+
resigned_ipa_file = resigned_package_path(ipa_file_path)
|
|
191
202
|
|
|
192
203
|
# 6. 创建任务
|
|
193
204
|
tasks = create_resign_tasks(
|
|
@@ -214,21 +225,25 @@ module Pindo
|
|
|
214
225
|
|
|
215
226
|
# 查找 IPA 文件
|
|
216
227
|
def find_ipa_file
|
|
217
|
-
# 1.
|
|
218
|
-
if @args_ipa_file
|
|
219
|
-
|
|
228
|
+
# 1. 如果通过选项或位置参数指定了安装包,严格校验后直接返回
|
|
229
|
+
if @args_ipa_file
|
|
230
|
+
unless File.exist?(@args_ipa_file)
|
|
231
|
+
raise Informative, "指定的安装包不存在: #{@args_ipa_file}"
|
|
232
|
+
end
|
|
233
|
+
validate_package_path!(@args_ipa_file)
|
|
234
|
+
puts "\n使用指定的安装包: #{@args_ipa_file}"
|
|
220
235
|
puts "修改时间: #{File.mtime(@args_ipa_file)}"
|
|
221
236
|
return @args_ipa_file
|
|
222
237
|
end
|
|
223
238
|
|
|
224
239
|
# 2. 在当前目录查找最新的非 _resigned 的 IPA
|
|
225
240
|
current_dir = Dir.pwd
|
|
226
|
-
|
|
241
|
+
pattern = macos_platform? ? "*.app" : "*.ipa"
|
|
242
|
+
ipa_files = Dir.glob(File.join(current_dir, pattern))
|
|
227
243
|
|
|
228
|
-
#
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
end
|
|
244
|
+
# 排除已经重签名的产物并找到最新安装包
|
|
245
|
+
ipa_files.reject! { |f| File.basename(f).include?("_resigned") }
|
|
246
|
+
ipa_file = ipa_files.max_by { |f| File.mtime(f) }
|
|
232
247
|
|
|
233
248
|
if ipa_file && File.exist?(ipa_file)
|
|
234
249
|
puts "\n自动找到 IPA 文件: #{ipa_file}"
|
|
@@ -237,12 +252,13 @@ module Pindo
|
|
|
237
252
|
end
|
|
238
253
|
|
|
239
254
|
# 3. 如果没有找到,从终端输入
|
|
240
|
-
|
|
241
|
-
puts "
|
|
255
|
+
package_name = macos_platform? ? "macOS .app" : "IPA"
|
|
256
|
+
puts "\n⚠️ 未找到 #{package_name}"
|
|
257
|
+
puts "请输入 #{package_name} 路径(支持相对路径或绝对路径):"
|
|
242
258
|
|
|
243
|
-
ipa_path = ask("
|
|
244
|
-
q.validate = /\.ipa$/i
|
|
245
|
-
q.responses[:not_valid] = "❌ 请输入有效的
|
|
259
|
+
ipa_path = ask("安装包路径: ") do |q|
|
|
260
|
+
q.validate = macos_platform? ? /\.app$/i : /\.ipa$/i
|
|
261
|
+
q.responses[:not_valid] = "❌ 请输入有效的 #{package_name} 路径"
|
|
246
262
|
end
|
|
247
263
|
|
|
248
264
|
# 去除首尾空格
|
|
@@ -251,7 +267,8 @@ module Pindo
|
|
|
251
267
|
# 验证文件是否存在
|
|
252
268
|
if ipa_path && !ipa_path.empty?
|
|
253
269
|
if File.exist?(ipa_path)
|
|
254
|
-
|
|
270
|
+
validate_package_path!(ipa_path)
|
|
271
|
+
puts "✓ 使用输入的安装包: #{ipa_path}"
|
|
255
272
|
puts " 修改时间: #{File.mtime(ipa_path)}"
|
|
256
273
|
return ipa_path
|
|
257
274
|
else
|
|
@@ -262,8 +279,32 @@ module Pindo
|
|
|
262
279
|
nil
|
|
263
280
|
end
|
|
264
281
|
|
|
282
|
+
def macos_platform?
|
|
283
|
+
@platform_type.to_s.downcase == 'macos'
|
|
284
|
+
end
|
|
285
|
+
|
|
286
|
+
def validate_package_path!(path)
|
|
287
|
+
if macos_platform?
|
|
288
|
+
unless File.directory?(path) && path.downcase.end_with?('.app')
|
|
289
|
+
raise Informative, "--macos 模式要求输入 macOS .app 目录: #{path}"
|
|
290
|
+
end
|
|
291
|
+
elsif !File.file?(path) || !path.downcase.end_with?('.ipa')
|
|
292
|
+
raise Informative, "iOS 模式要求输入 .ipa 文件: #{path}"
|
|
293
|
+
end
|
|
294
|
+
end
|
|
295
|
+
|
|
296
|
+
def resigned_package_path(path)
|
|
297
|
+
extension = macos_platform? ? '.app' : '.ipa'
|
|
298
|
+
path.sub(/#{Regexp.escape(extension)}$/i, "_resigned#{extension}")
|
|
299
|
+
end
|
|
300
|
+
|
|
265
301
|
# 选择 Bundle ID(根据 build_type)
|
|
266
302
|
def select_bundle_id
|
|
303
|
+
if @args_bundle_id && !@args_bundle_id.empty?
|
|
304
|
+
puts "\n使用指定的 Bundle ID: #{@args_bundle_id}"
|
|
305
|
+
return @args_bundle_id
|
|
306
|
+
end
|
|
307
|
+
|
|
267
308
|
if @args_deploy_flag || @build_type != 'development'
|
|
268
309
|
get_selected_deploy_bundleid()
|
|
269
310
|
else
|
|
@@ -274,8 +315,9 @@ module Pindo
|
|
|
274
315
|
# 拉取应用配置
|
|
275
316
|
def pull_app_config(bundle_id)
|
|
276
317
|
require 'pindo/config/build_info_manager'
|
|
318
|
+
repo_name = bundle_id.sub(/\.\*$/, '')
|
|
277
319
|
Pindo::BuildInfoManager.share_instance.pull_appconfig_with_reponame(
|
|
278
|
-
repo_name:
|
|
320
|
+
repo_name: repo_name,
|
|
279
321
|
target_dir: Dir.pwd
|
|
280
322
|
)
|
|
281
323
|
end
|
|
@@ -283,9 +325,8 @@ module Pindo
|
|
|
283
325
|
# 准备 JPS 配置
|
|
284
326
|
def prepare_jps_config
|
|
285
327
|
if @args_upload_flag
|
|
286
|
-
#
|
|
287
|
-
|
|
288
|
-
package_type = is_macos ? 'mac' : 'ipa'
|
|
328
|
+
# 以平台类型为唯一判定口径,与 create_resign_tasks 的上传任务保持一致
|
|
329
|
+
package_type = macos_platform? ? 'mac' : 'ipa'
|
|
289
330
|
app_info_obj, workflow_info = PgyerHelper.share_instace.prepare_upload(
|
|
290
331
|
working_directory: Dir.pwd,
|
|
291
332
|
conf: @args_conf,
|
|
@@ -327,7 +368,7 @@ module Pindo
|
|
|
327
368
|
# 2. 上传任务(仅在需要时创建)
|
|
328
369
|
if @args_upload_flag && app_info_obj
|
|
329
370
|
upload_task = Pindo::TaskSystem::JPSUploadTask.new(
|
|
330
|
-
'ipa',
|
|
371
|
+
macos_platform? ? 'mac' : 'ipa',
|
|
331
372
|
Dir.pwd,
|
|
332
373
|
resigned_ipa_file,
|
|
333
374
|
app_info_obj: app_info_obj,
|
|
@@ -270,7 +270,7 @@ module Pindo
|
|
|
270
270
|
begin FileUtils.mkdir_p(dest_dir) rescue StandardError => e end
|
|
271
271
|
FileUtils.cp_r(podspec, File.join(dest_dir, File.basename(podspec)))
|
|
272
272
|
puts "上传到仓库 #{private_source.repo}"
|
|
273
|
-
git_addpush_repo(path:private_source.repo, message:"
|
|
273
|
+
git_addpush_repo(path:private_source.repo, message:"chore(pod): 添加 #{pod_name} #{tag_name}")
|
|
274
274
|
end
|
|
275
275
|
end
|
|
276
276
|
|
|
@@ -188,7 +188,7 @@ module Pindo
|
|
|
188
188
|
tag_type: @args_tag_type,
|
|
189
189
|
tag_pre: @args_tag_pre,
|
|
190
190
|
process_type: process_type,
|
|
191
|
-
commit_message: "chore:
|
|
191
|
+
commit_message: "chore(nuget): 更新 nuget v#{confirmed_version} Release Notes",
|
|
192
192
|
fixed_version: confirmed_version # 传入确认后的版本号
|
|
193
193
|
)
|
|
194
194
|
tasks << git_commit_task
|
|
@@ -184,7 +184,7 @@ module Pindo
|
|
|
184
184
|
# 提交到 Git 仓库
|
|
185
185
|
Pindo::GitHandler.git_addpush_repo(
|
|
186
186
|
path: app_config_dir,
|
|
187
|
-
message: "
|
|
187
|
+
message: "chore(config): 同步 Apple Developer Portal 的 capabilities",
|
|
188
188
|
commit_file_params: ["config.json"]
|
|
189
189
|
)
|
|
190
190
|
|
|
@@ -220,7 +220,7 @@ module Pindo
|
|
|
220
220
|
f.write(JSON.pretty_generate(git_repo_json))
|
|
221
221
|
end
|
|
222
222
|
|
|
223
|
-
Pindo::GitHandler.git_addpush_repo(path: pindo_setting_dir, message: "
|
|
223
|
+
Pindo::GitHandler.git_addpush_repo(path: pindo_setting_dir, message: "chore(config): 添加 #{repo_name} 仓库")
|
|
224
224
|
end
|
|
225
225
|
|
|
226
226
|
# 更新应用配置仓库(从模板复制)
|
|
@@ -252,7 +252,7 @@ module Pindo
|
|
|
252
252
|
end
|
|
253
253
|
|
|
254
254
|
# 提交并推送到远程仓库
|
|
255
|
-
Pindo::GitHandler.git_addpush_repo(path: app_config_dir, message: "
|
|
255
|
+
Pindo::GitHandler.git_addpush_repo(path: app_config_dir, message: "chore(config): 初始化应用配置")
|
|
256
256
|
end
|
|
257
257
|
end
|
|
258
258
|
|
|
@@ -186,7 +186,7 @@ module Pindo
|
|
|
186
186
|
if File.exist?(app_config_file)
|
|
187
187
|
modify_appconfig_file(config_file: app_config_file, app_info_detail: app)
|
|
188
188
|
Pindo::GitHandler.prepare_gitenv()
|
|
189
|
-
Pindo::GitHandler.git_addpush_repo(path: app_config_dir, message: "
|
|
189
|
+
Pindo::GitHandler.git_addpush_repo(path: app_config_dir, message: "chore(config): 修改 apple id")
|
|
190
190
|
end
|
|
191
191
|
rescue StandardError => e
|
|
192
192
|
puts "更新远程配置仓库失败: #{e.message}"
|
|
@@ -127,7 +127,7 @@ module Pindo
|
|
|
127
127
|
f.write(JSON.pretty_generate(swark_authorize_json))
|
|
128
128
|
end
|
|
129
129
|
|
|
130
|
-
Pindo::GitHandler.git_addpush_repo(path: app_config_dir, message: "
|
|
130
|
+
Pindo::GitHandler.git_addpush_repo(path: app_config_dir, message: "chore(config): 添加 swark 授权配置")
|
|
131
131
|
end
|
|
132
132
|
|
|
133
133
|
end
|
|
@@ -143,7 +143,7 @@ module Pindo
|
|
|
143
143
|
|
|
144
144
|
# 提交并推送到远程仓库
|
|
145
145
|
Pindo::GitHandler.prepare_gitenv()
|
|
146
|
-
Pindo::GitHandler.git_addpush_repo(path: cert_repo_dir, message: "
|
|
146
|
+
Pindo::GitHandler.git_addpush_repo(path: cert_repo_dir, message: "chore(cert): 删除 #{apple_id} 的证书")
|
|
147
147
|
|
|
148
148
|
puts "✓ Git 仓库证书清理完成"
|
|
149
149
|
end
|
|
@@ -65,7 +65,7 @@ module Pindo
|
|
|
65
65
|
FileUtils.cp_r(File.join(push_path, "."), push_repo_dir)
|
|
66
66
|
|
|
67
67
|
Pindo::GitHandler.prepare_gitenv()
|
|
68
|
-
Pindo::GitHandler.git_addpush_repo(path: app_config_dir, message: "
|
|
68
|
+
Pindo::GitHandler.git_addpush_repo(path: app_config_dir, message: "chore(cert): 添加推送证书")
|
|
69
69
|
|
|
70
70
|
puts "✓ 证书已上传到配置仓库: #{push_repo_dir}"
|
|
71
71
|
end
|
|
@@ -432,7 +432,7 @@ module Pindo
|
|
|
432
432
|
|
|
433
433
|
# 确保已登录
|
|
434
434
|
unless login
|
|
435
|
-
raise Informative, "
|
|
435
|
+
raise Informative, "JPS 未登录或登录已失效,请执行 pindo jps login 重新登录"
|
|
436
436
|
end
|
|
437
437
|
|
|
438
438
|
# 获取 app_info_obj
|
|
@@ -506,7 +506,7 @@ module Pindo
|
|
|
506
506
|
end
|
|
507
507
|
|
|
508
508
|
unless login
|
|
509
|
-
raise Informative, "
|
|
509
|
+
raise Informative, "JPS 未登录或登录已失效,请执行 pindo jps login 重新登录"
|
|
510
510
|
end
|
|
511
511
|
|
|
512
512
|
puts "[PINDO_DEBUG] 正在查找项目: #{config_result[:project_name]}" if ENV['PINDO_DEBUG']
|
|
@@ -686,7 +686,7 @@ module Pindo
|
|
|
686
686
|
|
|
687
687
|
|
|
688
688
|
else
|
|
689
|
-
raise Informative, "
|
|
689
|
+
raise Informative, "JPS 未登录或登录已失效,请执行 pindo jps login 重新登录"
|
|
690
690
|
end
|
|
691
691
|
@proj_name = upload_proj_name
|
|
692
692
|
app_info_obj
|
|
@@ -751,23 +751,7 @@ module Pindo
|
|
|
751
751
|
if !ipa_file_upload.nil? &&
|
|
752
752
|
File.extname(ipa_file_upload).downcase.eql?(".exe")
|
|
753
753
|
|
|
754
|
-
|
|
755
|
-
windows_build_dir = File.dirname(windows_exe_path)
|
|
756
|
-
windows_zip_dir = File.dirname(windows_build_dir)
|
|
757
|
-
windows_build_name = File.basename(windows_exe_path, File.extname(windows_exe_path))
|
|
758
|
-
windows_exe_name = File.basename(windows_exe_path)
|
|
759
|
-
windows_zip_fullname = File.join(windows_zip_dir, windows_build_name + ".zip")
|
|
760
|
-
|
|
761
|
-
if File.exist?(windows_zip_fullname)
|
|
762
|
-
FileUtils.rm_rf(windows_zip_fullname)
|
|
763
|
-
end
|
|
764
|
-
|
|
765
|
-
Zip::File.open(windows_zip_fullname, Zip::File::CREATE) do |zipfile|
|
|
766
|
-
Dir.chdir(windows_build_dir) do
|
|
767
|
-
zipfile.add(windows_exe_name, windows_exe_name)
|
|
768
|
-
end
|
|
769
|
-
end
|
|
770
|
-
ipa_file_upload = windows_zip_fullname
|
|
754
|
+
ipa_file_upload = package_windows_exe_for_upload(ipa_file_upload)
|
|
771
755
|
end
|
|
772
756
|
unless !ipa_file_upload.nil? && File.exist?(ipa_file_upload)
|
|
773
757
|
return
|
|
@@ -898,6 +882,25 @@ module Pindo
|
|
|
898
882
|
|
|
899
883
|
end
|
|
900
884
|
|
|
885
|
+
def package_windows_exe_for_upload(exe_file_upload)
|
|
886
|
+
windows_exe_path = File.expand_path(exe_file_upload)
|
|
887
|
+
windows_build_dir = File.dirname(windows_exe_path)
|
|
888
|
+
windows_zip_dir = File.dirname(windows_build_dir)
|
|
889
|
+
windows_build_name = File.basename(windows_exe_path, File.extname(windows_exe_path))
|
|
890
|
+
windows_exe_name = File.basename(windows_exe_path)
|
|
891
|
+
windows_zip_fullname = File.join(windows_zip_dir, windows_build_name + ".zip")
|
|
892
|
+
|
|
893
|
+
if File.exist?(windows_zip_fullname)
|
|
894
|
+
FileUtils.rm_rf(windows_zip_fullname)
|
|
895
|
+
end
|
|
896
|
+
|
|
897
|
+
Zip::File.open(windows_zip_fullname, Zip::File::CREATE) do |zipfile|
|
|
898
|
+
zipfile.add(windows_exe_name, windows_exe_path)
|
|
899
|
+
end
|
|
900
|
+
|
|
901
|
+
windows_zip_fullname
|
|
902
|
+
end
|
|
903
|
+
|
|
901
904
|
# 上传 media 文件(图片、视频等)到 JPS
|
|
902
905
|
# 上传成功后自动更新 commit_log 记录
|
|
903
906
|
#
|
|
@@ -1457,7 +1460,7 @@ module Pindo
|
|
|
1457
1460
|
|
|
1458
1461
|
if app_info_list.nil?
|
|
1459
1462
|
Funlog.instance.fancyinfo_error("拉取app信息列表失败!")
|
|
1460
|
-
raise Informative, "JPS网络数据异常,请检查网络连接或重新登录(pindo
|
|
1463
|
+
raise Informative, "JPS网络数据异常,请检查网络连接或重新登录(pindo jps login)"
|
|
1461
1464
|
end
|
|
1462
1465
|
|
|
1463
1466
|
return app_info_list
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
require 'pindo/module/xcode/ipa_resign_helper'
|
|
2
|
+
|
|
3
|
+
module Pindo
|
|
4
|
+
module Resign
|
|
5
|
+
class IpaResignAdapter
|
|
6
|
+
def resign(package_path:, bundle_id:, **_options)
|
|
7
|
+
Pindo::IpaResignHelper.resign_ipa(
|
|
8
|
+
ipa_file_path: package_path,
|
|
9
|
+
bundle_id: bundle_id
|
|
10
|
+
)
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
require 'pindo/module/xcode/mac_app_resign_helper'
|
|
2
|
+
|
|
3
|
+
module Pindo
|
|
4
|
+
module Resign
|
|
5
|
+
class MacAppResignAdapter
|
|
6
|
+
def resign(package_path:, bundle_id:, signing_identity:, profiles:, **_options)
|
|
7
|
+
Pindo::MacAppResignHelper.resign_app(
|
|
8
|
+
app_path: package_path,
|
|
9
|
+
bundle_id: bundle_id,
|
|
10
|
+
signing_identity: signing_identity,
|
|
11
|
+
profiles: profiles
|
|
12
|
+
)
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -200,7 +200,7 @@ module Pindo
|
|
|
200
200
|
git_helper = Pindo::GitRepoHelper.share_instance
|
|
201
201
|
git_helper.git_addpush_repo(
|
|
202
202
|
path: app_config_repo_dir,
|
|
203
|
-
message: "
|
|
203
|
+
message: "chore(config): 递增 build number",
|
|
204
204
|
commit_file_params: ["config.json"]
|
|
205
205
|
)
|
|
206
206
|
end
|
|
@@ -173,7 +173,7 @@ module Pindo
|
|
|
173
173
|
git_helper = Pindo::GitRepoHelper.share_instance
|
|
174
174
|
git_helper.git_addpush_repo(
|
|
175
175
|
path: app_config_repo_dir,
|
|
176
|
-
message: "
|
|
176
|
+
message: "chore(config): 递增 build number",
|
|
177
177
|
commit_file_params: ["config.json"]
|
|
178
178
|
)
|
|
179
179
|
end
|
|
@@ -27,7 +27,7 @@ module Pindo
|
|
|
27
27
|
# - tag_pre: tag前缀,默认 'v'
|
|
28
28
|
# - fixed_version: 外部指定的固定版本号
|
|
29
29
|
# - process_type: 未提交文件的处理方式 ('skip', 'commit', 'reset', 'stash'),默认 'skip'
|
|
30
|
-
# - commit_message: 提交消息,默认 'build: 构建产生提交'
|
|
30
|
+
# - commit_message: 提交消息,默认 'chore(build): 构建产生提交'
|
|
31
31
|
#
|
|
32
32
|
# 版本号计算逻辑:
|
|
33
33
|
# 1. 如果 fixed_version 为 nil 且 HEAD 存在 tag 且工作目录干净,
|
|
@@ -38,7 +38,7 @@ module Pindo
|
|
|
38
38
|
# GitCommitTask 特有的属性
|
|
39
39
|
@fixed_version = options[:fixed_version] # 外部指定的固定版本号
|
|
40
40
|
@process_type = options[:process_type] || Pindo::UncommittedFilesProcessType::SKIP_WITH_TAG # 默认跳过但打tag
|
|
41
|
-
@commit_message = options[:commit_message] || 'build: 构建产生提交' # 默认提交消息
|
|
41
|
+
@commit_message = options[:commit_message] || 'chore(build): 构建产生提交' # 默认提交消息
|
|
42
42
|
|
|
43
43
|
options[:project_path] = project_path
|
|
44
44
|
# 调用基类初始化(基类会设置 release_branch, ver_inc, tag_type, tag_pre 等通用属性)
|
|
@@ -3,6 +3,8 @@ require 'pindo/module/task/task_config'
|
|
|
3
3
|
require 'pindo/module/cert/cert_helper'
|
|
4
4
|
require 'pindo/config/ios_config_parser'
|
|
5
5
|
require 'pindo/module/xcode/ipa_resign_helper'
|
|
6
|
+
require 'pindo/module/resign/ipa_resign_adapter'
|
|
7
|
+
require 'pindo/module/resign/mac_app_resign_adapter'
|
|
6
8
|
|
|
7
9
|
module Pindo
|
|
8
10
|
module TaskSystem
|
|
@@ -62,7 +64,7 @@ module Pindo
|
|
|
62
64
|
# 设置任务优先级
|
|
63
65
|
options[:priority] ||= TaskPriority::HIGH
|
|
64
66
|
|
|
65
|
-
super("
|
|
67
|
+
super("本地重签名", options)
|
|
66
68
|
end
|
|
67
69
|
|
|
68
70
|
# 验证任务参数
|
|
@@ -95,14 +97,16 @@ module Pindo
|
|
|
95
97
|
|
|
96
98
|
# 执行重签名
|
|
97
99
|
def do_work
|
|
98
|
-
# 1.
|
|
100
|
+
# 1. 确定要重签名的安装包
|
|
99
101
|
ipa_to_resign = determine_ipa_file
|
|
100
102
|
unless ipa_to_resign && File.exist?(ipa_to_resign)
|
|
101
|
-
raise "
|
|
103
|
+
raise "未找到需要重签名的安装包"
|
|
102
104
|
end
|
|
103
105
|
|
|
106
|
+
validate_package_type!(ipa_to_resign)
|
|
107
|
+
|
|
104
108
|
puts "\n▶ 重签名信息"
|
|
105
|
-
puts "
|
|
109
|
+
puts " 安装包: #{File.basename(ipa_to_resign)}"
|
|
106
110
|
puts " Bundle ID: #{@bundle_id}"
|
|
107
111
|
puts " 类型: #{@build_type}"
|
|
108
112
|
cert_info = []
|
|
@@ -114,17 +118,23 @@ module Pindo
|
|
|
114
118
|
load_config_if_needed
|
|
115
119
|
|
|
116
120
|
# 3. 安装证书
|
|
117
|
-
install_certificate
|
|
121
|
+
provisioning_info_array = install_certificate
|
|
118
122
|
|
|
119
123
|
# 4. 执行重签名
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
124
|
+
signing_identity = Array(provisioning_info_array)
|
|
125
|
+
.map { |item| item['signing_identity'] }
|
|
126
|
+
.compact
|
|
127
|
+
.first
|
|
128
|
+
resigned_ipa = resign_adapter.resign(
|
|
129
|
+
package_path: ipa_to_resign,
|
|
130
|
+
bundle_id: @bundle_id,
|
|
131
|
+
signing_identity: signing_identity,
|
|
132
|
+
profiles: provisioning_info_array
|
|
123
133
|
)
|
|
124
134
|
|
|
125
135
|
# 5. 验证重签名结果
|
|
126
136
|
unless resigned_ipa && File.exist?(resigned_ipa)
|
|
127
|
-
raise "
|
|
137
|
+
raise "重签名失败:未生成重签名后的安装包"
|
|
128
138
|
end
|
|
129
139
|
|
|
130
140
|
puts "✅ 重签名完成: #{File.basename(resigned_ipa)}\n"
|
|
@@ -146,13 +156,36 @@ module Pindo
|
|
|
146
156
|
end
|
|
147
157
|
end
|
|
148
158
|
|
|
159
|
+
def macos_platform?
|
|
160
|
+
@platform_type.to_s.downcase == 'macos'
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
def validate_package_type!(path)
|
|
164
|
+
valid = if macos_platform?
|
|
165
|
+
File.directory?(path) && path.downcase.end_with?('.app')
|
|
166
|
+
else
|
|
167
|
+
File.file?(path) && path.downcase.end_with?('.ipa')
|
|
168
|
+
end
|
|
169
|
+
expected = macos_platform? ? 'macOS .app 目录' : '.ipa 文件'
|
|
170
|
+
raise "当前平台要求输入 #{expected}: #{path}" unless valid
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
def resign_adapter
|
|
174
|
+
if macos_platform?
|
|
175
|
+
Pindo::Resign::MacAppResignAdapter.new
|
|
176
|
+
else
|
|
177
|
+
Pindo::Resign::IpaResignAdapter.new
|
|
178
|
+
end
|
|
179
|
+
end
|
|
180
|
+
|
|
149
181
|
# 查找最新的 IPA 文件(排除 _resigned.ipa)
|
|
150
182
|
def find_latest_ipa_file
|
|
151
183
|
unless File.directory?(@ipa_path)
|
|
152
184
|
return nil
|
|
153
185
|
end
|
|
154
186
|
|
|
155
|
-
|
|
187
|
+
pattern = macos_platform? ? '*.app' : '*.ipa'
|
|
188
|
+
ipa_files = Dir.glob(File.join(@ipa_path, pattern))
|
|
156
189
|
|
|
157
190
|
# 过滤掉 _resigned.ipa 文件
|
|
158
191
|
ipa_files = ipa_files.reject { |f| File.basename(f).include?("_resigned") }
|
|
@@ -204,6 +237,7 @@ module Pindo
|
|
|
204
237
|
unless provisioning_info_array && !provisioning_info_array.empty?
|
|
205
238
|
raise "证书获取失败:未找到有效的证书信息"
|
|
206
239
|
end
|
|
240
|
+
provisioning_info_array
|
|
207
241
|
end
|
|
208
242
|
end
|
|
209
243
|
end
|
|
@@ -57,7 +57,7 @@ module Pindo
|
|
|
57
57
|
current_branch = Pindo::GitHandler.git!(%W(-C #{current_git_root_path} rev-parse --abbrev-ref HEAD)).strip
|
|
58
58
|
Pindo::GitHandler.git!(%W(-C #{current_git_root_path} add cliff.toml))
|
|
59
59
|
# .gitignore 已由 check_gitignore 自动添加到暂存区,无需重复添加
|
|
60
|
-
commit_message = "docs: 添加日志变更配置".encode('UTF-8')
|
|
60
|
+
commit_message = "docs(config): 添加日志变更配置".encode('UTF-8')
|
|
61
61
|
Pindo::GitHandler.git!(%W(-C #{current_git_root_path} commit -m #{commit_message}))
|
|
62
62
|
Pindo::GitHandler.git!(%W(-C #{current_git_root_path} push origin #{current_branch}))
|
|
63
63
|
else
|
|
@@ -158,7 +158,7 @@ module Pindo
|
|
|
158
158
|
current_branch = Pindo::GitHandler.git!(%W(-C #{git_root_dir} rev-parse --abbrev-ref HEAD)).strip
|
|
159
159
|
|
|
160
160
|
# 提交
|
|
161
|
-
commit_message = "chore: 更新 .gitignore 规则"
|
|
161
|
+
commit_message = "chore(config): 更新 .gitignore 规则"
|
|
162
162
|
Pindo::GitHandler.git!(%W(-C #{git_root_dir} commit -m #{commit_message}))
|
|
163
163
|
Funlog.instance.fancyinfo_success("已自动提交 .gitignore 更改")
|
|
164
164
|
|
|
@@ -230,7 +230,7 @@ module Pindo
|
|
|
230
230
|
begin
|
|
231
231
|
Pindo::GitHandler.git_addpush_repo(
|
|
232
232
|
path: config_dir,
|
|
233
|
-
message: "Applovin SKAdNetworkItems",
|
|
233
|
+
message: "chore(config): 更新 Applovin SKAdNetworkItems",
|
|
234
234
|
commit_file_params: ["applovin_client_config.json"]
|
|
235
235
|
)
|
|
236
236
|
puts "✓ 配置已保存到远程仓库"
|
|
@@ -187,7 +187,7 @@ module Pindo
|
|
|
187
187
|
FileUtils.cp(proj_pod_file, File.join(app_config_dir, "Podfile.lock"))
|
|
188
188
|
Pindo::GitHandler.git_addpush_repo(
|
|
189
189
|
path: app_config_dir,
|
|
190
|
-
message: "#{app_version}
|
|
190
|
+
message: "chore(pod): 备份 #{app_version} 的 Podfile.lock",
|
|
191
191
|
commit_file_params: ["Podfile.lock"]
|
|
192
192
|
)
|
|
193
193
|
|
|
@@ -218,7 +218,7 @@ module Pindo
|
|
|
218
218
|
|
|
219
219
|
Pindo::GitHandler.git_addpush_repo(
|
|
220
220
|
path: app_config_dir,
|
|
221
|
-
message: "
|
|
221
|
+
message: "chore(build): 备份 #{app_version} 的构建输出信息",
|
|
222
222
|
commit_file_params: ["build_verify.json"]
|
|
223
223
|
)
|
|
224
224
|
|
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
require 'fileutils'
|
|
2
|
+
require 'find'
|
|
3
|
+
require 'open3'
|
|
4
|
+
require 'tmpdir'
|
|
5
|
+
|
|
6
|
+
module Pindo
|
|
7
|
+
class MacAppResignHelper
|
|
8
|
+
BUNDLE_EXTENSIONS = %w[.app .appex .framework .xpc .bundle .plugin].freeze
|
|
9
|
+
# 需要内嵌描述文件的可执行 bundle(含独立 Bundle ID),
|
|
10
|
+
# .framework / .bundle / .plugin 属于共享代码,不单独内嵌 profile。
|
|
11
|
+
PROFILE_BUNDLE_EXTENSIONS = %w[.app .appex .xpc].freeze
|
|
12
|
+
MACHO_MAGICS = [
|
|
13
|
+
"\xFE\xED\xFA\xCE", "\xCE\xFA\xED\xFE", "\xFE\xED\xFA\xCF",
|
|
14
|
+
"\xCF\xFA\xED\xFE", "\xCA\xFE\xBA\xBE", "\xBE\xBA\xFE\xCA",
|
|
15
|
+
"\xCA\xFE\xBA\xBF", "\xBF\xBA\xFE\xCA"
|
|
16
|
+
].map(&:b).freeze
|
|
17
|
+
|
|
18
|
+
class << self
|
|
19
|
+
def resign_app(app_path:, bundle_id:, signing_identity:, profiles: [])
|
|
20
|
+
validate_input!(app_path, signing_identity)
|
|
21
|
+
output_path = resigned_path(app_path)
|
|
22
|
+
FileUtils.rm_rf(output_path)
|
|
23
|
+
FileUtils.cp_r(app_path, output_path, preserve: true)
|
|
24
|
+
|
|
25
|
+
resolved_bundle_id = resolve_bundle_id(output_path, bundle_id)
|
|
26
|
+
puts "\n▶ macOS App 重签名"
|
|
27
|
+
puts " 输入: #{app_path}"
|
|
28
|
+
puts " 输出: #{output_path}"
|
|
29
|
+
puts " Bundle ID: #{bundle_id} → #{resolved_bundle_id}" if bundle_id != resolved_bundle_id
|
|
30
|
+
puts " Bundle ID: #{resolved_bundle_id}" if bundle_id == resolved_bundle_id
|
|
31
|
+
puts " 签名身份: #{signing_identity}"
|
|
32
|
+
update_main_bundle_id(output_path, resolved_bundle_id)
|
|
33
|
+
|
|
34
|
+
Dir.mktmpdir('pindo-macos-entitlements-') do |tmp_dir|
|
|
35
|
+
nested_paths = signable_paths(output_path)
|
|
36
|
+
puts " 嵌套组件: #{nested_paths.length} 个"
|
|
37
|
+
nested_paths.each_with_index do |path, index|
|
|
38
|
+
puts " [#{index + 1}/#{nested_paths.length}] 签名: #{relative_path(path, output_path)}"
|
|
39
|
+
sign_component(path, output_path, signing_identity, profiles, tmp_dir, index)
|
|
40
|
+
end
|
|
41
|
+
puts " 签名主 App: #{File.basename(output_path)}"
|
|
42
|
+
sign_component(output_path, output_path, signing_identity, profiles, tmp_dir, 'main',
|
|
43
|
+
bundle_id: resolved_bundle_id)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
puts " 验证签名: codesign --verify --strict"
|
|
47
|
+
verify!(output_path)
|
|
48
|
+
puts " ✓ macOS App 签名验证通过"
|
|
49
|
+
output_path
|
|
50
|
+
rescue StandardError
|
|
51
|
+
FileUtils.rm_rf(output_path) if output_path && File.exist?(output_path)
|
|
52
|
+
raise
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
private
|
|
56
|
+
|
|
57
|
+
def validate_input!(app_path, signing_identity)
|
|
58
|
+
unless File.directory?(app_path) && app_path.downcase.end_with?('.app')
|
|
59
|
+
raise Informative, "macOS 重签名要求输入 .app 目录: #{app_path}"
|
|
60
|
+
end
|
|
61
|
+
if signing_identity.to_s.strip.empty?
|
|
62
|
+
raise Informative, 'macOS 重签名未找到有效的 signing identity'
|
|
63
|
+
end
|
|
64
|
+
info_plist = File.join(app_path, 'Contents', 'Info.plist')
|
|
65
|
+
raise Informative, "不是有效的 macOS App,缺少 #{info_plist}" unless File.file?(info_plist)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def resigned_path(app_path)
|
|
69
|
+
app_path.sub(/\.app$/i, '_resigned.app')
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def update_main_bundle_id(app_path, bundle_id)
|
|
73
|
+
return if bundle_id.to_s.empty?
|
|
74
|
+
|
|
75
|
+
plist = File.join(app_path, 'Contents', 'Info.plist')
|
|
76
|
+
success = system('/usr/libexec/PlistBuddy', '-c', "Set :CFBundleIdentifier #{bundle_id}", plist)
|
|
77
|
+
raise Informative, "修改 macOS App Bundle ID 失败: #{plist}" unless success
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def resolve_bundle_id(app_path, bundle_id)
|
|
81
|
+
return bundle_id unless bundle_id.to_s.include?('*')
|
|
82
|
+
|
|
83
|
+
plist = File.join(app_path, 'Contents', 'Info.plist')
|
|
84
|
+
candidate = plist_value(plist, 'CFBundleName')
|
|
85
|
+
candidate = plist_value(plist, 'CFBundleDisplayName') if candidate.to_s.empty?
|
|
86
|
+
candidate = File.basename(app_path, '.app') if candidate.to_s.empty?
|
|
87
|
+
suffix = candidate.to_s.downcase.gsub(/[^a-z0-9-]+/, '-')
|
|
88
|
+
.gsub(/\A-+|-+\z/, '')
|
|
89
|
+
suffix = 'app' if suffix.empty?
|
|
90
|
+
bundle_id.sub('*', suffix)
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def plist_value(plist, key)
|
|
94
|
+
stdout, _stderr, status = Open3.capture3(
|
|
95
|
+
'/usr/libexec/PlistBuddy', '-c', "Print :#{key}", plist
|
|
96
|
+
)
|
|
97
|
+
status.success? ? stdout.strip : nil
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
# 对单个可签名组件重签名。
|
|
101
|
+
# 对需要描述文件的 bundle(.app/.appex/.xpc):内嵌匹配的 profile,并
|
|
102
|
+
# 优先使用 profile 内的 entitlements(含新的 team-identifier /
|
|
103
|
+
# application-identifier),从根本上避免沿用旧二进制里的旧身份。
|
|
104
|
+
# Developer ID 场景(profiles 为空)回退到从旧二进制导出的 entitlements。
|
|
105
|
+
def sign_component(path, app_root, identity, profiles, tmp_dir, index, bundle_id: nil)
|
|
106
|
+
entitlements =
|
|
107
|
+
if profile_required?(path)
|
|
108
|
+
component_bundle_id = bundle_id || bundle_identifier(path)
|
|
109
|
+
profile_path = matched_profile_path(component_bundle_id, profiles)
|
|
110
|
+
if profile_path
|
|
111
|
+
embed_profile_file(path, profile_path)
|
|
112
|
+
puts " 描述文件: #{File.basename(profile_path)}"
|
|
113
|
+
profile_entitlements(profile_path, tmp_dir, index) ||
|
|
114
|
+
extract_entitlements(path, tmp_dir, index)
|
|
115
|
+
elsif !Array(profiles).empty?
|
|
116
|
+
raise Informative,
|
|
117
|
+
"未找到匹配 #{component_bundle_id} 的描述文件,无法重签名: #{relative_path(path, app_root)}"
|
|
118
|
+
else
|
|
119
|
+
extract_entitlements(path, tmp_dir, index)
|
|
120
|
+
end
|
|
121
|
+
else
|
|
122
|
+
extract_entitlements(path, tmp_dir, index)
|
|
123
|
+
end
|
|
124
|
+
codesign(path, identity, entitlements)
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
# 仅 .app/.appex/.xpc 这类含 Info.plist 的可执行 bundle 需要描述文件。
|
|
128
|
+
def profile_required?(path)
|
|
129
|
+
return false unless File.directory?(path)
|
|
130
|
+
return false unless PROFILE_BUNDLE_EXTENSIONS.include?(File.extname(path).downcase)
|
|
131
|
+
|
|
132
|
+
!bundle_info_plist(path).nil?
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def bundle_info_plist(bundle_path)
|
|
136
|
+
[
|
|
137
|
+
File.join(bundle_path, 'Contents', 'Info.plist'),
|
|
138
|
+
File.join(bundle_path, 'Info.plist'),
|
|
139
|
+
File.join(bundle_path, 'Resources', 'Info.plist')
|
|
140
|
+
].find { |candidate| File.file?(candidate) }
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def bundle_identifier(bundle_path)
|
|
144
|
+
plist = bundle_info_plist(bundle_path)
|
|
145
|
+
plist && plist_value(plist, 'CFBundleIdentifier')
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
def matched_profile_path(bundle_id, profiles)
|
|
149
|
+
profile = Array(profiles).find do |item|
|
|
150
|
+
profile_bundle_id = item['bundle_id'].to_s
|
|
151
|
+
profile_bundle_id == bundle_id ||
|
|
152
|
+
(profile_bundle_id.end_with?('.*') &&
|
|
153
|
+
bundle_id.to_s.start_with?(profile_bundle_id.delete_suffix('*')))
|
|
154
|
+
end
|
|
155
|
+
profile_path = profile && profile['profile_path']
|
|
156
|
+
profile_path if profile_path && File.file?(profile_path)
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
def embed_profile_file(bundle_path, profile_path)
|
|
160
|
+
contents_dir = File.join(bundle_path, 'Contents')
|
|
161
|
+
dest_dir = File.directory?(contents_dir) ? contents_dir : bundle_path
|
|
162
|
+
FileUtils.cp(profile_path, File.join(dest_dir, 'embedded.provisionprofile'))
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
# 从描述文件解出 Entitlements,写成独立 plist 供 codesign --entitlements 使用。
|
|
166
|
+
def profile_entitlements(profile_path, tmp_dir, index)
|
|
167
|
+
decoded, _stderr, status = Open3.capture3(
|
|
168
|
+
'/usr/bin/security', 'cms', '-D', '-i', profile_path
|
|
169
|
+
)
|
|
170
|
+
return nil unless status.success?
|
|
171
|
+
|
|
172
|
+
profile_plist = File.join(tmp_dir, "profile-#{index}.plist")
|
|
173
|
+
File.write(profile_plist, decoded)
|
|
174
|
+
entitlements_xml, _err, extract_status = Open3.capture3(
|
|
175
|
+
'/usr/bin/plutil', '-extract', 'Entitlements', 'xml1', '-o', '-', profile_plist
|
|
176
|
+
)
|
|
177
|
+
return nil unless extract_status.success? && entitlements_xml.include?('<plist')
|
|
178
|
+
|
|
179
|
+
entitlements_path = File.join(tmp_dir, "profile-entitlements-#{index}.plist")
|
|
180
|
+
File.write(entitlements_path, entitlements_xml)
|
|
181
|
+
entitlements_path
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
def relative_path(path, app_path)
|
|
185
|
+
path.delete_prefix("#{app_path}/")
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
# Sign deepest nested code first. The main app is deliberately excluded
|
|
189
|
+
# here and signed last by resign_app.
|
|
190
|
+
def signable_paths(app_path)
|
|
191
|
+
paths = []
|
|
192
|
+
Find.find(app_path) do |path|
|
|
193
|
+
next if path == app_path
|
|
194
|
+
if File.directory?(path) && BUNDLE_EXTENSIONS.include?(File.extname(path).downcase)
|
|
195
|
+
paths << path
|
|
196
|
+
elsif File.file?(path) && (File.extname(path).downcase == '.dylib' || macho?(path))
|
|
197
|
+
paths << path
|
|
198
|
+
end
|
|
199
|
+
end
|
|
200
|
+
paths.uniq.sort_by { |path| [-path.count(File::SEPARATOR), File.directory?(path) ? 1 : 0] }
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
def macho?(path)
|
|
204
|
+
File.open(path, 'rb') { |file| MACHO_MAGICS.include?(file.read(4)) }
|
|
205
|
+
rescue Errno::EACCES, Errno::ENOENT
|
|
206
|
+
false
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
def extract_entitlements(path, tmp_dir, index)
|
|
210
|
+
stdout, _stderr, status = Open3.capture3(
|
|
211
|
+
'/usr/bin/codesign', '-d', '--entitlements', ':-', path
|
|
212
|
+
)
|
|
213
|
+
return nil unless status.success? && stdout.include?('<plist')
|
|
214
|
+
|
|
215
|
+
entitlements_path = File.join(tmp_dir, "#{index}.plist")
|
|
216
|
+
File.write(entitlements_path, stdout)
|
|
217
|
+
entitlements_path
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
def codesign(path, identity, entitlements)
|
|
221
|
+
command = [
|
|
222
|
+
'/usr/bin/codesign', '--force', '--sign', identity,
|
|
223
|
+
'--timestamp', '--options', 'runtime'
|
|
224
|
+
]
|
|
225
|
+
command.concat(['--entitlements', entitlements]) if entitlements
|
|
226
|
+
command << path
|
|
227
|
+
_stdout, stderr, status = Open3.capture3(*command)
|
|
228
|
+
return if status.success?
|
|
229
|
+
|
|
230
|
+
raise Informative, "codesign 失败: #{path}\n#{stderr.strip}"
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
def verify!(app_path)
|
|
234
|
+
_stdout, stderr, status = Open3.capture3(
|
|
235
|
+
'/usr/bin/codesign', '--verify', '--strict', '--verbose=2', app_path
|
|
236
|
+
)
|
|
237
|
+
return if status.success?
|
|
238
|
+
|
|
239
|
+
raise Informative, "macOS App 签名验证失败: #{app_path}\n#{stderr.strip}"
|
|
240
|
+
end
|
|
241
|
+
end
|
|
242
|
+
end
|
|
243
|
+
end
|
|
@@ -48,7 +48,7 @@ module Pindo
|
|
|
48
48
|
file.close
|
|
49
49
|
end
|
|
50
50
|
|
|
51
|
-
git_addpush_repo(path:app_config_dir, message:"
|
|
51
|
+
git_addpush_repo(path:app_config_dir, message:"chore(build): 回写发布信息", commit_file_params:["build_verify.json"])
|
|
52
52
|
|
|
53
53
|
if File.exist?(src_pod_file)
|
|
54
54
|
FileUtils.cp_r(src_pod_file, File.join(project_dir, "Podfile.lock"))
|
|
@@ -64,7 +64,7 @@ module Pindo
|
|
|
64
64
|
begin
|
|
65
65
|
proj_pod_file = File.join(project_dir, "Podfile.lock")
|
|
66
66
|
FileUtils.cp_r(proj_pod_file, File.join(app_config_dir, "Podfile.lock"))
|
|
67
|
-
git_addpush_repo(path:app_config_dir, message:"#{appversion}
|
|
67
|
+
git_addpush_repo(path:app_config_dir, message:"chore(pod): 备份 #{appversion} 的 Podfile.lock", commit_file_params:["Podfile.lock"])
|
|
68
68
|
|
|
69
69
|
bytes = File.binread(proj_pod_file)
|
|
70
70
|
checksum = Digest::MD5.hexdigest(bytes)
|
|
@@ -84,7 +84,7 @@ module Pindo
|
|
|
84
84
|
file.write(JSON.pretty_generate(build_verify_json))
|
|
85
85
|
file.close
|
|
86
86
|
end
|
|
87
|
-
git_addpush_repo(path:app_config_dir, message:"
|
|
87
|
+
git_addpush_repo(path:app_config_dir, message:"chore(build): 备份 #{appversion} 的构建输出信息", commit_file_params:["build_verify.json"])
|
|
88
88
|
|
|
89
89
|
rescue => error
|
|
90
90
|
raise Informative, "保存Podfile.lock 文件失败!!!"
|
|
@@ -333,7 +333,7 @@ module Pindo
|
|
|
333
333
|
end
|
|
334
334
|
|
|
335
335
|
# 提交到配置仓库
|
|
336
|
-
Pindo::GitHandler.git_addpush_repo(path: app_config_dir, message: "
|
|
336
|
+
Pindo::GitHandler.git_addpush_repo(path: app_config_dir, message: "chore(config): 完成 swark 授权")
|
|
337
337
|
|
|
338
338
|
Funlog.instance.fancyinfo_success("Swark 授权完成!")
|
|
339
339
|
return true
|
|
@@ -41,13 +41,23 @@ module Pindo
|
|
|
41
41
|
# @param item [OptionItem] 参数定义
|
|
42
42
|
# @return [Object, nil] 提取的值
|
|
43
43
|
def self.extract_from_argv(argv, item)
|
|
44
|
+
option_names = [item.key.to_s] + item.aliases.map(&:to_s)
|
|
45
|
+
|
|
44
46
|
if item.boolean?
|
|
45
47
|
# Boolean 类型:使用 flag?
|
|
46
|
-
|
|
48
|
+
option_names.each do |option_name|
|
|
49
|
+
value = argv.flag?(option_name, nil)
|
|
50
|
+
return value unless value.nil?
|
|
51
|
+
end
|
|
47
52
|
else
|
|
48
53
|
# 其他类型:使用 option
|
|
49
|
-
|
|
54
|
+
option_names.each do |option_name|
|
|
55
|
+
value = argv.option(option_name, nil)
|
|
56
|
+
return value unless value.nil?
|
|
57
|
+
end
|
|
50
58
|
end
|
|
59
|
+
|
|
60
|
+
nil
|
|
51
61
|
end
|
|
52
62
|
end
|
|
53
63
|
end
|
|
@@ -115,9 +115,10 @@ module Pindo
|
|
|
115
115
|
file: OptionItem.new(
|
|
116
116
|
key: :file,
|
|
117
117
|
name: '上传文件',
|
|
118
|
-
description: '指定要上传的文件路径(支持 ipa/apk/app/exe/html
|
|
118
|
+
description: '指定要上传的文件路径(支持 ipa/apk/app/exe/html;兼容 --ipa 别名)',
|
|
119
119
|
type: String,
|
|
120
120
|
env_name: 'PINDO_JPS_FILE',
|
|
121
|
+
aliases: [:ipa],
|
|
121
122
|
optional: true,
|
|
122
123
|
example: 'pindo jps upload --file=path/to/app.ipa'
|
|
123
124
|
),
|
|
@@ -28,6 +28,24 @@ module Pindo
|
|
|
28
28
|
example: 'pindo ios autoresign --ipa=path/to/demo.ipa'
|
|
29
29
|
),
|
|
30
30
|
|
|
31
|
+
app: OptionItem.new(
|
|
32
|
+
key: :app,
|
|
33
|
+
name: 'macOS App',
|
|
34
|
+
description: '指定要重签名的 macOS .app 目录',
|
|
35
|
+
type: String,
|
|
36
|
+
env_name: 'PINDO_APP_FILE',
|
|
37
|
+
optional: true,
|
|
38
|
+
verify_block: proc do |value|
|
|
39
|
+
unless value.downcase.end_with?('.app')
|
|
40
|
+
raise "App 路径格式错误: #{value},必须以 .app 结尾"
|
|
41
|
+
end
|
|
42
|
+
unless File.directory?(value)
|
|
43
|
+
raise "App 目录不存在: #{value}"
|
|
44
|
+
end
|
|
45
|
+
end,
|
|
46
|
+
example: 'pindo ios autoresign --macos --app=path/to/Demo.app'
|
|
47
|
+
),
|
|
48
|
+
|
|
31
49
|
apk: OptionItem.new(
|
|
32
50
|
key: :apk,
|
|
33
51
|
name: 'APK 文件',
|
data/lib/pindo/version.rb
CHANGED
|
@@ -6,7 +6,7 @@ require 'time'
|
|
|
6
6
|
|
|
7
7
|
module Pindo
|
|
8
8
|
|
|
9
|
-
VERSION = "5.19.
|
|
9
|
+
VERSION = "5.19.5"
|
|
10
10
|
|
|
11
11
|
class VersionCheck
|
|
12
12
|
RUBYGEMS_API = 'https://rubygems.org/api/v1/gems/pindo.json'
|
|
@@ -135,7 +135,10 @@ module Pindo
|
|
|
135
135
|
puts "当前pindo版本 #{Pindo::VERSION}"
|
|
136
136
|
puts "最新版本 #{pindo_latest_version}"
|
|
137
137
|
puts "要求最低版本 #{pindo_mini_version}"
|
|
138
|
-
|
|
138
|
+
puts "请使用 gem install pindo 升级!".red
|
|
139
|
+
# 强制升级必须真正中断:用 exit(1)(SystemExit) 绕过上层通用 rescue,
|
|
140
|
+
# 与 RubyGems API 强制升级路径保持一致;可用 PINDO_SKIP_FORCE_UPDATE=1 紧急跳过
|
|
141
|
+
exit(1)
|
|
139
142
|
end
|
|
140
143
|
end
|
|
141
144
|
|
|
@@ -187,7 +190,7 @@ module Pindo
|
|
|
187
190
|
# 创建 HTTP 连接,禁用代理
|
|
188
191
|
http = Net::HTTP.new(uri.host, uri.port, nil, nil)
|
|
189
192
|
http.use_ssl = true
|
|
190
|
-
http.verify_mode = OpenSSL::SSL::
|
|
193
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_PEER # 校验 SSL 证书(此连接直连 RubyGems、不走代理,公网有效证书可正常校验)
|
|
191
194
|
http.open_timeout = 3 # 3秒超时
|
|
192
195
|
http.read_timeout = 3
|
|
193
196
|
|
|
@@ -535,24 +538,28 @@ module Pindo
|
|
|
535
538
|
current_branch = `git rev-parse --abbrev-ref HEAD`.strip
|
|
536
539
|
current_branch = 'master' if current_branch.empty?
|
|
537
540
|
|
|
538
|
-
#
|
|
539
|
-
system("git fetch origin --quiet")
|
|
541
|
+
# 获取远程更新(数组式 system 避免 shell 注入;失败即抛出,不静默吞掉)
|
|
542
|
+
system("git", "fetch", "origin", "--quiet") or
|
|
543
|
+
raise "git fetch 失败: #{repo_name}"
|
|
540
544
|
|
|
541
545
|
# 强制重置到远程分支最新状态(覆盖本地修改)
|
|
542
|
-
system("git reset --hard origin/#{current_branch} --quiet")
|
|
546
|
+
system("git", "reset", "--hard", "origin/#{current_branch}", "--quiet") or
|
|
547
|
+
raise "git reset 失败: #{repo_name}"
|
|
543
548
|
|
|
544
|
-
#
|
|
545
|
-
system("git branch --set-upstream-to=origin/#{current_branch}
|
|
549
|
+
# 设置上游分支(失败可忽略)
|
|
550
|
+
system("git", "branch", "--set-upstream-to=origin/#{current_branch}", current_branch, "--quiet", err: File::NULL)
|
|
546
551
|
|
|
547
552
|
# 拉取最新更新
|
|
548
|
-
system("git pull --quiet")
|
|
553
|
+
system("git", "pull", "--quiet") or
|
|
554
|
+
raise "git pull 失败: #{repo_name}"
|
|
549
555
|
end
|
|
550
556
|
else
|
|
551
557
|
# 仓库不存在,执行 git clone
|
|
552
558
|
puts " 📦 克隆: #{repo_name}".cyan if ENV['PINDO_DEBUG']
|
|
553
559
|
parent_dir = File.dirname(dir)
|
|
554
560
|
FileUtils.mkdir_p(parent_dir) unless File.exist?(parent_dir)
|
|
555
|
-
system("git clone
|
|
561
|
+
system("git", "clone", url, dir, "--quiet") or
|
|
562
|
+
raise "git clone 失败: #{repo_name} (#{url})"
|
|
556
563
|
end
|
|
557
564
|
end
|
|
558
565
|
end
|
data/lib/pindo.rb
CHANGED
|
@@ -21,6 +21,18 @@ module Pindo
|
|
|
21
21
|
# 解析参数以确定是否是 help 或 version 命令
|
|
22
22
|
coerced_argv = CLAide::ARGV.coerce(argv)
|
|
23
23
|
|
|
24
|
+
# --verbose 等效 PINDO_DEBUG=1:必须在版本检查、参数初始化等任何逻辑之前设置,
|
|
25
|
+
# 否则子命令 initialize 早期执行的调试日志会因 ENV 未就绪而丢失
|
|
26
|
+
ENV['PINDO_DEBUG'] = '1' if coerced_argv.flag?('verbose')
|
|
27
|
+
|
|
28
|
+
# 依赖库 jpsclient 有自己的调试开关 JPS_DEBUG;pindo 处于调试模式时同步打开它。
|
|
29
|
+
# 仅当 PINDO_DEBUG 为真值时才桥接:PINDO_DEBUG=0/false 因 Ruby 字符串恒为真值本会误开,
|
|
30
|
+
# 这里按 jpsclient 的真值规则排除;且不覆盖用户显式设置的 JPS_DEBUG
|
|
31
|
+
pindo_debug_val = ENV['PINDO_DEBUG'].to_s.strip.downcase
|
|
32
|
+
if !pindo_debug_val.empty? && !%w[0 false no].include?(pindo_debug_val) && !ENV['JPS_DEBUG']
|
|
33
|
+
ENV['JPS_DEBUG'] = '1'
|
|
34
|
+
end
|
|
35
|
+
|
|
24
36
|
# 显示欢迎界面(除了 help/version 命令和特定情况)
|
|
25
37
|
show_welcome_banner(argv, coerced_argv)
|
|
26
38
|
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: pindo
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 5.19.
|
|
4
|
+
version: 5.19.5
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- wade
|
|
@@ -109,20 +109,20 @@ dependencies:
|
|
|
109
109
|
requirements:
|
|
110
110
|
- - "~>"
|
|
111
111
|
- !ruby/object:Gem::Version
|
|
112
|
-
version: '2.
|
|
112
|
+
version: '2.7'
|
|
113
113
|
- - ">="
|
|
114
114
|
- !ruby/object:Gem::Version
|
|
115
|
-
version: 2.
|
|
115
|
+
version: 2.7.0
|
|
116
116
|
type: :runtime
|
|
117
117
|
prerelease: false
|
|
118
118
|
version_requirements: !ruby/object:Gem::Requirement
|
|
119
119
|
requirements:
|
|
120
120
|
- - "~>"
|
|
121
121
|
- !ruby/object:Gem::Version
|
|
122
|
-
version: '2.
|
|
122
|
+
version: '2.7'
|
|
123
123
|
- - ">="
|
|
124
124
|
- !ruby/object:Gem::Version
|
|
125
|
-
version: 2.
|
|
125
|
+
version: 2.7.0
|
|
126
126
|
- !ruby/object:Gem::Dependency
|
|
127
127
|
name: rqrcode
|
|
128
128
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -406,6 +406,8 @@ files:
|
|
|
406
406
|
- lib/pindo/module/cert/pem_helper.rb
|
|
407
407
|
- lib/pindo/module/cert/provisioning_helper.rb
|
|
408
408
|
- lib/pindo/module/pgyer/pgyerhelper.rb
|
|
409
|
+
- lib/pindo/module/resign/ipa_resign_adapter.rb
|
|
410
|
+
- lib/pindo/module/resign/mac_app_resign_adapter.rb
|
|
409
411
|
- lib/pindo/module/task/core/concurrent_execution_strategy.rb
|
|
410
412
|
- lib/pindo/module/task/core/dependency_checker.rb
|
|
411
413
|
- lib/pindo/module/task/core/execution_strategy.rb
|
|
@@ -477,6 +479,7 @@ files:
|
|
|
477
479
|
- lib/pindo/module/xcode/applovin_xcode_helper.rb
|
|
478
480
|
- lib/pindo/module/xcode/cocoapods_helper.rb
|
|
479
481
|
- lib/pindo/module/xcode/ipa_resign_helper.rb
|
|
482
|
+
- lib/pindo/module/xcode/mac_app_resign_helper.rb
|
|
480
483
|
- lib/pindo/module/xcode/res/xcode_res_constant.rb
|
|
481
484
|
- lib/pindo/module/xcode/res/xcode_res_handler.rb
|
|
482
485
|
- lib/pindo/module/xcode/xcode_app_config.rb
|