pindo 5.14.4 → 5.14.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.
Files changed (32) hide show
  1. checksums.yaml +4 -4
  2. data/lib/pindo/base/git_handler.rb +140 -65
  3. data/lib/pindo/client/httpclient.rb +88 -12
  4. data/lib/pindo/command/android/autobuild.rb +100 -32
  5. data/lib/pindo/command/appstore/bundleid.rb +1 -1
  6. data/lib/pindo/command/appstore/pem.rb +1 -1
  7. data/lib/pindo/command/ios/autobuild.rb +116 -56
  8. data/lib/pindo/command/jps/apptest.rb +129 -50
  9. data/lib/pindo/command/jps/bind.rb +284 -121
  10. data/lib/pindo/command/jps/media.rb +1 -15
  11. data/lib/pindo/command/jps/resign.rb +109 -99
  12. data/lib/pindo/command/jps/upload.rb +31 -4
  13. data/lib/pindo/command/jps.rb +0 -1
  14. data/lib/pindo/command/unity/autobuild.rb +100 -39
  15. data/lib/pindo/command/web/autobuild.rb +95 -27
  16. data/lib/pindo/command.rb +23 -15
  17. data/lib/pindo/module/pgyer/pgyerhelper.rb +181 -0
  18. data/lib/pindo/module/task/model/git/git_commit_task.rb +55 -4
  19. data/lib/pindo/module/task/model/git/git_tag_task.rb +5 -4
  20. data/lib/pindo/module/task/model/jps/jps_bind_package_task.rb +233 -0
  21. data/lib/pindo/module/task/model/jps/jps_message_task.rb +9 -6
  22. data/lib/pindo/module/task/model/jps/jps_resign_task.rb +20 -21
  23. data/lib/pindo/module/task/model/jps/jps_upload_media_task.rb +57 -22
  24. data/lib/pindo/module/task/model/jps/jps_upload_task.rb +4 -4
  25. data/lib/pindo/module/task/model/jps/jps_workflow_message_task.rb +190 -0
  26. data/lib/pindo/options/core/option_configuration.rb +4 -36
  27. data/lib/pindo/options/core/option_initializer.rb +6 -3
  28. data/lib/pindo/options/core/option_item.rb +0 -3
  29. data/lib/pindo/options/groups/jps_options.rb +30 -10
  30. data/lib/pindo/version.rb +1 -1
  31. metadata +12 -37
  32. data/lib/pindo/command/jps/comment.rb +0 -84
@@ -0,0 +1,233 @@
1
+ require 'pindo/module/task/model/jps_task'
2
+ require 'pindo/module/task/task_config'
3
+ require 'pindo/module/pgyer/pgyerhelper'
4
+ require 'pindo/base/git_handler'
5
+
6
+ module Pindo
7
+ module TaskSystem
8
+ # JPS 绑定包任务
9
+ # 将 Git commit 绑定到已上传的项目包(支持批量绑定)
10
+ #
11
+ # 支持两种模式:
12
+ # 1. 指定模式:传入 git_commit_id 和 app_version_list
13
+ # 2. 依赖模式:从依赖任务(GitCommitTask、JPSUploadTask)获取信息
14
+ class JPSBindPackageTask < JPSTask
15
+ attr_reader :git_commit_id, :git_commit_time, :git_commit_desc
16
+ attr_reader :app_version_list
17
+
18
+ # 任务键
19
+ def self.task_key
20
+ :jps_bind_package
21
+ end
22
+
23
+ # 初始化绑定包任务
24
+ # @param app_version_list [Array<Hash>, nil] 应用版本信息列表(可选,如为 nil 则从依赖任务获取)
25
+ # @param options [Hash] 选项
26
+ # @option options [String] :git_commit_id Git commit SHA(可选,为空时从依赖任务获取)
27
+ # @option options [String] :git_commit_time Git commit 时间(可选)
28
+ # @option options [String] :git_commit_desc Git commit 描述(可选)
29
+ # @option options [String] :project_dir 项目目录(可选,用于自动获取 commit 信息)
30
+ # @option options [Hash] :app_info_obj JPS 应用信息对象(可选,继承自基类)
31
+ # @option options [Hash] :workflow_info 工作流信息(可选,继承自基类)
32
+ # @option options [String] :project_name 项目名称(可选,继承自基类)
33
+ def initialize(app_version_list = nil, options = {})
34
+ # 兼容性处理:如果传入的是单个 Hash,转为数组
35
+ if app_version_list.is_a?(Hash)
36
+ @app_version_list = [app_version_list]
37
+ elsif app_version_list.is_a?(Array)
38
+ @app_version_list = app_version_list
39
+ else
40
+ @app_version_list = nil
41
+ end
42
+
43
+ @git_commit_id = options[:git_commit_id]
44
+ @git_commit_time = options[:git_commit_time]
45
+ @git_commit_desc = options[:git_commit_desc]
46
+ @project_dir = options[:project_dir]
47
+
48
+ # 设置任务优先级为 LOW,确保在上传任务之后执行
49
+ options[:priority] ||= TaskPriority::LOW
50
+
51
+ super("绑定 包到Git工作流", options)
52
+ end
53
+
54
+ def validate
55
+ # app_version_list 和 git_commit_id 可以延迟获取,不在这里验证
56
+ true
57
+ end
58
+
59
+ # 绑定任务重试配置
60
+ def self.default_retry_mode
61
+ RetryMode::DELAYED
62
+ end
63
+
64
+ def self.default_retry_count
65
+ 2 # 绑定任务重试 2 次
66
+ end
67
+
68
+ def self.default_retry_delay
69
+ 3 # 延迟 3 秒
70
+ end
71
+
72
+ protected
73
+
74
+ # 构建任务参数(供其他任务使用)
75
+ def build_task_param
76
+ return {} unless @status == TaskStatus::SUCCESS && @result
77
+
78
+ {
79
+ git_commit_id: @git_commit_id,
80
+ app_version_list: @app_version_list,
81
+ bind_success: @result[:success],
82
+ bound_package_ids: @result[:bound_package_ids]
83
+ }
84
+ end
85
+
86
+ def do_work
87
+ puts ""
88
+ puts " 📦 开始绑定 Git Commit 到项目包..."
89
+
90
+ # 1. 如果没有提供 app_version_list,从依赖任务获取
91
+ if @app_version_list.nil? || @app_version_list.empty?
92
+ fetch_app_version_from_dependencies
93
+ end
94
+
95
+ # 验证 app_version_list
96
+ if @app_version_list.nil? || @app_version_list.empty?
97
+ raise "无法获取 app_version_list,请确保传入参数或添加 JPSUploadTask 依赖"
98
+ end
99
+
100
+ # 2. 如果没有提供 git_commit_id,从依赖任务获取或自动获取
101
+ if @git_commit_id.nil? || @git_commit_id.empty?
102
+ fetch_git_commit_info
103
+ end
104
+
105
+ # 验证 git_commit_id
106
+ if @git_commit_id.nil? || @git_commit_id.empty?
107
+ raise "无法获取 git_commit_id,请确保传入参数或添加 GitCommitTask 依赖"
108
+ end
109
+
110
+ # 3. 提取所有 project_package_ids
111
+ project_package_ids = @app_version_list.map { |pkg| pkg["id"] }.compact
112
+ if project_package_ids.empty?
113
+ raise "app_version_list 中的包都缺少 id 字段"
114
+ end
115
+
116
+ # 4. 打印绑定信息
117
+ puts ""
118
+ puts " 📝 绑定信息:"
119
+ puts " Git Commit: #{@git_commit_id[0..7]}"
120
+ puts " 包数量: #{project_package_ids.size} 个"
121
+ @app_version_list.each do |pkg|
122
+ package_type = pkg['nativePackageType'] || pkg['originalType'] || 'unknown'
123
+ puts " [#{package_type}] ID: #{pkg['id']}, Version: #{pkg['projectVersion']}, Build: #{pkg['build']}"
124
+ end
125
+ if @git_commit_desc
126
+ puts " Commit Desc: #{@git_commit_desc}"
127
+ end
128
+ if @git_commit_time
129
+ puts " Commit Time: #{@git_commit_time}"
130
+ end
131
+ puts ""
132
+
133
+ # 5. 确保 PgyerHelper 已登录
134
+ pgyer_helper = PgyerHelper.share_instace
135
+ unless pgyer_helper.login
136
+ raise "无法登录 JPS,请检查配置"
137
+ end
138
+
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. 获取工作流中已绑定的包 ID
146
+ existing_bound_ids = pgyer_helper.get_workflow_bound_package_ids(workflow_id: workflow_id)
147
+
148
+ if existing_bound_ids.any?
149
+ puts " 📋 工作流中已绑定的包: #{existing_bound_ids.size} 个"
150
+ end
151
+
152
+ # 8. 合并已绑定的包 ID 和新的包 ID(去重)
153
+ merged_package_ids = (existing_bound_ids + project_package_ids).uniq
154
+
155
+ puts " 📦 合并后的包 ID 数量: #{merged_package_ids.size} 个"
156
+ if merged_package_ids.size > project_package_ids.size
157
+ puts " └─ 新增: #{project_package_ids.size} 个"
158
+ puts " └─ 已存在: #{existing_bound_ids.size} 个"
159
+ end
160
+ puts ""
161
+
162
+ # 9. 批量绑定所有包
163
+ Funlog.instance.fancyinfo_start("正在绑定 #{merged_package_ids.size} 个项目包...")
164
+
165
+ bind_result = pgyer_helper.bind_commit_to_package(
166
+ commit_id: @git_commit_id,
167
+ project_package_ids: merged_package_ids
168
+ )
169
+
170
+ if bind_result[:success]
171
+ Funlog.instance.fancyinfo_success("绑定成功!")
172
+ puts ""
173
+
174
+ {
175
+ success: true,
176
+ git_commit_id: @git_commit_id,
177
+ bound_package_ids: merged_package_ids, # 返回合并后的包 ID 列表
178
+ app_version_list: @app_version_list
179
+ }
180
+ else
181
+ if ENV['PINDO_DEBUG']
182
+ puts "[PINDO_DEBUG] bind_commit_to_package 返回结果: #{bind_result.inspect}"
183
+ puts "[PINDO_DEBUG] git_commit_id: #{@git_commit_id}"
184
+ puts "[PINDO_DEBUG] project_package_ids: #{project_package_ids.inspect}"
185
+ end
186
+
187
+ raise "绑定失败: #{bind_result[:error]}"
188
+ end
189
+ end
190
+
191
+ private
192
+
193
+ # 从依赖任务获取 app_version_list
194
+ def fetch_app_version_from_dependencies
195
+ # 获取所有 JPSUploadTask 的数据(可能有多个平台的上传任务)
196
+ all_upload_data = get_all_data_params_by_key(:jps_upload)
197
+
198
+ @app_version_list = []
199
+
200
+ # 遍历所有上传任务,收集 app_version_info
201
+ all_upload_data.each do |upload_data|
202
+ if upload_data[:task_param] && upload_data[:task_param][:app_version_info]
203
+ @app_version_list << upload_data[:task_param][:app_version_info]
204
+ end
205
+ end
206
+ end
207
+
208
+ # 从依赖任务获取或自动获取 git commit 信息
209
+ def fetch_git_commit_info
210
+ # 1. 首先尝试从 GitCommitTask 依赖任务获取
211
+ git_commit_data = get_data_param_by_key(:git_commit)
212
+ if git_commit_data && git_commit_data[:task_param]
213
+ param = git_commit_data[:task_param]
214
+ @git_commit_id = param[:git_commit_id] if param[:git_commit_id]
215
+ @git_commit_time = param[:git_commit_time] if param[:git_commit_time]
216
+ @git_commit_desc = param[:git_commit_desc] if param[:git_commit_desc]
217
+ end
218
+
219
+ # 2. 如果依赖任务没有提供,且指定了 project_dir,使用自动获取
220
+ if (@git_commit_id.nil? || @git_commit_id.empty?) && @project_dir
221
+ # 查找 git 仓库根目录
222
+ git_root = Pindo::GitHandler.git_root_directory(local_repo_dir: @project_dir)
223
+ if git_root
224
+ git_info = Pindo::GitHandler.get_latest_conventional_commit(project_dir: git_root)
225
+ @git_commit_id = git_info[:commit_id]
226
+ @git_commit_time = git_info[:commit_time]
227
+ @git_commit_desc = git_info[:commit_desc]
228
+ end
229
+ end
230
+ end
231
+ end
232
+ end
233
+ end
@@ -27,7 +27,7 @@ module Pindo
27
27
  # 消息发送任务优先级为 LOW,确保在上传任务之后执行
28
28
  options[:priority] ||= TaskPriority::LOW
29
29
 
30
- super("JPS 消息发送", options)
30
+ super("JPS 发送包的消息", options)
31
31
  end
32
32
 
33
33
  def validate
@@ -71,11 +71,14 @@ module Pindo
71
71
  # 1. 打印应用版本信息(失败只警告,不中断)
72
72
  print_version_info(pgyer_helper)
73
73
 
74
- # 2. 发送消息给自己(失败只警告,不中断)
75
- send_message_to_self(pgyer_helper)
76
-
77
- # 3. 如果消息类型为 group,发送到测试群(失败只警告,不中断)
78
- send_message_to_group(pgyer_helper) if @send_message_type == 'group'
74
+ # 2. 根据消息类型发送消息(失败只警告,不中断)
75
+ if @send_message_type == 'group'
76
+ # 发送到测试群
77
+ send_message_to_group(pgyer_helper)
78
+ else
79
+ # 发送消息给自己
80
+ send_message_to_self(pgyer_helper)
81
+ end
79
82
 
80
83
  puts " ✅ JPS 消息发送全部完成\n"
81
84
 
@@ -7,22 +7,27 @@ module Pindo
7
7
  # JPS 重签名任务
8
8
  # 从 JPS 平台下载应用并使用指定证书重签名
9
9
  class JPSResignTask < JPSTask
10
- attr_reader :version_info, :cert_id, :send_flag
10
+ attr_reader :version_info, :cert_id
11
11
 
12
12
  # 重试配置(降低重试次数)
13
13
  def self.default_retry_count
14
14
  2 # 默认可以重试 2 次
15
15
  end
16
16
 
17
+ # 任务键
18
+ def self.task_key
19
+ :jps_resign
20
+ end
21
+
17
22
  # 初始化 JPS 重签名任务
18
23
  # @param options [Hash] 选项
19
24
  # @option options [Hash] :app_info_obj JPS 应用信息对象(可选,如为 nil 则延迟获取)
20
25
  # @option options [String] :project_name 项目名称(可选)
21
26
  # @option options [String] :cert_id 重签名使用的 Bundle ID(可选,nil 表示交互选择)
22
- # @option options [Boolean] :send_flag 是否发送到测试群(默认 false,始终会发送给自己)
27
+ # @option options [Boolean] :list_flag 是否列出历史版本(默认 false
23
28
  def initialize(options = {})
24
29
  @cert_id = options[:cert_id]
25
- @send_flag = options[:send_flag] || false
30
+ @list_flag = options[:list_flag] || false
26
31
  @version_info = nil
27
32
 
28
33
  # 设置重签名任务的优先级为 LOW,确保在上传任务之后执行
@@ -38,6 +43,16 @@ module Pindo
38
43
 
39
44
  protected
40
45
 
46
+ # 构建任务参数(供其他任务使用)
47
+ def build_task_param
48
+ return {} unless @status == TaskStatus::SUCCESS && @version_info
49
+
50
+ {
51
+ app_version_info: @version_info,
52
+ cert_id: @cert_id
53
+ }
54
+ end
55
+
41
56
  def do_work
42
57
  pgyer_helper = PgyerHelper.share_instace
43
58
 
@@ -49,7 +64,7 @@ module Pindo
49
64
  # 2. 获取要重签名的版本
50
65
  @version_info = pgyer_helper.get_versioon_history_item(
51
66
  app_info_obj: @app_info_obj,
52
- list_select_flat: false
67
+ list_select_flat: @list_flag # 使用 list_flag
53
68
  )
54
69
 
55
70
  if @version_info.nil?
@@ -99,23 +114,7 @@ module Pindo
99
114
  app_version_info_obj: @version_info
100
115
  )
101
116
 
102
- # 8. 发送消息给自己
103
- pgyer_helper.send_apptest_msg(
104
- app_info_obj: @app_info_obj,
105
- app_version_info_obj: @version_info,
106
- receiveType: "self"
107
- )
108
-
109
- # 9. 如果需要发送到测试群
110
- if @send_flag
111
- pgyer_helper.send_apptest_msg(
112
- app_info_obj: @app_info_obj,
113
- app_version_info_obj: @version_info,
114
- chatEnv: "DevTest",
115
- receiveType: "chat"
116
- )
117
- end
118
-
117
+ # 8. 返回结果(消息发送由外部任务处理)
119
118
  {
120
119
  success: true,
121
120
  version_info: @version_info,
@@ -43,7 +43,7 @@ module Pindo
43
43
  # 设置任务优先级为 LOW,确保在其他任务之后执行
44
44
  options[:priority] ||= TaskPriority::LOW
45
45
 
46
- name = "上传 Media 附件"
46
+ name = "上传 工作流的图片/视频"
47
47
 
48
48
  super(name, options)
49
49
  end
@@ -90,17 +90,30 @@ module Pindo
90
90
 
91
91
  def do_work
92
92
  # 1. 查找 git 仓库根目录
93
- git_root = find_git_root(@upload_path)
93
+ git_root = Pindo::GitHandler.git_root_directory(local_repo_dir: @upload_path)
94
94
  unless git_root
95
95
  raise "未找到 git 仓库,请确保 upload_path 在 git 仓库内"
96
96
  end
97
97
 
98
- # 2. 如果没有提供 git_commit_id,获取最新的符合规范的 commit
98
+ # 2. 如果没有提供 git_commit_id,尝试从依赖任务获取或自动获取
99
99
  if @git_commit_id.nil? || @git_commit_id.empty?
100
- git_info = Pindo::GitHandler.get_latest_conventional_commit(project_dir: git_root)
101
- @git_commit_id = git_info[:commit_id]
102
- @git_commit_time = git_info[:commit_time]
103
- @git_commit_desc = git_info[:commit_desc]
100
+ # 2.1 首先尝试从 GitCommitTask 依赖任务获取
101
+ git_commit_data = get_data_param_by_key(:git_commit)
102
+ if git_commit_data && git_commit_data[:task_param]
103
+ param = git_commit_data[:task_param]
104
+ # 尝试从 task_param 获取 commit 信息
105
+ @git_commit_id = param[:git_commit_id] if param[:git_commit_id]
106
+ @git_commit_time = param[:git_commit_time] if param[:git_commit_time]
107
+ @git_commit_desc = param[:git_commit_desc] if param[:git_commit_desc]
108
+ end
109
+
110
+ # 2.2 如果依赖任务没有提供,使用 get_latest_conventional_commit
111
+ if @git_commit_id.nil? || @git_commit_id.empty?
112
+ git_info = Pindo::GitHandler.get_latest_conventional_commit(project_dir: git_root)
113
+ @git_commit_id = git_info[:commit_id]
114
+ @git_commit_time = git_info[:commit_time]
115
+ @git_commit_desc = git_info[:commit_desc]
116
+ end
104
117
  end
105
118
 
106
119
  # 验证 git_commit_id
@@ -110,8 +123,8 @@ module Pindo
110
123
 
111
124
  # 3. 打印 git commit 信息
112
125
  puts ""
113
- puts " 📝 Commit: #{@git_commit_desc}" if @git_commit_desc
114
126
  puts " ID: #{@git_commit_id[0..7]}"
127
+ puts " 📝 Commit: #{@git_commit_desc}" if @git_commit_desc
115
128
  puts " Time: #{@git_commit_time}" if @git_commit_time
116
129
  puts ""
117
130
 
@@ -124,6 +137,9 @@ module Pindo
124
137
  @file_paths = expand_file_paths(@file_paths)
125
138
  end
126
139
 
140
+ # 保存源文件列表(用于上传成功后归档)
141
+ original_source_files = @file_paths.dup
142
+
127
143
  # 5. 自动压缩文件(如果有文件需要上传)
128
144
  if @file_paths.any?
129
145
  @file_paths = compress_media_files(@file_paths, git_root)
@@ -171,6 +187,13 @@ module Pindo
171
187
  # 上传成功后,将重试次数设为 0
172
188
  @retry_count = 0
173
189
 
190
+ # 8. 上传成功后,将源文件移动到备份目录
191
+ # 移动的是压缩前的原始文件,而不是压缩后的临时文件
192
+ # 这样可以避免下次编译时重复压缩和上传
193
+ if original_source_files.any?
194
+ move_uploaded_files_to_backup(original_source_files)
195
+ end
196
+
174
197
  {
175
198
  success: true,
176
199
  success_urls: upload_result[:success_urls],
@@ -192,20 +215,6 @@ module Pindo
192
215
 
193
216
  private
194
217
 
195
- # 查找 git 仓库根目录
196
- # @param path [String] 起始路径
197
- # @return [String, nil] git 仓库根目录路径,未找到返回 nil
198
- def find_git_root(path)
199
- current = File.expand_path(path)
200
- while current != '/'
201
- if File.exist?(File.join(current, '.git'))
202
- return current
203
- end
204
- current = File.dirname(current)
205
- end
206
- nil
207
- end
208
-
209
218
  # 展开文件路径(支持通配符和目录)
210
219
  # 自动过滤 3 小时以内的文件,超过 3 小时的文件归档
211
220
  # @param paths [Array<String>] 原始路径列表
@@ -248,6 +257,30 @@ module Pindo
248
257
 
249
258
  puts " 📦 归档 #{files.size} 个超时文件 → JPSMedia/#{backup_dir_name}/"
250
259
 
260
+ move_files_to_backup(files, backup_dir_name)
261
+ end
262
+
263
+ # 将已上传文件移动到备份目录
264
+ # @param files [Array<String>] 要移动的文件列表
265
+ def move_uploaded_files_to_backup(files)
266
+ return if files.empty?
267
+
268
+ # 备份目录名:backup_YYYY-MM-DD_HHMMSS
269
+ backup_dir_name = "backup_#{Time.now.strftime('%Y-%m-%d_%H%M%S')}"
270
+
271
+ puts ""
272
+ puts " 📦 归档 #{files.size} 个已上传文件 → JPSMedia/#{backup_dir_name}/"
273
+ puts ""
274
+
275
+ move_files_to_backup(files, backup_dir_name)
276
+ end
277
+
278
+ # 移动文件到备份目录(通用方法)
279
+ # @param files [Array<String>] 要移动的文件列表
280
+ # @param backup_dir_name [String] 备份目录名称
281
+ def move_files_to_backup(files, backup_dir_name)
282
+ return if files.empty?
283
+
251
284
  files.each do |file_path|
252
285
  begin
253
286
  # 在文件所在目录下创建备份子目录
@@ -278,6 +311,8 @@ module Pindo
278
311
  puts " ✗ #{file_name} - #{e.message}"
279
312
  end
280
313
  end
314
+
315
+ puts ""
281
316
  end
282
317
 
283
318
  # 在 JPSMedia 目录下查找 media 文件(仅查找根目录,不递归子目录)
@@ -34,13 +34,13 @@ module Pindo
34
34
 
35
35
  name = case file_type
36
36
  when 'ipa'
37
- "上传 IPA"
37
+ "上传 IPA"
38
38
  when 'apk'
39
- "上传 APK"
39
+ "上传 APK"
40
40
  when 'html'
41
- "上传 WebGL"
41
+ "上传 WebGL"
42
42
  when 'app'
43
- "上传 macOS App"
43
+ "上传 macOS App"
44
44
  else
45
45
  "上传 #{file_type.upcase}"
46
46
  end
@@ -0,0 +1,190 @@
1
+ require 'pindo/module/task/model/jps_task'
2
+ require 'pindo/module/task/task_config'
3
+ require 'pindo/module/pgyer/pgyerhelper'
4
+
5
+ module Pindo
6
+ module TaskSystem
7
+ # JPS 工作流消息发送任务
8
+ # 使用 commit_log/send_message 接口发送 Git commit 消息到工作流
9
+ class JPSWorkFlowMessageTask < JPSTask
10
+ attr_reader :git_commit_id, :git_commit_time, :git_commit_desc
11
+ attr_reader :project_id, :workflow_id, :branch
12
+
13
+ # 任务键
14
+ def self.task_key
15
+ :jps_workflow_message
16
+ end
17
+
18
+ # 初始化工作流消息发送任务
19
+ # @param options [Hash] 选项
20
+ # @option options [String] :git_commit_id Git commit SHA(可选,从依赖任务获取)
21
+ # @option options [String] :git_commit_time Git commit 时间(可选)
22
+ # @option options [String] :git_commit_desc Git commit 描述(可选)
23
+ # @option options [String] :project_id 项目 ID(可选,从 app_info_obj 获取)
24
+ # @option options [Integer] :workflow_id 工作流 ID(可选,从 workflow_info 获取)
25
+ # @option options [String] :branch 分支名(可选,默认 'master')
26
+ # @option options [Boolean] :single 是否单个提交(默认 true)
27
+ # @option options [Hash] :app_info_obj JPS 应用信息对象(可选,用于获取 project_id)
28
+ # @option options [Hash] :workflow_info 工作流信息(可选,用于获取 workflow_id)
29
+ def initialize(options = {})
30
+ @git_commit_id = options[:git_commit_id]
31
+ @git_commit_time = options[:git_commit_time]
32
+ @git_commit_desc = options[:git_commit_desc]
33
+ @project_id = options[:project_id]
34
+ @workflow_id = options[:workflow_id]
35
+ @branch = options[:branch] || 'master'
36
+ @single = options.fetch(:single, true)
37
+
38
+ # 消息发送任务优先级为 LOW,确保在其他任务之后执行
39
+ options[:priority] ||= TaskPriority::LOW
40
+
41
+ super("JPS 发送工作流消息", options)
42
+ end
43
+
44
+ def validate
45
+ # 参数可以从依赖任务获取,这里不做严格验证
46
+ true
47
+ end
48
+
49
+ protected
50
+
51
+ def do_work
52
+ puts "\n 📋 开始发送 JPS 工作流消息..."
53
+
54
+ begin
55
+ # 1. 如果没有提供参数,从依赖任务获取
56
+ fetch_data_from_dependencies if need_fetch_dependencies?
57
+
58
+ # 2. 验证必需参数
59
+ validate_required_params!
60
+
61
+ # 3. 发送消息
62
+ send_workflow_message
63
+
64
+ puts " ✅ JPS 工作流消息发送完成\n"
65
+
66
+ {
67
+ success: true,
68
+ git_commit_id: @git_commit_id,
69
+ project_id: @project_id,
70
+ workflow_id: @workflow_id
71
+ }
72
+ rescue => e
73
+ # 外层错误保护:消息发送失败不应影响整体流程
74
+ puts " ⚠️ JPS 工作流消息发送发生错误: #{e.message}"
75
+ puts " ⚠️ 错误堆栈: #{e.backtrace.first(3).join("\n ")}" if ENV['PINDO_DEBUG'] && e.backtrace
76
+ puts " ℹ️ 消息发送失败不影响主流程\n"
77
+
78
+ # 消息发送失败不抛出异常,返回成功但带警告
79
+ {
80
+ success: true,
81
+ warning: e.message,
82
+ git_commit_id: @git_commit_id
83
+ }
84
+ end
85
+ end
86
+
87
+ private
88
+
89
+ # 判断是否需要从依赖任务获取数据
90
+ def need_fetch_dependencies?
91
+ @git_commit_id.nil? || @project_id.nil? || @workflow_id.nil?
92
+ end
93
+
94
+ # 从依赖任务获取数据
95
+ def fetch_data_from_dependencies
96
+ # 1. 从 GitCommitTask 获取 commit 信息
97
+ if @git_commit_id.nil?
98
+ git_commit_data = get_data_param_by_key(:git_commit)
99
+ if git_commit_data && git_commit_data[:task_param]
100
+ param = git_commit_data[:task_param]
101
+ @git_commit_id = param[:git_commit_id] if param[:git_commit_id]
102
+ @git_commit_time = param[:git_commit_time] if param[:git_commit_time]
103
+ @git_commit_desc = param[:git_commit_desc] if param[:git_commit_desc]
104
+ end
105
+ end
106
+
107
+ # 2. 从 JPSUploadTask 获取 project_id 和 workflow_id
108
+ if @project_id.nil? || @workflow_id.nil?
109
+ upload_data = get_data_param_by_key(:jps_upload)
110
+ if upload_data && upload_data[:task_param]
111
+ param = upload_data[:task_param]
112
+
113
+ # 从 app_info_obj 获取 project_id
114
+ if @project_id.nil? && param[:app_info_obj]
115
+ @project_id = param[:app_info_obj]["id"] || param[:app_info_obj][:id]
116
+ end
117
+
118
+ # 从 workflow_info 获取 workflow_id
119
+ if @workflow_id.nil? && param[:workflow_info]
120
+ @workflow_id = param[:workflow_info]["id"] ||
121
+ param[:workflow_info][:id] ||
122
+ param[:workflow_info]["workflow_id"] ||
123
+ param[:workflow_info][:workflow_id]
124
+ end
125
+ end
126
+ end
127
+
128
+ # 3. 如果还没有,尝试从 app_info_obj 和 workflow_info(基类属性)获取
129
+ if @project_id.nil? && @app_info_obj
130
+ @project_id = @app_info_obj["id"] || @app_info_obj[:id]
131
+ end
132
+
133
+ if @workflow_id.nil? && @workflow_info
134
+ @workflow_id = @workflow_info["id"] ||
135
+ @workflow_info[:id] ||
136
+ @workflow_info["workflow_id"] ||
137
+ @workflow_info[:workflow_id]
138
+ end
139
+ end
140
+
141
+ # 验证必需参数
142
+ def validate_required_params!
143
+ missing_params = []
144
+ missing_params << "git_commit_id" if @git_commit_id.nil? || @git_commit_id.empty?
145
+ missing_params << "project_id" if @project_id.nil? || @project_id.empty?
146
+ missing_params << "workflow_id" if @workflow_id.nil?
147
+
148
+ unless missing_params.empty?
149
+ raise "缺少必需参数: #{missing_params.join(', ')}"
150
+ end
151
+ end
152
+
153
+ # 发送工作流消息
154
+ def send_workflow_message
155
+ puts " 📨 发送工作流消息..."
156
+ puts " Project ID: #{@project_id}"
157
+ puts " Workflow ID: #{@workflow_id}"
158
+ puts " Commit ID: #{@git_commit_id[0..7]}" if @git_commit_id
159
+ puts " Branch: #{@branch}"
160
+ puts ""
161
+
162
+ pgyer_helper = PgyerHelper.share_instace
163
+
164
+ # 确保已登录
165
+ unless pgyer_helper.login
166
+ raise "无法登录 JPS,请检查配置"
167
+ end
168
+
169
+ # 使用 PgyerHelper 的便捷方法发送工作流消息
170
+ result = pgyer_helper.send_workflow_message(
171
+ project_id: @project_id,
172
+ workflow_id: @workflow_id,
173
+ commit_id: @git_commit_id,
174
+ branch: @branch,
175
+ single: @single
176
+ )
177
+
178
+ if result[:success]
179
+ puts " ✓ 工作流消息发送成功"
180
+ else
181
+ if ENV['PINDO_DEBUG']
182
+ puts "[PINDO_DEBUG] send_workflow_message 返回结果: #{result.inspect}"
183
+ end
184
+
185
+ raise "工作流消息发送失败: #{result[:error]}"
186
+ end
187
+ end
188
+ end
189
+ end
190
+ end