pindo 5.18.17 → 5.18.20

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.
@@ -186,9 +186,9 @@ module Pindo
186
186
  begin
187
187
  response = appstore_client.create_in_app_purchase(
188
188
  name:purchase_item["reference_name"],
189
- product_id:purchase_item["product_id"],
190
- in_app_purchase_type:purchase_item["in_app_purchase_type"],
191
- review_note:purchase_item["review_note"],
189
+ productId:purchase_item["product_id"],
190
+ inAppPurchaseType:purchase_item["in_app_purchase_type"],
191
+ reviewNote:purchase_item["review_note"],
192
192
  relationships: {
193
193
  app:{
194
194
  data:{
@@ -228,7 +228,7 @@ module Pindo
228
228
  begin
229
229
  response = appstore_client.update_in_app_purchase(
230
230
  name:purchase_item["reference_name"],
231
- review_note:purchase_item["review_note"],
231
+ reviewNote:purchase_item["review_note"],
232
232
  id:in_app_purchase_id
233
233
  )
234
234
  rescue => err
@@ -255,22 +255,34 @@ module Pindo
255
255
  end
256
256
  end
257
257
 
258
- response = appstore_client.modify_in_app_purchase_territory_availablity(
259
- available_in_new_territories:true,
260
- relationships: {
261
- inAppPurchase:{
262
- data:{
263
- id: in_app_purchase_id,
264
- type: 'inAppPurchases'
265
- }
266
- },
267
- availableTerritories:{
268
- data:availableTerritories_data
269
- }
258
+ body = {
259
+ data: {
260
+ type: "inAppPurchaseAvailabilities",
261
+ attributes: {
262
+ availableInNewTerritories: true
263
+ },
264
+ relationships: {
265
+ inAppPurchase: {
266
+ data: {
267
+ id: in_app_purchase_id,
268
+ type: 'inAppPurchases'
270
269
  }
271
- )
270
+ },
271
+ availableTerritories: {
272
+ data: availableTerritories_data
273
+ }
274
+ }
275
+ }
276
+ }
272
277
 
273
- # puts JSON.pretty_generate(response)
278
+ begin
279
+ client = Spaceship::ConnectAPI
280
+ client.tunes_request_client.post("#{Spaceship::ConnectAPI::Tunes::API::Version::V1}/inAppPurchaseAvailabilities", body)
281
+ puts " Territory Availability 设置成功"
282
+ rescue => err
283
+ puts err
284
+ puts " 设置Territory Availability失败!!!"
285
+ end
274
286
 
275
287
  end
276
288
 
@@ -396,7 +408,7 @@ module Pindo
396
408
  if !price_id.nil?
397
409
  purchase_response = appstore_client.create_in_app_purchase_price_schedule(
398
410
  relationships: {
399
- manual_prices: {
411
+ manualPrices: {
400
412
  data: [
401
413
  {
402
414
  type: 'inAppPurchasePrices',
@@ -404,7 +416,7 @@ module Pindo
404
416
  }
405
417
  ]
406
418
  },
407
- in_app_purchase: {
419
+ inAppPurchase: {
408
420
  data: {
409
421
  type: 'inAppPurchases',
410
422
  id: in_app_purchase_id
@@ -488,8 +500,8 @@ module Pindo
488
500
 
489
501
  puts " 正在上传...."
490
502
  response_iap_screenshot = appstore_client.create_in_app_purchase_review_screenshot(
491
- file_name:filename,
492
- file_size: filesize,
503
+ fileName:filename,
504
+ fileSize: filesize,
493
505
  relationships: {
494
506
  inAppPurchaseV2:{
495
507
  data:{
@@ -519,7 +531,7 @@ module Pindo
519
531
  in_app_purchase = appstore_client.update_in_app_purchase_app_store_review_screenshot(
520
532
  id:upload_id,
521
533
  uploaded: true,
522
- source_file_checksum:checksum
534
+ sourceFileChecksum:checksum
523
535
  )
524
536
  puts " 上传完成!!"
525
537
 
@@ -632,7 +644,7 @@ module Pindo
632
644
 
633
645
  begin
634
646
  group_response = appstore_client.create_subscription_group(
635
- reference_name:subscription_group_item["group_reference_name"],
647
+ referenceName:subscription_group_item["group_reference_name"],
636
648
  relationships: {
637
649
  app:{
638
650
  data:{
@@ -684,7 +696,7 @@ module Pindo
684
696
  response = appstore_client.update_subscription_group_localization(
685
697
  id:locale_item["locale_id"],
686
698
  name:locale_item["group_display_name"],
687
- custom_app_name:locale_item["custom_app_name"]
699
+ customAppName:locale_item["custom_app_name"]
688
700
  )
689
701
  # puts JSON.pretty_generate(response)
690
702
 
@@ -693,7 +705,7 @@ module Pindo
693
705
  response = appstore_client.create_subscription_group_localization(
694
706
  name:locale_item["group_display_name"],
695
707
  locale:locale,
696
- custom_app_name:locale_item["custom_app_name"],
708
+ customAppName:locale_item["custom_app_name"],
697
709
  relationships: {
698
710
  subscriptionGroup:{
699
711
  data:{
@@ -881,11 +893,11 @@ module Pindo
881
893
  begin
882
894
  response = appstore_client.create_subscription(
883
895
  name:subscription_item["reference_name"],
884
- product_id:subscription_item["product_id"],
885
- family_sharable:false,
886
- review_note:subscription_item["review_note"],
887
- subscription_period:subscription_item["subscription_duration"],
888
- group_level:1,
896
+ productId:subscription_item["product_id"],
897
+ familySharable:false,
898
+ reviewNote:subscription_item["review_note"],
899
+ subscriptionPeriod:subscription_item["subscription_duration"],
900
+ groupLevel:1,
889
901
  relationships: {
890
902
  group:{
891
903
  data:{
@@ -928,9 +940,9 @@ module Pindo
928
940
  response = appstore_client.update_subscription(
929
941
  id:subscription_id,
930
942
  name:subscription_item["reference_name"],
931
- family_sharable:false,
932
- review_note:subscription_item["review_note"],
933
- group_level:1
943
+ familySharable:false,
944
+ reviewNote:subscription_item["review_note"],
945
+ groupLevel:1
934
946
  )
935
947
  # puts JSON.pretty_generate(response)
936
948
 
@@ -962,7 +974,7 @@ module Pindo
962
974
  puts " 设置订阅的周期: #{subscription_item["subscription_duration"]}"
963
975
  response = appstore_client.update_subscription(
964
976
  id:subscription_id,
965
- subscription_period:subscription_item["subscription_duration"]
977
+ subscriptionPeriod:subscription_item["subscription_duration"]
966
978
  )
967
979
  # puts JSON.pretty_generate(response)
968
980
 
@@ -998,22 +1010,34 @@ module Pindo
998
1010
  availableTerritories_data << new_territory_item
999
1011
  end
1000
1012
  end
1001
- response = appstore_client.modify_subscription_territory_availability(
1002
- available_in_new_territories:true,
1003
- relationships: {
1004
- subscription:{
1005
- data:{
1006
- id: subscription_id,
1007
- type: 'subscriptions'
1008
- }
1009
- },
1010
- availableTerritories:{
1011
- data:availableTerritories_data
1012
- }
1013
+ body = {
1014
+ data: {
1015
+ type: "subscriptionAvailabilities",
1016
+ attributes: {
1017
+ availableInNewTerritories: true
1018
+ },
1019
+ relationships: {
1020
+ subscription: {
1021
+ data: {
1022
+ id: subscription_id,
1023
+ type: 'subscriptions'
1013
1024
  }
1014
- )
1025
+ },
1026
+ availableTerritories: {
1027
+ data: availableTerritories_data
1028
+ }
1029
+ }
1030
+ }
1031
+ }
1015
1032
 
1016
- # puts JSON.pretty_generate(response)
1033
+ begin
1034
+ client = Spaceship::ConnectAPI
1035
+ client.tunes_request_client.post("#{Spaceship::ConnectAPI::Tunes::API::Version::V1}/subscriptionAvailabilities", body)
1036
+ puts " Territory Availability 设置成功"
1037
+ rescue => err
1038
+ puts err
1039
+ puts " 设置订阅的Territory Availability失败!!!"
1040
+ end
1017
1041
  end
1018
1042
 
1019
1043
 
@@ -1624,8 +1648,8 @@ module Pindo
1624
1648
 
1625
1649
  response = appstore_client.create_subscription_introductory_offer(
1626
1650
  duration:"THREE_DAYS",
1627
- number_of_periods:1,
1628
- offer_mode:'FREE_TRIAL',
1651
+ numberOfPeriods:1,
1652
+ offerMode:'FREE_TRIAL',
1629
1653
  relationships: {
1630
1654
  subscription: {
1631
1655
  data: {
@@ -1688,7 +1712,7 @@ module Pindo
1688
1712
  if !price_point_id.nil?
1689
1713
 
1690
1714
  respose_price = appstore_client.create_subscription_price(
1691
- preserve_current_price:true,
1715
+ preserveCurrentPrice:true,
1692
1716
  relationships: {
1693
1717
  subscription: {
1694
1718
  data: {
@@ -1733,7 +1757,7 @@ module Pindo
1733
1757
  puts " " + index_item.to_s + ".更新价格 地区:" + territory_id+ " 价格:" + price_local_item[:attributes][:customer_price]
1734
1758
 
1735
1759
  respose_price = appstore_client.create_subscription_price(
1736
- preserve_current_price:true,
1760
+ preserveCurrentPrice:true,
1737
1761
  relationships: {
1738
1762
  subscription: {
1739
1763
  data: {
@@ -1814,8 +1838,8 @@ module Pindo
1814
1838
 
1815
1839
  puts " 正在上传...."
1816
1840
  response_iap_screenshot = appstore_client.create_subscription_review_screenshot(
1817
- file_name:filename,
1818
- file_size: filesize,
1841
+ fileName:filename,
1842
+ fileSize: filesize,
1819
1843
  relationships: {
1820
1844
  subscription:{
1821
1845
  data:{
@@ -1848,7 +1872,7 @@ module Pindo
1848
1872
  in_app_purchase = appstore_client.update_subscription_review_screenshot(
1849
1873
  id:upload_id,
1850
1874
  uploaded: true,
1851
- source_file_checksum:checksum
1875
+ sourceFileChecksum:checksum
1852
1876
  )
1853
1877
  puts " 上传完成!!"
1854
1878
  # puts JSON.pretty_generate(in_app_purchase)
@@ -50,36 +50,10 @@ module Pindo
50
50
  load_ios_config
51
51
 
52
52
  # 1.5 获取 AdHoc 配置目录并合并配置
53
- adhoc_config_dir = nil
54
- begin
55
- config_parser = Pindo::IosConfigParser.instance
56
- config_json = config_parser.config_json
57
-
58
- # 根据 app_type 获取 AdHoc 配置仓库
59
- if config_json && config_json['project_info'] && config_json['project_info']['app_type']
60
- require 'pindo/config/build_info_manager'
61
-
62
- build_info_manager = Pindo::BuildInfoManager.share_instance
63
- adhoc_repo_name = build_info_manager.get_deploy_repo_with_modul_name(
64
- module_name: config_json['project_info']['app_type']
65
- )
66
-
67
- if adhoc_repo_name.nil? || adhoc_repo_name.empty?
68
- raise Informative, "config.json app_type is error!!!"
69
- end
70
-
71
- # 克隆 AdHoc 配置仓库
72
- adhoc_config_dir = Pindo::GitHandler.clong_buildconfig_repo(repo_name: adhoc_repo_name)
73
-
74
- # 合并 AdHoc 配置
75
- config_parser.modify_config_with_adhoc(adhoc_config_dir: adhoc_config_dir)
76
- else
77
- puts "配置中缺少 app_type,跳过 AdHoc 配置合并"
78
- end
79
- rescue => e
80
- puts "获取 AdHoc 配置失败: #{e.message}"
81
- adhoc_config_dir = nil
82
- end
53
+ # 复用 BuildInfoManager(命令层在导出前可能已合并过,幂等短路直接返回缓存目录)
54
+ # 合并失败 fail-fast:抛 Informative 由 TaskManager 标记任务失败
55
+ require 'pindo/config/build_info_manager'
56
+ adhoc_config_dir = Pindo::BuildInfoManager.share_instance.merge_adhoc_config_into_parser
83
57
 
84
58
  # 2. 自动增加版本号
85
59
  auto_increase_buildnumber
@@ -78,11 +78,21 @@ module Pindo
78
78
  latest_output = all_outputs.max_by { |f| File.mtime(f) }
79
79
  output_type = latest_output.end_with?('.ipa') ? 'IPA' : 'APP'
80
80
  puts " 找到 #{output_type} 文件: #{latest_output}"
81
- latest_output
82
- else
83
- puts " 警告: 未找到 IPA 或 APP 文件"
84
- nil
81
+ return latest_output
82
+ end
83
+
84
+ # 命令行工具产物为裸可执行文件(build 根目录下无扩展名的普通文件)
85
+ tool_outputs = Dir.glob(File.join(build_dir, "*")).select do |f|
86
+ File.file?(f) && File.extname(f).empty?
85
87
  end
88
+ if tool_outputs.any?
89
+ latest_output = tool_outputs.max_by { |f| File.mtime(f) }
90
+ puts " 找到命令行工具可执行文件: #{latest_output}"
91
+ return latest_output
92
+ end
93
+
94
+ puts " 警告: 未找到 IPA / APP / 可执行文件"
95
+ nil
86
96
  end
87
97
 
88
98
  # 处理 CocoaPods 依赖(Dev 构建)
@@ -51,93 +51,108 @@ module Pindo
51
51
 
52
52
  root_dir = @git_root_path
53
53
  git_repo_helper = Pindo::GitRepoHelper.share_instance
54
- stash_saved = false
55
54
  stash_name = "pindo_stash_#{Time.now.strftime('%Y%m%d%H%M%S')}_#{rand(1000)}"
56
55
  coding_branch = Pindo::GitHandler.git!(%W(-C #{root_dir} rev-parse --abbrev-ref HEAD)).strip
56
+ git_commit_data = get_data_param_by_key(:git_commit)
57
+ stash_saved = false
57
58
 
58
59
  begin
59
- # 1. 检查工作目录,不干净则 stash
60
- status = Pindo::GitHandler.git!(%W(-C #{root_dir} status --porcelain)).strip
61
- unless status.empty?
62
- Funlog.instance.fancyinfo_update("工作目录有未提交更改,暂存到 stash: #{stash_name}")
63
- Pindo::GitHandler.git!(%W(-C #{root_dir} stash push -u -m #{stash_name}))
64
- stash_saved = true
65
- end
66
-
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)
78
- if coding_branch != @release_branch
79
- Pindo::GitHandler.merge_branches(
80
- project_dir: root_dir,
81
- source_branch: coding_branch,
82
- target_branch: @release_branch,
83
- sync_branches: true # 双向合并,确保两分支完全同步
84
- )
85
- end
86
-
87
- # 4. 获取版本信息
88
- if git_commit_data && git_commit_data[:task_param] &&
89
- git_commit_data[:task_param][:build_version] && git_commit_data[:task_param][:build_number]
90
- @build_version = git_commit_data[:task_param][:build_version]
91
- @build_number = git_commit_data[:task_param][:build_number]
92
- Funlog.instance.fancyinfo_success("使用 GitCommitTask 的版本号: #{@build_version}, Build: #{@build_number}, Tag前缀: #{@tag_pre}, Tag类型: #{@tag_type}")
93
-
94
- # 降级:自己计算(向后兼容或 GitCommitTask 无有效数据)
95
- else
96
- @build_number, @commit_hash = git_repo_helper.get_build_number_from_commit(project_dir: root_dir)
97
- @build_version = git_repo_helper.calculate_build_version(
98
- project_dir: root_dir,
99
- tag_prefix: @tag_pre,
100
- create_tag_type: @tag_type,
101
- version_increase_type: @ver_inc
102
- )
103
- commit_short = @commit_hash ? @commit_hash[0..7] : "unknown"
104
- Funlog.instance.fancyinfo_warning("未找到 GitCommitTask 依赖,降级为自己计算版本号: #{@build_version}, Build: #{@build_number}, Commit: #{commit_short}")
105
- end
106
-
107
- # 4. 创建并推送 Tag
60
+ # 1. 工作目录不干净则暂存
61
+ stash_saved = stash_if_dirty(root_dir, stash_name)
62
+
63
+ # 2. GitCommitTask 回填参数(须在合并之前,确保 release_branch 等正确)
64
+ backfill_params_from_commit_task(git_commit_data)
65
+
66
+ # 3. 合并到发布分支
67
+ merge_to_release_branch(root_dir, coding_branch)
68
+
69
+ # 4. 解析版本号
70
+ resolve_build_version(root_dir, git_commit_data, git_repo_helper)
71
+
72
+ # 5. 创建并推送 Tag
108
73
  tag_name = "#{@tag_pre}#{@build_version}"
109
74
  git_repo_helper.create_and_push_tag(
110
75
  project_dir: root_dir,
111
76
  tag_name: tag_name,
112
77
  tag_type: @tag_type
113
78
  )
114
-
115
79
  ensure
116
- # 5. 还原 stash
117
-
118
- if stash_saved
119
- begin
120
- # 查找指定名字的 stash
121
- stash_list = Pindo::GitHandler.git!(%W(-C #{root_dir} stash list)).strip
122
- matched_line = stash_list.lines.find { |l| l.include?(stash_name) }
123
-
124
- if matched_line && (stash_id = matched_line.match(/(stash@\{\d+\})/)&.[](1))
125
- # 先应用 stash(不删除)
126
- Pindo::GitHandler.git!(%W(-C #{root_dir} stash apply #{stash_id}))
127
- # 应用成功后再删除 stash
128
- Pindo::GitHandler.git!(%W(-C #{root_dir} stash drop #{stash_id}))
129
- Funlog.instance.fancyinfo_success("已还原 stash: #{stash_name} (#{stash_id})")
130
- else
131
- Funlog.instance.fancyinfo_warning("未找到名为 #{stash_name} 的 stash,请手动检查")
132
- end
133
- rescue => e
134
- # 如果应用失败(通常是有冲突),stash 仍然保留,用户可以手动处理
135
- Funlog.instance.fancyinfo_warning("stash 还原时发生冲突: #{e.message}")
136
- Funlog.instance.fancyinfo_warning("stash 已保留,请手动执行 'git stash pop' 处理冲突")
137
- # 不抛出异常,任务仍然标记为成功(因为 tag 已经创建成功)
138
- end
139
- end
80
+ # 6. 还原 stash
81
+ restore_stash(root_dir, stash_name) if stash_saved
82
+ end
83
+ end
84
+
85
+ private
86
+
87
+ # 工作目录有未提交更改则暂存,返回是否已暂存
88
+ def stash_if_dirty(root_dir, stash_name)
89
+ status = Pindo::GitHandler.git!(%W(-C #{root_dir} status --porcelain)).strip
90
+ return false if status.empty?
91
+
92
+ Funlog.instance.fancyinfo_update("工作目录有未提交更改,暂存到 stash: #{stash_name}")
93
+ Pindo::GitHandler.git!(%W(-C #{root_dir} stash push -u -m #{stash_name}))
94
+ true
95
+ end
96
+
97
+ # GitCommitTask 回填 release_branch / tag_pre / tag_type / ver_inc
98
+ def backfill_params_from_commit_task(git_commit_data)
99
+ return unless git_commit_data && git_commit_data[:task_param]
100
+
101
+ param = git_commit_data[:task_param]
102
+ @release_branch = param[:release_branch] if param[:release_branch]
103
+ @tag_pre = param[:tag_pre] if param[:tag_pre]
104
+ @tag_type = param[:tag_type] if param[:tag_type]
105
+ @ver_inc = param[:ver_inc] if param[:ver_inc]
106
+ end
107
+
108
+ # 将编码分支双向合并到发布分支,确保两分支同步到同一节点
109
+ def merge_to_release_branch(root_dir, coding_branch)
110
+ return if coding_branch == @release_branch
111
+
112
+ Pindo::GitHandler.merge_branches(
113
+ project_dir: root_dir,
114
+ source_branch: coding_branch,
115
+ target_branch: @release_branch,
116
+ sync_branches: true # 双向合并,确保两分支完全同步
117
+ )
118
+ end
119
+
120
+ # 解析构建版本号:优先用 GitCommitTask 的,否则自己计算(向后兼容)
121
+ def resolve_build_version(root_dir, git_commit_data, git_repo_helper)
122
+ if git_commit_data && git_commit_data[:task_param] &&
123
+ git_commit_data[:task_param][:build_version] && git_commit_data[:task_param][:build_number]
124
+ @build_version = git_commit_data[:task_param][:build_version]
125
+ @build_number = git_commit_data[:task_param][:build_number]
126
+ Funlog.instance.fancyinfo_success("使用 GitCommitTask 的版本号: #{@build_version}, Build: #{@build_number}, Tag前缀: #{@tag_pre}, Tag类型: #{@tag_type}")
127
+ else
128
+ @build_number, @commit_hash = git_repo_helper.get_build_number_from_commit(project_dir: root_dir)
129
+ @build_version = git_repo_helper.calculate_build_version(
130
+ project_dir: root_dir,
131
+ tag_prefix: @tag_pre,
132
+ create_tag_type: @tag_type,
133
+ version_increase_type: @ver_inc
134
+ )
135
+ commit_short = @commit_hash ? @commit_hash[0..7] : "unknown"
136
+ Funlog.instance.fancyinfo_warning("未找到 GitCommitTask 依赖,降级为自己计算版本号: #{@build_version}, Build: #{@build_number}, Commit: #{commit_short}")
137
+ end
138
+ end
139
+
140
+ # 还原之前暂存的 stash;冲突时保留 stash 并告警,不抛异常(tag 已创建成功)
141
+ def restore_stash(root_dir, stash_name)
142
+ stash_list = Pindo::GitHandler.git!(%W(-C #{root_dir} stash list)).strip
143
+ matched_line = stash_list.lines.find { |l| l.include?(stash_name) }
144
+
145
+ if matched_line && (stash_id = matched_line.match(/(stash@\{\d+\})/)&.[](1))
146
+ # 先应用 stash(不删除),成功后再删除
147
+ Pindo::GitHandler.git!(%W(-C #{root_dir} stash apply #{stash_id}))
148
+ Pindo::GitHandler.git!(%W(-C #{root_dir} stash drop #{stash_id}))
149
+ Funlog.instance.fancyinfo_success("已还原 stash: #{stash_name} (#{stash_id})")
150
+ else
151
+ Funlog.instance.fancyinfo_warning("未找到名为 #{stash_name} 的 stash,请手动检查")
140
152
  end
153
+ rescue => e
154
+ Funlog.instance.fancyinfo_warning("stash 还原时发生冲突: #{e.message}")
155
+ Funlog.instance.fancyinfo_warning("stash 已保留,请手动执行 'git stash pop' 处理冲突")
141
156
  end
142
157
 
143
158
  end
@@ -1,5 +1,6 @@
1
1
  require 'pindo/module/task/model/unity_task'
2
2
  require 'pindo/base/funlog'
3
+ require 'json'
3
4
 
4
5
  module Pindo
5
6
  module TaskSystem
@@ -18,6 +19,7 @@ module Pindo
18
19
  # - :project_path [String] Unity 项目路径(默认当前目录)
19
20
  # - :export_path [String] 导出路径(nil 表示自动检测)
20
21
  # - :deploy_mode [String] 部署模式 ('dev', 'adhoc', 'release'),默认 'dev'
22
+ # - :app_config [Hash] 需写入工程 AppConfig 的键值(传入则在导出前先改写 AppConfig)
21
23
  # - :context [Hash] 上下文信息(如 index_count)
22
24
  def initialize(platform, options = {})
23
25
  @platform = platform
@@ -26,6 +28,7 @@ module Pindo
26
28
  @index_count = options[:context] ? options[:context][:index_count] : nil
27
29
  @export_path = options[:export_path] # 可由参数传入,nil 表示自动检测
28
30
  @deploy_mode = options[:deploy_mode] || 'dev' # 部署模式:dev/adhoc/release,默认 dev
31
+ @app_config = options[:app_config] # 需写入 AppConfig 的键值,nil/空表示跳过
29
32
 
30
33
  name = case platform
31
34
  when 'ios', 'ipa'
@@ -57,6 +60,9 @@ module Pindo
57
60
  protected
58
61
 
59
62
  def do_work
63
+ # 若传入了配置参数,先改写工程内的 AppConfig
64
+ update_app_config_file if @app_config && !@app_config.empty?
65
+
60
66
  # 获取 Unity 版本
61
67
  project_unity_version = get_unity_version
62
68
 
@@ -106,6 +112,44 @@ module Pindo
106
112
 
107
113
  private
108
114
 
115
+ # 使用传入的配置改写 Unity 工程内的 AppConfig(TextAsset JSON)
116
+ # 仅覆盖 @app_config 中提供的键,其余键保持原值
117
+ def update_app_config_file
118
+ app_config_file = File.join(@unity_root_path, "Assets", "Resources", "AppConfig", "AppConfig.json")
119
+ unless File.exist?(app_config_file)
120
+ Funlog.warning("未找到 AppConfig 文件,跳过 AppConfig 更新:#{app_config_file}")
121
+ return
122
+ end
123
+
124
+ puts "更新 AppConfig: #{app_config_file}"
125
+
126
+ begin
127
+ app_config_json = JSON.parse(File.read(app_config_file))
128
+ rescue JSON::ParserError => e
129
+ Funlog.warning("AppConfig 不是合法 JSON,跳过更新:#{e.message}")
130
+ return
131
+ end
132
+
133
+ changed = false
134
+ @app_config.each do |key, value|
135
+ next if value.nil? || value.to_s.strip.empty?
136
+ new_value = value.to_s.strip
137
+ old_value = app_config_json[key]
138
+ next if old_value.to_s == new_value
139
+
140
+ app_config_json[key] = new_value
141
+ puts " ✓ #{key}: #{old_value} → #{new_value}"
142
+ changed = true
143
+ end
144
+
145
+ if changed
146
+ File.open(app_config_file, "w") { |f| f.write(JSON.pretty_generate(app_config_json)) }
147
+ puts "✅ AppConfig 更新完成\n"
148
+ else
149
+ puts "AppConfig 无需更新(值一致)\n"
150
+ end
151
+ end
152
+
109
153
  # 导出 iOS
110
154
  def export_ios
111
155
  platform = 'iOS'
@@ -41,12 +41,57 @@ module Pindo
41
41
  end
42
42
  end
43
43
 
44
+ # 按依赖拓扑排序展示真实执行顺序
45
+ ordered = topological_execution_order(@queue.pending_snapshot)
46
+ is_serial = strategy.respond_to?(:name) && strategy.name.include?("串行")
47
+ puts "\e[34m"
48
+ if is_serial
49
+ puts "\e[34m" + " 实际执行顺序:"
50
+ else
51
+ puts "\e[34m" + " 执行顺序预览(并发模式下实际顺序受运行时调度影响):"
52
+ end
53
+ ordered.each_with_index do |task, index|
54
+ puts "\e[34m" + " #{index + 1}. #{task.name}"
55
+ end
56
+
44
57
  puts "\e[34m"
45
58
  puts "\e[34m" + " 总计: #{@queue.pending_count} 个任务"
46
59
  puts "\e[34m" + "=" * 60 + "\e[0m"
47
60
  puts "\n"
48
61
  end
49
62
 
63
+ # 按依赖关系生成执行顺序(贪心拓扑排序,模拟串行调度:
64
+ # 每轮取「入队顺序中第一个依赖已满足」的任务),与串行实际执行顺序一致
65
+ # @param tasks [Array<PindoTask>] 待排序任务(入队顺序)
66
+ # @return [Array<PindoTask>] 按执行顺序排列的任务
67
+ def topological_execution_order(tasks)
68
+ all_ids = tasks.map(&:id)
69
+ remaining = tasks.dup
70
+ completed_ids = []
71
+ ordered = []
72
+
73
+ until remaining.empty?
74
+ index = remaining.index do |task|
75
+ task.dependencies.all? do |dep_id|
76
+ # 依赖已完成,或依赖不在本批任务中(视为已提前完成)
77
+ completed_ids.include?(dep_id) || !all_ids.include?(dep_id)
78
+ end
79
+ end
80
+
81
+ # 存在循环依赖或依赖缺失,剩余任务按原顺序追加并结束
82
+ if index.nil?
83
+ ordered.concat(remaining)
84
+ break
85
+ end
86
+
87
+ task = remaining.delete_at(index)
88
+ completed_ids << task.id
89
+ ordered << task
90
+ end
91
+
92
+ ordered
93
+ end
94
+
50
95
  # 输出任务执行标题
51
96
  # @param task [PindoTask] 任务对象
52
97
  def print_task_title(task)