pindo 5.17.5 → 5.18.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.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/lib/pindo/base/git_handler.rb +120 -38
  3. data/lib/pindo/command/android/autobuild.rb +81 -40
  4. data/lib/pindo/command/appstore/adhocbuild.rb +1 -1
  5. data/lib/pindo/command/appstore/autobuild.rb +1 -1
  6. data/lib/pindo/command/appstore/autoresign.rb +1 -1
  7. data/lib/pindo/command/appstore/updateid.rb +229 -0
  8. data/lib/pindo/command/appstore.rb +1 -0
  9. data/lib/pindo/command/ios/autobuild.rb +70 -33
  10. data/lib/pindo/command/ios/podpush.rb +1 -1
  11. data/lib/pindo/command/jps/apptest.rb +2 -2
  12. data/lib/pindo/command/jps/bind.rb +1 -1
  13. data/lib/pindo/command/jps/media.rb +1 -1
  14. data/lib/pindo/command/jps/upload.rb +52 -22
  15. data/lib/pindo/command/unity/autobuild.rb +61 -44
  16. data/lib/pindo/command/utils/allcopyconfig.rb +144 -0
  17. data/lib/pindo/command/utils/copyconfig.rb +207 -0
  18. data/lib/pindo/command/utils/icon.rb +2 -2
  19. data/lib/pindo/command/utils/renewbundleid.rb +199 -0
  20. data/lib/pindo/command/utils/renewcert.rb +56 -54
  21. data/lib/pindo/command/utils.rb +3 -0
  22. data/lib/pindo/command/web/autobuild.rb +32 -26
  23. data/lib/pindo/config/build_info_manager.rb +1 -3
  24. data/lib/pindo/module/android/android_build_helper.rb +193 -33
  25. data/lib/pindo/module/android/android_config_helper.rb +305 -88
  26. data/lib/pindo/module/android/android_project_helper.rb +69 -14
  27. data/lib/pindo/module/android/android_res_helper.rb +349 -51
  28. data/lib/pindo/module/android/keystore_helper.rb +611 -295
  29. data/lib/pindo/module/android/workflow_gradle_injector.rb +702 -0
  30. data/lib/pindo/module/appselect.rb +4 -4
  31. data/lib/pindo/module/appstore/bundleid_helper.rb +204 -14
  32. data/lib/pindo/module/build/build_helper.rb +110 -10
  33. data/lib/pindo/module/build/git_repo_helper.rb +4 -4
  34. data/lib/pindo/module/cert/mode/base_cert_operator.rb +8 -6
  35. data/lib/pindo/module/pgyer/pgyerhelper.rb +105 -42
  36. data/lib/pindo/module/task/core/task_executor.rb +2 -0
  37. data/lib/pindo/module/task/model/build/android_build_dev_task.rb +64 -6
  38. data/lib/pindo/module/task/model/git/git_commit_task.rb +70 -54
  39. data/lib/pindo/module/task/model/git/git_tag_task.rb +13 -9
  40. data/lib/pindo/module/task/model/jps/jps_upload_task.rb +104 -1
  41. data/lib/pindo/module/task/model/unity/unity_export_task.rb +2 -1
  42. data/lib/pindo/module/task/model/unity/unity_update_task.rb +2 -1
  43. data/lib/pindo/module/task/model/unity/unity_yoo_asset_task.rb +2 -1
  44. data/lib/pindo/module/task/model/unity_task.rb +2 -1
  45. data/lib/pindo/module/task/task_manager.rb +8 -0
  46. data/lib/pindo/module/unity/unity_helper.rb +13 -10
  47. data/lib/pindo/module/unity/unity_proc_helper.rb +27 -2
  48. data/lib/pindo/module/xcode/applovin_xcode_helper.rb +4 -2
  49. data/lib/pindo/module/xcode/res/xcode_res_constant.rb +72 -0
  50. data/lib/pindo/module/xcode/xcode_build_config.rb +36 -17
  51. data/lib/pindo/module/xcode/xcode_build_helper.rb +180 -23
  52. data/lib/pindo/module/xcode/xcode_project_helper.rb +1 -1
  53. data/lib/pindo/module/xcode/xcode_res_helper.rb +32 -16
  54. data/lib/pindo/options/groups/build_options.rb +16 -5
  55. data/lib/pindo/options/groups/git_options.rb +7 -5
  56. data/lib/pindo/options/groups/unity_options.rb +11 -0
  57. data/lib/pindo/options/helpers/bundleid_selector.rb +25 -0
  58. data/lib/pindo/options/helpers/git_constants.rb +7 -6
  59. data/lib/pindo/version.rb +2 -2
  60. metadata +10 -5
@@ -9,6 +9,7 @@ require 'pindo/config/pindoconfig'
9
9
  require 'pindo/config/pindouserlocalconfig'
10
10
  require 'pindo/base/funlog'
11
11
  require 'pindo/base/git_handler'
12
+ require 'pindo/module/build/build_helper'
12
13
 
13
14
 
14
15
  module Pindo
@@ -55,9 +56,9 @@ module Pindo
55
56
  # - project_name [String] 项目名称
56
57
  # - project_id [String] 项目ID
57
58
  # - workflow_info [Hash] 工作流信息(如果有效)
58
- def try_load_jps_build_config(config_file:, package_type:, manage_type: "")
59
+ def parse_jps_build_config(config_file:, package_type:, manage_type: "")
59
60
  if ENV['PINDO_DEBUG']
60
- puts "\n[PINDO_DEBUG] try_load_jps_build_config 调用:"
61
+ puts "\n[PINDO_DEBUG] parse_jps_build_config 调用:"
61
62
  puts " config_file: #{config_file}"
62
63
  puts " package_type: #{package_type.inspect}"
63
64
  puts " manage_type: #{manage_type.inspect}"
@@ -394,7 +395,7 @@ module Pindo
394
395
  config_path = if conf && !conf.empty?
395
396
  File.expand_path(conf)
396
397
  else
397
- determine_config_file_path(working_directory)
398
+ Pindo::BuildHelper.share_instance.determine_jps_config_path(working_directory)
398
399
  end
399
400
 
400
401
  upload_proj_name = nil
@@ -462,7 +463,7 @@ module Pindo
462
463
  return app_info_obj, workflow_info
463
464
  end
464
465
 
465
- def prepare_upload(working_directory:nil, conf:nil, package_type:nil, manage_type: "")
466
+ def prepare_upload(working_directory:nil, conf:nil, package_type:nil, manage_type: "", bundle_name: nil)
466
467
  working_directory ||= Dir.pwd
467
468
 
468
469
  if ENV['PINDO_DEBUG']
@@ -477,14 +478,14 @@ module Pindo
477
478
  config_path = if conf && !conf.empty?
478
479
  File.expand_path(conf)
479
480
  else
480
- determine_config_file_path(working_directory)
481
+ Pindo::BuildHelper.share_instance.determine_jps_config_path(working_directory)
481
482
  end
482
483
 
483
484
  puts "[PINDO_DEBUG] 使用配置文件: #{config_path}" if ENV['PINDO_DEBUG']
484
485
 
485
486
  # 尝试从配置文件加载
486
487
  if package_type || manage_type
487
- config_result = try_load_jps_build_config(
488
+ config_result = parse_jps_build_config(
488
489
  config_file: config_path,
489
490
  package_type: package_type,
490
491
  manage_type: manage_type
@@ -509,8 +510,14 @@ module Pindo
509
510
  end
510
511
 
511
512
  puts "[PINDO_DEBUG] 正在查找项目: #{config_result[:project_name]}" if ENV['PINDO_DEBUG']
513
+ lookup_bundle_id = resolve_lookup_bundle_id(
514
+ bundle_name: bundle_name,
515
+ workflow_info: config_result[:workflow_info]
516
+ )
517
+ puts "[PINDO_DEBUG] bundle_id 查找键: #{lookup_bundle_id.inspect}" if ENV['PINDO_DEBUG']
512
518
  app_info_obj = find_app_info_with_obj_list(
513
- proj_name: config_result[:project_name]
519
+ proj_name: config_result[:project_name],
520
+ bundle_id: lookup_bundle_id
514
521
  )
515
522
 
516
523
  if app_info_obj
@@ -1343,9 +1350,19 @@ module Pindo
1343
1350
 
1344
1351
  end
1345
1352
 
1346
- def find_app_info_with_obj_list(proj_name:nil)
1353
+ # 通过 project_id 获取项目详情(轻量接口,比 find_app_info_with_obj_list 更快)
1354
+ # @param project_id [String] 项目ID
1355
+ # @return [Hash, nil] 项目信息对象
1356
+ def get_project_detail(project_id:)
1357
+ return nil if project_id.nil? || project_id.to_s.empty?
1358
+
1359
+ result = @pgyer_client.get_project_detail(project_id: project_id)
1360
+ result&.dig("data")
1361
+ end
1362
+
1363
+ def find_app_info_with_obj_list(proj_name:nil, bundle_id:nil)
1347
1364
 
1348
- if proj_name.nil?
1365
+ if proj_name.nil? && bundle_id.nil?
1349
1366
  return nil
1350
1367
  end
1351
1368
 
@@ -1353,13 +1370,24 @@ module Pindo
1353
1370
 
1354
1371
  get_app_list_in_pgyer()
1355
1372
 
1356
- key_proj_name = proj_name.downcase.strip.gsub(/[\s\-_]/, '')
1373
+ key_proj_name = proj_name&.downcase&.strip&.gsub(/[\s\-_]/, '')
1374
+ key_bundle_id = bundle_id&.downcase&.strip
1357
1375
 
1358
1376
  app_info_list = Pindoconfig.instance.get_pgyerapps_info_list()
1359
- app_info_obj = app_info_list&.find do |app_info_item|
1377
+ app_info_obj = nil
1378
+ if key_bundle_id && !key_bundle_id.empty?
1379
+ app_info_obj = app_info_list&.find do |app_info_item|
1380
+ app_info_bundle_id = app_info_item["bundleId"].to_s.downcase.strip
1381
+ app_info_bundle_id.eql?(key_bundle_id)
1382
+ end
1383
+ end
1384
+
1385
+ if app_info_obj.nil? && key_proj_name && !key_proj_name.empty?
1386
+ app_info_obj = app_info_list&.find do |app_info_item|
1360
1387
  # 新 API 使用 projectName 字段
1361
1388
  app_info_item_name = app_info_item["projectName"].to_s.downcase.strip.gsub(/[\s\-_]/, '')
1362
1389
  app_info_item_name.eql?(key_proj_name)
1390
+ end
1363
1391
  end
1364
1392
 
1365
1393
  Funlog.instance.fancyinfo_success("拉取app信息列表完成,app信息获取成功!")
@@ -1367,6 +1395,31 @@ module Pindo
1367
1395
  app_info_obj
1368
1396
  end
1369
1397
 
1398
+ def wildcard_android_bundle_name?(bundle_name)
1399
+ return false if bundle_name.nil? || bundle_name.empty?
1400
+
1401
+ bundle_name.include?('*') ||
1402
+ bundle_name.end_with?('.') ||
1403
+ ['com.test', 'com.example', 'com.demo', 'com.heroneverdie101'].include?(bundle_name)
1404
+ end
1405
+
1406
+ def resolve_lookup_bundle_id(bundle_name:, workflow_info:)
1407
+ return nil if bundle_name.nil? || bundle_name.empty?
1408
+
1409
+ if wildcard_android_bundle_name?(bundle_name)
1410
+ package_name = workflow_info && workflow_info[:package_name]
1411
+ return nil if package_name.nil? || package_name.empty?
1412
+
1413
+ prefix = bundle_name.sub(/\.\*$/, '').sub(/\.$/, '')
1414
+ return nil if prefix.empty?
1415
+
1416
+ package_suffix = package_name.to_s.gsub(/[^a-zA-Z0-9]/, '').downcase
1417
+ return "#{prefix}.#{package_suffix}"
1418
+ end
1419
+
1420
+ bundle_name
1421
+ end
1422
+
1370
1423
  def get_app_version(projectId:nil, app_version_index:nil, latest_version:true, package_type:nil)
1371
1424
 
1372
1425
  params = {}
@@ -1891,28 +1944,6 @@ module Pindo
1891
1944
 
1892
1945
  private
1893
1946
 
1894
- # 确定 JPSBuildConfig.json 文件路径
1895
- # Unity 工程:仓库根目录/ProjectSettings/JPSBuildConfig.json
1896
- # iOS/Android 工程:仓库根目录/JPSBuildConfig.json
1897
- #
1898
- # @param working_directory [String] 工作目录
1899
- # @return [String] 配置文件完整路径
1900
- def determine_config_file_path(working_directory)
1901
- # 获取 Git 仓库根目录
1902
- repo_root_dir = nil
1903
- if Pindo::GitHandler.is_git_directory?(local_repo_dir: working_directory)
1904
- repo_root_dir = Pindo::GitHandler.git_root_directory(local_repo_dir: working_directory)
1905
- end
1906
- repo_root_dir ||= working_directory
1907
-
1908
- # 判断工程类型
1909
- if File.directory?(File.join(repo_root_dir, 'ProjectSettings'))
1910
- File.join(repo_root_dir, 'ProjectSettings', 'JPSBuildConfig.json')
1911
- else
1912
- File.join(repo_root_dir, 'JPSBuildConfig.json')
1913
- end
1914
- end
1915
-
1916
1947
  # 验证工作流配置是否有效
1917
1948
  #
1918
1949
  # @param workflow [Hash] 工作流配置对象
@@ -1947,13 +1978,17 @@ module Pindo
1947
1978
  # @param project_id [String] 项目ID
1948
1979
  # @param project_name [String] 项目名称
1949
1980
  # @param project_scheme [String] 项目scheme
1981
+ # @param bundle_group_name [String, nil] 非通配符组名(来自 API bundleId)
1982
+ # @param wildcard_bundle_group_name [String, nil] 通配符组名(来自 API wildcardBundleId)
1950
1983
  # @param workflow_key [String] 工作流键名
1951
1984
  # @param workflow_data [Hash] 工作流数据
1952
- def create_new_config(config_file, project_id, project_name, project_scheme, workflow_key, workflow_data)
1985
+ def create_new_config(config_file:, project_id:, project_name:, project_scheme:, bundle_group_name: nil, wildcard_bundle_group_name: nil, workflow_key:, workflow_data:)
1953
1986
  new_config = {
1954
1987
  "project_name" => project_name,
1955
1988
  "project_scheme" => project_scheme,
1956
1989
  "project_id" => project_id,
1990
+ "bundle_group_name" => bundle_group_name,
1991
+ "wildcard_bundle_group_name" => wildcard_bundle_group_name,
1957
1992
  workflow_key => workflow_data
1958
1993
  }
1959
1994
 
@@ -1976,7 +2011,7 @@ module Pindo
1976
2011
  return if working_directory.nil? || app_info_obj.nil? || workflow_info.nil?
1977
2012
 
1978
2013
  # 1. 确定配置文件路径
1979
- config_file = determine_config_file_path(working_directory)
2014
+ config_file = Pindo::BuildHelper.share_instance.determine_jps_config_path(working_directory)
1980
2015
 
1981
2016
  # 2. 根据 manage_type 或 package_type 确定 workflow_key
1982
2017
  workflow_key = nil
@@ -1998,6 +2033,8 @@ module Pindo
1998
2033
  # 3. 准备新的项目基础信息
1999
2034
  new_project_id = app_info_obj["id"]
2000
2035
  new_project_name = app_info_obj["projectName"]
2036
+ new_bundle_group_name = app_info_obj["bundleId"]
2037
+ new_wildcard_bundle_group_name = app_info_obj["wildcardBundleId"]
2001
2038
  new_project_scheme = app_info_obj["scheme"] ||
2002
2039
  app_info_obj["projectName"].to_s.downcase.strip.gsub(/[\s\-_]/, '')
2003
2040
 
@@ -2012,8 +2049,16 @@ module Pindo
2012
2049
 
2013
2050
  # 5. 配置文件不存在 → 创建新配置
2014
2051
  if !File.exist?(config_file)
2015
- create_new_config(config_file, new_project_id, new_project_name,
2016
- new_project_scheme, workflow_key, new_workflow_data)
2052
+ create_new_config(
2053
+ config_file: config_file,
2054
+ project_id: new_project_id,
2055
+ project_name: new_project_name,
2056
+ project_scheme: new_project_scheme,
2057
+ bundle_group_name: new_bundle_group_name,
2058
+ wildcard_bundle_group_name: new_wildcard_bundle_group_name,
2059
+ workflow_key: workflow_key,
2060
+ workflow_data: new_workflow_data
2061
+ )
2017
2062
  return
2018
2063
  end
2019
2064
 
@@ -2022,8 +2067,16 @@ module Pindo
2022
2067
  existing_config = JSON.parse(File.read(config_file))
2023
2068
  rescue => e
2024
2069
  puts "[PgyerHelper] 读取配置文件失败: #{e.message},将创建新配置"
2025
- create_new_config(config_file, new_project_id, new_project_name,
2026
- new_project_scheme, workflow_key, new_workflow_data)
2070
+ create_new_config(
2071
+ config_file: config_file,
2072
+ project_id: new_project_id,
2073
+ project_name: new_project_name,
2074
+ project_scheme: new_project_scheme,
2075
+ bundle_group_name: new_bundle_group_name,
2076
+ wildcard_bundle_group_name: new_wildcard_bundle_group_name,
2077
+ workflow_key: workflow_key,
2078
+ workflow_data: new_workflow_data
2079
+ )
2027
2080
  return
2028
2081
  end
2029
2082
 
@@ -2033,8 +2086,16 @@ module Pindo
2033
2086
  existing_config['project_id'] != new_project_id
2034
2087
 
2035
2088
  puts "项目ID变更,重新写入完整配置"
2036
- create_new_config(config_file, new_project_id, new_project_name,
2037
- new_project_scheme, workflow_key, new_workflow_data)
2089
+ create_new_config(
2090
+ config_file: config_file,
2091
+ project_id: new_project_id,
2092
+ project_name: new_project_name,
2093
+ project_scheme: new_project_scheme,
2094
+ bundle_group_name: new_bundle_group_name,
2095
+ wildcard_bundle_group_name: new_wildcard_bundle_group_name,
2096
+ workflow_key: workflow_key,
2097
+ workflow_data: new_workflow_data
2098
+ )
2038
2099
  return
2039
2100
  end
2040
2101
 
@@ -2046,9 +2107,11 @@ module Pindo
2046
2107
  existing_workflow_id.to_s.empty? ||
2047
2108
  existing_workflow_id != workflow_info[:workflow_id]
2048
2109
 
2049
- # Workflow ID 变更 → 仅更新对应的 workflow
2110
+ # Workflow ID 变更 → 更新对应的 workflow 和项目信息
2050
2111
  puts "#{workflow_key} 变更,更新工作流配置"
2051
2112
  existing_config[workflow_key] = new_workflow_data
2113
+ existing_config["bundle_group_name"] = new_bundle_group_name
2114
+ existing_config["wildcard_bundle_group_name"] = new_wildcard_bundle_group_name
2052
2115
  File.write(config_file, JSON.pretty_generate(existing_config))
2053
2116
  puts "已更新 #{workflow_key}"
2054
2117
  return
@@ -120,6 +120,8 @@ module Pindo
120
120
 
121
121
  rescue => e
122
122
  # 任务失败
123
+ task.status = TaskStatus::FAILED
124
+ task.error = e
123
125
  @reporter.print_task_failure(task, e)
124
126
  end
125
127
  end
@@ -44,6 +44,13 @@ module Pindo
44
44
  update_project_config
45
45
  update_version_info
46
46
  handle_bundle_name_config if @bundle_name
47
+ if @bundle_name.nil?
48
+ # 当用户不选择 bundle_name 时,仍在 google-services.json 中合并工作流 applicationId(追加 client,不覆盖旧包名)
49
+ Pindo::AndroidConfigHelper.update_google_services_package_name(
50
+ project_dir: @project_path,
51
+ package_name: expected_android_package_name_from_workflow
52
+ )
53
+ end
47
54
  add_application_id_scheme
48
55
  end
49
56
 
@@ -177,13 +184,30 @@ module Pindo
177
184
  puts "\n正在处理指定的 Bundle Name: #{@bundle_name}..."
178
185
 
179
186
  # 检查是否为通配符
180
- is_wildcard = @bundle_name.include?('*') ||
181
- @bundle_name.end_with?('.') ||
182
- ['com.test', 'com.example', 'com.demo'].include?(@bundle_name)
187
+ is_wildcard = wildcard_bundle_name?(@bundle_name)
183
188
 
184
189
  if is_wildcard
185
190
  puts " ⚠️ 检测到通配符或通用 Bundle Name: #{@bundle_name}"
186
- puts " ⚠️ 跳过 google-services.json Application ID 更新"
191
+ # 通配符模式下,applicationId google-services.json 需与工作流的 package_name(当前项目名)一致;json 侧为合并追加 client。
192
+ expected_package_name = expected_android_package_name_from_workflow
193
+ Pindo::AndroidConfigHelper.update_application_id(
194
+ project_dir: @project_path,
195
+ application_id: expected_package_name
196
+ )
197
+ gs_paths = Pindo::AndroidConfigHelper.existing_google_services_json_paths(@project_path)
198
+ if gs_paths.any?
199
+ merged = Pindo::AndroidConfigHelper.update_google_services_package_name(
200
+ project_dir: @project_path,
201
+ package_name: expected_package_name
202
+ )
203
+ if merged
204
+ puts " ✓ 通配符模式已更新 applicationId 并已合并 google-services client: #{expected_package_name}"
205
+ else
206
+ puts " ✓ 通配符模式已更新 applicationId: #{expected_package_name}(google-services 无需追加新 client)"
207
+ end
208
+ else
209
+ puts " ✓ 通配符模式已更新 applicationId: #{expected_package_name}(项目内无 google-services.json,跳过 client 合并)"
210
+ end
187
211
  else
188
212
  # 拉取配置仓库
189
213
  config_repo_dir = Pindo::GitHandler.clong_buildconfig_repo(repo_name: @bundle_name)
@@ -201,6 +225,12 @@ module Pindo
201
225
  application_id: @bundle_name
202
226
  )
203
227
 
228
+ # 合并 google-services.json:追加与 applicationId 一致的 client,不删除历史 package_name
229
+ Pindo::AndroidConfigHelper.update_google_services_package_name(
230
+ project_dir: @project_path,
231
+ package_name: @bundle_name
232
+ )
233
+
204
234
  puts " ✓ Bundle Name 配置处理完成"
205
235
  else
206
236
  raise Informative, "无法获取配置仓库"
@@ -215,11 +245,39 @@ module Pindo
215
245
  )
216
246
  end
217
247
 
248
+ # 从 workflow_packname 生成符合 Android applicationId/google-services.json 的包名后缀
249
+ def expected_android_package_name_from_workflow
250
+ workflow_packname = @workflow_info[:package_name]
251
+ app_id_suffix = workflow_packname.gsub(/[^a-zA-Z0-9]/, '').downcase
252
+ "com.heroneverdie101.#{app_id_suffix}"
253
+ end
254
+
218
255
  # 构建 Android 工程
219
256
  def build_android_project
220
257
  android_build_helper = Pindo::AndroidBuildHelper.share_instance
221
- # 第二个参数 true 表示 debug 模式
222
- android_build_helper.auto_build_apk(@project_path, true)
258
+ # 第二个参数 true 表示 debug 模式,bundle_name 会用于 JPS JKS 查询和签名
259
+ resolved_bundle_id = signing_bundle_id
260
+ puts " 使用签名 Bundle ID: #{resolved_bundle_id}"
261
+ android_build_helper.auto_build_apk(
262
+ @project_path,
263
+ true,
264
+ bundle_name: resolved_bundle_id,
265
+ workflow_name: @workflow_info[:package_name]
266
+ )
267
+ end
268
+
269
+ def wildcard_bundle_name?(bundle_name)
270
+ return false if bundle_name.nil? || bundle_name.empty?
271
+
272
+ bundle_name.include?('*') ||
273
+ bundle_name.end_with?('.') ||
274
+ ['com.test', 'com.example', 'com.demo', 'com.heroneverdie101'].include?(bundle_name)
275
+ end
276
+
277
+ def signing_bundle_id
278
+ return @bundle_name if @bundle_name && !wildcard_bundle_name?(@bundle_name)
279
+
280
+ expected_android_package_name_from_workflow
223
281
  end
224
282
  end
225
283
  end
@@ -37,7 +37,7 @@ module Pindo
37
37
  def initialize(project_path, options = {})
38
38
  # GitCommitTask 特有的属性
39
39
  @fixed_version = options[:fixed_version] # 外部指定的固定版本号
40
- @process_type = options[:process_type] || Pindo::UncommittedFilesProcessType::SKIP # 默认跳过
40
+ @process_type = options[:process_type] || Pindo::UncommittedFilesProcessType::SKIP_WITH_TAG # 默认跳过但打tag
41
41
  @commit_message = options[:commit_message] || 'build: 构建产生提交' # 默认提交消息
42
42
 
43
43
  options[:project_path] = project_path
@@ -103,7 +103,25 @@ module Pindo
103
103
  raise e
104
104
  end
105
105
 
106
+ # skip_without_tag 模式:跳过所有 git 同步操作,直接返回
107
+ if @process_type == Pindo::UncommittedFilesProcessType::SKIP_WITHOUT_TAG
108
+ coding_branch = get_current_branch_name
109
+ @build_number, @commit_hash = git_repo_helper.get_build_number_from_commit(project_dir: root_dir)
110
+ @build_version = "0.0.0"
111
+ Funlog.instance.fancyinfo_warning("skip_without_tag 模式:跳过分支合并和 tag 创建")
112
+
113
+ # 显示 commit 信息后直接返回
114
+ display_all_repos_commit_info(root_dir)
115
+ return {
116
+ success: true,
117
+ root_dir: root_dir,
118
+ current_branch: coding_branch,
119
+ message: "skip_without_tag: 跳过 Git 同步操作"
120
+ }
121
+ end
122
+
106
123
  # 4. Stash 工作目录的残留修改(为分支同步做准备)
124
+ coding_branch = nil
107
125
  stash_saved = false
108
126
  stash_name = "pindo_stash_#{Time.now.strftime('%Y%m%d%H%M%S')}_#{rand(1000)}"
109
127
  status = Pindo::GitHandler.git!(%W(-C #{root_dir} status --porcelain)).strip
@@ -113,66 +131,64 @@ module Pindo
113
131
  stash_saved = true
114
132
  end
115
133
 
116
- # 5. 获取当前分支
117
- coding_branch = get_current_branch_name
118
-
119
- # 6. 检查并推送本地提交到远程(确保本地和远程同步)
120
- Pindo::GitHandler.check_unpushed_commits(project_dir: root_dir, branch: coding_branch)
134
+ begin
135
+ # 5. 获取当前分支
136
+ coding_branch = get_current_branch_name
121
137
 
122
- # 7. 分支同步:将 coding_branch 和 release_branch 双向合并(确保两分支在同一节点)
123
- if coding_branch != @release_branch
124
- Funlog.instance.fancyinfo_start("开始同步 #{coding_branch} 和 #{@release_branch} 分支")
125
- Pindo::GitHandler.merge_branches(
126
- project_dir: root_dir,
127
- source_branch: coding_branch,
128
- target_branch: @release_branch,
129
- sync_branches: true # 双向合并,确保两分支完全同步
130
- )
131
- Funlog.instance.fancyinfo_success("分支同步完成,#{coding_branch} 和 #{@release_branch} 现在在同一节点")
132
- end
138
+ # 6. 检查并推送本地提交到远程(确保本地和远程同步)
139
+ Pindo::GitHandler.check_unpushed_commits(project_dir: root_dir, branch: coding_branch)
133
140
 
134
- # 8. 计算 build_version
135
- # 优先级 1: 如果指定了 fixed_version(外部传入或从 HEAD tag 获取),使用它
136
- if @fixed_version && !@fixed_version.empty?
137
- @build_version = @fixed_version
138
- @build_number, @commit_hash = git_repo_helper.get_build_number_from_commit(project_dir: root_dir)
139
- commit_short = @commit_hash ? @commit_hash[0..7] : "unknown"
140
- Funlog.instance.fancyinfo_success("Version: #{@build_version}, Build: #{@build_number}, Commit: #{commit_short}")
141
+ # 7. 分支同步:将 coding_branch 和 release_branch 双向合并(确保两分支在同一节点)
142
+ if coding_branch != @release_branch
143
+ Funlog.instance.fancyinfo_start("开始同步 #{coding_branch} 和 #{@release_branch} 分支")
144
+ Pindo::GitHandler.merge_branches(
145
+ project_dir: root_dir,
146
+ source_branch: coding_branch,
147
+ target_branch: @release_branch,
148
+ sync_branches: true # 双向合并,确保两分支完全同步
149
+ )
150
+ Funlog.instance.fancyinfo_success("分支同步完成,#{coding_branch} 和 #{@release_branch} 现在在同一节点")
151
+ end
141
152
 
142
- # 优先级 2: 计算新版本号
143
- else
144
- @build_number, @commit_hash = git_repo_helper.get_build_number_from_commit(project_dir: root_dir)
145
- @build_version = git_repo_helper.calculate_build_version(
146
- project_dir: root_dir,
147
- tag_prefix: @tag_pre,
148
- create_tag_type: @tag_type,
149
- version_increase_type: @ver_inc
150
- )
151
- commit_short = @commit_hash ? @commit_hash[0..7] : "unknown"
152
- Funlog.instance.fancyinfo_success("Version: #{@build_version}, Build: #{@build_number}, Commit: #{commit_short}")
153
- end
153
+ # 8. 计算 build_version
154
+ # 优先级 1: 如果指定了 fixed_version(外部传入或从 HEAD tag 获取),使用它
155
+ if @fixed_version && !@fixed_version.empty?
156
+ @build_version = @fixed_version
157
+ @build_number, @commit_hash = git_repo_helper.get_build_number_from_commit(project_dir: root_dir)
158
+ commit_short = @commit_hash ? @commit_hash[0..7] : "unknown"
159
+ Funlog.instance.fancyinfo_success("Version: #{@build_version}, Build: #{@build_number}, Commit: #{commit_short}")
154
160
 
161
+ # 优先级 2: 计算新版本号
162
+ else
163
+ @build_number, @commit_hash = git_repo_helper.get_build_number_from_commit(project_dir: root_dir)
164
+ @build_version = git_repo_helper.calculate_build_version(
165
+ project_dir: root_dir,
166
+ tag_prefix: @tag_pre,
167
+ create_tag_type: @tag_type,
168
+ version_increase_type: @ver_inc
169
+ )
170
+ commit_short = @commit_hash ? @commit_hash[0..7] : "unknown"
171
+ Funlog.instance.fancyinfo_success("Version: #{@build_version}, Build: #{@build_number}, Commit: #{commit_short}")
172
+ end
155
173
 
156
- # 9. 还原 stash(如果之前有 stash)
157
- if stash_saved
158
- begin
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) }
174
+ ensure
175
+ # 9. 还原 stash(无论成功或失败都执行)
176
+ if stash_saved
177
+ begin
178
+ stash_list = Pindo::GitHandler.git!(%W(-C #{root_dir} stash list)).strip
179
+ matched_line = stash_list.lines.find { |l| l.include?(stash_name) }
162
180
 
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,请手动检查")
181
+ if matched_line && (stash_id = matched_line.match(/(stash@\{\d+\})/)&.[](1))
182
+ Pindo::GitHandler.git!(%W(-C #{root_dir} stash apply #{stash_id}))
183
+ Pindo::GitHandler.git!(%W(-C #{root_dir} stash drop #{stash_id}))
184
+ Funlog.instance.fancyinfo_success("已还原 stash: #{stash_name} (#{stash_id})")
185
+ else
186
+ Funlog.instance.fancyinfo_warning("未找到名为 #{stash_name} 的 stash,请手动检查")
187
+ end
188
+ rescue => e
189
+ Funlog.instance.fancyinfo_warning("stash 还原时发生冲突: #{e.message}")
190
+ Funlog.instance.fancyinfo_warning("stash 已保留,请手动执行 'git stash pop' 处理冲突")
171
191
  end
172
- rescue => e
173
- Funlog.instance.fancyinfo_warning("stash 还原时发生冲突: #{e.message}")
174
- Funlog.instance.fancyinfo_warning("stash 已保留,请手动执行 'git stash pop' 处理冲突")
175
- # 不抛出异常,任务继续(版本号已计算成功,stash 冲突不影响构建)
176
192
  end
177
193
  end
178
194
 
@@ -64,7 +64,17 @@ module Pindo
64
64
  stash_saved = true
65
65
  end
66
66
 
67
- # 2. 合并到发布分支(双向同步,确保 coding_branch release_branch 保持一致)
67
+ # 2. GitCommitTask 获取参数(必须在合并之前,确保 release_branch 等参数正确)
68
+ git_commit_data = get_data_param_by_key(:git_commit)
69
+ if git_commit_data && git_commit_data[:task_param]
70
+ param = git_commit_data[:task_param]
71
+ @release_branch = param[:release_branch] if param[:release_branch]
72
+ @tag_pre = param[:tag_pre] if param[:tag_pre]
73
+ @tag_type = param[:tag_type] if param[:tag_type]
74
+ @ver_inc = param[:ver_inc] if param[:ver_inc]
75
+ end
76
+
77
+ # 3. 合并到发布分支(使用已回填的 @release_branch)
68
78
  if coding_branch != @release_branch
69
79
  Pindo::GitHandler.merge_branches(
70
80
  project_dir: root_dir,
@@ -74,20 +84,14 @@ module Pindo
74
84
  )
75
85
  end
76
86
 
77
- # 3. 获取版本信息
78
- # 优先级 1: 从 GitCommitTask 获取所有版本相关参数(标准方式)
79
- git_commit_data = get_data_param_by_key(:git_commit)
87
+ # 4. 获取版本信息
80
88
  if git_commit_data && git_commit_data[:task_param] &&
81
89
  git_commit_data[:task_param][:build_version] && git_commit_data[:task_param][:build_number]
82
90
  @build_version = git_commit_data[:task_param][:build_version]
83
91
  @build_number = git_commit_data[:task_param][:build_number]
84
- @tag_pre = git_commit_data[:task_param][:tag_pre] if git_commit_data[:task_param][:tag_pre]
85
- @release_branch = git_commit_data[:task_param][:release_branch] if git_commit_data[:task_param][:release_branch]
86
- @tag_type = git_commit_data[:task_param][:tag_type] if git_commit_data[:task_param][:tag_type]
87
- @ver_inc = git_commit_data[:task_param][:ver_inc] if git_commit_data[:task_param][:ver_inc]
88
92
  Funlog.instance.fancyinfo_success("使用 GitCommitTask 的版本号: #{@build_version}, Build: #{@build_number}, Tag前缀: #{@tag_pre}, Tag类型: #{@tag_type}")
89
93
 
90
- # 优先级 2: 自己计算(降级方案,用于向后兼容或 GitCommitTask 无有效数据)
94
+ # 降级:自己计算(向后兼容或 GitCommitTask 无有效数据)
91
95
  else
92
96
  @build_number, @commit_hash = git_repo_helper.get_build_number_from_commit(project_dir: root_dir)
93
97
  @build_version = git_repo_helper.calculate_build_version(