pindo 5.14.8 → 5.15.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/pindo/base/aeshelper.rb +53 -22
- data/lib/pindo/base/git_handler.rb +243 -22
- data/lib/pindo/client/giteeclient.rb +15 -6
- data/lib/pindo/command/android/autobuild.rb +7 -5
- data/lib/pindo/command/appstore/autobuild.rb +5 -2
- data/lib/pindo/command/appstore/cert.rb +6 -0
- data/lib/pindo/command/ios/autobuild.rb +31 -21
- data/lib/pindo/command/ios/cert.rb +1 -1
- data/lib/pindo/command/jps/apptest.rb +1 -1
- data/lib/pindo/command/jps/bind.rb +6 -2
- data/lib/pindo/command/jps/media.rb +6 -2
- data/lib/pindo/command/jps/upload.rb +6 -4
- data/lib/pindo/command/repo/clone.rb +110 -32
- data/lib/pindo/command/repo/subgit.rb +91 -0
- data/lib/pindo/command/repo.rb +1 -0
- data/lib/pindo/command/unity/autobuild.rb +6 -4
- data/lib/pindo/command/unity/packbuild.rb +14 -7
- data/lib/pindo/command/utils/tag.rb +5 -3
- data/lib/pindo/command/web/autobuild.rb +7 -5
- data/lib/pindo/command.rb +1 -1
- data/lib/pindo/config/build_info_manager.rb +37 -14
- data/lib/pindo/module/appstore/bundleid_helper.rb +7 -3
- data/lib/pindo/module/build/git_repo_helper.rb +1 -14
- data/lib/pindo/module/cert/cert_helper.rb +33 -9
- data/lib/pindo/module/cert/xcode_cert_helper.rb +17 -7
- data/lib/pindo/module/pgyer/pgyerhelper.rb +110 -22
- data/lib/pindo/module/task/model/git/git_commit_task.rb +106 -6
- data/lib/pindo/module/task/model/git/git_tag_task.rb +17 -7
- data/lib/pindo/module/task/model/jps/jps_upload_media_task.rb +13 -8
- data/lib/pindo/module/task/model/resign/ipa_local_resign_task.rb +5 -0
- data/lib/pindo/options/core/option_item.rb +4 -5
- data/lib/pindo/options/groups/git_options.rb +40 -0
- data/lib/pindo/options/helpers/git_constants.rb +28 -0
- data/lib/pindo/version.rb +1 -1
- metadata +7 -5
|
@@ -32,13 +32,17 @@ module Pindo
|
|
|
32
32
|
config_info[:bundle_id_extensionad] = app_info['app_identifier_extensionad']
|
|
33
33
|
config_info[:bundle_id_watchapp] = app_info['app_identifier_watchapp']
|
|
34
34
|
config_info[:bundle_id_watchapp_extension] = app_info['app_identifier_watchapp_extension']
|
|
35
|
+
|
|
36
|
+
# 从 app_info 提取 app_group_id(优先)
|
|
37
|
+
config_info[:group_id] = app_info['app_group_id']
|
|
38
|
+
config_info[:icloud_id] = app_info['app_icloud_id']
|
|
35
39
|
end
|
|
36
40
|
|
|
37
|
-
#
|
|
41
|
+
# 从 app_setting 提取(如果 app_info 中没有,则使用这里的配置)
|
|
38
42
|
if config_json['app_setting']
|
|
39
43
|
app_setting = config_json['app_setting']
|
|
40
|
-
config_info[:group_id]
|
|
41
|
-
config_info[:icloud_id]
|
|
44
|
+
config_info[:group_id] ||= app_setting['app_group_id']
|
|
45
|
+
config_info[:icloud_id] ||= app_setting['app_icloud_id']
|
|
42
46
|
end
|
|
43
47
|
|
|
44
48
|
config_info
|
|
@@ -2,22 +2,9 @@ require 'singleton'
|
|
|
2
2
|
require 'pindo/base/git_handler'
|
|
3
3
|
require 'pindo/base/executable'
|
|
4
4
|
require 'highline/import'
|
|
5
|
+
require 'pindo/options/helpers/git_constants'
|
|
5
6
|
|
|
6
7
|
module Pindo
|
|
7
|
-
# 版本号增加类型常量(与 GitOptions::VERSION_INCREASE_TYPES 一致)
|
|
8
|
-
module VersionIncreaseType
|
|
9
|
-
MAIN = :main # 大版本号增加1 (x.0.0)
|
|
10
|
-
MINI = :mini # 小版本号增加1 (0.x.0)
|
|
11
|
-
PATCH = :patch # patch版本号增加1 (0.0.x)
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
# 创建Tag类型常量(与 GitOptions::CREATE_TAG_TYPES 一致)
|
|
15
|
-
module CreateTagType
|
|
16
|
-
NEW = :new # 创建新的tag,新的版本号
|
|
17
|
-
RECREATE = :recreate # 重新创建当前版本号
|
|
18
|
-
NONE = :none # 不创建版本号
|
|
19
|
-
end
|
|
20
|
-
|
|
21
8
|
class GitRepoHelper
|
|
22
9
|
include Singleton
|
|
23
10
|
|
|
@@ -189,20 +189,29 @@ module Pindo
|
|
|
189
189
|
decrypt_password = CertHelper.get_cached_password(cert_url)
|
|
190
190
|
Funlog.instance.fancyinfo_start("正在安装证书...")
|
|
191
191
|
|
|
192
|
-
|
|
193
|
-
|
|
192
|
+
begin
|
|
193
|
+
cert_path = AESHelper.decrypt_specific_file(src_file: certs.first, password:decrypt_password, output_dir: output_dir)
|
|
194
|
+
rescue Informative => e
|
|
194
195
|
AESHelper.delete_password(keychain_name:cert_url)
|
|
195
|
-
# 清除内存中的密码缓存,避免重复使用错误密码
|
|
196
196
|
@@password_cache.delete(cert_url)
|
|
197
|
-
raise Informative, "
|
|
197
|
+
raise Informative, "证书解析失败,已清除错误的密码,请重新运行输入正确的密码"
|
|
198
198
|
end
|
|
199
199
|
|
|
200
|
-
|
|
201
|
-
|
|
200
|
+
begin
|
|
201
|
+
key_path = AESHelper.decrypt_specific_file(src_file: keys.first, password:decrypt_password, output_dir: output_dir)
|
|
202
|
+
rescue Informative => e
|
|
202
203
|
AESHelper.delete_password(keychain_name:cert_url)
|
|
203
|
-
# 清除内存中的密码缓存,避免重复使用错误密码
|
|
204
204
|
@@password_cache.delete(cert_url)
|
|
205
|
-
raise Informative, "
|
|
205
|
+
raise Informative, "密钥解析失败,已清除错误的密码,请重新运行输入正确的密码"
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
# 解密成功,保存密码到 Keychain
|
|
209
|
+
begin
|
|
210
|
+
AESHelper.store_password(keychain_name: cert_url, password: decrypt_password)
|
|
211
|
+
Funlog.instance.fancyinfo_success("证书解密成功,密码已保存到Keychain")
|
|
212
|
+
rescue => e
|
|
213
|
+
Funlog.instance.fancyinfo_error("密码保存到Keychain失败: #{e.message}")
|
|
214
|
+
Funlog.instance.fancyinfo_error("下次使用时需要重新输入密码")
|
|
206
215
|
end
|
|
207
216
|
|
|
208
217
|
unless is_cert_valid?(cert_path)
|
|
@@ -272,9 +281,12 @@ module Pindo
|
|
|
272
281
|
un_exist_files = []
|
|
273
282
|
provisioning_info_array = []
|
|
274
283
|
|
|
275
|
-
#
|
|
284
|
+
# 在循环外获取密码
|
|
276
285
|
decrypt_password = CertHelper.get_cached_password(cert_url)
|
|
277
286
|
|
|
287
|
+
# 标记是否已成功解密(用于判断是否保存密码)
|
|
288
|
+
decrypt_success = false
|
|
289
|
+
|
|
278
290
|
bundle_id_map.each do |type, bundle_id_temp|
|
|
279
291
|
profile_filename = File.join(certs_dir, "profiles", cert_sub_dir, [provision_start_name.to_s, bundle_id_temp].join('_') + provision_extension_name)
|
|
280
292
|
unless File.exist?(profile_filename)
|
|
@@ -284,6 +296,7 @@ module Pindo
|
|
|
284
296
|
# puts "正在安装 #{bundle_id_temp}..."
|
|
285
297
|
output_dir = Dir.mktmpdir
|
|
286
298
|
file_decrypt = AESHelper.decrypt_specific_file(src_file: profile_filename, password:decrypt_password, output_dir: output_dir)
|
|
299
|
+
decrypt_success = true # 标记至少有一个文件解密成功
|
|
287
300
|
destpath = Provisioninghelper.install(file_decrypt)
|
|
288
301
|
parsed_data = Provisioninghelper.parse(destpath)
|
|
289
302
|
|
|
@@ -301,6 +314,17 @@ module Pindo
|
|
|
301
314
|
provisioning_info_array << provisioning_info
|
|
302
315
|
end
|
|
303
316
|
|
|
317
|
+
# 如果有文件解密成功,保存密码到 Keychain
|
|
318
|
+
if decrypt_success
|
|
319
|
+
begin
|
|
320
|
+
AESHelper.store_password(keychain_name: cert_url, password: decrypt_password)
|
|
321
|
+
Funlog.instance.fancyinfo_success("Provisioning Profile 解密成功,密码已保存到Keychain")
|
|
322
|
+
rescue => e
|
|
323
|
+
Funlog.instance.fancyinfo_error("密码保存到Keychain失败: #{e.message}")
|
|
324
|
+
Funlog.instance.fancyinfo_error("下次使用时需要重新输入密码")
|
|
325
|
+
end
|
|
326
|
+
end
|
|
327
|
+
|
|
304
328
|
Funlog.instance.fancyinfo_success("#{provision_start_name} #{platform_type} Provisioning Profiles文件安装完成!")
|
|
305
329
|
|
|
306
330
|
if un_exist_files.size > 0
|
|
@@ -504,15 +504,25 @@ module Pindo
|
|
|
504
504
|
certs_dir = Pindo::GitHandler.getcode_to_dir(reponame:cert_reponame, remote_url:cert_git_url, path: pindo_single_config.pindo_dir, new_branch:apple_id)
|
|
505
505
|
|
|
506
506
|
|
|
507
|
-
keys = Dir[File.join(certs_dir, "certs", cert_sub_dir, "*.p12")]
|
|
507
|
+
keys = Dir[File.join(certs_dir, "certs", cert_sub_dir, "*.p12")]
|
|
508
508
|
decrypt_password = Pindo::CertHelper.get_cached_password(cert_git_url)
|
|
509
509
|
output_dir = Dir.mktmpdir
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
510
|
+
begin
|
|
511
|
+
key_path = AESHelper.decrypt_specific_file(src_file: keys.first, password:decrypt_password, output_dir: output_dir)
|
|
512
|
+
rescue Informative => e
|
|
513
|
+
AESHelper.delete_password(keychain_name:cert_git_url)
|
|
514
|
+
# 清除内存中的密码缓存,避免重复使用错误密码
|
|
515
|
+
Pindo::CertHelper.clear_password_cache_for_url(cert_git_url)
|
|
516
|
+
raise Informative, "密钥解析失败,已清除错误的密码,请重新运行输入正确的密码"
|
|
517
|
+
end
|
|
518
|
+
|
|
519
|
+
# 解密成功,保存密码到 Keychain
|
|
520
|
+
begin
|
|
521
|
+
AESHelper.store_password(keychain_name: cert_git_url, password: decrypt_password)
|
|
522
|
+
Funlog.instance.fancyinfo_success("密钥解密成功,密码已保存到Keychain")
|
|
523
|
+
rescue => e
|
|
524
|
+
Funlog.instance.fancyinfo_error("密码保存到Keychain失败: #{e.message}")
|
|
525
|
+
Funlog.instance.fancyinfo_error("下次使用时需要重新输入密码")
|
|
516
526
|
end
|
|
517
527
|
|
|
518
528
|
FileUtils.copy(key_path, File.join(cert_dest_dir, "#{cert_type_temp}.p12"))
|
|
@@ -56,6 +56,13 @@ module Pindo
|
|
|
56
56
|
# - project_id [String] 项目ID
|
|
57
57
|
# - workflow_info [Hash] 工作流信息(如果有效)
|
|
58
58
|
def try_load_jps_build_config(working_directory:, package_type:, manage_type: "")
|
|
59
|
+
if ENV['PINDO_DEBUG']
|
|
60
|
+
puts "\n[PINDO_DEBUG] try_load_jps_build_config 调用:"
|
|
61
|
+
puts " working_directory: #{working_directory}"
|
|
62
|
+
puts " package_type: #{package_type.inspect}"
|
|
63
|
+
puts " manage_type: #{manage_type.inspect}"
|
|
64
|
+
end
|
|
65
|
+
|
|
59
66
|
result = {
|
|
60
67
|
valid: false,
|
|
61
68
|
project_name: nil,
|
|
@@ -66,15 +73,23 @@ module Pindo
|
|
|
66
73
|
# 1. 确定配置文件路径
|
|
67
74
|
config_file = determine_config_file_path(working_directory)
|
|
68
75
|
|
|
76
|
+
if ENV['PINDO_DEBUG']
|
|
77
|
+
puts "[PINDO_DEBUG] 配置文件路径: #{config_file}"
|
|
78
|
+
puts "[PINDO_DEBUG] 文件存在: #{File.exist?(config_file)}"
|
|
79
|
+
end
|
|
80
|
+
|
|
69
81
|
unless File.exist?(config_file)
|
|
70
|
-
puts "[
|
|
82
|
+
puts "[PINDO_DEBUG] ❌ 配置文件不存在,返回 valid=false" if ENV['PINDO_DEBUG']
|
|
83
|
+
puts "[JPSConfig] 配置文件不存在" if ENV['PINDO_DEBUG']
|
|
71
84
|
return result
|
|
72
85
|
end
|
|
73
86
|
|
|
74
87
|
# 2. 读取并解析配置
|
|
75
88
|
begin
|
|
76
89
|
config = JSON.parse(File.read(config_file))
|
|
90
|
+
puts "[PINDO_DEBUG] ✓ 配置文件解析成功" if ENV['PINDO_DEBUG']
|
|
77
91
|
rescue => e
|
|
92
|
+
puts "[PINDO_DEBUG] ❌ 配置文件解析失败: #{e.message}" if ENV['PINDO_DEBUG']
|
|
78
93
|
puts "[JPSConfig] 配置文件解析失败: #{e.message}"
|
|
79
94
|
return result
|
|
80
95
|
end
|
|
@@ -83,9 +98,17 @@ module Pindo
|
|
|
83
98
|
result[:project_name] = config['project_name']
|
|
84
99
|
result[:project_id] = config['project_id']
|
|
85
100
|
|
|
101
|
+
if ENV['PINDO_DEBUG']
|
|
102
|
+
puts "[PINDO_DEBUG] 配置文件内容:"
|
|
103
|
+
puts " project_name: #{result[:project_name].inspect}"
|
|
104
|
+
puts " project_id: #{result[:project_id].inspect}"
|
|
105
|
+
puts " 配置keys: #{config.keys.inspect}"
|
|
106
|
+
end
|
|
107
|
+
|
|
86
108
|
# 4. 验证项目ID
|
|
87
109
|
if result[:project_id].nil? || result[:project_id].to_s.empty?
|
|
88
|
-
puts "[
|
|
110
|
+
puts "[PINDO_DEBUG] ❌ 项目ID为空,返回 valid=false" if ENV['PINDO_DEBUG']
|
|
111
|
+
puts "[JPSConfig] 项目ID为空" if ENV['PINDO_DEBUG']
|
|
89
112
|
return result
|
|
90
113
|
end
|
|
91
114
|
|
|
@@ -95,7 +118,8 @@ module Pindo
|
|
|
95
118
|
if manage_type == "git"
|
|
96
119
|
# manage_type 为 git 时,直接使用 git_workflow
|
|
97
120
|
workflow_key = 'git_workflow'
|
|
98
|
-
puts "[
|
|
121
|
+
puts "[PINDO_DEBUG] ✓ manage_type=git,使用 workflow_key='git_workflow'" if ENV['PINDO_DEBUG']
|
|
122
|
+
puts "[JPSConfig] 使用 git_workflow 配置" if ENV['PINDO_DEBUG']
|
|
99
123
|
else
|
|
100
124
|
# 按 package_type 查找
|
|
101
125
|
workflow_key = case package_type
|
|
@@ -105,16 +129,25 @@ module Pindo
|
|
|
105
129
|
when 'app' then 'macos_workflow'
|
|
106
130
|
when 'exe' then 'win_workflow'
|
|
107
131
|
else
|
|
132
|
+
puts "[PINDO_DEBUG] ❌ 不支持的 package_type: #{package_type}" if ENV['PINDO_DEBUG']
|
|
108
133
|
puts "[JPSConfig] 不支持的 package_type: #{package_type}"
|
|
109
134
|
return result
|
|
110
135
|
end
|
|
136
|
+
puts "[PINDO_DEBUG] package_type=#{package_type},使用 workflow_key='#{workflow_key}'" if ENV['PINDO_DEBUG']
|
|
111
137
|
end
|
|
112
138
|
|
|
113
139
|
# 6. 验证工作流配置
|
|
114
140
|
workflow = config[workflow_key]
|
|
115
141
|
|
|
142
|
+
if ENV['PINDO_DEBUG']
|
|
143
|
+
puts "[PINDO_DEBUG] 查找 workflow_key='#{workflow_key}'"
|
|
144
|
+
puts "[PINDO_DEBUG] workflow 存在: #{!workflow.nil?}"
|
|
145
|
+
puts "[PINDO_DEBUG] workflow 内容: #{workflow.inspect}" if workflow
|
|
146
|
+
end
|
|
147
|
+
|
|
116
148
|
unless workflow_valid?(workflow)
|
|
117
|
-
puts "[
|
|
149
|
+
puts "[PINDO_DEBUG] ❌ #{workflow_key} 配置无效或不完整,返回 valid=false" if ENV['PINDO_DEBUG']
|
|
150
|
+
puts "[JPSConfig] #{workflow_key} 配置无效或不完整" if ENV['PINDO_DEBUG']
|
|
118
151
|
return result
|
|
119
152
|
end
|
|
120
153
|
|
|
@@ -128,7 +161,14 @@ module Pindo
|
|
|
128
161
|
manage_type: workflow['manage_type'] || ""
|
|
129
162
|
}
|
|
130
163
|
|
|
131
|
-
|
|
164
|
+
if ENV['PINDO_DEBUG']
|
|
165
|
+
puts "[PINDO_DEBUG] ✓✓✓ 配置验证通过 (#{workflow_key})"
|
|
166
|
+
puts "[PINDO_DEBUG] 返回 valid=true,workflow_info:"
|
|
167
|
+
puts " workflow_id: #{result[:workflow_info][:workflow_id]}"
|
|
168
|
+
puts " tab_name: #{result[:workflow_info][:tab_name]}"
|
|
169
|
+
puts " manage_type: #{result[:workflow_info][:manage_type]}"
|
|
170
|
+
end
|
|
171
|
+
puts "[JPSConfig] 配置验证通过 (#{workflow_key})" if ENV['PINDO_DEBUG']
|
|
132
172
|
return result
|
|
133
173
|
end
|
|
134
174
|
|
|
@@ -204,7 +244,12 @@ module Pindo
|
|
|
204
244
|
|
|
205
245
|
if display_workflows.empty?
|
|
206
246
|
# 情况1: 没有匹配的工作流
|
|
207
|
-
|
|
247
|
+
error_msg = if manage_type == "git"
|
|
248
|
+
"没有找到匹配 #{type_desc} 的工作流,请在 JPS 后台创建 Git 类型工作流(项目ID: #{project_id})"
|
|
249
|
+
else
|
|
250
|
+
"没有找到匹配 #{type_desc} 的工作流,请在 JPS 后台配置(项目ID: #{project_id})"
|
|
251
|
+
end
|
|
252
|
+
raise Informative, error_msg
|
|
208
253
|
|
|
209
254
|
elsif display_workflows.size == 1
|
|
210
255
|
# 情况2: 只有1个匹配的工作流,自动选择
|
|
@@ -402,6 +447,14 @@ module Pindo
|
|
|
402
447
|
end
|
|
403
448
|
|
|
404
449
|
def prepare_upload(working_directory:nil, proj_name:nil, package_type:nil, manage_type: "")
|
|
450
|
+
if ENV['PINDO_DEBUG']
|
|
451
|
+
puts "\n[PINDO_DEBUG] prepare_upload 调用参数:"
|
|
452
|
+
puts " working_directory: #{working_directory}"
|
|
453
|
+
puts " proj_name: #{proj_name.inspect}"
|
|
454
|
+
puts " package_type: #{package_type.inspect}"
|
|
455
|
+
puts " manage_type: #{manage_type.inspect}"
|
|
456
|
+
end
|
|
457
|
+
|
|
405
458
|
upload_proj_name = proj_name
|
|
406
459
|
if upload_proj_name.nil? || upload_proj_name.empty?
|
|
407
460
|
upload_proj_name = @proj_name
|
|
@@ -416,36 +469,54 @@ module Pindo
|
|
|
416
469
|
end
|
|
417
470
|
|
|
418
471
|
# 【核心优化】尝试从 JPSBuildConfig.json 加载配置
|
|
419
|
-
if package_type
|
|
472
|
+
if package_type || manage_type
|
|
473
|
+
puts "[PINDO_DEBUG] 准备加载配置文件 (package_type=#{package_type.inspect}, manage_type=#{manage_type.inspect})" if ENV['PINDO_DEBUG']
|
|
474
|
+
|
|
420
475
|
config_result = try_load_jps_build_config(
|
|
421
476
|
working_directory: working_directory,
|
|
422
477
|
package_type: package_type,
|
|
423
478
|
manage_type: manage_type
|
|
424
479
|
)
|
|
425
480
|
|
|
481
|
+
puts "[PINDO_DEBUG] 配置加载结果: valid=#{config_result[:valid]}" if ENV['PINDO_DEBUG']
|
|
482
|
+
|
|
426
483
|
if config_result[:valid]
|
|
427
484
|
# 配置有效,直接使用
|
|
428
485
|
puts "\n使用 JPSBuildConfig.json 配置:"
|
|
429
486
|
puts " 项目: #{config_result[:project_name]}"
|
|
430
487
|
puts " 工作流: #{config_result[:workflow_info][:tab_name]}"
|
|
431
488
|
|
|
489
|
+
if ENV['PINDO_DEBUG']
|
|
490
|
+
puts "[PINDO_DEBUG] 配置详细信息:"
|
|
491
|
+
puts " project_name: #{config_result[:project_name]}"
|
|
492
|
+
puts " project_id: #{config_result[:project_id]}"
|
|
493
|
+
puts " workflow_info: #{config_result[:workflow_info].inspect}"
|
|
494
|
+
end
|
|
495
|
+
|
|
432
496
|
# 确保已登录
|
|
433
497
|
unless login
|
|
434
498
|
raise Informative, "请先登录JPS网站"
|
|
435
499
|
end
|
|
436
500
|
|
|
437
501
|
# 获取完整的 app_info_obj
|
|
502
|
+
puts "[PINDO_DEBUG] 正在查找项目: #{config_result[:project_name]}" if ENV['PINDO_DEBUG']
|
|
438
503
|
app_info_obj = find_app_info_with_obj_list(
|
|
439
504
|
proj_name: config_result[:project_name]
|
|
440
505
|
)
|
|
441
506
|
|
|
442
507
|
if app_info_obj
|
|
508
|
+
puts "[PINDO_DEBUG] 项目找到,返回配置" if ENV['PINDO_DEBUG']
|
|
443
509
|
@proj_name = config_result[:project_name]
|
|
444
510
|
return app_info_obj, config_result[:workflow_info]
|
|
445
511
|
else
|
|
512
|
+
puts "[PINDO_DEBUG] 配置的项目在 JPS 中不存在: #{config_result[:project_name]}" if ENV['PINDO_DEBUG']
|
|
446
513
|
puts "配置的项目不存在,将重新选择"
|
|
447
514
|
end
|
|
515
|
+
else
|
|
516
|
+
puts "[PINDO_DEBUG] 配置无效,进入交互选择流程" if ENV['PINDO_DEBUG']
|
|
448
517
|
end
|
|
518
|
+
else
|
|
519
|
+
puts "[PINDO_DEBUG] 跳过配置加载(package_type 和 manage_type 都为空)" if ENV['PINDO_DEBUG']
|
|
449
520
|
end
|
|
450
521
|
|
|
451
522
|
# ===== 配置无效或不存在,进入用户选择流程 =====
|
|
@@ -463,8 +534,8 @@ module Pindo
|
|
|
463
534
|
Pindo::Options::GlobalOptionsState.instance[:proj] = upload_proj_name
|
|
464
535
|
end
|
|
465
536
|
|
|
466
|
-
# 如果提供了 package_type,选择工作流并保存配置
|
|
467
|
-
if package_type
|
|
537
|
+
# 如果提供了 package_type 或 manage_type,选择工作流并保存配置
|
|
538
|
+
if package_type || manage_type
|
|
468
539
|
workflow_info = select_workflow_for_project(
|
|
469
540
|
project_id: app_info_obj["id"],
|
|
470
541
|
package_type: package_type,
|
|
@@ -589,8 +660,8 @@ module Pindo
|
|
|
589
660
|
# 记录上次上传的项目
|
|
590
661
|
PindoUserLocalConfig.instance.write_last_work_project(proj_name:app_info_obj["projectName"])
|
|
591
662
|
|
|
592
|
-
# 如果提供了 package_type,选择工作流并保存配置
|
|
593
|
-
if package_type
|
|
663
|
+
# 如果提供了 package_type 或 manage_type,选择工作流并保存配置
|
|
664
|
+
if package_type || manage_type
|
|
594
665
|
workflow_info = select_workflow_for_project(
|
|
595
666
|
project_id: app_info_obj["id"],
|
|
596
667
|
package_type: package_type,
|
|
@@ -1415,11 +1486,11 @@ module Pindo
|
|
|
1415
1486
|
# 根据 HEAD 是否有 tag 决定使用哪种参数
|
|
1416
1487
|
cliff_args = if has_tag_at_head
|
|
1417
1488
|
# HEAD 有 tag,输出最新 tag 的更改(相对于前一个 tag)
|
|
1418
|
-
puts "HEAD 存在 tag: #{head_tag},使用 --latest 参数" if ENV['
|
|
1489
|
+
puts "HEAD 存在 tag: #{head_tag},使用 --latest 参数" if ENV['PINDO_DEBUG']
|
|
1419
1490
|
"--latest"
|
|
1420
1491
|
else
|
|
1421
1492
|
# HEAD 没有 tag,输出未发布的更改(从最新 tag 到 HEAD)
|
|
1422
|
-
puts "HEAD 不存在 tag,使用 --unreleased 参数" if ENV['
|
|
1493
|
+
puts "HEAD 不存在 tag,使用 --unreleased 参数" if ENV['PINDO_DEBUG']
|
|
1423
1494
|
"--unreleased"
|
|
1424
1495
|
end
|
|
1425
1496
|
|
|
@@ -1429,14 +1500,14 @@ module Pindo
|
|
|
1429
1500
|
# 策略1: 使用项目根目录的 cliff.toml
|
|
1430
1501
|
project_cliff_toml = File.join(current_git_root_path, "cliff.toml")
|
|
1431
1502
|
if File.exist?(project_cliff_toml)
|
|
1432
|
-
puts "使用项目配置文件: #{project_cliff_toml}" if ENV['
|
|
1503
|
+
puts "使用项目配置文件: #{project_cliff_toml}" if ENV['PINDO_DEBUG']
|
|
1433
1504
|
cliff_config_cmd = "git-cliff -c \"#{project_cliff_toml}\" #{cliff_args} -o -"
|
|
1434
1505
|
else
|
|
1435
1506
|
# 策略2: 使用 Pindo 默认配置文件(直接从 Pindoconfig 获取目录,避免更新仓库)
|
|
1436
1507
|
pindo_common_dir = Pindoconfig.instance.pindo_common_configdir
|
|
1437
1508
|
pindo_cliff_toml = File.join(pindo_common_dir, 'cliff.toml')
|
|
1438
1509
|
if File.exist?(pindo_cliff_toml)
|
|
1439
|
-
puts "使用 Pindo 默认配置文件: #{pindo_cliff_toml}" if ENV['
|
|
1510
|
+
puts "使用 Pindo 默认配置文件: #{pindo_cliff_toml}" if ENV['PINDO_DEBUG']
|
|
1440
1511
|
cliff_config_cmd = "git-cliff -c \"#{pindo_cliff_toml}\" #{cliff_args} -o -"
|
|
1441
1512
|
end
|
|
1442
1513
|
end
|
|
@@ -1451,20 +1522,20 @@ module Pindo
|
|
|
1451
1522
|
description = stdout.strip
|
|
1452
1523
|
# 如果有版本更新提示,输出到终端但不包含在描述中
|
|
1453
1524
|
if stderr && !stderr.empty?
|
|
1454
|
-
puts stderr if stderr.include?("new version") || ENV['
|
|
1525
|
+
puts stderr if stderr.include?("new version") || ENV['PINDO_DEBUG']
|
|
1455
1526
|
end
|
|
1456
|
-
puts "git-cliff 输出成功" if ENV['
|
|
1527
|
+
puts "git-cliff 输出成功" if ENV['PINDO_DEBUG']
|
|
1457
1528
|
else
|
|
1458
1529
|
Funlog.warning("git-cliff 执行失败,使用默认描述")
|
|
1459
1530
|
error_msg = stderr && !stderr.empty? ? stderr : stdout
|
|
1460
|
-
puts "错误信息: #{error_msg}" if ENV['
|
|
1531
|
+
puts "错误信息: #{error_msg}" if ENV['PINDO_DEBUG']
|
|
1461
1532
|
# 使用默认描述而不是抛出异常
|
|
1462
1533
|
description = "版本更新"
|
|
1463
1534
|
end
|
|
1464
1535
|
else
|
|
1465
1536
|
# 没有找到任何配置文件
|
|
1466
1537
|
Funlog.warning("未找到 cliff.toml 配置文件,使用默认描述")
|
|
1467
|
-
if ENV['
|
|
1538
|
+
if ENV['PINDO_DEBUG']
|
|
1468
1539
|
puts "请确保:"
|
|
1469
1540
|
puts " 1. 项目根目录存在 cliff.toml 文件"
|
|
1470
1541
|
puts " 2. 或 Pindo 工具目录存在默认配置文件"
|
|
@@ -1483,7 +1554,7 @@ module Pindo
|
|
|
1483
1554
|
raise Informative, "git-cliff 未安装,无法生成版本描述"
|
|
1484
1555
|
end
|
|
1485
1556
|
else
|
|
1486
|
-
puts "当前目录不是 git 仓库" if ENV['
|
|
1557
|
+
puts "当前目录不是 git 仓库" if ENV['PINDO_DEBUG']
|
|
1487
1558
|
end
|
|
1488
1559
|
|
|
1489
1560
|
return description
|
|
@@ -1832,8 +1903,25 @@ module Pindo
|
|
|
1832
1903
|
# @return [Boolean] 是否有效
|
|
1833
1904
|
def workflow_valid?(workflow)
|
|
1834
1905
|
return false if workflow.nil?
|
|
1906
|
+
|
|
1907
|
+
# 检查 workflow_id
|
|
1835
1908
|
return false if workflow['workflow_id'].nil? || workflow['workflow_id'].to_s.empty?
|
|
1836
|
-
|
|
1909
|
+
|
|
1910
|
+
# git 类型的 workflow 不需要 package_name(管理 git commit,不是包文件)
|
|
1911
|
+
# 其他类型的 workflow 需要 package_name
|
|
1912
|
+
is_git_workflow = workflow['manage_type'] == 'git'
|
|
1913
|
+
unless is_git_workflow
|
|
1914
|
+
return false if workflow['package_name'].nil? || workflow['package_name'].empty?
|
|
1915
|
+
end
|
|
1916
|
+
|
|
1917
|
+
if ENV['PINDO_DEBUG']
|
|
1918
|
+
puts "[PINDO_DEBUG] workflow_valid? 检查通过:"
|
|
1919
|
+
puts " workflow_id: #{workflow['workflow_id']}"
|
|
1920
|
+
puts " manage_type: #{workflow['manage_type']}"
|
|
1921
|
+
puts " is_git_workflow: #{is_git_workflow}"
|
|
1922
|
+
puts " package_name: #{workflow['package_name'].inspect}"
|
|
1923
|
+
end
|
|
1924
|
+
|
|
1837
1925
|
true
|
|
1838
1926
|
end
|
|
1839
1927
|
|
|
@@ -1951,7 +2039,7 @@ module Pindo
|
|
|
1951
2039
|
end
|
|
1952
2040
|
|
|
1953
2041
|
# 9. Project ID 和 Workflow ID 都不变 → 不修改
|
|
1954
|
-
puts "配置未变更,跳过保存" if ENV['
|
|
2042
|
+
puts "配置未变更,跳过保存" if ENV['PINDO_DEBUG']
|
|
1955
2043
|
end
|
|
1956
2044
|
end
|
|
1957
2045
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
require 'pindo/module/task/model/git_task'
|
|
2
2
|
require 'pindo/base/git_handler'
|
|
3
3
|
require 'pindo/module/build/git_repo_helper'
|
|
4
|
+
require 'pindo/options/helpers/git_constants'
|
|
4
5
|
|
|
5
6
|
module Pindo
|
|
6
7
|
module TaskSystem
|
|
@@ -36,7 +37,7 @@ module Pindo
|
|
|
36
37
|
def initialize(project_path, options = {})
|
|
37
38
|
# GitCommitTask 特有的属性
|
|
38
39
|
@fixed_version = options[:fixed_version] # 外部指定的固定版本号
|
|
39
|
-
@process_type = options[:process_type] ||
|
|
40
|
+
@process_type = options[:process_type] || Pindo::UncommittedFilesProcessType::SKIP # 默认跳过
|
|
40
41
|
@commit_message = options[:commit_message] || 'build: 构建产生提交' # 默认提交消息
|
|
41
42
|
|
|
42
43
|
options[:project_path] = project_path
|
|
@@ -90,7 +91,7 @@ module Pindo
|
|
|
90
91
|
begin
|
|
91
92
|
Pindo::GitHandler.process_need_add_files(
|
|
92
93
|
project_dir: root_dir,
|
|
93
|
-
process_type: @process_type ||
|
|
94
|
+
process_type: @process_type || Pindo::UncommittedFilesProcessType::NONE,
|
|
94
95
|
commit_message: @commit_message
|
|
95
96
|
)
|
|
96
97
|
rescue Pindo::Informative => e
|
|
@@ -104,10 +105,11 @@ module Pindo
|
|
|
104
105
|
|
|
105
106
|
# 4. Stash 工作目录的残留修改(为分支同步做准备)
|
|
106
107
|
stash_saved = false
|
|
108
|
+
stash_name = "pindo_stash_#{Time.now.strftime('%Y%m%d%H%M%S')}_#{rand(1000)}"
|
|
107
109
|
status = Pindo::GitHandler.git!(%W(-C #{root_dir} status --porcelain)).strip
|
|
108
110
|
unless status.empty?
|
|
109
|
-
Funlog.instance.fancyinfo_update("工作目录有未提交更改,暂存到 stash")
|
|
110
|
-
Pindo::GitHandler.git!(%W(-C #{root_dir} stash -u))
|
|
111
|
+
Funlog.instance.fancyinfo_update("工作目录有未提交更改,暂存到 stash: #{stash_name}")
|
|
112
|
+
Pindo::GitHandler.git!(%W(-C #{root_dir} stash push -u -m #{stash_name}))
|
|
111
113
|
stash_saved = true
|
|
112
114
|
end
|
|
113
115
|
|
|
@@ -150,11 +152,23 @@ module Pindo
|
|
|
150
152
|
Funlog.instance.fancyinfo_success("Version: #{@build_version}, Build: #{@build_number}, Commit: #{commit_short}")
|
|
151
153
|
end
|
|
152
154
|
|
|
155
|
+
|
|
153
156
|
# 9. 还原 stash(如果之前有 stash)
|
|
154
157
|
if stash_saved
|
|
155
158
|
begin
|
|
156
|
-
|
|
157
|
-
|
|
159
|
+
# 查找指定名字的 stash
|
|
160
|
+
stash_list = Pindo::GitHandler.git!(%W(-C #{root_dir} stash list)).strip
|
|
161
|
+
matched_line = stash_list.lines.find { |l| l.include?(stash_name) }
|
|
162
|
+
|
|
163
|
+
if matched_line && (stash_id = matched_line.match(/(stash@\{\d+\})/)&.[](1))
|
|
164
|
+
# 先应用 stash(不删除)
|
|
165
|
+
Pindo::GitHandler.git!(%W(-C #{root_dir} stash apply #{stash_id}))
|
|
166
|
+
# 应用成功后再删除 stash
|
|
167
|
+
Pindo::GitHandler.git!(%W(-C #{root_dir} stash drop #{stash_id}))
|
|
168
|
+
Funlog.instance.fancyinfo_success("已还原 stash: #{stash_name} (#{stash_id})")
|
|
169
|
+
else
|
|
170
|
+
Funlog.instance.fancyinfo_warning("未找到名为 #{stash_name} 的 stash,请手动检查")
|
|
171
|
+
end
|
|
158
172
|
rescue => e
|
|
159
173
|
Funlog.instance.fancyinfo_warning("stash 还原时发生冲突: #{e.message}")
|
|
160
174
|
Funlog.instance.fancyinfo_warning("stash 已保留,请手动执行 'git stash pop' 处理冲突")
|
|
@@ -162,6 +176,10 @@ module Pindo
|
|
|
162
176
|
end
|
|
163
177
|
end
|
|
164
178
|
|
|
179
|
+
|
|
180
|
+
# 10. 显示主仓库和所有子仓库的 commit info
|
|
181
|
+
display_all_repos_commit_info(root_dir)
|
|
182
|
+
|
|
165
183
|
{
|
|
166
184
|
success: true,
|
|
167
185
|
root_dir: root_dir,
|
|
@@ -169,6 +187,88 @@ module Pindo
|
|
|
169
187
|
message: "Git 提交检查完成"
|
|
170
188
|
}
|
|
171
189
|
end
|
|
190
|
+
|
|
191
|
+
# ----------------------------------------------------
|
|
192
|
+
# 10. 显示主仓库和所有子仓库的 commit id 和 commit message
|
|
193
|
+
# ----------------------------------------------------
|
|
194
|
+
def display_all_repos_commit_info(root_dir)
|
|
195
|
+
Funlog.instance.fancyinfo_start("仓库及子模块 Commit 信息概览")
|
|
196
|
+
|
|
197
|
+
# 10.1 主仓库
|
|
198
|
+
begin
|
|
199
|
+
main_info = Pindo::GitHandler.git!(%W(-C #{root_dir} log -1 --format=%h|%s)).strip
|
|
200
|
+
main_id, main_msg = main_info.split('|', 2)
|
|
201
|
+
puts ""
|
|
202
|
+
puts " [Main Repo] #{File.basename(root_dir)}".green
|
|
203
|
+
puts " Commit: #{main_id} - #{main_msg}"
|
|
204
|
+
rescue => e
|
|
205
|
+
Funlog.instance.warning("获取主仓库信息失败: #{e.message}")
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
# 10.2 子模块
|
|
209
|
+
begin
|
|
210
|
+
# 使用 git submodule status 获取列表,更可靠
|
|
211
|
+
submodule_status_output = Pindo::GitHandler.git!(%W(-C #{root_dir} submodule status --recursive)).strip
|
|
212
|
+
|
|
213
|
+
unless submodule_status_output.empty?
|
|
214
|
+
puts ""
|
|
215
|
+
puts " [Submodules]".yellow
|
|
216
|
+
submodule_status_output.each_line do |line|
|
|
217
|
+
# line format: " 923... path/to/sub (v1.2)" or "-..." for uninitialized
|
|
218
|
+
parts = line.strip.split(' ')
|
|
219
|
+
next if parts.length < 2
|
|
220
|
+
|
|
221
|
+
clean_sha = parts[0].gsub(/^[-+U]/, '') # 去除状态前缀
|
|
222
|
+
short_sha = clean_sha[0..6]
|
|
223
|
+
sub_path = parts[1]
|
|
224
|
+
sub_abs_path = File.join(root_dir, sub_path)
|
|
225
|
+
|
|
226
|
+
# 只有当目录存在且是 git 仓库时才尝试读取 log
|
|
227
|
+
if File.directory?(sub_abs_path) && File.exist?(File.join(sub_abs_path, '.git'))
|
|
228
|
+
begin
|
|
229
|
+
# 使用 git show 指定 SHA 获取 message,避免 HEAD 指向不明的问题
|
|
230
|
+
raw_msg = Pindo::GitHandler.git!(%W(-C #{sub_abs_path} show -s --format=%s #{clean_sha}))
|
|
231
|
+
sub_msg = raw_msg.strip
|
|
232
|
+
|
|
233
|
+
# 处理编码问题:将 ASCII-8BIT 转换为 UTF-8,无效字符替换为 ?
|
|
234
|
+
if sub_msg.respond_to?(:force_encoding)
|
|
235
|
+
sub_msg.force_encoding("UTF-8")
|
|
236
|
+
unless sub_msg.valid_encoding?
|
|
237
|
+
sub_msg = sub_msg.encode("UTF-8", "binary", invalid: :replace, undef: :replace, replace: "?")
|
|
238
|
+
end
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
puts " • #{sub_path}: #{short_sha} - #{sub_msg}"
|
|
242
|
+
rescue => e
|
|
243
|
+
# 如果获取 log 失败,显示错误原因
|
|
244
|
+
puts " • #{sub_path}: #{short_sha} (获取Message失败: #{e.message.strip})"
|
|
245
|
+
end
|
|
246
|
+
else
|
|
247
|
+
# 未初始化或其他情况
|
|
248
|
+
status_char = parts[0][0] # 获取状态字符 (+, -, U, space)
|
|
249
|
+
status_desc = case status_char
|
|
250
|
+
when '-' then "未初始化"
|
|
251
|
+
when '+' then "版本不一致"
|
|
252
|
+
when 'U' then "合并冲突"
|
|
253
|
+
else "目录或.git不存在"
|
|
254
|
+
end
|
|
255
|
+
puts " • #{sub_path}: #{short_sha} (#{status_desc})"
|
|
256
|
+
end
|
|
257
|
+
end
|
|
258
|
+
end
|
|
259
|
+
rescue => e
|
|
260
|
+
# 忽略子模块错误
|
|
261
|
+
# Funlog.instance.warning("获取子模块信息异常: #{e.message}")
|
|
262
|
+
end
|
|
263
|
+
|
|
264
|
+
puts ""
|
|
265
|
+
Funlog.instance.fancyinfo_success("Commit 信息展示完成")
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
# 在 do_work 结束前调用
|
|
269
|
+
def do_work_end_hook(root_dir)
|
|
270
|
+
display_all_repos_commit_info(root_dir)
|
|
271
|
+
end
|
|
172
272
|
end
|
|
173
273
|
end
|
|
174
274
|
end
|