pindo 5.13.1 → 5.13.2
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 +692 -0
- data/lib/pindo/command/android/autobuild.rb +2 -2
- data/lib/pindo/command/appstore/adhocbuild.rb +258 -311
- data/lib/pindo/command/appstore/autobuild.rb +203 -0
- data/lib/pindo/command/appstore/autoresign.rb +35 -17
- data/lib/pindo/command/appstore/bundleid.rb +120 -0
- data/lib/pindo/command/appstore/cert.rb +212 -0
- data/lib/pindo/command/appstore/configproj.rb +81 -0
- data/lib/pindo/command/{deploy → appstore}/getitcinfo.rb +76 -91
- data/lib/pindo/command/appstore/iap.rb +788 -24
- data/lib/pindo/command/appstore/initconfig.rb +105 -0
- data/lib/pindo/command/appstore/itcapp.rb +95 -13
- data/lib/pindo/command/{deploy → appstore}/itcinfo.rb +90 -118
- data/lib/pindo/command/appstore/pem.rb +136 -0
- data/lib/pindo/command/appstore/pullconfig.rb +99 -0
- data/lib/pindo/command/appstore/quswark.rb +87 -0
- data/lib/pindo/command/appstore/quswauth.rb +67 -0
- data/lib/pindo/command/appstore/tag.rb +77 -0
- data/lib/pindo/command/appstore.rb +13 -1
- data/lib/pindo/command/env/quarkenv.rb +11 -13
- data/lib/pindo/command/env/swarkenv.rb +11 -16
- data/lib/pindo/command/ios/autobuild.rb +64 -43
- data/lib/pindo/command/ios/autoresign.rb +34 -19
- data/lib/pindo/command/ios/build.rb +9 -6
- data/lib/pindo/command/ios/cert.rb +27 -20
- data/lib/pindo/command/jps/upload.rb +3 -3
- data/lib/pindo/command/unity/autobuild.rb +2 -2
- data/lib/pindo/command/utils/clearcert.rb +2 -17
- data/lib/pindo/command/{deploy → utils}/fabric.rb +13 -13
- data/lib/pindo/command/utils/renewcert.rb +62 -38
- data/lib/pindo/command/utils/renewproj.rb +0 -3
- data/lib/pindo/command/{deploy → utils}/updateconfig.rb +6 -7
- data/lib/pindo/command/utils.rb +2 -0
- data/lib/pindo/command/web/autobuild.rb +2 -2
- data/lib/pindo/command.rb +30 -3
- data/lib/pindo/config/build_info_manager.rb +176 -0
- data/lib/pindo/config/ios_config_parser.rb +404 -0
- data/lib/pindo/module/android/android_config_helper.rb +9 -5
- data/lib/pindo/module/appstore/bundleid_helper.rb +349 -0
- data/lib/pindo/module/appstore/itcapp_helper.rb +228 -0
- data/lib/pindo/module/build/build_helper.rb +12 -0
- data/lib/pindo/module/build/swark_helper.rb +116 -77
- data/lib/pindo/module/cert/cert_helper.rb +74 -0
- data/lib/pindo/module/cert/pem_helper.rb +72 -0
- data/lib/pindo/module/cert/{xcodecerthelper.rb → xcode_cert_helper.rb} +208 -6
- data/lib/pindo/module/task/model/appstore/appstore_task.rb +18 -0
- data/lib/pindo/module/task/model/appstore/appstore_upload_ipa_task.rb +151 -0
- data/lib/pindo/module/task/model/appstore/appstore_upload_metadata_task.rb +250 -0
- data/lib/pindo/module/task/model/appstore/appstore_upload_screenshot_task.rb +276 -0
- data/lib/pindo/module/task/model/build/android_build_adhoc_task.rb +210 -0
- data/lib/pindo/module/task/model/build/{android_dev_build_task.rb → android_build_dev_task.rb} +2 -2
- data/lib/pindo/module/task/model/build/android_build_gplay_task.rb +210 -0
- data/lib/pindo/module/task/model/build/android_build_task.rb +13 -0
- data/lib/pindo/module/task/model/build/ios_build_adhoc_task.rb +197 -0
- data/lib/pindo/module/task/model/build/ios_build_appstore_task.rb +367 -0
- data/lib/pindo/module/task/model/build/{ios_dev_build_task.rb → ios_build_dev_task.rb} +37 -27
- data/lib/pindo/module/task/model/build/ios_build_task.rb +13 -0
- data/lib/pindo/module/task/model/build/{web_dev_build_task.rb → web_build_dev_task.rb} +1 -1
- data/lib/pindo/module/task/model/build_task.rb +15 -12
- data/lib/pindo/module/task/model/jps_resign_task.rb +185 -0
- data/lib/pindo/module/task/model/{upload_task.rb → jps_upload_task.rb} +3 -3
- data/lib/pindo/module/task/model/unity_export_task.rb +3 -1
- data/lib/pindo/module/unity/unity_helper.rb +2 -1
- data/lib/pindo/module/xcode/ipa_resign_helper.rb +210 -0
- data/lib/pindo/module/xcode/{xcodeappconfig.rb → xcode_app_config.rb} +79 -0
- data/lib/pindo/module/xcode/xcode_build_config.rb +152 -17
- data/lib/pindo/module/xcode/xcode_build_helper.rb +151 -1
- data/lib/pindo/module/xcode/xcode_swark_helper.rb +341 -0
- data/lib/pindo/options/core/global_options_state.rb +268 -0
- data/lib/pindo/options/core/option_configuration.rb +206 -0
- data/lib/pindo/options/core/option_initializer.rb +51 -0
- data/lib/pindo/options/core/option_item.rb +144 -0
- data/lib/pindo/options/core/option_value_parser.rb +54 -0
- data/lib/pindo/options/groups/build_options.rb +60 -0
- data/lib/pindo/options/groups/jps_options.rb +70 -0
- data/lib/pindo/options/groups/option_group.rb +73 -0
- data/lib/pindo/options/helpers/bundleid_selector.rb +103 -0
- data/lib/pindo/options/options.rb +14 -0
- data/lib/pindo/version.rb +1 -1
- metadata +49 -40
- data/lib/pindo/command/appstore/import.rb +0 -259
- data/lib/pindo/command/deploy/build.rb +0 -250
- data/lib/pindo/command/deploy/bundleid.rb +0 -259
- data/lib/pindo/command/deploy/cert.rb +0 -202
- data/lib/pindo/command/deploy/check.rb +0 -93
- data/lib/pindo/command/deploy/configproj.rb +0 -120
- data/lib/pindo/command/deploy/confusecode.rb +0 -262
- data/lib/pindo/command/deploy/confuseproj.rb +0 -122
- data/lib/pindo/command/deploy/iap.rb +0 -826
- data/lib/pindo/command/deploy/initconfig.rb +0 -138
- data/lib/pindo/command/deploy/itcapp.rb +0 -146
- data/lib/pindo/command/deploy/pem.rb +0 -55
- data/lib/pindo/command/deploy/pullconfig.rb +0 -56
- data/lib/pindo/command/deploy/pushconfig.rb +0 -93
- data/lib/pindo/command/deploy/quswark.rb +0 -156
- data/lib/pindo/command/deploy/quswauth.rb +0 -76
- data/lib/pindo/command/deploy/reportbug.rb +0 -145
- data/lib/pindo/command/deploy/resign.rb +0 -300
- data/lib/pindo/command/deploy/tag.rb +0 -108
- data/lib/pindo/command/deploy/uploadipa.rb +0 -73
- data/lib/pindo/command/deploy.rb +0 -42
- data/lib/pindo/command/dev/autobuild.rb +0 -117
- data/lib/pindo/command/dev/build.rb +0 -94
- data/lib/pindo/command/dev/debug.rb +0 -112
- data/lib/pindo/module/task/model/build/android_release_build_task.rb +0 -29
- data/lib/pindo/module/task/model/build/ios_adhoc_build_task.rb +0 -53
- data/lib/pindo/module/task/model/build/ios_release_build_task.rb +0 -53
- data/lib/pindo/options/appconfigoptions.rb +0 -24
- data/lib/pindo/options/deployoptions.rb +0 -372
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
require_relative '../pindo_task'
|
|
2
|
+
require_relative '../task_config'
|
|
3
|
+
require 'pindo/module/pgyer/pgyerhelper'
|
|
4
|
+
|
|
5
|
+
module Pindo
|
|
6
|
+
module TaskSystem
|
|
7
|
+
# JPS 重签名任务
|
|
8
|
+
# 从 JPS 平台下载应用并使用指定证书重签名
|
|
9
|
+
class JPSResignTask < PindoTask
|
|
10
|
+
attr_reader :app_info_obj, :version_info, :cert_id, :send_flag
|
|
11
|
+
|
|
12
|
+
def self.task_type
|
|
13
|
+
:jps_resign
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# 重试配置
|
|
17
|
+
def self.default_retry_mode
|
|
18
|
+
RetryMode::DELAYED # 延迟重试
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def self.default_retry_count
|
|
22
|
+
2 # 默认可以重试 2 次
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def self.default_retry_delay
|
|
26
|
+
10 # 默认延迟 10 秒
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# 初始化 JPS 重签名任务
|
|
30
|
+
# @param options [Hash] 选项
|
|
31
|
+
# @option options [Hash] :app_info_obj JPS 应用信息对象(可选,如为 nil 则延迟获取)
|
|
32
|
+
# @option options [String] :project_name 项目名称(可选)
|
|
33
|
+
# @option options [String] :cert_id 重签名使用的 Bundle ID(可选,nil 表示交互选择)
|
|
34
|
+
# @option options [Boolean] :send_flag 是否发送到测试群(默认 false,始终会发送给自己)
|
|
35
|
+
def initialize(options = {})
|
|
36
|
+
@app_info_obj = options[:app_info_obj]
|
|
37
|
+
@project_name = options[:project_name]
|
|
38
|
+
@cert_id = options[:cert_id]
|
|
39
|
+
@send_flag = options[:send_flag] || false
|
|
40
|
+
@version_info = nil
|
|
41
|
+
|
|
42
|
+
# 设置重签名任务的优先级为 LOW,确保在上传任务之后执行
|
|
43
|
+
options[:priority] ||= TaskPriority::LOW
|
|
44
|
+
|
|
45
|
+
super("JPS 重签名", options)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def validate
|
|
49
|
+
# app_info_obj 可以延迟获取,不在这里验证
|
|
50
|
+
true
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
protected
|
|
54
|
+
|
|
55
|
+
def do_work
|
|
56
|
+
pgyer_helper = PgyerHelper.share_instace
|
|
57
|
+
|
|
58
|
+
# 1. 如果没有 app_info_obj,延迟获取
|
|
59
|
+
if @app_info_obj.nil?
|
|
60
|
+
fetch_jps_config
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# 2. 获取要重签名的版本
|
|
64
|
+
@version_info = pgyer_helper.get_versioon_history_item(
|
|
65
|
+
app_info_obj: @app_info_obj,
|
|
66
|
+
list_select_flat: false
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
if @version_info.nil?
|
|
70
|
+
@retry_count = 0 # 没有版本记录时不重试
|
|
71
|
+
raise "没有找到上传记录"
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# 3. 获取证书列表
|
|
75
|
+
cert_list = pgyer_helper.get_cert_list
|
|
76
|
+
|
|
77
|
+
if cert_list.nil? || cert_list.empty?
|
|
78
|
+
@retry_count = 0 # 没有证书时不重试
|
|
79
|
+
raise "没有找到可用的证书"
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
# 4. 选择证书
|
|
83
|
+
cert_item = select_certificate(cert_list)
|
|
84
|
+
|
|
85
|
+
if cert_item.nil?
|
|
86
|
+
@retry_count = 0 # 没有匹配的证书时不重试
|
|
87
|
+
raise "未找到匹配的证书"
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# 5. 执行重签名
|
|
91
|
+
result = pgyer_helper.resign(
|
|
92
|
+
package_id: @version_info["id"],
|
|
93
|
+
cert_id: cert_item["id"]
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
unless result
|
|
97
|
+
raise "重签名失败"
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
# 6. 获取重签名后的版本信息
|
|
101
|
+
@version_info = pgyer_helper.get_versioon_history_item(
|
|
102
|
+
app_info_obj: @app_info_obj,
|
|
103
|
+
list_select_flat: false
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
if @version_info.nil?
|
|
107
|
+
raise "重签名成功但无法获取新版本信息"
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
# 7. 打印版本信息
|
|
111
|
+
pgyer_helper.print_app_version_info(
|
|
112
|
+
app_info_obj: @app_info_obj,
|
|
113
|
+
app_version_info_obj: @version_info
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
# 8. 发送消息给自己
|
|
117
|
+
pgyer_helper.send_apptest_msg(
|
|
118
|
+
app_info_obj: @app_info_obj,
|
|
119
|
+
app_version_info_obj: @version_info,
|
|
120
|
+
receiveType: "self"
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
# 9. 如果需要发送到测试群
|
|
124
|
+
if @send_flag
|
|
125
|
+
pgyer_helper.send_apptest_msg(
|
|
126
|
+
app_info_obj: @app_info_obj,
|
|
127
|
+
app_version_info_obj: @version_info,
|
|
128
|
+
chatEnv: "DevTest",
|
|
129
|
+
receiveType: "chat"
|
|
130
|
+
)
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
{
|
|
134
|
+
success: true,
|
|
135
|
+
version_info: @version_info,
|
|
136
|
+
cert_id: cert_item["mainBundleId"]
|
|
137
|
+
}
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
private
|
|
141
|
+
|
|
142
|
+
# 延迟获取 JPS 配置
|
|
143
|
+
def fetch_jps_config
|
|
144
|
+
puts " 获取 JPS 配置..."
|
|
145
|
+
|
|
146
|
+
# 获取当前工作目录
|
|
147
|
+
working_directory = Dir.pwd
|
|
148
|
+
|
|
149
|
+
# 调用 PgyerHelper 获取配置
|
|
150
|
+
@app_info_obj = PgyerHelper.share_instace.prepare_upload(
|
|
151
|
+
working_directory: working_directory,
|
|
152
|
+
proj_name: @project_name
|
|
153
|
+
)
|
|
154
|
+
|
|
155
|
+
unless @app_info_obj
|
|
156
|
+
raise "无法获取 JPS 配置"
|
|
157
|
+
end
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
# 选择证书
|
|
161
|
+
def select_certificate(cert_list)
|
|
162
|
+
if @cert_id.nil? && cert_list.size > 0
|
|
163
|
+
# 交互式选择证书
|
|
164
|
+
bundle_id_list = cert_list.map { |cert| [cert["certType"], cert["mainBundleId"]].join("_") }
|
|
165
|
+
cli = HighLine.new
|
|
166
|
+
selected = cli.choose do |menu|
|
|
167
|
+
menu.prompt = "请选择重签名的证书:"
|
|
168
|
+
menu.choices(*bundle_id_list)
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
# 根据选择找到对应的证书
|
|
172
|
+
cert_list.select { |certitem|
|
|
173
|
+
[certitem["certType"], certitem["mainBundleId"]].join("_") == selected
|
|
174
|
+
}.first
|
|
175
|
+
else
|
|
176
|
+
# 根据 cert_id 查找 adhoc 证书
|
|
177
|
+
cert_list.select { |certitem|
|
|
178
|
+
certitem["mainBundleId"] == @cert_id &&
|
|
179
|
+
certitem["certType"].downcase.include?("adhoc")
|
|
180
|
+
}.first
|
|
181
|
+
end
|
|
182
|
+
end
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
end
|
|
@@ -4,9 +4,9 @@ require 'pindo/module/pgyer/pgyerhelper'
|
|
|
4
4
|
|
|
5
5
|
module Pindo
|
|
6
6
|
module TaskSystem
|
|
7
|
-
# 上传任务
|
|
8
|
-
#
|
|
9
|
-
class
|
|
7
|
+
# JPS 上传任务
|
|
8
|
+
# 上传构建产物到 JPS 测试平台
|
|
9
|
+
class JPSUploadTask < PindoTask
|
|
10
10
|
attr_reader :file_type, :upload_path, :upload_file
|
|
11
11
|
|
|
12
12
|
def self.task_type
|
|
@@ -31,6 +31,7 @@ module Pindo
|
|
|
31
31
|
@is_library_mode = false # 不再支持库模式
|
|
32
32
|
@index_count = options[:context] ? options[:context][:index_count] : nil
|
|
33
33
|
@export_path = options[:export_path] # 可由参数传入,nil 表示自动检测
|
|
34
|
+
@deploy_mode = options[:deploy_mode] || 'dev' # 部署模式:dev/adhoc/release,默认 dev
|
|
34
35
|
|
|
35
36
|
name = case platform
|
|
36
37
|
when 'ios', 'ipa'
|
|
@@ -188,7 +189,8 @@ module Pindo
|
|
|
188
189
|
project_path: @unity_project_path,
|
|
189
190
|
platform: platform,
|
|
190
191
|
isLibrary: @is_library_mode,
|
|
191
|
-
indexNo: @index_count
|
|
192
|
+
indexNo: @index_count,
|
|
193
|
+
deployMode: @deploy_mode
|
|
192
194
|
)
|
|
193
195
|
|
|
194
196
|
# 清理 Unity 进程
|
|
@@ -422,7 +422,7 @@ module Pindo
|
|
|
422
422
|
nil
|
|
423
423
|
end
|
|
424
424
|
|
|
425
|
-
def build_project(unity_exe_full_path:nil, project_path:nil, platform: nil, isLibrary: false, indexNo: nil)
|
|
425
|
+
def build_project(unity_exe_full_path:nil, project_path:nil, platform: nil, isLibrary: false, indexNo: nil, deployMode: nil)
|
|
426
426
|
|
|
427
427
|
# 检查是否有Unity进程在运行,传入Unity路径和项目路径以精确匹配
|
|
428
428
|
check_unity_processes(unity_exe_full_path: unity_exe_full_path, project_path: project_path)
|
|
@@ -434,6 +434,7 @@ module Pindo
|
|
|
434
434
|
additional_args[:platform] = platform if platform
|
|
435
435
|
additional_args[:buildtype] = 'library' if isLibrary
|
|
436
436
|
additional_args[:indexno] = indexNo if indexNo
|
|
437
|
+
additional_args[:deploymode] = deployMode || 'dev' if deployMode || true # 默认为 dev
|
|
437
438
|
|
|
438
439
|
# 使用GoodUnityBuild.BuildManager.BatchBuild进行构建
|
|
439
440
|
result = execute_unity_command(unity_exe_full_path, project_path, additional_args)
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
require 'fileutils'
|
|
2
|
+
require 'sigh'
|
|
3
|
+
require 'zip'
|
|
4
|
+
require 'pindo/config/pindoconfig'
|
|
5
|
+
|
|
6
|
+
module Pindo
|
|
7
|
+
class IpaResignHelper
|
|
8
|
+
|
|
9
|
+
class << self
|
|
10
|
+
|
|
11
|
+
# 重签名 IPA 文件的主入口方法
|
|
12
|
+
# @param ipa_file_path [String] IPA 文件路径(可选,如果为 nil 则自动查找当前目录下的 IPA)
|
|
13
|
+
# @param bundle_id [String] 新的 Bundle ID
|
|
14
|
+
# @return [String, nil] 重签名后的 IPA 文件路径,失败返回 nil
|
|
15
|
+
def resign_ipa(ipa_file_path: nil, bundle_id:)
|
|
16
|
+
ipa_path = find_ipa_file(ipa_file_path)
|
|
17
|
+
|
|
18
|
+
if ipa_path.nil? || ipa_path.empty?
|
|
19
|
+
puts "未找到 IPA 文件"
|
|
20
|
+
return nil
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# 准备重签名的 IPA(修改 Bundle ID)
|
|
24
|
+
resigned_ipa_path = prepare_resign_ipa(ipa_name: ipa_path, bundle_id: bundle_id)
|
|
25
|
+
|
|
26
|
+
if resigned_ipa_path.nil?
|
|
27
|
+
puts "准备重签名 IPA 失败"
|
|
28
|
+
return nil
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# 使用新证书签名
|
|
32
|
+
sign_ipa_with_new_cert(ipa_name: resigned_ipa_path, bundle_id: bundle_id)
|
|
33
|
+
|
|
34
|
+
resigned_ipa_path
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
private
|
|
38
|
+
|
|
39
|
+
# 查找 IPA 文件
|
|
40
|
+
# @param ipa_file_path [String, nil] 指定的 IPA 文件路径
|
|
41
|
+
# @return [String, nil] IPA 文件的完整路径
|
|
42
|
+
def find_ipa_file(ipa_file_path)
|
|
43
|
+
if ipa_file_path
|
|
44
|
+
return File.expand_path(ipa_file_path)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# 自动查找当前目录下的 IPA 文件
|
|
48
|
+
current_dir = Dir.pwd
|
|
49
|
+
Dir.foreach(current_dir) do |file|
|
|
50
|
+
if file =~ /(.*).ipa/
|
|
51
|
+
return File.join(current_dir, file)
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
nil
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# 准备重签名的 IPA(修改 Bundle ID)
|
|
59
|
+
# @param ipa_name [String] 原始 IPA 文件路径
|
|
60
|
+
# @param bundle_id [String] 新的 Bundle ID
|
|
61
|
+
# @return [String, nil] 准备好的 IPA 文件路径
|
|
62
|
+
def prepare_resign_ipa(ipa_name:, bundle_id:)
|
|
63
|
+
ipa_base_name = File.basename(ipa_name, ".ipa")
|
|
64
|
+
ipa_dir = File.dirname(ipa_name)
|
|
65
|
+
|
|
66
|
+
resign_ipa_name = ipa_base_name + "_resigned.ipa"
|
|
67
|
+
resign_ipa_full_name = File.join(ipa_dir, resign_ipa_name)
|
|
68
|
+
FileUtils.cp_r(ipa_name, resign_ipa_full_name)
|
|
69
|
+
puts resign_ipa_full_name
|
|
70
|
+
|
|
71
|
+
tmp_time = "tmp_" + Time.now.strftime('%y%m%d_%H%M%S')
|
|
72
|
+
tmp_dir = File.join(ipa_dir, tmp_time)
|
|
73
|
+
FileUtils.mkdir(tmp_dir) unless File.exist?(tmp_dir)
|
|
74
|
+
|
|
75
|
+
# 解压 IPA
|
|
76
|
+
command = "unzip -q \"#{resign_ipa_full_name}\" -d #{tmp_dir}"
|
|
77
|
+
puts command
|
|
78
|
+
system command
|
|
79
|
+
|
|
80
|
+
payload_path = File.join(tmp_dir, "Payload")
|
|
81
|
+
if File.exist?(payload_path)
|
|
82
|
+
FileUtils.rm_rf(resign_ipa_full_name)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# 查找 .app 目录
|
|
86
|
+
modify_content_path = ""
|
|
87
|
+
Dir.foreach(payload_path) do |file|
|
|
88
|
+
if file =~ /(.*).app/
|
|
89
|
+
modify_content_path = File.join(payload_path, file)
|
|
90
|
+
break
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
# 修改 Info.plist 中的 Bundle ID
|
|
95
|
+
modify_ipa_info_plist(modify_content_path: modify_content_path, bundle_id: bundle_id)
|
|
96
|
+
|
|
97
|
+
# 重新打包 IPA
|
|
98
|
+
current_dir = Dir.pwd
|
|
99
|
+
if File.exist?(payload_path)
|
|
100
|
+
Dir.chdir(tmp_dir)
|
|
101
|
+
command = "zip -qry \"#{resign_ipa_full_name}\" * "
|
|
102
|
+
puts command
|
|
103
|
+
system command
|
|
104
|
+
Dir.chdir(current_dir)
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
# 清理临时目录
|
|
108
|
+
FileUtils.rm_rf(tmp_dir) if File.exist?(resign_ipa_full_name)
|
|
109
|
+
|
|
110
|
+
resign_ipa_full_name
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
# 修改 IPA 中的 Info.plist 文件
|
|
114
|
+
# @param modify_content_path [String] .app 目录路径
|
|
115
|
+
# @param bundle_id [String] 新的 Bundle ID
|
|
116
|
+
def modify_ipa_info_plist(modify_content_path:, bundle_id:)
|
|
117
|
+
main_info_plist = File.join(modify_content_path, "Info.plist")
|
|
118
|
+
puts main_info_plist
|
|
119
|
+
|
|
120
|
+
# 确保 PlistBuddy 可用
|
|
121
|
+
unless File.exist?("/usr/local/bin/PlistBuddy")
|
|
122
|
+
command = 'ln -s /usr/libexec/PlistBuddy /usr/local/bin/PlistBuddy'
|
|
123
|
+
system command
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
# 读取旧的 Bundle ID
|
|
127
|
+
old_bundle_id_command = '/usr/local/bin/PlistBuddy -c "Print :CFBundleIdentifier" ' + main_info_plist
|
|
128
|
+
puts old_bundle_id_command
|
|
129
|
+
old_bundle_id = ""
|
|
130
|
+
IO.popen(old_bundle_id_command) { |f| old_bundle_id = f.gets }
|
|
131
|
+
puts old_bundle_id
|
|
132
|
+
|
|
133
|
+
# 修改主应用的 Bundle ID
|
|
134
|
+
exchange_bundleid_command = '/usr/local/bin/PlistBuddy -c "Set :CFBundleIdentifier ' + bundle_id + '" ' + main_info_plist
|
|
135
|
+
puts exchange_bundleid_command
|
|
136
|
+
system exchange_bundleid_command
|
|
137
|
+
|
|
138
|
+
# 修改插件扩展的 Bundle ID
|
|
139
|
+
plugin_path = File.join(modify_content_path, "PlugIns")
|
|
140
|
+
if File.exist?(plugin_path)
|
|
141
|
+
Dir.foreach(plugin_path) do |file|
|
|
142
|
+
next unless file =~ /(.*).appex/
|
|
143
|
+
|
|
144
|
+
appex_path = File.join(plugin_path, file)
|
|
145
|
+
tmp_info_plist = File.join(appex_path, "Info.plist")
|
|
146
|
+
|
|
147
|
+
old_bundle_id_command = '/usr/local/bin/PlistBuddy -c "Print :CFBundleIdentifier" ' + tmp_info_plist
|
|
148
|
+
puts old_bundle_id_command
|
|
149
|
+
old_plugin_bundle_id = ""
|
|
150
|
+
IO.popen(old_bundle_id_command) { |f| old_plugin_bundle_id = f.gets }
|
|
151
|
+
puts "old_bundle_id = #{old_plugin_bundle_id}"
|
|
152
|
+
|
|
153
|
+
# 根据插件类型修改 Bundle ID
|
|
154
|
+
update_plugin_bundle_id(tmp_info_plist, old_plugin_bundle_id, bundle_id)
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
# 更新插件的 Bundle ID
|
|
160
|
+
# @param plist_path [String] 插件的 Info.plist 路径
|
|
161
|
+
# @param old_bundle_id [String] 旧的 Bundle ID
|
|
162
|
+
# @param new_base_bundle_id [String] 新的基础 Bundle ID
|
|
163
|
+
def update_plugin_bundle_id(plist_path, old_bundle_id, new_base_bundle_id)
|
|
164
|
+
plugin_types = [
|
|
165
|
+
".content", ".service", ".imessage", ".keyboard",
|
|
166
|
+
".siri", ".widget", ".siriui", ".extension",
|
|
167
|
+
".extensionad", ".extensionporn"
|
|
168
|
+
]
|
|
169
|
+
|
|
170
|
+
plugin_types.each do |suffix|
|
|
171
|
+
if old_bundle_id.include?(suffix)
|
|
172
|
+
new_plugin_bundle_id = new_base_bundle_id + suffix
|
|
173
|
+
exchange_bundleid_command = '/usr/local/bin/PlistBuddy -c "Set :CFBundleIdentifier ' + new_plugin_bundle_id + '" ' + plist_path
|
|
174
|
+
puts exchange_bundleid_command
|
|
175
|
+
system exchange_bundleid_command
|
|
176
|
+
break
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
# 使用新证书签名 IPA
|
|
182
|
+
# @param ipa_name [String] IPA 文件路径
|
|
183
|
+
# @param bundle_id [String] Bundle ID
|
|
184
|
+
def sign_ipa_with_new_cert(ipa_name:, bundle_id:)
|
|
185
|
+
require 'pindo/config/pindoconfig'
|
|
186
|
+
|
|
187
|
+
profil_info_array = Pindo::PindoSingleConfig.instance.get_cert_info
|
|
188
|
+
bundle_id_signing_identity = profil_info_array.first['signing_identity']
|
|
189
|
+
|
|
190
|
+
profile_dict = build_resign_profile_dict(profil_info_array: profil_info_array)
|
|
191
|
+
|
|
192
|
+
# 调用 Sigh::Resign 进行重签名
|
|
193
|
+
# resign(ipa, signing_identity, provisioning_profiles, entitlements, version, display_name, short_version, bundle_version, new_bundle_id, use_app_entitlements, keychain_path)
|
|
194
|
+
Sigh::Resign.resign(ipa_name, bundle_id_signing_identity, profile_dict, nil, nil, nil, nil, nil, bundle_id, true, nil)
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
# 构建重签名用的 profile 字典
|
|
198
|
+
# @param profil_info_array [Array<Hash>] 证书信息数组
|
|
199
|
+
# @return [Hash] Bundle ID 到 profile 路径的映射
|
|
200
|
+
def build_resign_profile_dict(profil_info_array:)
|
|
201
|
+
resign_dict = {}
|
|
202
|
+
profil_info_array.each do |profil_info|
|
|
203
|
+
resign_dict[profil_info["bundle_id"]] = profil_info["profile_path"]
|
|
204
|
+
end
|
|
205
|
+
resign_dict
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
end
|
|
209
|
+
end
|
|
210
|
+
end
|
|
@@ -209,5 +209,84 @@ module Pindo
|
|
|
209
209
|
end
|
|
210
210
|
end
|
|
211
211
|
|
|
212
|
+
# 创建发布 tag
|
|
213
|
+
# @param project_dir [String] 项目目录
|
|
214
|
+
# @param config_json [Hash] 配置 JSON
|
|
215
|
+
# @param bundle_id [String] Bundle ID
|
|
216
|
+
# @param delete_tag_name [String] 可选,要删除的 tag 名称
|
|
217
|
+
# @return [Boolean] 是否成功
|
|
218
|
+
def create_release_tag(project_dir:, config_json:, bundle_id:, delete_tag_name: nil)
|
|
219
|
+
require 'pindo/base/git_handler'
|
|
220
|
+
require 'pindo/config/pindoconfig'
|
|
221
|
+
require_relative '../../base/funlog'
|
|
222
|
+
|
|
223
|
+
begin
|
|
224
|
+
pindo_dir = File.expand_path(Pindo::PindoConfig.pindo_single_config.pindo_dir)
|
|
225
|
+
app_config_dir = File.join(pindo_dir, bundle_id)
|
|
226
|
+
|
|
227
|
+
# 如果指定了要删除的 tag
|
|
228
|
+
if !delete_tag_name.nil? && !delete_tag_name.empty?
|
|
229
|
+
result = Pindo::GitHandler.remove_tag(local_repo_dir: project_dir, tag_name: delete_tag_name)
|
|
230
|
+
if result
|
|
231
|
+
puts
|
|
232
|
+
puts "代码仓库路径#{project_dir}"
|
|
233
|
+
puts "已删除tag : #{delete_tag_name}"
|
|
234
|
+
puts
|
|
235
|
+
puts
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
result = Pindo::GitHandler.remove_tag(local_repo_dir: app_config_dir, tag_name: delete_tag_name)
|
|
239
|
+
if result
|
|
240
|
+
puts
|
|
241
|
+
puts "配置仓库路径#{app_config_dir}"
|
|
242
|
+
puts "已删除tag : #{delete_tag_name}"
|
|
243
|
+
puts
|
|
244
|
+
puts
|
|
245
|
+
end
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
# 创建新的 tag
|
|
249
|
+
if config_json && config_json["app_info"] && config_json["app_info"]["app_version"]
|
|
250
|
+
temp_version = config_json["app_info"]["app_version"]
|
|
251
|
+
else
|
|
252
|
+
Funlog.instance.fancyinfo_error("无法从配置中获取 app_version")
|
|
253
|
+
return false
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
tag_name = "ios_release_" + temp_version
|
|
257
|
+
puts tag_name
|
|
258
|
+
|
|
259
|
+
# 为代码仓库创建 tag
|
|
260
|
+
Pindo::GitHandler.remove_tag(local_repo_dir: project_dir, tag_name: tag_name)
|
|
261
|
+
result = Pindo::GitHandler.add_tag(local_repo_dir: project_dir, tag_name: tag_name)
|
|
262
|
+
if result
|
|
263
|
+
puts
|
|
264
|
+
puts "代码仓库路径#{project_dir}"
|
|
265
|
+
puts "已添加tag : #{tag_name}"
|
|
266
|
+
puts
|
|
267
|
+
puts
|
|
268
|
+
end
|
|
269
|
+
|
|
270
|
+
# 为配置仓库创建 tag
|
|
271
|
+
Pindo::GitHandler.remove_tag(local_repo_dir: app_config_dir, tag_name: tag_name)
|
|
272
|
+
result = Pindo::GitHandler.add_tag(local_repo_dir: app_config_dir, tag_name: tag_name)
|
|
273
|
+
|
|
274
|
+
if result
|
|
275
|
+
puts
|
|
276
|
+
puts "配置仓库路径#{app_config_dir}"
|
|
277
|
+
puts "已添加tag : #{tag_name}"
|
|
278
|
+
puts
|
|
279
|
+
puts
|
|
280
|
+
end
|
|
281
|
+
|
|
282
|
+
return true
|
|
283
|
+
|
|
284
|
+
rescue StandardError => e
|
|
285
|
+
Funlog.instance.fancyinfo_error("创建 tag 失败: #{e.message}")
|
|
286
|
+
puts e.backtrace
|
|
287
|
+
return false
|
|
288
|
+
end
|
|
289
|
+
end
|
|
290
|
+
|
|
212
291
|
end
|
|
213
292
|
end
|