pindo 5.13.5 → 5.13.6

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6afa5bb728d863ac22047d3a4861d3fd093bf103f25e51495bfd4f74d42c5b08
4
- data.tar.gz: '05999b51d89aea0c1c09407469bcf4d3e61a971303393a239e3fced117946f0b'
3
+ metadata.gz: bdf43dd4c0b65e41d7ae75cfaafa4bb9446dbf0ab735e6179e03f09ff25e96d8
4
+ data.tar.gz: 781f6bc039fe30f66f9d024f5a0ffe498c969687ffb0053113d45464e13621f9
5
5
  SHA512:
6
- metadata.gz: da020921268583412cd1194b9b89234c0ca26db407632d867e8897ddfc2404bdef72f90023954df26f8a3c406f0c4ebf0232983d878b18bd505c41079fbab72a
7
- data.tar.gz: 83bf6fed728974d527c96e13892e6f64489f92a7742583a4bfbb6905f01f0cafc9e1f58969c21853d3f5cd5083a66f1e8100fc23d3d74c3acf9eb8e0a9343885
6
+ metadata.gz: ee0911513edf4360270825cf5ee938736b0aba41a0b89d0ad9fd6b1062c590b7594edd8258d3c245eee8f36f565c48056dc6e8119d7dcf84ce616751db76b705
7
+ data.tar.gz: 82d6558b35038c5f97ee2595947ad0afa080a184d079b0d86cea3590830b2d3d5ebd21d0c5be61f724474c853f5aa08073a45c8eec7c5dc84a844f5614b411a9
@@ -48,9 +48,15 @@ module Pindo
48
48
 
49
49
  * 支持自动增加版本号
50
50
 
51
+ * 支持位置参数(向后兼容)和选项参数两种格式
52
+
51
53
  使用示例:
52
54
 
53
- $ pindo appstore adhocbuild # 编译 AdHoc 包
55
+ $ pindo appstore adhocbuild # 使用当前目录的 config.json
56
+
57
+ $ pindo appstore adhocbuild com.example.app # 位置参数指定 Bundle ID(向后兼容)
58
+
59
+ $ pindo appstore adhocbuild --bundleid=com.example.app # 选项参数指定 Bundle ID
54
60
 
55
61
  $ pindo appstore adhocbuild --upload # 编译并上传到JPS
56
62
 
@@ -59,13 +65,11 @@ module Pindo
59
65
  $ pindo appstore adhocbuild --increase # 自动增加版本号
60
66
 
61
67
  $ pindo appstore adhocbuild --proj="My App" # 指定项目名称
62
-
63
- $ pindo appstore adhocbuild --bundleid=com.example.app # 指定 Bundle ID
64
68
  DESC
65
69
 
66
- # 命令的参数列表
70
+ # 定义位置参数(向后兼容)
67
71
  self.arguments = [
68
- # 暂无参数
72
+ CLAide::Argument.new('bundleid', true)
69
73
  ]
70
74
 
71
75
  # 定义此命令使用的参数项(类方法,避免重复定义)
@@ -96,11 +100,15 @@ module Pindo
96
100
  end
97
101
 
98
102
  def initialize(argv)
103
+ # 首先获取位置参数(向后兼容)
104
+ positional_bundleid = argv.shift_argument
105
+
99
106
  # 一行代码完成参数初始化(自动推导命令名、自动启用缓存)
100
107
  @options = initialize_options(argv)
101
108
 
102
109
  # 保存参数到实例变量
103
- @args_bundle_id = @options[:bundleid]
110
+ # 优先使用选项参数,如果没有则使用位置参数
111
+ @args_bundle_id = @options[:bundleid] || positional_bundleid
104
112
  @args_send_flag = @options[:send]
105
113
  # send 依赖 upload:如果指定了 send,自动启用 upload
106
114
  @args_upload_flag = @options[:send] || @options[:upload]
@@ -182,7 +190,9 @@ module Pindo
182
190
  puts "\n使用当前目录配置文件: #{config_file}"
183
191
  Pindo::IosConfigParser.instance.load_config(config_file: config_file)
184
192
  else
185
- raise Informative, "当前目录未找到 config.json 文件,请使用 --bundleid 参数指定 Bundle ID"
193
+ raise Informative, "当前目录未找到 config.json 文件,请使用以下方式指定 Bundle ID:\n" \
194
+ " 方式1: pindo appstore adhocbuild com.example.app\n" \
195
+ " 方式2: pindo appstore adhocbuild --bundleid=com.example.app"
186
196
  end
187
197
  end
188
198
  end
@@ -236,9 +246,7 @@ module Pindo
236
246
  project_path: ios_project_path,
237
247
  proj_name: @args_proj_name,
238
248
  upload: @args_upload_flag,
239
- send: @args_send_flag,
240
- app_info_obj: config[:app_info_obj],
241
- workflow_info: config[:workflow_info]
249
+ send: @args_send_flag
242
250
  }
243
251
  build_options[:bundle_id] = @args_bundle_id if @args_bundle_id
244
252
  build_options[:unity_root_path] = config[:project_path] if is_unity
@@ -251,20 +259,23 @@ module Pindo
251
259
  build_task.dependencies << tasks.last.id if tasks.any?
252
260
  tasks << build_task
253
261
 
254
- # 3. 上传任务(总是添加)
255
- upload_task = Pindo::TaskSystem::JPSUploadTask.new(
256
- 'ipa',
257
- File.join(ios_project_path, 'build'),
258
- nil,
259
- app_info_obj: config[:app_info_obj],
260
- workflow_info: config[:workflow_info],
261
- project_name: @args_proj_name,
262
- context: {
263
- send_to_chat: @args_send_flag
264
- },
265
- dependencies: [build_task.id]
266
- )
267
- tasks << upload_task
262
+ # 3. 上传任务(仅在需要时添加)
263
+ if @args_upload_flag
264
+ upload_task = Pindo::TaskSystem::JPSUploadTask.new(
265
+ 'ipa',
266
+ File.join(ios_project_path, 'build'),
267
+ nil,
268
+ app_info_obj: config[:app_info_obj],
269
+ workflow_info: config[:workflow_info],
270
+ project_name: @args_proj_name,
271
+ upload_desc: "AdHoc 包",
272
+ context: {
273
+ send_to_chat: @args_send_flag
274
+ },
275
+ dependencies: [build_task.id]
276
+ )
277
+ tasks << upload_task
278
+ end
268
279
 
269
280
  tasks
270
281
  else
@@ -274,12 +285,32 @@ module Pindo
274
285
 
275
286
  # 准备 iOS 配置
276
287
  def prepare_ios_config(pindo_project_dir)
277
- # 获取 JPS 配置
278
- app_info_obj, workflow_info = PgyerHelper.share_instace.prepare_upload(
279
- working_directory: pindo_project_dir,
280
- proj_name: @args_proj_name,
281
- package_type: 'ipa'
282
- )
288
+ # IosConfigParser 获取项目名称
289
+ proj_name = nil
290
+ begin
291
+ require 'pindo/config/ios_config_parser'
292
+ config_parser = Pindo::IosConfigParser.instance
293
+ if config_parser.config_json
294
+ proj_name = config_parser.config_json.dig("project_info", "project_name")
295
+ end
296
+ rescue => e
297
+ # 忽略错误,proj_name 保持为 nil
298
+ end
299
+
300
+ # 如果有命令行参数的 proj_name,优先使用
301
+ proj_name = @args_proj_name if @args_proj_name && !@args_proj_name.empty?
302
+
303
+ # 只在需要上传时获取 JPS 配置
304
+ if @args_upload_flag
305
+ app_info_obj, workflow_info = PgyerHelper.share_instace.get_adhoc_upload_info(
306
+ working_directory: pindo_project_dir,
307
+ package_type: 'ipa',
308
+ proj_name: proj_name
309
+ )
310
+ else
311
+ app_info_obj = nil
312
+ workflow_info = nil
313
+ end
283
314
 
284
315
  {
285
316
  project_path: pindo_project_dir,
@@ -40,14 +40,21 @@ module Pindo
40
40
 
41
41
  * 处理 Applovin(如果使用)
42
42
 
43
+ * 支持位置参数(向后兼容)和选项参数两种格式
44
+
43
45
  使用示例:
44
46
 
45
- $ pindo appstore autobuild # 编译 App Store 提交包
47
+ $ pindo appstore autobuild # 使用当前目录的 config.json
48
+
49
+ $ pindo appstore autobuild com.example.app # 位置参数指定 Bundle ID(向后兼容)
46
50
 
47
- $ pindo appstore autobuild --bundleid=com.example.app # 指定 Bundle ID
51
+ $ pindo appstore autobuild --bundleid=com.example.app # 选项参数指定 Bundle ID
48
52
  DESC
49
53
 
50
- self.arguments = []
54
+ # 定义位置参数(向后兼容)
55
+ self.arguments = [
56
+ CLAide::Argument.new('bundleid', true)
57
+ ]
51
58
 
52
59
  # 定义此命令使用的参数项
53
60
  def self.option_items
@@ -61,11 +68,15 @@ module Pindo
61
68
  end
62
69
 
63
70
  def initialize(argv)
71
+ # 首先获取位置参数(向后兼容)
72
+ positional_bundleid = argv.shift_argument
73
+
64
74
  # 使用 Options 模块初始化参数
65
75
  @options = initialize_options(argv)
66
76
 
67
77
  # 保存参数到实例变量
68
- @args_bundle_id = @options[:bundleid]
78
+ # 优先使用选项参数,如果没有则使用位置参数
79
+ @args_bundle_id = @options[:bundleid] || positional_bundleid
69
80
 
70
81
  super(argv)
71
82
  end
@@ -133,7 +144,9 @@ module Pindo
133
144
  puts "\n使用当前目录配置文件: #{config_file}"
134
145
  Pindo::IosConfigParser.instance.load_config(config_file: config_file)
135
146
  else
136
- raise Informative, "当前目录未找到 config.json 文件,请使用 --bundleid 参数指定 Bundle ID"
147
+ raise Informative, "当前目录未找到 config.json 文件,请使用以下方式指定 Bundle ID:\n" \
148
+ " 方式1: pindo appstore autobuild com.example.app\n" \
149
+ " 方式2: pindo appstore autobuild --bundleid=com.example.app"
137
150
  end
138
151
  end
139
152
  end
@@ -4,196 +4,327 @@ require 'find'
4
4
  require 'fileutils'
5
5
  require 'pindo/base/executable'
6
6
  require 'pindo/config/ios_config_parser'
7
- require 'pindo/module/xcode/ipa_resign_helper'
7
+ require 'pindo/config/build_info_manager'
8
+ require 'pindo/base/pindocontext'
9
+ require 'pindo/module/task/task_manager'
10
+ require 'pindo/module/task/model/ipa_local_resign_task'
11
+ require 'pindo/module/task/model/jps_upload_task'
12
+ require 'pindo/options/options'
8
13
 
9
14
  module Pindo
10
- class Command
11
- class Appstore < Command
12
- class Autoresign < Appstore
15
+ class Command
16
+ class Appstore < Command
17
+ class Autoresign < Appstore
13
18
 
14
- include Appselect
19
+ include Appselect
15
20
 
16
- self.summary = '发布阶段ipa包重签名及上传'
21
+ # 命令的简要说明
22
+ self.summary = 'IPA 包重签名及上传到 JPS 测试平台'
17
23
 
18
- self.description = <<-DESC
19
- 发布阶段ipa包重签名及上传。
24
+ # 启用缓存机制
25
+ def self.use_cache?
26
+ true
27
+ end
20
28
 
21
- 支持功能:
29
+ # 命令的详细说明
30
+ self.description = <<-DESC
31
+ 对 IPA 文件进行重签名,并可选上传到 JPS 测试平台。
22
32
 
23
- * IPA包重签名
33
+ 支持功能:
24
34
 
25
- * 上传到测试平台
35
+ * IPA 文件重签名(支持 dev/adhoc 证书)
26
36
 
27
- * 发送测试通知
37
+ * 自动查找或手动指定 IPA 文件
28
38
 
29
- 使用示例:
39
+ * 上传到 JPS 测试平台
30
40
 
31
- $ pindo appstore autoresign demo.ipa # 仅重签名
41
+ * 发送测试通知到群组
32
42
 
33
- $ pindo appstore autoresign demo.ipa --upload # 重签名并上传
43
+ * 支持 dev/adhoc 构建类型
34
44
 
35
- $ pindo appstore autoresign demo.ipa --send # 重签名、上传并发送通知
36
- DESC
45
+ 使用示例:
37
46
 
38
- self.arguments = [
39
- CLAide::Argument.new('path/to/ipa', true),
40
- ]
47
+ $ pindo appstore autoresign # 自动查找并重签名(adhoc)
41
48
 
42
- def self.options
43
- [
44
- ['--ipa', 'iap file name.'],
45
- ['--proj', '指定哪个项目(忽略大小写空格等等字符): --proj=\"prancksoundv4\"'],
46
- ['--upload', '编译完成后是否上传ipa到JPS: --upload'],
47
- ['--send', '上传到JPS之后是否发送测试信息: --send'],
48
- ['--ipa', '强制指定重签名的ipa包,用法: --ipa=path/to/demo.ipa'],
49
- ['--dev', '使用dev证书,默认使用adhoc证书: --dev'],
50
- ['--test', '使用测试的bundle id, 默认是用发布bundle id,用法:--test'],
51
- ].concat(super)
52
- end
49
+ $ pindo appstore autoresign demo.ipa # 重签名指定 IPA(adhoc)
50
+
51
+ $ pindo appstore autoresign --ipa=demo.ipa # 使用选项指定 IPA
53
52
 
53
+ $ pindo appstore autoresign --type=dev # 使用 dev 证书和测试 Bundle ID
54
54
 
55
- def initialize(argv)
55
+ $ pindo appstore autoresign --upload # 重签名并上传
56
56
 
57
- @args_ipa_file = argv.shift_argument
58
- @args_set_ipa_name = argv.option('ipa')
59
- @args_dev_flag = argv.flag?('dev', false)
60
- @args_test_flag = argv.flag?('test', false)
57
+ $ pindo appstore autoresign --send # 重签名、上传并发送通知
61
58
 
62
- @args_upload_flag = argv.flag?('upload', false)
63
- @args_send_flag = argv.flag?('send', false)
64
- @args_proj_name = argv.option('proj')
59
+ $ pindo appstore autoresign --proj="My App" # 指定项目名称
60
+ DESC
65
61
 
66
- if @args_send_flag
67
- @args_upload_flag = true
68
- end
62
+ # 位置参数(向后兼容)
63
+ self.arguments = [
64
+ CLAide::Argument.new('path/to/ipa', true)
65
+ ]
69
66
 
70
- super
71
- @additional_args = argv.remainder!
67
+ # 定义此命令使用的参数项
68
+ def self.option_items
69
+ @option_items ||= begin
70
+ items = []
71
+
72
+ # 添加 --ipa 参数
73
+ items << Pindo::Options::OptionItem.new(
74
+ key: :ipa,
75
+ description: '指定要重签名的 IPA 文件路径',
76
+ type: String,
77
+ optional: true,
78
+ verify_block: proc do |value|
79
+ unless value.end_with?('.ipa')
80
+ raise "IPA 文件路径格式错误: #{value},必须以 .ipa 结尾"
81
+ end
82
+ unless File.exist?(value)
83
+ raise "IPA 文件不存在: #{value}"
72
84
  end
85
+ end,
86
+ example: 'pindo appstore autoresign --ipa=path/to/demo.ipa'
87
+ )
88
+
89
+ # 添加 --type 参数
90
+ items << Pindo::Options::OptionItem.new(
91
+ key: :type,
92
+ description: '构建类型(dev/adhoc,默认 adhoc)。dev=使用dev证书+测试BundleID,adhoc=使用adhoc证书+发布BundleID',
93
+ type: String,
94
+ default_value: 'adhoc',
95
+ optional: true,
96
+ verify_block: proc do |value|
97
+ valid_types = ['dev', 'adhoc']
98
+ unless valid_types.include?(value.to_s.downcase)
99
+ raise "构建类型错误: #{value},必须是 dev 或 adhoc"
100
+ end
101
+ end,
102
+ example: 'pindo appstore autoresign --type=dev'
103
+ )
73
104
 
105
+ # 合并 JPSOptions
106
+ items.concat(Pindo::Options::JPSOptions.select(:proj, :upload, :send))
74
107
 
75
- def run
76
-
77
- ipa_file_name = @args_ipa_file
78
- if !@args_set_ipa_name.nil?
79
- ipa_file_name = @args_set_ipa_name
80
- end
81
-
82
- if !ipa_file_name.nil? && File.exist?(ipa_file_name)
83
- else
84
- current_dir = Dir.pwd
85
- # File.basename(f).include?("_resigned") ? Time.local(0, 0, 0) : File.mtime(f)
86
- ipa_file_name = Dir.glob(File.join(current_dir, "/*.ipa")).max_by {|f| File.basename(f).include?("_resigned") ? Time.local(0, 1, 1) : File.mtime(f)}
87
-
88
- end
89
-
90
- if !ipa_file_name.nil? && File.exist?(ipa_file_name)
91
- puts
92
- puts "正在重签名的ipa: #{ipa_file_name}"
93
- puts "时间: #{File.mtime(ipa_file_name)}"
94
- puts
95
- else
96
- return
97
- end
98
-
99
-
100
- mainapp_bundleid = nil
101
-
102
- if @args_test_flag
103
- mainapp_bundleid = get_selected_dev_bundleid()
104
- else
105
- mainapp_bundleid = get_selected_deploy_bundleid()
106
- end
107
- puts "mainapp_bundleid: #{mainapp_bundleid}"
108
-
109
- # 拉取应用配置
110
- require 'pindo/config/build_info_manager'
111
- Pindo::BuildInfoManager.share_instance.pull_appconfig_with_reponame(
112
- repo_name: mainapp_bundleid,
113
- target_dir: Dir.pwd
114
- )
115
-
116
- app_info_obj = nil
117
- workflow_info = nil
118
- if @args_upload_flag || @args_send_flag
119
- # 传入 package_type 获取 workflow_info
120
- app_info_obj, workflow_info = PgyerHelper.share_instace.prepare_upload(
121
- working_directory: Dir.pwd,
122
- proj_name: @args_proj_name,
123
- package_type: 'ipa'
124
- )
125
- end
126
-
127
-
128
- if !ipa_file_name.nil?
129
- # 加载配置获取 Bundle ID
130
- config_file = File.join(Dir.pwd, "config.json")
131
- config_parser = Pindo::IosConfigParser.instance
132
- config_parser.load_config(config_file: config_file)
133
- bundle_id = config_parser.bundle_id
134
-
135
- if bundle_id.nil? || bundle_id.empty?
136
- raise Informative, "无法从配置文件中获取 Bundle ID"
137
- end
138
-
139
- # 确定构建类型并安装证书
140
- build_type = @args_dev_flag ? 'dev' : 'adhoc'
141
- cert_args = build_type == 'adhoc' ? ['--build_type=adhoc'] : []
142
- Pindo::Command::Appstore::Cert::run(cert_args)
143
-
144
- # 使用 IpaResignHelper 进行重签名
145
- ipa_file_upload = Pindo::IpaResignHelper.resign_ipa(
146
- ipa_file_path: ipa_file_name,
147
- bundle_id: bundle_id
148
- )
149
-
150
- if ipa_file_upload.nil?
151
- raise Informative, "重签名失败"
152
- end
153
-
154
- puts "\n重签名成功!"
155
- puts "重签名后的 IPA: #{ipa_file_upload}"
156
- end
157
-
158
- if !ipa_file_upload.nil? && !app_info_obj.nil?
159
-
160
- if !ipa_file_upload.nil? && !app_info_obj.nil?
161
- description = "提交包重签名"
162
- result_data = PgyerHelper.share_instace.start_upload(
163
- app_info_obj: app_info_obj,
164
- ipa_file_upload: ipa_file_upload,
165
- description: description,
166
- workflow_info: workflow_info
167
- )
168
- if !result_data.nil? && !result_data["data"].nil? && !result_data["data"]["id"].nil?
169
- PgyerHelper.share_instace.print_app_version_info(
170
- app_info_obj: app_info_obj,
171
- app_version_info_obj: result_data["data"]
172
- )
173
- # 始终发送给自己
174
- PgyerHelper.share_instace.send_apptest_msg(
175
- app_info_obj: app_info_obj,
176
- app_version_info_obj: result_data["data"],
177
- receiveType: "self"
178
- )
179
-
180
- # 如果有 --send 参数,额外发送到测试群
181
- if @args_send_flag
182
- PgyerHelper.share_instace.send_apptest_msg(
183
- app_info_obj: app_info_obj,
184
- app_version_info_obj: result_data["data"],
185
- chatEnv: "DevTest",
186
- receiveType: "chat"
187
- )
188
- end
189
- end
190
- end
191
-
192
- end
108
+ items
109
+ end
110
+ end
193
111
 
112
+ # 命令的选项列表
113
+ def self.options
114
+ option_items.map { |item| item.to_claide_option }.concat(super)
115
+ end
194
116
 
195
- end
117
+ def initialize(argv)
118
+ # 首先获取位置参数(向后兼容)
119
+ positional_ipa = argv.shift_argument
120
+
121
+ # 使用 Options 模块初始化参数
122
+ @options = initialize_options(argv)
123
+
124
+ # 优先使用选项参数,如果没有则使用位置参数
125
+ @args_ipa_file = @options[:ipa] || positional_ipa
126
+ @args_build_type = (@options[:type] || 'adhoc').downcase
127
+ @args_upload_flag = @options[:send] || @options[:upload]
128
+ @args_send_flag = @options[:send]
129
+ @args_proj_name = @options[:proj]
130
+
131
+ super
132
+ @additional_args = argv.remainder!
133
+ end
134
+
135
+ def validate!
136
+ super
137
+ end
138
+
139
+ def run
140
+ begin
141
+ # 加载 JPS 配置(如果存在)
142
+ context = Pindo::PindoContext.instance
143
+ context.load_and_apply_jps_config(Dir.pwd)
144
+
145
+ # 1. 查找或指定 IPA 文件
146
+ ipa_file_path = find_ipa_file()
147
+
148
+ unless ipa_file_path && File.exist?(ipa_file_path)
149
+ raise Informative, "未找到需要重签名的 IPA 文件"
196
150
  end
151
+
152
+ # 2. 选择 Bundle ID(根据 build_type)
153
+ bundle_id = select_bundle_id()
154
+
155
+ # 3. 拉取应用配置
156
+ pull_app_config(bundle_id)
157
+
158
+ # 4. 准备 JPS 配置(如果需要上传)
159
+ app_info_obj, workflow_info = prepare_jps_config()
160
+
161
+ # 5. 计算重签名后的 IPA 文件名
162
+ resigned_ipa_file = calculate_resigned_ipa_name(ipa_file_path)
163
+
164
+ # 6. 创建任务
165
+ tasks = create_resign_tasks(
166
+ ipa_file_path: ipa_file_path,
167
+ resigned_ipa_file: resigned_ipa_file,
168
+ bundle_id: bundle_id,
169
+ app_info_obj: app_info_obj,
170
+ workflow_info: workflow_info
171
+ )
172
+
173
+ # 7. 执行任务
174
+ task_manager = Pindo::TaskSystem::TaskManager.instance
175
+ task_manager.clear_all
176
+ tasks.each { |task| task_manager.add_task(task) }
177
+ task_manager.start
178
+
179
+ ensure
180
+ # 清除命令状态(如果启用了缓存,这里会自动保存)
181
+ Pindo::Options::GlobalOptionsState.instance.clear
182
+ end
183
+ end
184
+
185
+ private
186
+
187
+ # 查找 IPA 文件
188
+ def find_ipa_file
189
+ # 1. 如果通过选项或位置参数指定了 IPA 文件且存在,直接返回
190
+ if @args_ipa_file && File.exist?(@args_ipa_file)
191
+ puts "\n使用指定的 IPA 文件: #{@args_ipa_file}"
192
+ puts "修改时间: #{File.mtime(@args_ipa_file)}"
193
+ return @args_ipa_file
194
+ end
195
+
196
+ # 2. 在当前目录查找最新的非 _resigned 的 IPA
197
+ current_dir = Dir.pwd
198
+ ipa_files = Dir.glob(File.join(current_dir, "*.ipa"))
199
+
200
+ # 过滤掉 _resigned.ipa 并找到最新的
201
+ ipa_file = ipa_files.max_by do |f|
202
+ File.basename(f).include?("_resigned") ? Time.local(0, 1, 1) : File.mtime(f)
203
+ end
204
+
205
+ if ipa_file && File.exist?(ipa_file)
206
+ puts "\n自动找到 IPA 文件: #{ipa_file}"
207
+ puts "修改时间: #{File.mtime(ipa_file)}"
208
+ return ipa_file
209
+ end
210
+
211
+ # 3. 如果没有找到,从终端输入
212
+ puts "\n⚠️ 未找到 IPA 文件"
213
+ puts "请输入 IPA 文件路径(支持相对路径或绝对路径):"
214
+
215
+ ipa_path = ask("IPA 文件路径: ") do |q|
216
+ q.validate = /\.ipa$/i
217
+ q.responses[:not_valid] = "❌ 请输入有效的 IPA 文件路径(必须以 .ipa 结尾)"
218
+ end
219
+
220
+ # 去除首尾空格
221
+ ipa_path = ipa_path.strip if ipa_path
222
+
223
+ # 验证文件是否存在
224
+ if ipa_path && !ipa_path.empty?
225
+ if File.exist?(ipa_path)
226
+ puts "✓ 使用输入的 IPA 文件: #{ipa_path}"
227
+ puts " 修改时间: #{File.mtime(ipa_path)}"
228
+ return ipa_path
229
+ else
230
+ puts "❌ IPA 文件不存在: #{ipa_path}"
231
+ end
232
+ end
233
+
234
+ nil
235
+ end
236
+
237
+ # 选择 Bundle ID(根据 build_type)
238
+ def select_bundle_id
239
+ bundle_id = if @args_build_type == 'dev'
240
+ # dev 类型使用测试 Bundle ID
241
+ get_selected_dev_bundleid()
242
+ else
243
+ # adhoc 类型使用发布 Bundle ID
244
+ get_selected_deploy_bundleid()
245
+ end
246
+
247
+ puts "目标 Bundle ID: #{bundle_id}"
248
+ bundle_id
249
+ end
250
+
251
+ # 拉取应用配置
252
+ def pull_app_config(bundle_id)
253
+ puts "\n拉取应用配置: #{bundle_id}"
254
+
255
+ require 'pindo/config/build_info_manager'
256
+ success = Pindo::BuildInfoManager.share_instance.pull_appconfig_with_reponame(
257
+ repo_name: bundle_id,
258
+ target_dir: Dir.pwd
259
+ )
260
+
261
+ unless success
262
+ raise Informative, "拉取配置失败: #{bundle_id}"
263
+ end
197
264
  end
265
+
266
+ # 准备 JPS 配置
267
+ def prepare_jps_config
268
+ if @args_upload_flag || @args_send_flag
269
+ # 只使用命令行参数的 proj_name,不从 config.json 获取
270
+ # skip_config_file: true 会跳过从 config.json 读取项目名称
271
+ # 这样如果用户没有指定 --proj,会直接提示用户输入
272
+ proj_name = @args_proj_name
273
+
274
+ app_info_obj, workflow_info = PgyerHelper.share_instace.get_adhoc_upload_info(
275
+ working_directory: Dir.pwd,
276
+ package_type: 'ipa',
277
+ proj_name: proj_name,
278
+ skip_config_file: true
279
+ )
280
+ return [app_info_obj, workflow_info]
281
+ end
282
+
283
+ [nil, nil]
284
+ end
285
+
286
+ # 计算重签名后的 IPA 文件名
287
+ # 例如:SlimeSavior.ipa → SlimeSavior_resigned.ipa
288
+ def calculate_resigned_ipa_name(ipa_file_path)
289
+ ipa_file_path.gsub(/\.ipa$/, '_resigned.ipa')
290
+ end
291
+
292
+ # 创建任务列表
293
+ def create_resign_tasks(ipa_file_path:, resigned_ipa_file:, bundle_id:, app_info_obj:, workflow_info:)
294
+ tasks = []
295
+
296
+ # 1. 重签名任务
297
+ resign_task = Pindo::TaskSystem::IpaLocalResignTask.new(
298
+ Dir.pwd, # ipa_path(搜索路径)
299
+ ipa_file_path, # ipa_file(明确指定)
300
+ bundle_id, # bundle_id
301
+ build_type: @args_build_type, # dev 或 adhoc
302
+ project_dir: Dir.pwd
303
+ )
304
+ tasks << resign_task
305
+
306
+ # 2. 上传任务(仅在需要时创建)
307
+ if @args_upload_flag && app_info_obj
308
+ upload_task = Pindo::TaskSystem::JPSUploadTask.new(
309
+ 'ipa',
310
+ Dir.pwd, # upload_path(搜索路径)
311
+ resigned_ipa_file, # upload_file(明确指定重签名后的文件)
312
+ app_info_obj: app_info_obj,
313
+ workflow_info: workflow_info,
314
+ project_name: @args_proj_name,
315
+ upload_desc: "重签名包", # 上传描述
316
+ context: {
317
+ send_to_chat: @args_send_flag
318
+ },
319
+ dependencies: [resign_task.id] # 依赖重签名任务
320
+ )
321
+ tasks << upload_task
322
+ end
323
+
324
+ tasks
325
+ end
326
+
327
+ end
198
328
  end
329
+ end
199
330
  end
@@ -394,8 +394,8 @@ module Pindo
394
394
  app_info_obj: app_info_obj,
395
395
  workflow_info: workflow_info,
396
396
  project_name: @args_proj_name,
397
+ upload_desc: @args_upload_desc,
397
398
  context: {
398
- upload_desc: @args_upload_desc,
399
399
  send_to_chat: @args_send_flag
400
400
  }
401
401
  )
@@ -220,6 +220,168 @@ module Pindo
220
220
  }
221
221
  end
222
222
 
223
+ # AdHoc 专用工作流选择
224
+ # 筛选条件:
225
+ # 1. package_type 匹配
226
+ # 2. tab_name 必须包含 "提交包"
227
+ #
228
+ # @param project_id [String] 项目ID
229
+ # @param package_type [String] 包类型(ipa/apk/zip/app)
230
+ # @return [Hash] 选择的工作流信息
231
+ def select_workflow_for_adhoc(project_id:, package_type:)
232
+ # 1. 从 JPS API 获取可用工作流列表
233
+ workflow_result = @pgyer_client.get_project_workflows(project_id: project_id)
234
+
235
+ if workflow_result.nil? || workflow_result['data'].nil?
236
+ raise Informative, "获取工作流列表失败"
237
+ end
238
+
239
+ workflows = workflow_result['data']
240
+
241
+ if workflows.empty?
242
+ raise Informative, "该项目没有可用的工作流"
243
+ end
244
+
245
+ # 2. 第一层过滤:根据 package_type
246
+ filtered_by_type = workflows.select do |w|
247
+ if w['packageType']
248
+ case package_type
249
+ when 'ipa'
250
+ w['packageType'] == 'ipa'
251
+ when 'apk'
252
+ w['packageType'] == 'apk'
253
+ when 'zip'
254
+ w['packageType'] == 'zip'
255
+ when 'app'
256
+ w['packageType'] == 'app'
257
+ else
258
+ true
259
+ end
260
+ else
261
+ # 如果没有 packageType 字段,保留(后续通过名称筛选)
262
+ true
263
+ end
264
+ end
265
+
266
+ # 3. 第二层过滤:tab_name 必须包含 "提交包"
267
+ adhoc_workflows = filtered_by_type.select do |w|
268
+ tab_name = w['tabName'] || w['tab_name'] || ''
269
+ tab_name.include?('提交包')
270
+ end
271
+
272
+ if adhoc_workflows.empty?
273
+ raise Informative, "未找到符合条件的 AdHoc 工作流\n" \
274
+ "要求:package_type=#{package_type} 且 tab_name 包含 '提交包'\n" \
275
+ "请检查 JPS 工作流配置"
276
+ end
277
+
278
+ # 4. 根据匹配数量决定选择方式
279
+ workflow = nil
280
+
281
+ if adhoc_workflows.size == 1
282
+ # 只有 1 个匹配,自动选择
283
+ workflow = adhoc_workflows.first
284
+ else
285
+ # 有多个匹配,让用户选择
286
+ require 'highline/import'
287
+ cli = HighLine.new
288
+
289
+ workflow_choices = adhoc_workflows.map do |w|
290
+ tab_name = w['tabName'] || w['tab_name']
291
+ workflow_id = w['id'] || w['workflow_id']
292
+ "#{tab_name} (ID: #{workflow_id})"
293
+ end
294
+
295
+ selected = cli.choose do |menu|
296
+ menu.prompt = "请选择 AdHoc 工作流:"
297
+ menu.choices(*workflow_choices)
298
+ end
299
+
300
+ # 提取选择的工作流
301
+ selected_index = workflow_choices.index(selected)
302
+ workflow = adhoc_workflows[selected_index]
303
+ end
304
+
305
+ # 5. 返回标准化的工作流信息
306
+ {
307
+ workflow_id: workflow['id'] || workflow['workflow_id'],
308
+ tab_name: workflow['tabName'] || workflow['tab_name'],
309
+ package_type: workflow['packageType'] || package_type,
310
+ package_name: workflow['packageName'] || workflow['package_name'] || '',
311
+ manage_type: workflow['manageType'] || workflow['manage_type'] || ''
312
+ }
313
+ end
314
+
315
+ # 获取 AdHoc 上传信息
316
+ # 用于 adhoc 编译命令,不保存配置到 JPSBuildConfig.json
317
+ #
318
+ # @param working_directory [String] 工作目录
319
+ # @param package_type [String] 包类型(ipa/apk/zip/app)
320
+ # @param proj_name [String] 项目名称(可选)
321
+ # @param skip_config_file [Boolean] 是否跳过从 config.json 获取项目名称(默认 false)
322
+ # @return [Array] [app_info_obj, workflow_info]
323
+ def get_adhoc_upload_info(working_directory:, package_type:, proj_name: nil, skip_config_file: false)
324
+ upload_proj_name = proj_name
325
+
326
+ # 1. 项目名称获取逻辑
327
+ # 1.1 如果 proj_name 为空,从环境变量获取
328
+ if upload_proj_name.nil? || upload_proj_name.empty?
329
+ upload_proj_name = ENV['PINDO_PROJECT_NAME']
330
+ end
331
+
332
+ # 1.2 如果仍为空且未禁用,从 IosConfigParser 获取
333
+ if (upload_proj_name.nil? || upload_proj_name.empty?) && !skip_config_file
334
+ require 'pindo/config/ios_config_parser'
335
+ config_parser = Pindo::IosConfigParser.instance
336
+ if config_parser.config_json
337
+ upload_proj_name = config_parser.config_json.dig("project_info", "project_name")
338
+ end
339
+ end
340
+
341
+ # 1.3 如果还是为空,让用户输入
342
+ if upload_proj_name.nil? || upload_proj_name.empty?
343
+ require 'highline/import'
344
+ puts "\n未找到项目名称配置"
345
+ upload_proj_name = ask("请输入 JPS 项目名称: ") do |q|
346
+ q.validate = /\S+/
347
+ q.responses[:not_valid] = "项目名称不能为空"
348
+ end
349
+ upload_proj_name = upload_proj_name.strip if upload_proj_name
350
+ end
351
+
352
+ # 2. 确保已登录
353
+ unless login
354
+ raise Informative, "请先登录 JPS 网站"
355
+ end
356
+
357
+ # 3. 获取 app_info_obj
358
+ app_info_obj = find_app_info_with_obj_list(proj_name: upload_proj_name)
359
+
360
+ unless app_info_obj
361
+ raise Informative, "未找到项目: #{upload_proj_name},请检查项目名称是否正确"
362
+ end
363
+
364
+ # 4. 获取 AdHoc 工作流(调用专用函数)
365
+ workflow_info = select_workflow_for_adhoc(
366
+ project_id: app_info_obj["id"],
367
+ package_type: package_type
368
+ )
369
+
370
+ unless workflow_info
371
+ raise Informative, "未能获取 AdHoc 工作流信息"
372
+ end
373
+
374
+ # 5. 输出最终选择的项目和工作流
375
+ puts "\n✓ 项目: #{app_info_obj['projectName']}"
376
+ puts "✓ 工作流: #{workflow_info[:tab_name]}"
377
+
378
+ # 6. 保存项目名称到实例变量
379
+ @proj_name = upload_proj_name
380
+
381
+ # 7. 返回结果(不保存配置到 JPSBuildConfig.json)
382
+ return app_info_obj, workflow_info
383
+ end
384
+
223
385
  def prepare_upload(working_directory:nil, proj_name:nil, package_type:nil)
224
386
  upload_proj_name = proj_name
225
387
  if upload_proj_name.nil? || upload_proj_name.empty?
@@ -0,0 +1,189 @@
1
+ require_relative '../pindo_task'
2
+ require_relative '../task_config'
3
+
4
+ module Pindo
5
+ module TaskSystem
6
+ # IPA 本地重签名任务
7
+ # 使用新的证书和 Bundle ID 对 IPA 文件进行重签名
8
+ class IpaLocalResignTask < PindoTask
9
+ attr_reader :ipa_path, :ipa_file, :bundle_id, :build_type
10
+
11
+ # 任务类型
12
+ def self.task_type
13
+ :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
+ 5 # 延迟 5 秒
27
+ end
28
+
29
+ # 初始化重签名任务
30
+ # @param ipa_path [String] IPA 搜索路径(当 ipa_file 为 nil 时使用)
31
+ # @param ipa_file [String] 指定的 IPA 文件(nil 表示自动查找)
32
+ # @param bundle_id [String] 目标 Bundle ID
33
+ # @param options [Hash] 选项
34
+ # @option options [String] :build_type 构建类型('dev' 或 'adhoc',默认 'adhoc')
35
+ # @option options [String] :project_dir 项目目录(用于加载 config.json)
36
+ def initialize(ipa_path, ipa_file, bundle_id, options = {})
37
+ @ipa_path = ipa_path # IPA 搜索路径
38
+ @ipa_file = ipa_file # 指定的 IPA 文件(nil 表示自动查找)
39
+ @bundle_id = bundle_id # 目标 Bundle ID
40
+ @build_type = options[:build_type] || 'adhoc'
41
+ @project_dir = options[:project_dir] || Dir.pwd
42
+
43
+ # 设置任务优先级
44
+ options[:priority] ||= TaskPriority::HIGH
45
+
46
+ super("重签名 IPA", options)
47
+ end
48
+
49
+ # 验证任务参数
50
+ def validate
51
+ # 验证 Bundle ID
52
+ unless @bundle_id && !@bundle_id.empty?
53
+ @error = "缺少必需参数: bundle_id"
54
+ return false
55
+ end
56
+
57
+ # 验证 build_type
58
+ unless ['dev', 'adhoc'].include?(@build_type)
59
+ @error = "无效的 build_type: #{@build_type}(必须是 'dev' 或 'adhoc')"
60
+ return false
61
+ end
62
+
63
+ # 验证 ipa_path(当 ipa_file 为空时)
64
+ if (@ipa_file.nil? || @ipa_file.empty?)
65
+ unless @ipa_path && !@ipa_path.empty?
66
+ @error = "缺少必需参数: ipa_path(当 ipa_file 未指定时)"
67
+ return false
68
+ end
69
+ end
70
+
71
+ true
72
+ end
73
+
74
+ protected
75
+
76
+ # 执行重签名
77
+ def do_work
78
+ # 1. 确定要重签名的 IPA 文件
79
+ ipa_to_resign = determine_ipa_file
80
+ unless ipa_to_resign && File.exist?(ipa_to_resign)
81
+ raise "未找到需要重签名的 IPA 文件"
82
+ end
83
+
84
+ puts "\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
85
+ puts " 正在重签名 IPA"
86
+ puts "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
87
+ puts " IPA 文件: #{ipa_to_resign}"
88
+ puts " Bundle ID: #{@bundle_id}"
89
+ puts " 构建类型: #{@build_type}"
90
+ puts " 修改时间: #{File.mtime(ipa_to_resign)}"
91
+ puts "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n"
92
+
93
+ # 2. 加载配置(如果尚未加载)
94
+ load_config_if_needed
95
+
96
+ # 3. 安装证书
97
+ install_certificate
98
+
99
+ # 4. 执行重签名
100
+ require 'pindo/module/xcode/ipa_resign_helper'
101
+ resigned_ipa = Pindo::IpaResignHelper.resign_ipa(
102
+ ipa_file_path: ipa_to_resign,
103
+ bundle_id: @bundle_id
104
+ )
105
+
106
+ # 5. 验证重签名结果
107
+ unless resigned_ipa && File.exist?(resigned_ipa)
108
+ raise "重签名失败:未生成重签名后的 IPA 文件"
109
+ end
110
+
111
+ puts "\n✅ 重签名成功!"
112
+ puts " 重签名后的 IPA: #{resigned_ipa}"
113
+
114
+ # 6. 返回重签名后的 IPA 路径
115
+ @result = resigned_ipa
116
+ end
117
+
118
+ private
119
+
120
+ # 确定要重签名的 IPA 文件
121
+ def determine_ipa_file
122
+ if @ipa_file && !@ipa_file.empty? && File.exist?(@ipa_file)
123
+ # 使用指定的 IPA 文件
124
+ puts " 使用指定的 IPA 文件: #{@ipa_file}"
125
+ return @ipa_file
126
+ else
127
+ # 在 ipa_path 中查找最新的非 _resigned 的 IPA
128
+ find_latest_ipa_file
129
+ end
130
+ end
131
+
132
+ # 查找最新的 IPA 文件(排除 _resigned.ipa)
133
+ def find_latest_ipa_file
134
+ unless File.directory?(@ipa_path)
135
+ return nil
136
+ end
137
+
138
+ ipa_files = Dir.glob(File.join(@ipa_path, "*.ipa"))
139
+
140
+ # 过滤掉 _resigned.ipa 文件
141
+ ipa_files = ipa_files.reject { |f| File.basename(f).include?("_resigned") }
142
+
143
+ if ipa_files.empty?
144
+ return nil
145
+ end
146
+
147
+ # 返回最新的 IPA 文件
148
+ latest_ipa = ipa_files.max_by { |f| File.mtime(f) }
149
+ puts " 自动查找到 IPA 文件: #{latest_ipa}"
150
+
151
+ latest_ipa
152
+ end
153
+
154
+ # 加载配置(如果尚未加载)
155
+ def load_config_if_needed
156
+ require 'pindo/config/ios_config_parser'
157
+ config_parser = Pindo::IosConfigParser.instance
158
+
159
+ # 如果配置已加载,直接返回
160
+ if config_parser.config_json && !config_parser.config_json.empty?
161
+ puts " 使用已加载的配置"
162
+ return
163
+ end
164
+
165
+ # 加载 config.json
166
+ config_file = File.join(@project_dir, "config.json")
167
+ if File.exist?(config_file)
168
+ puts " 加载配置文件: #{config_file}"
169
+ config_parser.load_config(config_file: config_file)
170
+ else
171
+ raise "配置文件不存在: #{config_file}"
172
+ end
173
+ end
174
+
175
+ # 安装证书
176
+ def install_certificate
177
+ puts "\n📜 安装证书..."
178
+ puts " 证书类型: #{@build_type}"
179
+
180
+ # 调用证书安装命令
181
+ require 'pindo/command/appstore/cert'
182
+ cert_args = ["--build_type=#{@build_type}"]
183
+ Pindo::Command::Appstore::Cert.run(cert_args)
184
+
185
+ puts " ✓ 证书安装完成"
186
+ end
187
+ end
188
+ end
189
+ end
@@ -34,6 +34,7 @@ module Pindo
34
34
  # @option options [Hash] :app_info_obj JPS 应用信息对象(可选,如为 nil 则延迟获取)
35
35
  # @option options [Hash] :workflow_info 工作流信息(可选,如为 nil 则延迟获取)
36
36
  # @option options [String] :project_name 项目名称(可选)
37
+ # @option options [String] :upload_desc 上传描述(可选)
37
38
  def initialize(file_type, upload_path, upload_file, options = {})
38
39
  @file_type = file_type # 'ipa' | 'apk' | 'html' | 'app'
39
40
  @upload_path = upload_path # 搜索文件的路径
@@ -43,6 +44,7 @@ module Pindo
43
44
  @app_info_obj = options[:app_info_obj]
44
45
  @workflow_info = options[:workflow_info]
45
46
  @project_name = options[:project_name]
47
+ @upload_desc = options[:upload_desc] # 上传描述
46
48
 
47
49
  # 设置上传任务的优先级为 LOW,确保在构建任务之后执行
48
50
  options[:priority] ||= TaskPriority::LOW
@@ -180,38 +182,80 @@ module Pindo
180
182
  result_data = pgyer_helper.start_upload(
181
183
  app_info_obj: @app_info_obj,
182
184
  ipa_file_upload: file_path,
183
- description: @context[:upload_desc], # 从 context 获取描述
185
+ description: @upload_desc, # 使用上传描述
184
186
  workflow_info: @workflow_info
185
187
  )
186
188
 
187
- # 解析上传结果
188
- if result_data && result_data["data"] && result_data["data"]["id"]
189
- app_version_info = result_data["data"]
189
+ # 验证上传结果
190
+ unless result_data && result_data["data"] && result_data["data"]["id"]
191
+ raise "上传失败:未获取到有效的返回数据"
192
+ end
190
193
 
191
- # 打印应用版本信息
192
- pgyer_helper.print_app_version_info(
193
- app_info_obj: @app_info_obj,
194
- app_version_info_obj: app_version_info
195
- )
194
+ # ========== 上传成功,后续操作失败不应导致重试 ==========
195
+ # 将重试次数设为 0,即使后续操作失败也不会重复上传
196
+ @retry_count = 0
196
197
 
197
- # 发送消息给自己
198
- pgyer_helper.send_apptest_msg(
199
- app_info_obj: @app_info_obj,
200
- app_version_info_obj: app_version_info,
201
- receiveType: "self"
202
- )
198
+ app_version_info = result_data["data"]
203
199
 
204
- # 如果需要发送到测试群
205
- if @context[:send_to_chat]
200
+ # 处理上传成功后的操作
201
+ handle_post_upload_actions(app_version_info)
202
+ end
203
+
204
+ # 处理上传成功后的操作
205
+ # @param app_version_info [Hash] 应用版本信息
206
+ def handle_post_upload_actions(app_version_info)
207
+ puts "\n 📋 开始处理上传后续操作..."
208
+
209
+ begin
210
+ pgyer_helper = PgyerHelper.share_instace
211
+
212
+ # 打印应用版本信息(失败只警告,不中断)
213
+ begin
214
+ puts " 📝 打印应用版本信息..."
215
+ pgyer_helper.print_app_version_info(
216
+ app_info_obj: @app_info_obj,
217
+ app_version_info_obj: app_version_info
218
+ )
219
+ puts " ✓ 应用版本信息打印成功"
220
+ rescue => e
221
+ puts " ⚠️ 打印应用版本信息失败: #{e.message}"
222
+ end
223
+
224
+ # 发送消息给自己(失败只警告,不中断)
225
+ begin
226
+ puts " 📨 发送消息给自己..."
206
227
  pgyer_helper.send_apptest_msg(
207
228
  app_info_obj: @app_info_obj,
208
229
  app_version_info_obj: app_version_info,
209
- chatEnv: "DevTest",
210
- receiveType: "chat"
230
+ receiveType: "self"
211
231
  )
232
+ puts " ✓ 消息发送成功"
233
+ rescue => e
234
+ puts " ⚠️ 发送消息给自己失败: #{e.message}"
212
235
  end
213
- else
214
- raise "上传失败:未获取到有效的返回数据"
236
+
237
+ # 如果需要发送到测试群(失败只警告,不中断)
238
+ if @context[:send_to_chat]
239
+ begin
240
+ puts " 📢 发送消息到测试群..."
241
+ pgyer_helper.send_apptest_msg(
242
+ app_info_obj: @app_info_obj,
243
+ app_version_info_obj: app_version_info,
244
+ chatEnv: "DevTest",
245
+ receiveType: "chat"
246
+ )
247
+ puts " ✓ 测试群消息发送成功"
248
+ rescue => e
249
+ puts " ⚠️ 发送消息到测试群失败: #{e.message}"
250
+ end
251
+ end
252
+
253
+ puts " ✅ 上传后续操作全部完成\n"
254
+ rescue => e
255
+ # 外层错误保护:任何未预期的错误都不应影响上传任务的成功状态
256
+ puts " ⚠️ 上传后续操作发生未预期错误: #{e.message}"
257
+ puts " ⚠️ 错误堆栈: #{e.backtrace.first(3).join("\n ")}" if e.backtrace
258
+ puts " ℹ️ 上传已成功,后续操作失败不影响上传结果\n"
215
259
  end
216
260
  end
217
261
  end
@@ -184,7 +184,7 @@ module Pindo
184
184
  def sign_ipa_with_new_cert(ipa_name:, bundle_id:)
185
185
  require 'pindo/config/pindoconfig'
186
186
 
187
- profil_info_array = Pindo::PindoSingleConfig.instance.get_cert_info
187
+ profil_info_array = Pindo::Pindoconfig.instance.get_cert_info
188
188
  bundle_id_signing_identity = profil_info_array.first['signing_identity']
189
189
 
190
190
  profile_dict = build_resign_profile_dict(profil_info_array: profil_info_array)
data/lib/pindo/version.rb CHANGED
@@ -6,7 +6,7 @@ require 'time'
6
6
 
7
7
  module Pindo
8
8
 
9
- VERSION = "5.13.5"
9
+ VERSION = "5.13.6"
10
10
 
11
11
  class VersionCheck
12
12
  RUBYGEMS_API = 'https://rubygems.org/api/v1/gems/pindo.json'
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.13.5
4
+ version: 5.13.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - wade
@@ -441,6 +441,7 @@ files:
441
441
  - lib/pindo/module/task/model/build/web_build_dev_task.rb
442
442
  - lib/pindo/module/task/model/build_task.rb
443
443
  - lib/pindo/module/task/model/git_tag_task.rb
444
+ - lib/pindo/module/task/model/ipa_local_resign_task.rb
444
445
  - lib/pindo/module/task/model/jps_resign_task.rb
445
446
  - lib/pindo/module/task/model/jps_upload_task.rb
446
447
  - lib/pindo/module/task/model/unity_export_task.rb