pindo 5.11.2 → 5.11.4

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: c01ace2237a0df141f7e2194f2826d967a770b00ceff2baf2fae6b1d0af8d7e1
4
- data.tar.gz: 778177150ddcdb9aea701bb48c095d63d19ef6d2affb9478ea39f845e1c060d4
3
+ metadata.gz: a75938a4d1faa0bfd2b4495da318e4eabda71704345a47af18fa252c0f8d78ca
4
+ data.tar.gz: 8cb15952591243cee1081720169bd5835626ac990cc3e91a1fac6964114e122e
5
5
  SHA512:
6
- metadata.gz: 918922d789aeba7a7def7ccf5f43eb387044ceb1cf4b477ac845e3406ea5303e8764053cb39d6c0c7b5523e4bac49f3e27125accb7963b611c50965df4204157
7
- data.tar.gz: 5d31433f1670b8ccee41d4c6d8cc62c9d57d4f86031b72b5d6974a725970e5629357e3d7f74554caf30e8d3dea3bbfbe72da7ec227b17948a3426f2fe33908ce
6
+ metadata.gz: 11e4c1ba858176b538827aa9bed454f1d1294d10a90ea6f6c0f4665e12ed02e0a32ad33145dade2adda700b8e41098b79e4775e8fca71191c67cc85d7da26552
7
+ data.tar.gz: f50d76e666f5d061c41e89c23791aa347299e4c157a52eb5080c37f7bd750e58bb76f0ad6c3ddace280e7c64d69223ca61b152b1c0fd56b2c6a8d78dd5aa42f5
@@ -4,7 +4,7 @@ require 'pindo/base/executable'
4
4
  require 'pindo/module/build/build_helper'
5
5
  require 'pindo/module/build/version_helper'
6
6
  require 'pindo/module/android/android_build_helper'
7
- require 'pindo/module/android/android_build_config_helper'
7
+ require 'pindo/module/android/android_config_helper'
8
8
 
9
9
  module Pindo
10
10
  class Command
@@ -151,7 +151,7 @@ module Pindo
151
151
  puts " Workflow Package Name: #{workflow_packname}"
152
152
 
153
153
  # 一次性更新 App Name、Application ID 和 URL Schemes
154
- Pindo::AndroidBuildConfigHelper.update_project_with_workflow(
154
+ Pindo::AndroidConfigHelper.update_project_with_workflow(
155
155
  project_dir: pindo_project_dir,
156
156
  workflow_packname: workflow_packname
157
157
  )
@@ -161,7 +161,7 @@ module Pindo
161
161
 
162
162
  # ===== 从 JPS 下载并替换项目 Icon =====
163
163
  if app_info_obj && app_info_obj["projectIcon"] && !app_info_obj["projectIcon"].empty?
164
- icon_replace_success = Pindo::AndroidBuildConfigHelper.download_and_replace_icon_from_url(
164
+ icon_replace_success = Pindo::AndroidConfigHelper.download_and_replace_icon_from_url(
165
165
  project_dir: pindo_project_dir,
166
166
  icon_url: app_info_obj["projectIcon"]
167
167
  )
@@ -180,7 +180,7 @@ module Pindo
180
180
 
181
181
  if version_info[:is_git_repo]
182
182
  # 更新Android工程版本
183
- Pindo::AndroidBuildConfigHelper.update_android_project_version(
183
+ Pindo::AndroidConfigHelper.update_android_project_version(
184
184
  project_dir: pindo_project_dir,
185
185
  version_name: version_info[:version],
186
186
  version_code: version_info[:build_number]
@@ -211,13 +211,13 @@ module Pindo
211
211
 
212
212
  if config_repo_dir && File.exist?(config_repo_dir)
213
213
  # 1. 拷贝 google-services.json 到 launcher 目录
214
- Pindo::AndroidBuildConfigHelper.copy_google_services_from_config_repo(
214
+ Pindo::AndroidConfigHelper.copy_google_services_from_config_repo(
215
215
  config_repo_dir: config_repo_dir,
216
216
  project_dir: pindo_project_dir
217
217
  )
218
218
 
219
219
  # 2. 更新 Application ID 为指定的 bundle_name(覆盖工作流设置)
220
- Pindo::AndroidBuildConfigHelper.update_application_id(
220
+ Pindo::AndroidConfigHelper.update_application_id(
221
221
  project_dir: pindo_project_dir,
222
222
  application_id: @main_bundle_name
223
223
  )
@@ -231,7 +231,7 @@ module Pindo
231
231
 
232
232
  # 添加基于 Application ID 的 Scheme
233
233
  # 无论是使用 workflow 的默认 Application ID,还是通过 bundle_name 覆盖的,都需要添加对应的 Scheme
234
- Pindo::AndroidBuildConfigHelper.add_application_id_based_scheme(
234
+ Pindo::AndroidConfigHelper.add_application_id_based_scheme(
235
235
  project_dir: pindo_project_dir
236
236
  )
237
237
 
@@ -107,13 +107,13 @@ module Pindo
107
107
  puts " Workflow Package Name: #{workflow_packname}"
108
108
 
109
109
  # 一次性更新 App Name、Application ID 和 URL Schemes
110
- Pindo::AndroidBuildConfigHelper.update_project_with_workflow(
110
+ Pindo::AndroidConfigHelper.update_project_with_workflow(
111
111
  project_dir: pindo_project_dir,
112
112
  workflow_packname: workflow_packname
113
113
  )
114
114
 
115
115
  # 添加基于 Application ID 的 Scheme(在 workflow 设置完成后)
116
- Pindo::AndroidBuildConfigHelper.add_application_id_based_scheme(
116
+ Pindo::AndroidConfigHelper.add_application_id_based_scheme(
117
117
  project_dir: pindo_project_dir
118
118
  )
119
119
  else
@@ -87,13 +87,13 @@ module Pindo
87
87
  puts " Workflow Package Name: #{workflow_packname}"
88
88
 
89
89
  # 一次性更新 App Name、Application ID 和 URL Schemes
90
- Pindo::AndroidBuildConfigHelper.update_project_with_workflow(
90
+ Pindo::AndroidConfigHelper.update_project_with_workflow(
91
91
  project_dir: pindo_project_dir,
92
92
  workflow_packname: workflow_packname
93
93
  )
94
94
 
95
95
  # 添加基于 Application ID 的 Scheme(在 workflow 设置完成后)
96
- Pindo::AndroidBuildConfigHelper.add_application_id_based_scheme(
96
+ Pindo::AndroidConfigHelper.add_application_id_based_scheme(
97
97
  project_dir: pindo_project_dir
98
98
  )
99
99
  else
@@ -5,6 +5,11 @@ require 'fileutils'
5
5
  require 'pindo/base/executable'
6
6
  require 'pindo/module/unity/unity_helper'
7
7
  require 'pindo/module/build/build_helper'
8
+ require 'pindo/module/task/pindo_task'
9
+ require 'pindo/module/task/task_manager'
10
+ require 'pindo/module/task/model/build_task'
11
+ require 'pindo/module/task/model/unity_export_task'
12
+ require 'pindo/module/task/model/upload_task'
8
13
 
9
14
  module Pindo
10
15
  class Command
@@ -23,13 +28,15 @@ module Pindo
23
28
 
24
29
  支持功能:
25
30
 
26
- * 多平台自动构建(iOSAndroidWebGL
31
+ * 多类型自动构建(IPAAPKHTML
32
+
33
+ * 支持选择性构建指定类型
27
34
 
28
35
  * 生成iOS IPA文件
29
36
 
30
37
  * 生成Android APK文件
31
38
 
32
- * 生成WebGL包
39
+ * 生成WebGL HTML
33
40
 
34
41
  * 支持上传到JPS测试平台
35
42
 
@@ -37,15 +44,19 @@ module Pindo
37
44
 
38
45
  使用示例:
39
46
 
40
- $ pindo unity autobuild # 编译所有平台
47
+ $ pindo unity autobuild # 编译所有类型(默认)
48
+
49
+ $ pindo unity autobuild --types=ipa # 仅编译IPA
41
50
 
42
- $ pindo unity autobuild --upload # 编译并上传到JPS
51
+ $ pindo unity autobuild --types=apk,html # 编译APK和HTML
43
52
 
44
- $ pindo unity autobuild --send # 编译、上传并发送通知
53
+ $ pindo unity autobuild --types=ipa,apk # 编译IPA和APK
45
54
 
46
- $ pindo unity autobuild --proj="My App" # 指定项目名称
55
+ $ pindo unity autobuild --upload # 编译所有类型并上传到JPS
47
56
 
48
- $ pindo unity autobuild --base # Unity lib模式
57
+ $ pindo unity autobuild --proj="My App" # 指定项目名称
58
+
59
+ $ pindo unity autobuild --base # Unity lib模式
49
60
  DESC
50
61
 
51
62
  # 命令参数
@@ -59,6 +70,7 @@ DESC
59
70
  ['--bundleid=ID', '指定iOS打包的bundleID'],
60
71
  ['--bundle_name=NAME', '指定Android Package Name(如com.example.app,会拉取对应配置)'],
61
72
  ['--proj=NAME', '指定上传到测试平台的项目名称'],
73
+ ['--types=TYPES', '指定要构建的类型,逗号分隔(如:ipa,apk,html),默认全部类型'],
62
74
  ['--upload', '上传编译后的IPA/APK到测试平台'],
63
75
  ['--base', 'Unity工程编译lib模式(生成库而非完整应用)'],
64
76
  ].concat(super)
@@ -72,15 +84,46 @@ DESC
72
84
  @args_base_flag = argv.flag?('base', false)
73
85
  @args_bundle_id = argv.option('bundleid')
74
86
  @args_bundle_name = argv.option('bundle_name')
87
+ @args_types = argv.option('types')
75
88
 
76
89
 
77
90
  super
78
91
  end
79
-
80
92
 
81
- def run
93
+ # 获取要构建的类型列表
94
+ def get_selected_build_types
95
+ # 定义类型映射关系
96
+ type_mapping = {
97
+ 'ipa' => 'ios',
98
+ 'apk' => 'android',
99
+ 'html' => 'web'
100
+ }
101
+
102
+ available_types = ['ipa', 'apk', 'html']
103
+
104
+ # 如果指定了 --types 参数
105
+ if @args_types
106
+ # 解析类型参数
107
+ types = @args_types.downcase.split(',').map(&:strip)
108
+
109
+ # 验证类型是否有效
110
+ invalid_types = types - available_types
111
+ unless invalid_types.empty?
112
+ raise Informative, "无效的构建类型: #{invalid_types.join(', ')}。可用类型: #{available_types.join(', ')}"
113
+ end
82
114
 
115
+ # 转换为平台列表
116
+ platforms = types.map { |type| type_mapping[type] }
117
+ return platforms.empty? ? type_mapping.values : platforms
118
+ end
119
+
120
+ # 默认返回所有平台
121
+ return type_mapping.values
122
+ end
123
+
124
+ def run
83
125
  pindo_project_dir = Dir.pwd
126
+
84
127
  # 检查是否是Unity工程
85
128
  unity_helper = Pindo::Client::UnityHelper.share_instance
86
129
  unless unity_helper.unity_project?(pindo_project_dir)
@@ -105,17 +148,186 @@ DESC
105
148
  proj_name = @args_proj_name
106
149
  @app_info_obj = PgyerHelper.share_instace.prepare_upload(working_directory:Dir.pwd, proj_name:proj_name)
107
150
 
151
+ # 获取要构建的类型列表
152
+ selected_platforms = get_selected_build_types()
108
153
 
109
- pindo_project_dir = Dir.pwd
110
- Dir.chdir(pindo_project_dir)
111
- ios_autobuild(unity_helper:unity_helper, unity_exe_path:unity_exe_path)
112
-
113
- Dir.chdir(pindo_project_dir)
114
- and_autobuild(unity_helper:unity_helper, unity_exe_path:unity_exe_path)
115
-
116
- Dir.chdir(pindo_project_dir)
117
- web_autobuild(unity_helper:unity_helper, unity_exe_path:unity_exe_path)
154
+ # 使用任务系统执行构建
155
+ execute_with_task_system(selected_platforms, unity_helper, unity_exe_path)
156
+ end
157
+
158
+ def execute_with_task_system(selected_platforms, unity_helper, unity_exe_path)
159
+ # 初始化任务管理器
160
+ task_manager = Pindo::TaskSystem::TaskManager.instance
161
+ task_manager.clear_all # 清空之前的任务
162
+
163
+ # 类型到显示名称的映射
164
+ display_names = {
165
+ 'ios' => 'IPA',
166
+ 'android' => 'APK',
167
+ 'web' => 'HTML'
168
+ }
169
+
170
+ # 显示任务计划
171
+ puts
172
+ puts "========================================".cyan
173
+ puts "任务执行计划".green
174
+ puts "========================================".cyan
175
+ puts "构建类型: #{selected_platforms.map { |p| display_names[p] }.join(', ')}"
176
+ puts "上传: #{@args_upload_flag ? '是' : '否'}"
177
+
178
+ task_count = selected_platforms.length * 2 # Unity导出 + 构建
179
+ task_count += selected_platforms.length if @args_upload_flag # 上传任务
180
+ puts "总任务数: #{task_count}"
181
+ puts "========================================".cyan
182
+ puts
183
+
184
+ # 创建任务
185
+ unity_tasks = {}
186
+ build_tasks = {}
187
+ upload_tasks = {}
188
+
189
+ # 1. 创建 Unity 导出任务
190
+ selected_platforms.each do |platform|
191
+ unity_task = Pindo::TaskSystem::UnityExportTask.new(
192
+ platform,
193
+ project_path: Dir.pwd,
194
+ unity_exe_path: unity_exe_path,
195
+ unity_helper: unity_helper,
196
+ context: {
197
+ project_name: @app_info_obj["projectName"]
198
+ }
199
+ )
200
+ unity_tasks[platform] = unity_task
201
+ task_manager.add_task(unity_task)
202
+ end
203
+
204
+ # 2. 创建构建任务
205
+ selected_platforms.each do |platform|
206
+ # 准备构建配置
207
+ build_config = prepare_build_config(platform)
208
+
209
+ build_task = Pindo::TaskSystem::BuildTask.new(
210
+ platform,
211
+ project_path: Dir.pwd,
212
+ build_config: build_config,
213
+ context: {
214
+ project_name: @app_info_obj["projectName"],
215
+ bundle_id: build_config[:bundle_id],
216
+ bundle_name: build_config[:bundle_name]
217
+ },
218
+ dependencies: [unity_tasks[platform].id] # 依赖 Unity 导出
219
+ )
220
+ build_tasks[platform] = build_task
221
+ task_manager.add_task(build_task)
222
+ end
223
+
224
+ # 3. 如果需要上传,创建上传任务
225
+ if @args_upload_flag
226
+ selected_platforms.each do |platform|
227
+ upload_task = Pindo::TaskSystem::UploadTask.new(
228
+ platform,
229
+ nil, # 文件路径将从构建任务结果获取
230
+ project_name: @app_info_obj["projectName"],
231
+ context: {
232
+ project_name: @app_info_obj["projectName"]
233
+ },
234
+ dependencies: [build_tasks[platform].id] # 依赖构建任务
235
+ )
236
+
237
+ # 设置构建完成后传递输出路径
238
+ build_tasks[platform].on(:on_success) do |task|
239
+ if task.result && task.result[:output]
240
+ upload_task.context[:output_path] = task.result[:output]
241
+ end
242
+ end
243
+
244
+ upload_tasks[platform] = upload_task
245
+ task_manager.add_task(upload_task)
246
+ end
247
+ end
248
+
249
+ # 执行任务
250
+ task_manager.start
251
+
252
+ # 显示执行报告
253
+ show_execution_report(task_manager.execution_report)
254
+ end
255
+
256
+ def prepare_build_config(platform)
257
+ config = {}
258
+
259
+ case platform
260
+ when 'ios'
261
+ # 获取 iOS Bundle ID
262
+ if @args_bundle_id
263
+ config[:bundle_id] = @args_bundle_id
264
+ else
265
+ if @args_deploy_flag
266
+ config[:bundle_id] = get_selected_deploy_bundleid()
267
+ else
268
+ config[:bundle_id] = get_selected_dev_bundleid()
269
+ end
270
+ end
271
+ when 'android', 'web'
272
+ # 获取 Android/Web Bundle Name
273
+ if @args_bundle_name
274
+ config[:bundle_name] = @args_bundle_name
275
+ else
276
+ config[:bundle_name] = get_selected_dev_bundle_name()
277
+ end
278
+ end
279
+
280
+ config
281
+ end
282
+
283
+ def show_execution_report(report)
284
+ puts
285
+ puts "========================================".cyan
286
+ puts "任务执行报告".green
287
+ puts "========================================".cyan
288
+
289
+ # 显示统计
290
+ puts "执行统计:"
291
+ puts " 成功: #{report[:success]}".green if report[:success] > 0
292
+ puts " 失败: #{report[:failed]}".red if report[:failed] > 0
293
+ puts
294
+
295
+ # 显示每个任务的状态
296
+ puts "任务详情:"
297
+ report[:tasks].each do |task|
298
+ status_icon = case task[:status]
299
+ when :success then "✅"
300
+ when :failed then "❌"
301
+ when :cancelled then "⏹"
302
+ else "⏸"
303
+ end
304
+
305
+ status_color = case task[:status]
306
+ when :success then :green
307
+ when :failed then :red
308
+ when :cancelled then :yellow
309
+ else :gray
310
+ end
311
+
312
+ time_str = task[:execution_time] ? " (#{task[:execution_time].round(2)}s)" : ""
313
+ status_str = "#{status_icon} #{task[:name]}#{time_str}"
314
+
315
+ if status_color == :green && defined?(String.green)
316
+ puts status_str.green
317
+ elsif status_color == :red && defined?(String.red)
318
+ puts status_str.red
319
+ elsif status_color == :yellow && defined?(String.yellow)
320
+ puts status_str.yellow
321
+ else
322
+ puts status_str
323
+ end
324
+
325
+ if task[:status] == :failed && task[:error]
326
+ puts " 错误: #{task[:error]}".red if defined?(String.red)
327
+ end
328
+ end
118
329
 
330
+ puts "========================================".cyan
119
331
  end
120
332
 
121
333
  def web_autobuild(unity_helper:nil, unity_exe_path:nil)
@@ -169,9 +169,19 @@ module Pindo
169
169
  config_json = jps_client.config_json
170
170
  config_json['upload_config']['bucket_name'] = 'nuget-resource'
171
171
 
172
+ # 开始上传主文件,记录开始时间
173
+ file_size_mb = File.size(nupkg_file) / (1024.0 * 1024.0)
174
+ puts "\n开始上传文件 (#{file_size_mb.round(2)} MB)..."
175
+ upload_start_time = Time.now
176
+
172
177
  upload_client = JPSClient::UploadClient.new(jps_client)
173
178
  file_url = upload_client.upload_file(binary_file: nupkg_file)
174
179
 
180
+ # 计算上传耗时
181
+ upload_duration = Time.now - upload_start_time
182
+ upload_speed = file_size_mb / upload_duration
183
+ puts "✅ 文件上传完成! 耗时: #{upload_duration.round(2)} 秒, 平均速度: #{upload_speed.round(2)} MB/s"
184
+
175
185
  if file_url.nil?
176
186
  raise Informative, "文件上传失败"
177
187
  end
@@ -274,18 +274,8 @@ module Pindo
274
274
  # 确保目标目录存在
275
275
  FileUtils.mkdir_p(dst_dir)
276
276
 
277
- # 拷贝目录内容(不包括目录本身)
278
- Dir.glob(File.join(src_dir, "*")).each do |src_item|
279
- dst_item = File.join(dst_dir, File.basename(src_item))
280
-
281
- if File.directory?(src_item)
282
- # 递归拷贝子目录
283
- FileUtils.cp_r(src_item, dst_item, remove_destination: true)
284
- else
285
- # 拷贝文件
286
- FileUtils.cp(src_item, dst_item)
287
- end
288
- end
277
+ # 递归拷贝函数,合并内容而不是替换整个目录
278
+ copy_merge_recursive(src_dir, dst_dir)
289
279
  else
290
280
  puts " ⚠ 跳过: #{dir} (目录不存在)"
291
281
  end
@@ -294,6 +284,26 @@ module Pindo
294
284
  puts "Unity 编译产物拷贝完成\n"
295
285
  end
296
286
 
287
+ # 递归合并拷贝:将源目录的内容合并到目标目录
288
+ def copy_merge_recursive(src_dir, dst_dir)
289
+ # 获取源目录中的所有文件和子目录
290
+ Dir.glob(File.join(src_dir, "{*,.*}")).each do |src_item|
291
+ # 跳过 . 和 ..
292
+ next if File.basename(src_item) == '.' || File.basename(src_item) == '..'
293
+
294
+ dst_item = File.join(dst_dir, File.basename(src_item))
295
+
296
+ if File.directory?(src_item)
297
+ # 如果是目录,确保目标子目录存在,然后递归拷贝
298
+ FileUtils.mkdir_p(dst_item)
299
+ copy_merge_recursive(src_item, dst_item)
300
+ else
301
+ # 如果是文件,直接覆盖(Unity 编译的文件应该覆盖旧的)
302
+ FileUtils.cp(src_item, dst_item)
303
+ end
304
+ end
305
+ end
306
+
297
307
 
298
308
  end
299
309
  end
@@ -7,7 +7,7 @@ require_relative 'android_res_helper'
7
7
 
8
8
  module Pindo
9
9
 
10
- class AndroidBuildConfigHelper
10
+ class AndroidConfigHelper
11
11
 
12
12
  # 使用工作流配置一次性更新App Name、Application ID和URL Schemes
13
13
  # 优化版本:提高性能,减少代码重复
@@ -933,10 +933,26 @@ module Pindo
933
933
 
934
934
  # 下载 icon
935
935
  Funlog.instance.fancyinfo_start("正在从 JPS 下载项目 Icon...")
936
- URI.open(icon_url) do |file|
937
- File.binwrite(icon_download_path, file.read)
936
+
937
+ begin
938
+ require 'open-uri'
939
+ require 'openssl'
940
+
941
+ options = {
942
+ :read_timeout => 30,
943
+ :open_timeout => 10,
944
+ :redirect => true,
945
+ :ssl_verify_mode => OpenSSL::SSL::VERIFY_NONE
946
+ }
947
+
948
+ URI.open(icon_url, options) do |file|
949
+ File.binwrite(icon_download_path, file.read)
950
+ end
951
+
952
+ Funlog.instance.fancyinfo_success("Icon 下载成功!")
953
+ rescue => download_error
954
+ raise Informative, "Icon 下载失败: #{download_error.message}"
938
955
  end
939
- Funlog.instance.fancyinfo_success("Icon 下载成功!")
940
956
 
941
957
  # 验证文件已下载
942
958
  unless File.exist?(icon_download_path)