pindo 5.15.9 → 5.15.10
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/command/appstore/autoresign.rb +75 -31
- data/lib/pindo/command/ios/autoresign.rb +230 -102
- data/lib/pindo/module/android/android_build_helper.rb +5 -4
- data/lib/pindo/module/android/java_env_helper.rb +14 -15
- data/lib/pindo/module/task/model/resign/ipa_local_resign_task.rb +41 -30
- data/lib/pindo/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: fccc8a94b142c2ded9b8c84ec32547c169f5430a47399bb137d5ee41dccbb231
|
|
4
|
+
data.tar.gz: b7b206af7a824e6ce3b6aa22d7430338a4508ad8e35e384314cbcf8f8067c167
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 170d6fc09e62a728fccb206db5721e49edc0fcedaddaa038d35c360b8d9b3c40f67ee5c0ced6619a528d46d070115b2196bf21e224eeee15db18edadda90a1d2
|
|
7
|
+
data.tar.gz: 9a04148c8f7aed1404597cea62465d5ca282633823f69d4f0fcdfc5d6cdb7bf5160b781af749d6463f6f9395ff7c75620607902bf159ddf85fffa7ed9392f4b6
|
|
@@ -9,6 +9,7 @@ require 'pindo/module/task/task_manager'
|
|
|
9
9
|
require 'pindo/module/task/model/resign/ipa_local_resign_task'
|
|
10
10
|
require 'pindo/module/task/model/jps/jps_upload_task'
|
|
11
11
|
require 'pindo/options/options'
|
|
12
|
+
require 'pindo/options/groups/cert_options'
|
|
12
13
|
|
|
13
14
|
module Pindo
|
|
14
15
|
class Command
|
|
@@ -31,7 +32,9 @@ module Pindo
|
|
|
31
32
|
|
|
32
33
|
支持功能:
|
|
33
34
|
|
|
34
|
-
* IPA 文件重签名(支持 dev/adhoc
|
|
35
|
+
* IPA 文件重签名(支持 dev/adhoc/appstore 等证书类型)
|
|
36
|
+
|
|
37
|
+
* 支持三种证书模式: Match+Git / Custom+Git / Custom+HTTPS
|
|
35
38
|
|
|
36
39
|
* 自动查找或手动指定 IPA 文件
|
|
37
40
|
|
|
@@ -39,23 +42,27 @@ module Pindo
|
|
|
39
42
|
|
|
40
43
|
* 发送测试通知到群组
|
|
41
44
|
|
|
42
|
-
* 支持 dev/adhoc 构建类型
|
|
43
|
-
|
|
44
45
|
使用示例:
|
|
45
46
|
|
|
46
|
-
$ pindo appstore autoresign
|
|
47
|
+
$ pindo appstore autoresign # 自动查找并重签名(adhoc,custom+https)
|
|
48
|
+
|
|
49
|
+
$ pindo appstore autoresign demo.ipa # 重签名指定 IPA
|
|
47
50
|
|
|
48
|
-
$ pindo appstore autoresign demo.ipa
|
|
51
|
+
$ pindo appstore autoresign --ipa=demo.ipa # 使用选项指定 IPA
|
|
49
52
|
|
|
50
|
-
$ pindo appstore autoresign --
|
|
53
|
+
$ pindo appstore autoresign --dev # 使用 dev 证书
|
|
51
54
|
|
|
52
|
-
$ pindo appstore autoresign --
|
|
55
|
+
$ pindo appstore autoresign --adhoc # 使用 adhoc 证书(默认)
|
|
53
56
|
|
|
54
|
-
$ pindo appstore autoresign --
|
|
57
|
+
$ pindo appstore autoresign --match # 使用 match+git 模式
|
|
55
58
|
|
|
56
|
-
$ pindo appstore autoresign --
|
|
59
|
+
$ pindo appstore autoresign --cert-mode=custom --storage=git # 使用 custom+git 模式
|
|
57
60
|
|
|
58
|
-
$ pindo appstore autoresign --
|
|
61
|
+
$ pindo appstore autoresign --upload # 重签名并上传
|
|
62
|
+
|
|
63
|
+
$ pindo appstore autoresign --send # 重签名、上传并发送通知
|
|
64
|
+
|
|
65
|
+
$ pindo appstore autoresign --proj="My App" # 指定项目名称
|
|
59
66
|
DESC
|
|
60
67
|
|
|
61
68
|
# 位置参数(向后兼容)
|
|
@@ -85,21 +92,11 @@ module Pindo
|
|
|
85
92
|
example: 'pindo appstore autoresign --ipa=path/to/demo.ipa'
|
|
86
93
|
)
|
|
87
94
|
|
|
88
|
-
#
|
|
89
|
-
items
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
default_value: 'adhoc',
|
|
94
|
-
optional: true,
|
|
95
|
-
verify_block: proc do |value|
|
|
96
|
-
valid_types = ['dev', 'adhoc']
|
|
97
|
-
unless valid_types.include?(value.to_s.downcase)
|
|
98
|
-
raise "构建类型错误: #{value},必须是 dev 或 adhoc"
|
|
99
|
-
end
|
|
100
|
-
end,
|
|
101
|
-
example: 'pindo appstore autoresign --type=dev'
|
|
102
|
-
)
|
|
95
|
+
# 添加证书相关参数(CertOptions)
|
|
96
|
+
items.concat(Pindo::Options::CertOptions.select(
|
|
97
|
+
:dev, :adhoc, :develop_id, :build_type,
|
|
98
|
+
:platform, :macos, :cert_mode, :storage, :match
|
|
99
|
+
))
|
|
103
100
|
|
|
104
101
|
# 合并 JPSOptions
|
|
105
102
|
items.concat(Pindo::Options::JPSOptions.select(:proj, :upload, :send))
|
|
@@ -122,11 +119,55 @@ module Pindo
|
|
|
122
119
|
|
|
123
120
|
# 优先使用选项参数,如果没有则使用位置参数
|
|
124
121
|
@args_ipa_file = @options[:ipa] || positional_ipa
|
|
125
|
-
|
|
122
|
+
|
|
123
|
+
# JPS 参数
|
|
126
124
|
@args_upload_flag = @options[:send] || @options[:upload]
|
|
127
125
|
@args_send_flag = @options[:send]
|
|
128
126
|
@args_proj_name = @options[:proj]
|
|
129
127
|
|
|
128
|
+
# 证书快捷参数
|
|
129
|
+
@args_adhoc_flag = @options[:adhoc]
|
|
130
|
+
@args_dev_flag = @options[:dev]
|
|
131
|
+
@args_develop_id_flag = @options[:develop_id]
|
|
132
|
+
@args_macos_flag = @options[:macos]
|
|
133
|
+
@args_match_flag = @options[:match]
|
|
134
|
+
|
|
135
|
+
# 证书模式参数(appstore autoresign 默认: custom + https)
|
|
136
|
+
@cert_mode = @options[:cert_mode] || 'custom'
|
|
137
|
+
@storage = @options[:storage] || 'https'
|
|
138
|
+
|
|
139
|
+
# 处理 --match 快捷方式
|
|
140
|
+
if @args_match_flag
|
|
141
|
+
@cert_mode = 'match'
|
|
142
|
+
@storage = 'git'
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
# 构建类型优先级:--develop_id > --adhoc > --dev > --build_type > 默认 adhoc
|
|
146
|
+
@args_build_type = @options[:build_type]
|
|
147
|
+
if @args_develop_id_flag
|
|
148
|
+
@args_build_type = 'developer_id'
|
|
149
|
+
elsif @args_adhoc_flag
|
|
150
|
+
@args_build_type = 'adhoc'
|
|
151
|
+
elsif @args_dev_flag
|
|
152
|
+
@args_build_type = 'dev'
|
|
153
|
+
elsif @args_build_type.nil? || @args_build_type.to_s.empty?
|
|
154
|
+
@args_build_type = 'adhoc'
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
# 标准化构建类型
|
|
158
|
+
@args_build_type = Pindo::Options::CertOptions.normalize_build_type(@args_build_type)
|
|
159
|
+
|
|
160
|
+
# 处理平台类型
|
|
161
|
+
@platform_type = @options[:platform]
|
|
162
|
+
if @args_macos_flag
|
|
163
|
+
@platform_type = 'macos'
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
# macOS 平台特殊处理
|
|
167
|
+
if @platform_type == 'macos' && @args_build_type == 'adhoc'
|
|
168
|
+
@args_build_type = 'developer_id'
|
|
169
|
+
end
|
|
170
|
+
|
|
130
171
|
super
|
|
131
172
|
@additional_args = argv.remainder!
|
|
132
173
|
end
|
|
@@ -234,11 +275,11 @@ module Pindo
|
|
|
234
275
|
|
|
235
276
|
# 选择 Bundle ID(根据 build_type)
|
|
236
277
|
def select_bundle_id
|
|
237
|
-
bundle_id = if @args_build_type == '
|
|
238
|
-
# dev 类型使用测试 Bundle ID
|
|
278
|
+
bundle_id = if @args_build_type == 'development'
|
|
279
|
+
# dev/development 类型使用测试 Bundle ID
|
|
239
280
|
get_selected_dev_bundleid()
|
|
240
281
|
else
|
|
241
|
-
# adhoc 类型使用发布 Bundle ID
|
|
282
|
+
# adhoc/appstore/developer_id 类型使用发布 Bundle ID
|
|
242
283
|
get_selected_deploy_bundleid()
|
|
243
284
|
end
|
|
244
285
|
|
|
@@ -296,8 +337,11 @@ module Pindo
|
|
|
296
337
|
Dir.pwd, # ipa_path(搜索路径)
|
|
297
338
|
ipa_file_path, # ipa_file(明确指定)
|
|
298
339
|
bundle_id, # bundle_id
|
|
299
|
-
build_type: @args_build_type,
|
|
300
|
-
project_dir: Dir.pwd
|
|
340
|
+
build_type: @args_build_type,
|
|
341
|
+
project_dir: Dir.pwd,
|
|
342
|
+
cert_mode: @cert_mode,
|
|
343
|
+
storage: @storage,
|
|
344
|
+
platform_type: @platform_type
|
|
301
345
|
)
|
|
302
346
|
tasks << resign_task
|
|
303
347
|
|
|
@@ -4,16 +4,26 @@ require 'find'
|
|
|
4
4
|
require 'fileutils'
|
|
5
5
|
require 'pindo/base/executable'
|
|
6
6
|
require 'pindo/config/ios_config_parser'
|
|
7
|
+
require 'pindo/config/build_info_manager'
|
|
7
8
|
require 'pindo/module/xcode/ipa_resign_helper'
|
|
9
|
+
require 'pindo/module/task/task_manager'
|
|
10
|
+
require 'pindo/module/task/model/resign/ipa_local_resign_task'
|
|
11
|
+
require 'pindo/module/task/model/jps/jps_upload_task'
|
|
12
|
+
require 'pindo/options/groups/cert_options'
|
|
8
13
|
|
|
9
14
|
module Pindo
|
|
10
15
|
class Command
|
|
11
16
|
class Ios < Command
|
|
12
17
|
class Autoresign < Ios
|
|
13
|
-
|
|
18
|
+
|
|
14
19
|
include Appselect
|
|
15
20
|
self.summary = 'IPA包重签名工具'
|
|
16
21
|
|
|
22
|
+
# 启用缓存机制
|
|
23
|
+
def self.use_cache?
|
|
24
|
+
true
|
|
25
|
+
end
|
|
26
|
+
|
|
17
27
|
self.description = <<-DESC
|
|
18
28
|
使用最新的证书重签名IPA包。
|
|
19
29
|
|
|
@@ -21,185 +31,303 @@ module Pindo
|
|
|
21
31
|
|
|
22
32
|
* 使用开发或发布证书重签名
|
|
23
33
|
|
|
34
|
+
* 支持三种证书模式: Match+Git / Custom+Git / Custom+HTTPS
|
|
35
|
+
|
|
24
36
|
* 支持指定IPA路径
|
|
25
37
|
|
|
26
38
|
* 支持上传到JPS测试平台
|
|
27
39
|
|
|
28
40
|
* 支持发送测试通知
|
|
29
41
|
|
|
42
|
+
* 支持完整的证书参数(与 pindo ios cert 一致)
|
|
43
|
+
|
|
30
44
|
使用示例:
|
|
31
45
|
|
|
32
|
-
$ pindo ios autoresign
|
|
46
|
+
$ pindo ios autoresign # 重签名当前目录下的IPA(dev,custom+https)
|
|
47
|
+
|
|
48
|
+
$ pindo ios autoresign demo.ipa # 重签名指定IPA文件
|
|
49
|
+
|
|
50
|
+
$ pindo ios autoresign --adhoc # 使用adhoc证书重签名
|
|
51
|
+
|
|
52
|
+
$ pindo ios autoresign --deploy # 使用发布bundle id
|
|
33
53
|
|
|
34
|
-
$ pindo ios autoresign
|
|
54
|
+
$ pindo ios autoresign --upload # 重签名并上传到JPS
|
|
35
55
|
|
|
36
|
-
$ pindo ios autoresign --
|
|
56
|
+
$ pindo ios autoresign --send # 重签名、上传并发送通知
|
|
37
57
|
|
|
38
|
-
$ pindo ios autoresign --
|
|
58
|
+
$ pindo ios autoresign --build_type=appstore # 使用appstore证书
|
|
39
59
|
|
|
40
|
-
$ pindo ios autoresign --
|
|
60
|
+
$ pindo ios autoresign --cert-mode=match --storage=git # 使用match模式
|
|
41
61
|
|
|
42
|
-
$ pindo ios autoresign --
|
|
62
|
+
$ pindo ios autoresign --match # 使用match+git模式(快捷方式)
|
|
63
|
+
|
|
64
|
+
$ pindo ios autoresign --cert-mode=custom --storage=https # 使用custom+https模式(默认)
|
|
43
65
|
DESC
|
|
44
66
|
|
|
45
67
|
self.arguments = [
|
|
46
68
|
CLAide::Argument.new('path/to/demo.ipa', true),
|
|
47
69
|
]
|
|
48
70
|
|
|
71
|
+
def self.option_items
|
|
72
|
+
@option_items ||= Pindo::Options::CertOptions.select(
|
|
73
|
+
:dev, :adhoc, :develop_id, :build_type,
|
|
74
|
+
:platform, :macos, :cert_mode, :storage, :match
|
|
75
|
+
)
|
|
76
|
+
end
|
|
77
|
+
|
|
49
78
|
def self.options
|
|
50
79
|
[
|
|
51
80
|
['--ipa', '指定要重签名的IPA文件路径'],
|
|
52
|
-
['--
|
|
53
|
-
['--deploy', '使用发布证书和bundle id重签名(默认使用开发证书)'],
|
|
81
|
+
['--deploy', '使用发布证书和bundle id重签名(默认使用开发证书)'],
|
|
54
82
|
['--proj', '指定上传到测试平台的项目名称'],
|
|
55
83
|
['--upload', '上传重签名后的IPA到测试平台'],
|
|
56
84
|
['--send', '上传成功后发送测试通知'],
|
|
57
|
-
].concat(super)
|
|
85
|
+
].concat(option_items.map { |item| item.to_claide_option }).concat(super)
|
|
58
86
|
end
|
|
59
87
|
|
|
60
|
-
|
|
88
|
+
|
|
61
89
|
def initialize(argv)
|
|
62
90
|
|
|
91
|
+
# autoresign 自有参数(手动解析)
|
|
63
92
|
@args_ipa_file = argv.shift_argument
|
|
64
93
|
@args_set_ipa_name = argv.option('ipa')
|
|
65
|
-
@args_adhoc_flag = argv.flag?('adhoc', false)
|
|
66
94
|
@args_deploy_flag = argv.flag?('deploy', false)
|
|
67
|
-
|
|
68
|
-
@
|
|
69
|
-
@args_send_flag = argv.flag?('send', false)
|
|
95
|
+
@args_upload_flag = argv.flag?('upload', false)
|
|
96
|
+
@args_send_flag = argv.flag?('send', false)
|
|
70
97
|
@args_proj_name = argv.option('proj')
|
|
71
98
|
|
|
72
99
|
if @args_send_flag
|
|
73
100
|
@args_upload_flag = true
|
|
74
101
|
end
|
|
75
102
|
|
|
103
|
+
# 使用 Options 模块初始化证书参数
|
|
104
|
+
@options = initialize_options(argv)
|
|
105
|
+
|
|
106
|
+
# 证书快捷参数
|
|
107
|
+
@args_adhoc_flag = @options[:adhoc]
|
|
108
|
+
@args_dev_flag = @options[:dev]
|
|
109
|
+
@args_develop_id_flag = @options[:develop_id]
|
|
110
|
+
@args_macos_flag = @options[:macos]
|
|
111
|
+
@args_match_flag = @options[:match]
|
|
112
|
+
|
|
113
|
+
# 证书参数(ios autoresign 默认: custom + https)
|
|
114
|
+
@cert_mode = @options[:cert_mode] || 'custom'
|
|
115
|
+
@storage = @options[:storage] || 'https'
|
|
116
|
+
|
|
117
|
+
# 处理 --match 快捷方式
|
|
118
|
+
if @args_match_flag
|
|
119
|
+
@cert_mode = 'match'
|
|
120
|
+
@storage = 'git'
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
# 构建类型优先级:--develop_id > --adhoc > --dev > --build_type > 默认 dev
|
|
124
|
+
@build_type = @options[:build_type]
|
|
125
|
+
if @args_develop_id_flag
|
|
126
|
+
@build_type = 'developer_id'
|
|
127
|
+
elsif @args_adhoc_flag
|
|
128
|
+
@build_type = 'adhoc'
|
|
129
|
+
elsif @args_dev_flag
|
|
130
|
+
@build_type = 'dev'
|
|
131
|
+
elsif @build_type.nil? || @build_type.to_s.empty?
|
|
132
|
+
@build_type = 'dev' # autoresign 默认使用 dev 证书
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
# 标准化构建类型
|
|
136
|
+
@build_type = Pindo::Options::CertOptions.normalize_build_type(@build_type)
|
|
137
|
+
|
|
138
|
+
# 处理平台类型
|
|
139
|
+
@platform_type = @options[:platform]
|
|
140
|
+
if @args_macos_flag
|
|
141
|
+
@platform_type = 'macos'
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
# macOS 平台特殊处理
|
|
145
|
+
if @platform_type == 'macos' && @build_type == 'adhoc'
|
|
146
|
+
@build_type = 'developer_id'
|
|
147
|
+
end
|
|
148
|
+
|
|
76
149
|
super
|
|
77
150
|
@additional_args = argv.remainder!
|
|
78
151
|
end
|
|
79
152
|
|
|
80
153
|
|
|
81
154
|
def run
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
155
|
+
begin
|
|
156
|
+
# 1. 查找 IPA 文件
|
|
157
|
+
ipa_file_path = find_ipa_file()
|
|
158
|
+
unless ipa_file_path && File.exist?(ipa_file_path)
|
|
159
|
+
raise Informative, "未找到需要重签名的 IPA 文件"
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
# 2. 选择 Bundle ID
|
|
163
|
+
bundle_id = select_bundle_id()
|
|
164
|
+
puts "mainapp_bundleid: #{bundle_id}"
|
|
165
|
+
|
|
166
|
+
# 3. 拉取应用配置
|
|
167
|
+
pull_app_config(bundle_id)
|
|
168
|
+
|
|
169
|
+
# 4. 准备 JPS 配置(如果需要上传)
|
|
170
|
+
app_info_obj, workflow_info = prepare_jps_config()
|
|
171
|
+
|
|
172
|
+
# 5. 计算重签名后的 IPA 文件名
|
|
173
|
+
resigned_ipa_file = ipa_file_path.gsub(/\.ipa$/, '_resigned.ipa')
|
|
174
|
+
|
|
175
|
+
# 6. 创建任务
|
|
176
|
+
tasks = create_resign_tasks(
|
|
177
|
+
ipa_file_path: ipa_file_path,
|
|
178
|
+
resigned_ipa_file: resigned_ipa_file,
|
|
179
|
+
bundle_id: bundle_id,
|
|
180
|
+
app_info_obj: app_info_obj,
|
|
181
|
+
workflow_info: workflow_info
|
|
182
|
+
)
|
|
183
|
+
|
|
184
|
+
# 7. 执行任务
|
|
185
|
+
task_manager = Pindo::TaskSystem::TaskManager.instance
|
|
186
|
+
task_manager.clear_all
|
|
187
|
+
tasks.each { |task| task_manager.add_task(task) }
|
|
188
|
+
task_manager.start
|
|
189
|
+
|
|
190
|
+
ensure
|
|
191
|
+
# 清除命令状态
|
|
192
|
+
Pindo::Options::GlobalOptionsState.instance.clear
|
|
86
193
|
end
|
|
194
|
+
end
|
|
87
195
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
196
|
+
private
|
|
197
|
+
|
|
198
|
+
# 查找 IPA 文件
|
|
199
|
+
def find_ipa_file
|
|
200
|
+
# 1. 如果通过选项或位置参数指定了 IPA 文件且存在,直接返回
|
|
201
|
+
ipa_file_name = @args_set_ipa_name || @args_ipa_file
|
|
202
|
+
if ipa_file_name && File.exist?(ipa_file_name)
|
|
203
|
+
puts "\n使用指定的 IPA 文件: #{ipa_file_name}"
|
|
204
|
+
puts "修改时间: #{File.mtime(ipa_file_name)}"
|
|
205
|
+
return ipa_file_name
|
|
93
206
|
end
|
|
94
207
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
208
|
+
# 2. 在当前目录查找最新的非 _resigned 的 IPA
|
|
209
|
+
current_dir = Dir.pwd
|
|
210
|
+
ipa_files = Dir.glob(File.join(current_dir, "*.ipa"))
|
|
211
|
+
|
|
212
|
+
# 过滤掉 _resigned.ipa 并找到最新的
|
|
213
|
+
ipa_file = ipa_files.max_by do |f|
|
|
214
|
+
File.basename(f).include?("_resigned") ? Time.local(0, 1, 1) : File.mtime(f)
|
|
102
215
|
end
|
|
103
216
|
|
|
217
|
+
if ipa_file && File.exist?(ipa_file)
|
|
218
|
+
puts "\n自动找到 IPA 文件: #{ipa_file}"
|
|
219
|
+
puts "修改时间: #{File.mtime(ipa_file)}"
|
|
220
|
+
return ipa_file
|
|
221
|
+
end
|
|
104
222
|
|
|
105
|
-
|
|
223
|
+
# 3. 如果没有找到,从终端输入
|
|
224
|
+
puts "\n⚠️ 未找到 IPA 文件"
|
|
225
|
+
puts "请输入 IPA 文件路径(支持相对路径或绝对路径):"
|
|
106
226
|
|
|
107
|
-
|
|
108
|
-
|
|
227
|
+
ipa_path = ask("IPA 文件路径: ") do |q|
|
|
228
|
+
q.validate = /\.ipa$/i
|
|
229
|
+
q.responses[:not_valid] = "❌ 请输入有效的 IPA 文件路径(必须以 .ipa 结尾)"
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
# 去除首尾空格
|
|
233
|
+
ipa_path = ipa_path.strip if ipa_path
|
|
234
|
+
|
|
235
|
+
# 验证文件是否存在
|
|
236
|
+
if ipa_path && !ipa_path.empty?
|
|
237
|
+
if File.exist?(ipa_path)
|
|
238
|
+
puts "✓ 使用输入的 IPA 文件: #{ipa_path}"
|
|
239
|
+
puts " 修改时间: #{File.mtime(ipa_path)}"
|
|
240
|
+
return ipa_path
|
|
241
|
+
else
|
|
242
|
+
puts "❌ IPA 文件不存在: #{ipa_path}"
|
|
243
|
+
end
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
nil
|
|
247
|
+
end
|
|
248
|
+
|
|
249
|
+
# 选择 Bundle ID(根据 build_type)
|
|
250
|
+
def select_bundle_id
|
|
251
|
+
if @args_deploy_flag || @build_type != 'development'
|
|
252
|
+
get_selected_deploy_bundleid()
|
|
109
253
|
else
|
|
110
|
-
|
|
254
|
+
get_selected_dev_bundleid()
|
|
111
255
|
end
|
|
112
|
-
|
|
256
|
+
end
|
|
113
257
|
|
|
114
|
-
|
|
258
|
+
# 拉取应用配置
|
|
259
|
+
def pull_app_config(bundle_id)
|
|
115
260
|
require 'pindo/config/build_info_manager'
|
|
116
261
|
Pindo::BuildInfoManager.share_instance.pull_appconfig_with_reponame(
|
|
117
|
-
repo_name:
|
|
262
|
+
repo_name: bundle_id,
|
|
118
263
|
target_dir: Dir.pwd
|
|
119
264
|
)
|
|
265
|
+
end
|
|
120
266
|
|
|
121
|
-
|
|
122
|
-
|
|
267
|
+
# 准备 JPS 配置
|
|
268
|
+
def prepare_jps_config
|
|
123
269
|
if @args_upload_flag
|
|
124
270
|
proj_name = @args_proj_name
|
|
125
|
-
# 传入 package_type 获取 workflow_info
|
|
126
271
|
app_info_obj, workflow_info = PgyerHelper.share_instace.prepare_upload(
|
|
127
272
|
working_directory: Dir.pwd,
|
|
128
273
|
proj_name: proj_name,
|
|
129
274
|
package_type: 'ipa'
|
|
130
275
|
)
|
|
276
|
+
return [app_info_obj, workflow_info]
|
|
131
277
|
end
|
|
132
|
-
|
|
133
|
-
if !ipa_file_name.nil?
|
|
134
|
-
# 加载配置获取 Bundle ID
|
|
135
|
-
config_file = File.join(Dir.pwd, "config.json")
|
|
136
|
-
config_parser = Pindo::IosConfigParser.instance
|
|
137
|
-
config_parser.load_config(config_file: config_file)
|
|
138
|
-
bundle_id = config_parser.bundle_id
|
|
139
|
-
|
|
140
|
-
if bundle_id.nil? || bundle_id.empty?
|
|
141
|
-
raise Informative, "无法从配置文件中获取 Bundle ID"
|
|
142
|
-
end
|
|
143
278
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
cert_args = build_type == 'adhoc' ? ['--build_type=adhoc'] : []
|
|
147
|
-
Pindo::Command::Appstore::Cert::run(cert_args)
|
|
279
|
+
[nil, nil]
|
|
280
|
+
end
|
|
148
281
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
bundle_id: bundle_id
|
|
153
|
-
)
|
|
282
|
+
# 创建任务列表
|
|
283
|
+
def create_resign_tasks(ipa_file_path:, resigned_ipa_file:, bundle_id:, app_info_obj:, workflow_info:)
|
|
284
|
+
tasks = []
|
|
154
285
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
286
|
+
# 加载配置获取 Bundle ID
|
|
287
|
+
config_file = File.join(Dir.pwd, "config.json")
|
|
288
|
+
config_parser = Pindo::IosConfigParser.instance
|
|
289
|
+
config_parser.load_config(config_file: config_file)
|
|
290
|
+
config_bundle_id = config_parser.bundle_id
|
|
158
291
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
if !ipa_file_upload.nil? && !app_info_obj.nil?
|
|
163
|
-
result_data = PgyerHelper.share_instace.start_upload(
|
|
164
|
-
app_info_obj: app_info_obj,
|
|
165
|
-
ipa_file_upload: ipa_file_upload,
|
|
166
|
-
description: nil,
|
|
167
|
-
workflow_info: workflow_info
|
|
168
|
-
)
|
|
169
|
-
if !result_data.nil? && !result_data["data"].nil? && !result_data["data"]["id"].nil?
|
|
170
|
-
PgyerHelper.share_instace.print_app_version_info(
|
|
171
|
-
app_info_obj: app_info_obj,
|
|
172
|
-
app_version_info_obj: result_data["data"]
|
|
173
|
-
)
|
|
174
|
-
# 始终发送给自己
|
|
175
|
-
PgyerHelper.share_instace.send_apptest_msg(
|
|
176
|
-
app_info_obj: app_info_obj,
|
|
177
|
-
app_version_info_obj: result_data["data"],
|
|
178
|
-
receiveType: "self"
|
|
179
|
-
)
|
|
180
|
-
|
|
181
|
-
# 如果有 --send 参数,额外发送到测试群
|
|
182
|
-
if @args_send_flag
|
|
183
|
-
PgyerHelper.share_instace.send_apptest_msg(
|
|
184
|
-
app_info_obj: app_info_obj,
|
|
185
|
-
app_version_info_obj: result_data["data"],
|
|
186
|
-
chatEnv: "DevTest",
|
|
187
|
-
receiveType: "chat"
|
|
188
|
-
)
|
|
189
|
-
end
|
|
190
|
-
end
|
|
191
|
-
end
|
|
292
|
+
if config_bundle_id.nil? || config_bundle_id.empty?
|
|
293
|
+
raise Informative, "无法从配置文件中获取 Bundle ID"
|
|
294
|
+
end
|
|
192
295
|
|
|
296
|
+
# 1. 重签名任务
|
|
297
|
+
resign_task = Pindo::TaskSystem::IpaLocalResignTask.new(
|
|
298
|
+
Dir.pwd,
|
|
299
|
+
ipa_file_path,
|
|
300
|
+
config_bundle_id,
|
|
301
|
+
build_type: @build_type,
|
|
302
|
+
project_dir: Dir.pwd,
|
|
303
|
+
cert_mode: @cert_mode,
|
|
304
|
+
storage: @storage,
|
|
305
|
+
platform_type: @platform_type
|
|
306
|
+
)
|
|
307
|
+
tasks << resign_task
|
|
308
|
+
|
|
309
|
+
# 2. 上传任务(仅在需要时创建)
|
|
310
|
+
if @args_upload_flag && app_info_obj
|
|
311
|
+
upload_task = Pindo::TaskSystem::JPSUploadTask.new(
|
|
312
|
+
'ipa',
|
|
313
|
+
Dir.pwd,
|
|
314
|
+
resigned_ipa_file,
|
|
315
|
+
app_info_obj: app_info_obj,
|
|
316
|
+
workflow_info: workflow_info,
|
|
317
|
+
project_name: @args_proj_name,
|
|
318
|
+
upload_desc: "重签名包",
|
|
319
|
+
context: {
|
|
320
|
+
send_to_chat: @args_send_flag
|
|
321
|
+
},
|
|
322
|
+
dependencies: [resign_task.id]
|
|
323
|
+
)
|
|
324
|
+
tasks << upload_task
|
|
193
325
|
end
|
|
194
|
-
|
|
195
|
-
|
|
196
326
|
|
|
197
|
-
|
|
327
|
+
tasks
|
|
198
328
|
end
|
|
199
329
|
|
|
200
|
-
|
|
201
330
|
end
|
|
202
331
|
end
|
|
203
332
|
end
|
|
204
333
|
end
|
|
205
|
-
|
|
@@ -72,9 +72,6 @@ module Pindo
|
|
|
72
72
|
puts "Unity SO库编译完成,切换到主工程编译环境"
|
|
73
73
|
Pindo::JavaEnvHelper.setup_java_home_from_project(project_dir, use_main: true)
|
|
74
74
|
Pindo::GradleHelper.check_gradle_with_project(project_dir, configure_main: true)
|
|
75
|
-
|
|
76
|
-
# 检查并配置主工程的 local.properties
|
|
77
|
-
Pindo::AndroidProjectHelper.check_main_local_properties(project_dir)
|
|
78
75
|
else
|
|
79
76
|
puts "未检测到 IL2CPP 目录,可能使用 Mono 后端,跳过 SO 库构建"
|
|
80
77
|
end
|
|
@@ -89,6 +86,9 @@ module Pindo
|
|
|
89
86
|
Pindo::GradleHelper.update_build_gradle(project_dir)
|
|
90
87
|
end
|
|
91
88
|
|
|
89
|
+
# 检查并配置 local.properties(所有项目类型都需要)
|
|
90
|
+
Pindo::AndroidProjectHelper.check_main_local_properties(project_dir)
|
|
91
|
+
|
|
92
92
|
# 配置 Keystore 签名
|
|
93
93
|
build_type = debug ? "debug" : "release"
|
|
94
94
|
if Pindo::KeystoreHelper.apply_keystore_config(project_dir, build_type)
|
|
@@ -301,11 +301,12 @@ module Pindo
|
|
|
301
301
|
end
|
|
302
302
|
|
|
303
303
|
# 设置 Play Asset Delivery:直接扫描导出工程中的资源目录,按照 Android 原生方式创建 .androidpack 目录
|
|
304
|
+
# 仅适用于 Unity 项目,对于原生 Android 项目会静默跳过
|
|
304
305
|
def setup_play_asset_delivery(project_dir)
|
|
305
306
|
# 获取 unityLibrary 路径
|
|
306
307
|
unity_library_path = File.join(project_dir, "unityLibrary", "src", "main")
|
|
307
308
|
unless File.directory?(unity_library_path)
|
|
308
|
-
|
|
309
|
+
# 原生 Android 项目没有 unityLibrary 目录,静默跳过
|
|
309
310
|
return
|
|
310
311
|
end
|
|
311
312
|
|
|
@@ -69,26 +69,25 @@ module Pindo
|
|
|
69
69
|
end
|
|
70
70
|
|
|
71
71
|
# 如果 gradle.properties 中没有配置 Java Home,尝试自动查找
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
puts " ✗ 未找到 Java 17,请安装 Java 17 或在 gradle.properties 中配置 org.gradle.java.home"
|
|
84
|
-
end
|
|
72
|
+
puts " ⚠ gradle.properties 中未配置 org.gradle.java.home"
|
|
73
|
+
puts " ✓ 尝试自动查找合适的 Java 环境(>= 17)..."
|
|
74
|
+
|
|
75
|
+
java_home_path = find_suitable_java_home
|
|
76
|
+
if java_home_path
|
|
77
|
+
ENV['JAVA_HOME'] = java_home_path
|
|
78
|
+
ENV['PATH'] = "#{java_home_path}/bin:#{ENV['PATH']}"
|
|
79
|
+
puts " ✓ 找到合适的 Java 环境: #{java_home_path}"
|
|
80
|
+
return java_home_path
|
|
81
|
+
else
|
|
82
|
+
puts " ✗ 未找到 Java 17+,请安装 Java 17 或在 gradle.properties 中配置 org.gradle.java.home"
|
|
85
83
|
end
|
|
86
84
|
|
|
87
85
|
nil
|
|
88
86
|
end
|
|
89
87
|
|
|
90
|
-
#
|
|
91
|
-
|
|
88
|
+
# 查找系统中合适的 Java Home(版本 >= 17)
|
|
89
|
+
# @return [String, nil] 返回找到的 Java Home 路径,未找到则返回 nil
|
|
90
|
+
def find_suitable_java_home
|
|
92
91
|
# 1. 检查 Android Studio 内置的 JDK
|
|
93
92
|
android_studio_paths = [
|
|
94
93
|
"/Applications/Android Studio.app/Contents/jbr/Contents/Home",
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
require 'pindo/module/task/pindo_task'
|
|
2
2
|
require 'pindo/module/task/task_config'
|
|
3
|
+
require 'pindo/module/cert/cert_helper'
|
|
4
|
+
require 'pindo/config/ios_config_parser'
|
|
5
|
+
require 'pindo/module/xcode/ipa_resign_helper'
|
|
3
6
|
|
|
4
7
|
module Pindo
|
|
5
8
|
module TaskSystem
|
|
@@ -41,14 +44,20 @@ module Pindo
|
|
|
41
44
|
# @param ipa_file [String] 指定的 IPA 文件(nil 表示自动查找)
|
|
42
45
|
# @param bundle_id [String] 目标 Bundle ID
|
|
43
46
|
# @param options [Hash] 选项
|
|
44
|
-
# @option options [String] :build_type 构建类型('dev'
|
|
47
|
+
# @option options [String] :build_type 构建类型('dev'/'adhoc'/'appstore'/'development'/'developer_id',默认 'adhoc')
|
|
45
48
|
# @option options [String] :project_dir 项目目录(用于加载 config.json)
|
|
49
|
+
# @option options [String] :cert_mode 证书操作方式('match'/'custom',默认 nil 由 Cert 命令决定)
|
|
50
|
+
# @option options [String] :storage 证书存储后端('git'/'https'/'s3',默认 nil 由 Cert 命令决定)
|
|
51
|
+
# @option options [String] :platform_type 平台类型('ios'/'macos',默认 nil)
|
|
46
52
|
def initialize(ipa_path, ipa_file, bundle_id, options = {})
|
|
47
53
|
@ipa_path = ipa_path # IPA 搜索路径
|
|
48
54
|
@ipa_file = ipa_file # 指定的 IPA 文件(nil 表示自动查找)
|
|
49
55
|
@bundle_id = bundle_id # 目标 Bundle ID
|
|
50
56
|
@build_type = options[:build_type] || 'adhoc'
|
|
51
57
|
@project_dir = options[:project_dir] || Dir.pwd
|
|
58
|
+
@cert_mode = options[:cert_mode]
|
|
59
|
+
@storage = options[:storage]
|
|
60
|
+
@platform_type = options[:platform_type]
|
|
52
61
|
|
|
53
62
|
# 设置任务优先级
|
|
54
63
|
options[:priority] ||= TaskPriority::HIGH
|
|
@@ -65,8 +74,9 @@ module Pindo
|
|
|
65
74
|
end
|
|
66
75
|
|
|
67
76
|
# 验证 build_type
|
|
68
|
-
|
|
69
|
-
|
|
77
|
+
valid_build_types = %w[dev adhoc appstore development developer_id]
|
|
78
|
+
unless valid_build_types.include?(@build_type)
|
|
79
|
+
@error = "无效的 build_type: #{@build_type}(必须是 #{valid_build_types.join('/')})"
|
|
70
80
|
return false
|
|
71
81
|
end
|
|
72
82
|
|
|
@@ -91,14 +101,14 @@ module Pindo
|
|
|
91
101
|
raise "未找到需要重签名的 IPA 文件"
|
|
92
102
|
end
|
|
93
103
|
|
|
94
|
-
puts "\n
|
|
95
|
-
puts "
|
|
96
|
-
puts "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
97
|
-
puts " IPA 文件: #{ipa_to_resign}"
|
|
104
|
+
puts "\n▶ 重签名信息"
|
|
105
|
+
puts " IPA: #{File.basename(ipa_to_resign)}"
|
|
98
106
|
puts " Bundle ID: #{@bundle_id}"
|
|
99
|
-
puts "
|
|
100
|
-
|
|
101
|
-
|
|
107
|
+
puts " 类型: #{@build_type}"
|
|
108
|
+
cert_info = []
|
|
109
|
+
cert_info << @cert_mode if @cert_mode
|
|
110
|
+
cert_info << @storage if @storage
|
|
111
|
+
puts " 证书: #{cert_info.join(' + ')}" unless cert_info.empty?
|
|
102
112
|
|
|
103
113
|
# 2. 加载配置(如果尚未加载)
|
|
104
114
|
load_config_if_needed
|
|
@@ -107,7 +117,6 @@ module Pindo
|
|
|
107
117
|
install_certificate
|
|
108
118
|
|
|
109
119
|
# 4. 执行重签名
|
|
110
|
-
require 'pindo/module/xcode/ipa_resign_helper'
|
|
111
120
|
resigned_ipa = Pindo::IpaResignHelper.resign_ipa(
|
|
112
121
|
ipa_file_path: ipa_to_resign,
|
|
113
122
|
bundle_id: @bundle_id
|
|
@@ -118,8 +127,7 @@ module Pindo
|
|
|
118
127
|
raise "重签名失败:未生成重签名后的 IPA 文件"
|
|
119
128
|
end
|
|
120
129
|
|
|
121
|
-
puts "\n
|
|
122
|
-
puts " 重签名后的 IPA: #{resigned_ipa}"
|
|
130
|
+
puts "✅ 重签名完成: #{File.basename(resigned_ipa)}\n"
|
|
123
131
|
|
|
124
132
|
# 6. 返回重签名后的 IPA 路径
|
|
125
133
|
@result = resigned_ipa
|
|
@@ -131,7 +139,6 @@ module Pindo
|
|
|
131
139
|
def determine_ipa_file
|
|
132
140
|
if @ipa_file && !@ipa_file.empty? && File.exist?(@ipa_file)
|
|
133
141
|
# 使用指定的 IPA 文件
|
|
134
|
-
puts " 使用指定的 IPA 文件: #{@ipa_file}"
|
|
135
142
|
return @ipa_file
|
|
136
143
|
else
|
|
137
144
|
# 在 ipa_path 中查找最新的非 _resigned 的 IPA
|
|
@@ -156,26 +163,19 @@ module Pindo
|
|
|
156
163
|
|
|
157
164
|
# 返回最新的 IPA 文件
|
|
158
165
|
latest_ipa = ipa_files.max_by { |f| File.mtime(f) }
|
|
159
|
-
puts " 自动查找到 IPA 文件: #{latest_ipa}"
|
|
160
|
-
|
|
161
166
|
latest_ipa
|
|
162
167
|
end
|
|
163
168
|
|
|
164
169
|
# 加载配置(如果尚未加载)
|
|
165
170
|
def load_config_if_needed
|
|
166
|
-
require 'pindo/config/ios_config_parser'
|
|
167
171
|
config_parser = Pindo::IosConfigParser.instance
|
|
168
172
|
|
|
169
173
|
# 如果配置已加载,直接返回
|
|
170
|
-
if config_parser.config_json && !config_parser.config_json.empty?
|
|
171
|
-
puts " 使用已加载的配置"
|
|
172
|
-
return
|
|
173
|
-
end
|
|
174
|
+
return if config_parser.config_json && !config_parser.config_json.empty?
|
|
174
175
|
|
|
175
176
|
# 加载 config.json
|
|
176
177
|
config_file = File.join(@project_dir, "config.json")
|
|
177
178
|
if File.exist?(config_file)
|
|
178
|
-
puts " 加载配置文件: #{config_file}"
|
|
179
179
|
config_parser.load_config(config_file: config_file)
|
|
180
180
|
else
|
|
181
181
|
raise "配置文件不存在: #{config_file}"
|
|
@@ -184,15 +184,26 @@ module Pindo
|
|
|
184
184
|
|
|
185
185
|
# 安装证书
|
|
186
186
|
def install_certificate
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
Pindo::
|
|
187
|
+
# 直接调用 CertHelper 获取并安装证书
|
|
188
|
+
config_parser = Pindo::IosConfigParser.instance
|
|
189
|
+
apple_id = config_parser.apple_id
|
|
190
|
+
bundle_id_array = config_parser.get_bundle_id_array
|
|
191
|
+
|
|
192
|
+
# 获取证书(不创建新证书)
|
|
193
|
+
provisioning_info_array = Pindo::CertHelper.fetch_and_install_certs(
|
|
194
|
+
cert_mode: @cert_mode,
|
|
195
|
+
storage: @storage,
|
|
196
|
+
apple_id: apple_id,
|
|
197
|
+
bundle_id_array: bundle_id_array,
|
|
198
|
+
cert_type: @build_type,
|
|
199
|
+
platform_type: @platform_type,
|
|
200
|
+
project_dir: @project_dir,
|
|
201
|
+
match_flag: false
|
|
202
|
+
)
|
|
194
203
|
|
|
195
|
-
|
|
204
|
+
unless provisioning_info_array && !provisioning_info_array.empty?
|
|
205
|
+
raise "证书获取失败:未找到有效的证书信息"
|
|
206
|
+
end
|
|
196
207
|
end
|
|
197
208
|
end
|
|
198
209
|
end
|
data/lib/pindo/version.rb
CHANGED