pindo 5.14.5 → 5.14.7

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.
Files changed (31) hide show
  1. checksums.yaml +4 -4
  2. data/lib/pindo/base/git_handler.rb +140 -65
  3. data/lib/pindo/command/android/autobuild.rb +101 -33
  4. data/lib/pindo/command/appstore/bundleid.rb +1 -1
  5. data/lib/pindo/command/appstore/pem.rb +1 -1
  6. data/lib/pindo/command/ios/autobuild.rb +116 -56
  7. data/lib/pindo/command/jps/apptest.rb +129 -50
  8. data/lib/pindo/command/jps/resign.rb +109 -99
  9. data/lib/pindo/command/jps/upload.rb +31 -4
  10. data/lib/pindo/command/jps.rb +0 -1
  11. data/lib/pindo/command/unity/autobuild.rb +101 -40
  12. data/lib/pindo/command/web/autobuild.rb +96 -28
  13. data/lib/pindo/command.rb +23 -15
  14. data/lib/pindo/module/appselect.rb +14 -0
  15. data/lib/pindo/module/pgyer/pgyerhelper.rb +166 -0
  16. data/lib/pindo/module/task/model/git/git_commit_task.rb +36 -3
  17. data/lib/pindo/module/task/model/git/git_tag_task.rb +5 -4
  18. data/lib/pindo/module/task/model/jps/jps_bind_package_task.rb +38 -19
  19. data/lib/pindo/module/task/model/jps/jps_message_task.rb +9 -6
  20. data/lib/pindo/module/task/model/jps/jps_resign_task.rb +20 -21
  21. data/lib/pindo/module/task/model/jps/jps_upload_media_task.rb +37 -1
  22. data/lib/pindo/module/task/model/jps/jps_upload_task.rb +4 -4
  23. data/lib/pindo/module/task/model/jps/jps_workflow_message_task.rb +1 -1
  24. data/lib/pindo/options/core/option_configuration.rb +4 -36
  25. data/lib/pindo/options/core/option_initializer.rb +6 -3
  26. data/lib/pindo/options/core/option_item.rb +0 -3
  27. data/lib/pindo/options/groups/build_options.rb +3 -2
  28. data/lib/pindo/options/groups/jps_options.rb +30 -10
  29. data/lib/pindo/version.rb +1 -1
  30. metadata +25 -8
  31. data/lib/pindo/command/jps/comment.rb +0 -84
@@ -33,33 +33,55 @@ module Pindo
33
33
 
34
34
  # 命令的详细说明,包含用法示例
35
35
  self.description = <<-DESC
36
- 编译WebGL包并支持上传到测试平台。
36
+ 编译WebGL包并支持上传到JPS测试平台。
37
37
 
38
- 支持功能:
38
+ 参数优先级说明(从低到高):
39
+
40
+ 1. 无参数:
41
+ - Git 提交 → 打 Git Tag → 编译 WebGL → 检查输出
42
+
43
+ 2. --upload:
44
+ - 在基础流程上增加:上传 WebGL → 发送消息给自己
45
+
46
+ 3. --media:
47
+ - 自动启用 --upload
48
+ - 在 --upload 基础上增加:上传媒体附件(JPSMedia/ 目录)
39
49
 
40
- * 编译Debug包
50
+ 4. --bind:
51
+ - 自动启用 --media 和 --upload
52
+ - 在 --media 基础上增加:绑定 Git commit 到已上传的包
41
53
 
42
- * 上传到测试平台
54
+ 5. --send:
55
+ - 自动启用 --bind、--media 和 --upload
56
+ - 在 --bind 基础上增加:发送工作流消息到测试群
43
57
 
44
- * 发送测试通知
58
+ 支持功能:
45
59
 
60
+ * 编译 Unity WebGL 包
61
+ * 上传到 JPS 测试平台
62
+ * 上传媒体附件(图片、视频)
63
+ * 绑定 Git commit 到已上传的包
64
+ * 发送测试通知(自己/测试群)
65
+ * 支持本地预览(使用 --run 参数)
46
66
  * 支持并发任务执行(使用 --multi 参数)
47
67
 
48
68
  使用示例:
49
69
 
50
- $ pindo web autobuild # 编译Debug包
70
+ $ pindo web autobuild --proj="My App" # 指定项目名称
71
+
72
+ $ pindo web autobuild # 编译、打tag
51
73
 
52
- $ pindo web autobuild --upload # 编译并上传
74
+ $ pindo web autobuild --upload # 编译、打tag、上传、发上传消息
53
75
 
54
- $ pindo web autobuild --proj=myapp # 指定项目名称
76
+ $ pindo web autobuild --media # 编译、打tag、上传、发上传消息、上传媒体附件
55
77
 
56
- $ pindo web autobuild --media # 编译、上传并上传媒体附件
78
+ $ pindo web autobuild --bind # 编译、打tag、上传、发上传消息、上传媒体附件 + 绑定包到工作流
57
79
 
58
- $ pindo web autobuild --run # 编译完成后再本地打开webgl包
80
+ $ pindo web autobuild --send # 编译、打tag、上传、发上传消息、上传媒体附件、绑定包到工作流 + 发送群消息
59
81
 
60
- $ pindo web autobuild --multi # 使用并发模式执行(速度更快)
82
+ $ pindo web autobuild --run # 编译完成后在本地打开 WebGL 包
61
83
 
62
- $ pindo web autobuild --multi --upload # 并发执行并上传
84
+ $ pindo web autobuild --multi # 使用并发模式执行
63
85
  DESC
64
86
 
65
87
  # 命令的参数列表
@@ -70,7 +92,8 @@ module Pindo
70
92
  # 定义此命令使用的参数项
71
93
  def self.option_items
72
94
  @option_items ||= Pindo::Options::OptionGroup.merge(
73
- Pindo::Options::JPSOptions.select(:proj, :upload, :send, :media),
95
+ Pindo::Options::BuildOptions.select(:bundleid), # 添加 bundleid 参数
96
+ Pindo::Options::JPSOptions.select(:proj, :upload, :send, :media, :bind),
74
97
  Pindo::Options::UnityOptions.select(:skiplib, :skipyoo),
75
98
  Pindo::Options::UnityOptions.select_with_defaults(skipconfig: true),
76
99
  Pindo::Options::TaskOptions.select(:multi),
@@ -81,7 +104,6 @@ module Pindo
81
104
  # 命令的选项列表
82
105
  def self.options
83
106
  [
84
- ['--bundleid', '指定打包的bundleID'],
85
107
  ['--run', '编译完成后再本地打开webgl包']
86
108
  ].concat(option_items.map(&:to_claide_option)).concat(super)
87
109
  end
@@ -91,12 +113,22 @@ module Pindo
91
113
 
92
114
  @args_deploy_flag = argv.flag?('deploy', false)
93
115
  @args_adhoc_flag = argv.flag?('adhoc', false)
94
- @args_upload_flag = @options[:upload] || false
95
- @args_send_flag = @options[:send] || false
96
- @args_media_flag = @options[:media] || false
97
116
  @args_proj_name = @options[:proj]
98
- @args_bundle_id = argv.option('bundleid')
117
+ @args_bundle_id = @options[:bundleid] # 从 @options 获取,确保能被缓存
99
118
  @args_run_flag = argv.flag?('run', false)
119
+
120
+ # send、media 或 bind 都依赖 upload:如果指定了任一参数,自动启用 upload
121
+ @args_upload_flag = @options[:send] || @options[:bind] || @options[:media] || @options[:upload]
122
+
123
+ # media 任务是独立的,不依赖任何其他任务,但是为输入命令参数更加简单,如果有--bind和--send, 则默认认为一定会有--media参数
124
+ @args_media_flag = @options[:send] || @options[:bind] || @options[:media] || false
125
+
126
+ # send 都依赖 bind:如果指定了任一参数,自动启用 bind
127
+ @args_bind_flag = @options[:send] || @options[:bind] || false
128
+
129
+ @args_send_flag = @options[:send]
130
+
131
+ # Unity 参数
100
132
  @args_skip_lib = @options[:skiplib] || false
101
133
  @args_skip_yoo = @options[:skipyoo] || false
102
134
 
@@ -109,10 +141,6 @@ module Pindo
109
141
  @args_tag_type = Pindo::Options::GitOptions.parse_create_tag_type(@options[:tag_type] || 'new')
110
142
  @args_tag_pre = @options[:tag_pre] || 'v'
111
143
 
112
- if @args_send_flag || @args_media_flag
113
- @args_upload_flag = true
114
- end
115
-
116
144
  super
117
145
  @additional_args = argv.remainder!
118
146
  end
@@ -292,8 +320,6 @@ module Pindo
292
320
  options: {
293
321
  project_path: config[:project_path],
294
322
  proj_name: @args_proj_name,
295
- upload: @args_upload_flag,
296
- send: @args_send_flag,
297
323
  app_info_obj: config[:app_info_obj],
298
324
  workflow_info: config[:workflow_info]
299
325
  }
@@ -302,6 +328,7 @@ module Pindo
302
328
  tasks << build_task
303
329
 
304
330
  # 7. 上传和消息发送任务(如果需要)
331
+ upload_task = nil # 声明变量以便后续绑定任务使用
305
332
  if @args_upload_flag
306
333
  # WebGL 输出路径: GoodPlatform/WebGL/build
307
334
  webgl_build_path = File.join(config[:project_path], 'GoodPlatform', 'WebGL', 'build')
@@ -318,15 +345,15 @@ module Pindo
318
345
  upload_task.dependencies << build_task.id
319
346
  tasks << upload_task
320
347
 
321
- # 7.2 创建消息发送任务(只依赖上传任务)
348
+ # 7.2 创建消息发送任务(只依赖上传任务,固定发送给自己)
322
349
  # app_version_info 将从 upload_task 的数据参数中获取
323
350
  message_task = Pindo::TaskSystem::JPSMessageTask.new(
324
351
  nil, # app_version_info 为 nil,从依赖任务获取
325
352
  app_info_obj: config[:app_info_obj],
326
353
  project_name: @args_proj_name,
327
- send_message_type: @args_send_flag ? 'group' : 'self',
328
- dependencies: [upload_task.id] # 从 upload_task 获取数据
354
+ send_message_type: 'self' # 固定发送给自己
329
355
  )
356
+ message_task.dependencies << upload_task.id
330
357
  tasks << message_task
331
358
  end
332
359
 
@@ -347,11 +374,52 @@ module Pindo
347
374
  workflow_info: git_workflow_info,
348
375
  project_name: @args_proj_name
349
376
  )
350
- # 只依赖 Git 提交任务
377
+ # 依赖 Git 提交任务
351
378
  media_upload_task.dependencies << git_commit_task.id
352
379
  tasks << media_upload_task
353
380
  end
354
381
 
382
+ # 9. 创建 Git Commit 绑定任务(如果需要,依赖上传任务)
383
+ bind_package_task = nil # 声明变量以便后续工作流消息任务使用
384
+ if @args_bind_flag
385
+ bind_package_task = Pindo::TaskSystem::JPSBindPackageTask.new(
386
+ nil, # app_version_list 为 nil,从依赖任务获取
387
+ project_dir: config[:project_path],
388
+ app_info_obj: config[:app_info_obj],
389
+ workflow_info: config[:workflow_info],
390
+ project_name: @args_proj_name
391
+ )
392
+ # 依赖上传任务和 Git 提交任务
393
+ bind_package_task.dependencies << upload_task.id
394
+ bind_package_task.dependencies << git_commit_task.id
395
+ tasks << bind_package_task
396
+ end
397
+
398
+ # 10. 创建工作流消息任务(如果需要,发送到测试群)
399
+ if @args_send_flag
400
+ # 获取 Git 工作流信息
401
+ git_app_info_obj, git_workflow_info = PgyerHelper.share_instace.prepare_upload(
402
+ working_directory: config[:project_path],
403
+ proj_name: @args_proj_name,
404
+ package_type: "",
405
+ manage_type: "git"
406
+ )
407
+
408
+ workflow_message_task = Pindo::TaskSystem::JPSWorkFlowMessageTask.new(
409
+ project_id: git_app_info_obj["id"],
410
+ workflow_id: git_workflow_info["id"],
411
+ branch: 'master',
412
+ single: true,
413
+ app_info_obj: git_app_info_obj,
414
+ workflow_info: git_workflow_info
415
+ )
416
+ # 依赖 Git Commit、Git Tag 和 Bind Package 任务
417
+ workflow_message_task.dependencies << git_commit_task.id
418
+ workflow_message_task.dependencies << git_tag_task.id
419
+ workflow_message_task.dependencies << bind_package_task.id
420
+ tasks << workflow_message_task
421
+ end
422
+
355
423
  tasks
356
424
  else
357
425
  raise Informative, "Web 编译只支持 Unity 工程"
data/lib/pindo/command.rb CHANGED
@@ -11,7 +11,22 @@ require 'pindo/client/giteeclient'
11
11
  require 'pindo/config/pindoconfig'
12
12
 
13
13
  module Pindo
14
+ # Help 拦截器模块:统一处理 --help 参数
15
+ # 使用 prepend 确保在所有子类的 validate! 方法之前执行
16
+ module HelpValidator
17
+ def validate!
18
+ # 如果是 help 请求,调用 help! 并终止执行
19
+ # help! 会抛出 CLAide::Help 异常,阻止后续逻辑执行
20
+ help! if @args_help_flag
21
+
22
+ # 否则正常执行
23
+ super
24
+ end
25
+ end
26
+
14
27
  class Command < CLAide::Command
28
+ # 使用 prepend 确保 HelpValidator 在所有子类之前执行
29
+ prepend HelpValidator
15
30
 
16
31
  include Pindoconfig::Mixin
17
32
  include Funlog::Mixin
@@ -105,30 +120,23 @@ module Pindo
105
120
  end
106
121
  end
107
122
 
108
- def validate!
109
- super
110
- help! if args_help_flag?
111
- end
112
-
113
123
  def self.run(argv)
114
124
  super(argv)
115
125
  end
116
126
 
117
127
  def initialize(argv)
118
128
  super
119
- @args_help_flag = argv.flag?('help', false)
120
- @args_verbose_flag = argv.flag?('verbose', false)
121
129
 
122
- # 检查是否是 help 请求(检查原始命令行参数)
123
- original_args = ARGV.join(' ')
124
- is_help_request = @args_help_flag ||
125
- original_args.include?('--help') ||
126
- original_args.include?('-h') ||
127
- argv.remainder.include?('--help') ||
128
- argv.remainder.include?('-h')
130
+ # 检查是否是 help 请求
131
+ # CLAide 可能提前处理了 --help,所以我们需要检查原始参数
132
+ @args_help_flag = argv.flag?('help', false) ||
133
+ ARGV.include?('--help') ||
134
+ ARGV.include?('-h')
135
+
136
+ @args_verbose_flag = argv.flag?('verbose', false)
129
137
 
130
138
  # 设置全局 verbose 标志
131
- ENV['PINDO_VERBOSE'] = '1' if @args_verbose_flag
139
+ ENV['PINDO_DEBUG'] = '1' if @args_verbose_flag
132
140
  end
133
141
 
134
142
  end
@@ -239,6 +239,13 @@ module Pindo
239
239
  puts "选择的Bundle Name是: #{menu_choice}"
240
240
  puts
241
241
 
242
+ # 去除通配符后缀(如 com.test.* -> com.test)
243
+ if menu_choice.end_with?(".*")
244
+ menu_choice = menu_choice.sub(/\.\*$/, '')
245
+ puts "去除通配符后的Bundle Name: #{menu_choice}"
246
+ puts
247
+ end
248
+
242
249
  # 保存选择到 GlobalOptionsState
243
250
  state[:bundle_name] = menu_choice
244
251
 
@@ -270,6 +277,13 @@ module Pindo
270
277
  puts "选择的Bundle Name是: #{menu_choice}"
271
278
  puts
272
279
 
280
+ # 去除通配符后缀(如 com.test.* -> com.test)
281
+ if menu_choice.end_with?(".*")
282
+ menu_choice = menu_choice.sub(/\.\*$/, '')
283
+ puts "去除通配符后的Bundle Name: #{menu_choice}"
284
+ puts
285
+ end
286
+
273
287
  return menu_choice
274
288
  end
275
289
 
@@ -103,6 +103,7 @@ module Pindo
103
103
  when 'apk' then 'apk_workflow'
104
104
  when 'zip' then 'webgl_workflow'
105
105
  when 'app' then 'macos_workflow'
106
+ when 'exe' then 'win_workflow'
106
107
  else
107
108
  puts "[JPSConfig] 不支持的 package_type: #{package_type}"
108
109
  return result
@@ -1550,6 +1551,170 @@ module Pindo
1550
1551
  end
1551
1552
  end
1552
1553
 
1554
+ # 获取特定 commit 已绑定的包 ID
1555
+ #
1556
+ # @param commit_id [String] Git commit SHA(必需)
1557
+ # @param workflow_id [Integer, String] 工作流 ID(必需,API 需要)
1558
+ # @return [Array<String>] 已绑定的包 ID 数组
1559
+ def get_commit_bound_package_ids(commit_id:, workflow_id:)
1560
+ return [] if commit_id.nil? || commit_id.empty?
1561
+ return [] if workflow_id.nil?
1562
+
1563
+ begin
1564
+ # 使用 commit_log/preview API 直接查询特定 commit
1565
+ result = @pgyer_client.get_commit_log_preview(
1566
+ workflowId: workflow_id,
1567
+ commitIds: [commit_id],
1568
+ params: { onlyCliff: false } # 需要完整信息
1569
+ )
1570
+
1571
+ # 兼容两种响应格式
1572
+ response_code = result&.dig("code") || result&.dig("meta", "code")
1573
+
1574
+ if result && (response_code == 0 || response_code == 200)
1575
+ # 从响应中提取 commit 信息
1576
+ # preview API 可能返回数组或单个对象
1577
+ commit_data = result&.dig("data")
1578
+ commit_list = commit_data.is_a?(Array) ? commit_data : [commit_data].compact
1579
+
1580
+ # 查找匹配的 commit
1581
+ commit_info = commit_list.find { |item| item && item["commitId"] == commit_id }
1582
+
1583
+ if commit_info && commit_info["bindVersions"]
1584
+ # 从 bindVersions 中提取所有平台的 projectPackageId
1585
+ bind_versions = commit_info["bindVersions"]
1586
+ package_ids = []
1587
+
1588
+ # 遍历所有平台(ipa, apk, zip, mac, exe 等)
1589
+ bind_versions.each do |_platform, version_info|
1590
+ if version_info && version_info["projectPackageId"]
1591
+ package_ids << version_info["projectPackageId"]
1592
+ end
1593
+ end
1594
+
1595
+ return package_ids.compact.uniq
1596
+ else
1597
+ # 如果没有找到或没有绑定信息,返回空数组(可能是首次绑定)
1598
+ if ENV['PINDO_DEBUG']
1599
+ puts "[PINDO_DEBUG] Commit #{commit_id[0..7]} 没有绑定信息"
1600
+ end
1601
+ return []
1602
+ end
1603
+ else
1604
+ # 如果获取失败,返回空数组(不阻止绑定流程)
1605
+ if ENV['PINDO_DEBUG']
1606
+ error_msg = result&.dig("msg") || result&.dig("meta", "message") || "未知错误"
1607
+ puts "[PINDO_DEBUG] 获取 commit 绑定包失败: #{error_msg}"
1608
+ end
1609
+ return []
1610
+ end
1611
+ rescue => e
1612
+ # 异常时返回空数组,不阻止绑定流程
1613
+ if ENV['PINDO_DEBUG']
1614
+ puts "[PINDO_DEBUG] 获取 commit 绑定包异常: #{e.message}"
1615
+ puts "[PINDO_DEBUG] Backtrace: #{e.backtrace[0..2].join("\n")}"
1616
+ end
1617
+ return []
1618
+ end
1619
+ end
1620
+
1621
+ # 获取工作流中已绑定的包 ID(已废弃,请使用 get_commit_bound_package_ids)
1622
+ #
1623
+ # @deprecated 使用 get_commit_bound_package_ids(commit_id:, workflow_id:) 替代
1624
+ # @param workflow_id [Integer, String] 工作流 ID
1625
+ # @return [Array<String>] 已绑定的包 ID 数组
1626
+ def get_workflow_bound_package_ids(workflow_id:)
1627
+ if ENV['PINDO_DEBUG']
1628
+ puts "[PINDO_DEBUG] ⚠️ get_workflow_bound_package_ids 已废弃,请使用 get_commit_bound_package_ids"
1629
+ end
1630
+
1631
+ return [] if workflow_id.nil?
1632
+
1633
+ begin
1634
+ # 调用 JPS API 获取工作流详情
1635
+ result = @pgyer_client.get_workflow_detail(workflowId: workflow_id)
1636
+
1637
+ # 兼容两种响应格式
1638
+ response_code = result&.dig("code") || result&.dig("meta", "code")
1639
+
1640
+ if result && (response_code == 0 || response_code == 200)
1641
+ # 从响应中提取 boundPackageIds
1642
+ workflow_data = result&.dig("data") || result&.dig("result")
1643
+ bound_ids = workflow_data&.dig("boundPackageIds") || []
1644
+
1645
+ # 确保返回数组(兼容字符串和数组)
1646
+ bound_ids = [bound_ids] unless bound_ids.is_a?(Array)
1647
+
1648
+ return bound_ids.compact
1649
+ else
1650
+ # 如果获取失败,返回空数组(不阻止绑定流程)
1651
+ if ENV['PINDO_DEBUG']
1652
+ error_msg = result&.dig("msg") || result&.dig("meta", "message") || "未知错误"
1653
+ puts "[PINDO_DEBUG] 获取工作流绑定包失败: #{error_msg}"
1654
+ end
1655
+ return []
1656
+ end
1657
+ rescue => e
1658
+ # 异常时返回空数组,不阻止绑定流程
1659
+ if ENV['PINDO_DEBUG']
1660
+ puts "[PINDO_DEBUG] 获取工作流绑定包异常: #{e.message}"
1661
+ end
1662
+ return []
1663
+ end
1664
+ end
1665
+
1666
+ # 获取工作流中最新的 commit id
1667
+ #
1668
+ # @param workflow_id [Integer, String] 工作流 ID
1669
+ # @return [String, nil] 最新的 commit id,失败时返回 nil
1670
+ def get_workflow_latest_commit_id(workflow_id:)
1671
+ return nil if workflow_id.nil?
1672
+
1673
+ begin
1674
+ # 调用 JPS API 获取工作流详情
1675
+ result = @pgyer_client.get_workflow_detail(workflowId: workflow_id)
1676
+
1677
+ # 兼容两种响应格式
1678
+ response_code = result&.dig("code") || result&.dig("meta", "code")
1679
+
1680
+ if result && (response_code == 0 || response_code == 200)
1681
+ # 从响应中提取工作流数据
1682
+ workflow_data = result&.dig("data") || result&.dig("result")
1683
+
1684
+ # 尝试从不同字段获取最新的 commit id
1685
+ # 1. 尝试从 latestCommitId 字段获取
1686
+ latest_commit = workflow_data&.dig("latestCommitId")
1687
+
1688
+ # 2. 如果没有 latestCommitId,尝试从 commits 数组获取第一个
1689
+ if latest_commit.nil? || latest_commit.empty?
1690
+ commits = workflow_data&.dig("commits") || []
1691
+ latest_commit = commits.first&.dig("id") || commits.first&.dig("commitId") if commits.any?
1692
+ end
1693
+
1694
+ # 3. 如果还是没有,尝试从 lastCommit 对象获取
1695
+ if latest_commit.nil? || latest_commit.empty?
1696
+ last_commit = workflow_data&.dig("lastCommit")
1697
+ latest_commit = last_commit&.dig("id") || last_commit&.dig("commitId")
1698
+ end
1699
+
1700
+ return latest_commit
1701
+ else
1702
+ # 如果获取失败,返回 nil
1703
+ if ENV['PINDO_DEBUG']
1704
+ error_msg = result&.dig("msg") || result&.dig("meta", "message") || "未知错误"
1705
+ puts "[PINDO_DEBUG] 获取工作流最新 commit id 失败: #{error_msg}"
1706
+ end
1707
+ return nil
1708
+ end
1709
+ rescue => e
1710
+ # 异常时返回 nil
1711
+ if ENV['PINDO_DEBUG']
1712
+ puts "[PINDO_DEBUG] 获取工作流最新 commit id 异常: #{e.message}"
1713
+ end
1714
+ return nil
1715
+ end
1716
+ end
1717
+
1553
1718
  # 绑定 Git commit 到项目包
1554
1719
  #
1555
1720
  # @param commit_id [String] Git commit SHA
@@ -1721,6 +1886,7 @@ module Pindo
1721
1886
  when 'apk' then 'apk_workflow'
1722
1887
  when 'zip' then 'webgl_workflow'
1723
1888
  when 'app' then 'macos_workflow'
1889
+ when 'exe' then 'win_workflow'
1724
1890
  else raise Informative, "不支持的 package_type: #{package_type}"
1725
1891
  end
1726
1892
  end
@@ -110,13 +110,34 @@ module Pindo
110
110
  raise e
111
111
  end
112
112
 
113
- # 4. 获取当前分支
113
+ # 4. Stash 工作目录的残留修改(为分支同步做准备)
114
+ stash_saved = false
115
+ status = Pindo::GitHandler.git!(%W(-C #{root_dir} status --porcelain)).strip
116
+ unless status.empty?
117
+ Funlog.instance.fancyinfo_update("工作目录有未提交更改,暂存到 stash")
118
+ Pindo::GitHandler.git!(%W(-C #{root_dir} stash -u))
119
+ stash_saved = true
120
+ end
121
+
122
+ # 5. 获取当前分支
114
123
  coding_branch = get_current_branch_name
115
124
 
116
- # 5. 检查并推送本地提交到远程
125
+ # 6. 检查并推送本地提交到远程(确保本地和远程同步)
117
126
  Pindo::GitHandler.check_unpushed_commits(project_dir: root_dir, branch: coding_branch)
118
127
 
119
- # 6. 计算 build_version
128
+ # 7. 分支同步:将 coding_branch 和 release_branch 双向合并(确保两分支在同一节点)
129
+ if coding_branch != @release_branch
130
+ Funlog.instance.fancyinfo_start("开始同步 #{coding_branch} 和 #{@release_branch} 分支")
131
+ Pindo::GitHandler.merge_branches(
132
+ project_dir: root_dir,
133
+ source_branch: coding_branch,
134
+ target_branch: @release_branch,
135
+ sync_branches: true # 双向合并,确保两分支完全同步
136
+ )
137
+ Funlog.instance.fancyinfo_success("分支同步完成,#{coding_branch} 和 #{@release_branch} 现在在同一节点")
138
+ end
139
+
140
+ # 8. 计算 build_version
120
141
  # 优先级 1: 如果指定了 fixed_version(外部传入或从 HEAD tag 获取),使用它
121
142
  if @fixed_version && !@fixed_version.empty?
122
143
  @build_version = @fixed_version
@@ -135,6 +156,18 @@ module Pindo
135
156
  Funlog.instance.fancyinfo_success("计算新版本号: #{@build_version}, Build: #{@build_number}")
136
157
  end
137
158
 
159
+ # 9. 还原 stash(如果之前有 stash)
160
+ if stash_saved
161
+ begin
162
+ Pindo::GitHandler.git!(%W(-C #{root_dir} stash pop))
163
+ Funlog.instance.fancyinfo_success("已还原 stash")
164
+ rescue => e
165
+ Funlog.instance.fancyinfo_warning("stash 还原时发生冲突: #{e.message}")
166
+ Funlog.instance.fancyinfo_warning("stash 已保留,请手动执行 'git stash pop' 处理冲突")
167
+ # 不抛出异常,任务继续(版本号已计算成功,stash 冲突不影响构建)
168
+ end
169
+ end
170
+
138
171
  {
139
172
  success: true,
140
173
  root_dir: root_dir,
@@ -73,12 +73,13 @@ module Pindo
73
73
  stash_saved = true
74
74
  end
75
75
 
76
- # 2. 合并到发布分支(方法内部会切回 coding_branch
76
+ # 2. 合并到发布分支(双向同步,确保 coding_branch 和 release_branch 保持一致)
77
77
  if coding_branch != @release_branch
78
- Pindo::GitHandler.merge_to_release_branch(
78
+ Pindo::GitHandler.merge_branches(
79
79
  project_dir: root_dir,
80
- release_branch: @release_branch,
81
- coding_branch: coding_branch
80
+ source_branch: coding_branch,
81
+ target_branch: @release_branch,
82
+ sync_branches: true # 双向合并,确保两分支完全同步
82
83
  )
83
84
  end
84
85
 
@@ -48,7 +48,7 @@ module Pindo
48
48
  # 设置任务优先级为 LOW,确保在上传任务之后执行
49
49
  options[:priority] ||= TaskPriority::LOW
50
50
 
51
- super("绑定 Git Commit 到项目包", options)
51
+ super("绑定 包到Git工作流", options)
52
52
  end
53
53
 
54
54
  def validate
@@ -136,12 +136,38 @@ module Pindo
136
136
  raise "无法登录 JPS,请检查配置"
137
137
  end
138
138
 
139
- # 6. 批量绑定所有包
140
- Funlog.instance.fancyinfo_start("正在绑定 #{project_package_ids.size} 个项目包...")
139
+ # 6. 获取工作流 ID
140
+ workflow_id = @workflow_info&.dig(:workflow_id) || @workflow_info&.dig('id')
141
+ unless workflow_id
142
+ raise "缺少 workflow_info,无法获取 workflow_id"
143
+ end
144
+
145
+ # 7. 获取当前 commit 已绑定的包 ID
146
+ existing_bound_ids = pgyer_helper.get_commit_bound_package_ids(
147
+ commit_id: @git_commit_id,
148
+ workflow_id: workflow_id
149
+ )
150
+
151
+ if existing_bound_ids.any?
152
+ puts " 📋 当前 Commit 已绑定的包: #{existing_bound_ids.size} 个"
153
+ end
154
+
155
+ # 8. 合并当前 commit 已绑定的 ID 和新上传的包 ID(去重)
156
+ merged_package_ids = (existing_bound_ids + project_package_ids).uniq
157
+
158
+ puts " 📦 合并后的包 ID 数量: #{merged_package_ids.size} 个"
159
+ if merged_package_ids.size > project_package_ids.size
160
+ puts " └─ 新增: #{project_package_ids.size} 个"
161
+ puts " └─ 已绑定: #{existing_bound_ids.size} 个"
162
+ end
163
+ puts ""
164
+
165
+ # 9. 批量绑定所有包(API 是覆盖式,所以需要包含已绑定的)
166
+ Funlog.instance.fancyinfo_start("正在绑定 #{merged_package_ids.size} 个项目包...")
141
167
 
142
168
  bind_result = pgyer_helper.bind_commit_to_package(
143
169
  commit_id: @git_commit_id,
144
- project_package_ids: project_package_ids
170
+ project_package_ids: merged_package_ids
145
171
  )
146
172
 
147
173
  if bind_result[:success]
@@ -151,7 +177,7 @@ module Pindo
151
177
  {
152
178
  success: true,
153
179
  git_commit_id: @git_commit_id,
154
- bound_package_ids: project_package_ids,
180
+ bound_package_ids: merged_package_ids, # 返回合并后的包 ID 列表
155
181
  app_version_list: @app_version_list
156
182
  }
157
183
  else
@@ -169,22 +195,15 @@ module Pindo
169
195
 
170
196
  # 从依赖任务获取 app_version_list
171
197
  def fetch_app_version_from_dependencies
172
- # JPSUploadTask 获取数据
173
- upload_data = get_data_param_by_key(:jps_upload)
174
-
175
- if upload_data && upload_data[:task_param] && upload_data[:task_param][:app_version_info]
176
- # 兼容单个版本信息,转为数组
177
- @app_version_list = [upload_data[:task_param][:app_version_info]]
178
- return
179
- end
198
+ # 获取所有 JPSUploadTask 的数据(可能有多个平台的上传任务)
199
+ all_upload_data = get_all_data_params_by_key(:jps_upload)
180
200
 
181
- # 兼容旧机制:从第一个依赖获取结果
182
- unless @dependencies.empty?
183
- upload_result = get_dependency_result(@dependencies.first)
201
+ @app_version_list = []
184
202
 
185
- if upload_result && upload_result[:app_version_info]
186
- # 兼容单个版本信息,转为数组
187
- @app_version_list = [upload_result[:app_version_info]]
203
+ # 遍历所有上传任务,收集 app_version_info
204
+ all_upload_data.each do |upload_data|
205
+ if upload_data[:task_param] && upload_data[:task_param][:app_version_info]
206
+ @app_version_list << upload_data[:task_param][:app_version_info]
188
207
  end
189
208
  end
190
209
  end