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.
- checksums.yaml +4 -4
- data/lib/pindo/base/git_handler.rb +17 -29
- data/lib/pindo/command/appstore/adhocbuild.rb +13 -2
- data/lib/pindo/command/appstore/autobuild.rb +2 -1
- data/lib/pindo/command/appstore/iap.rb +58 -54
- data/lib/pindo/config/build_info_manager.rb +31 -0
- data/lib/pindo/config/ios_config_parser.rb +212 -140
- data/lib/pindo/module/appstore/appstore_in_app_purchase.rb +80 -56
- data/lib/pindo/module/task/model/build/ios_build_adhoc_task.rb +4 -30
- data/lib/pindo/module/task/model/build/ios_build_dev_task.rb +14 -4
- data/lib/pindo/module/task/model/git/git_tag_task.rb +90 -75
- data/lib/pindo/module/task/model/unity/unity_export_task.rb +44 -0
- data/lib/pindo/module/task/task_reporter.rb +45 -0
- data/lib/pindo/module/utils/git_repo_helper.rb +40 -2
- data/lib/pindo/module/xcode/res/xcode_res_handler.rb +25 -4
- data/lib/pindo/module/xcode/xcode_build_config.rb +7 -1
- data/lib/pindo/module/xcode/xcode_build_helper.rb +36 -4
- data/lib/pindo/module/xcode/xcode_res_helper.rb +8 -0
- data/lib/pindo/options/helpers/bundleid_selector.rb +23 -6
- data/lib/pindo/version.rb +1 -1
- metadata +2 -2
|
@@ -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
|
-
|
|
190
|
-
|
|
191
|
-
|
|
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
|
-
|
|
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
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
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
|
-
|
|
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
|
-
|
|
411
|
+
manualPrices: {
|
|
400
412
|
data: [
|
|
401
413
|
{
|
|
402
414
|
type: 'inAppPurchasePrices',
|
|
@@ -404,7 +416,7 @@ module Pindo
|
|
|
404
416
|
}
|
|
405
417
|
]
|
|
406
418
|
},
|
|
407
|
-
|
|
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
|
-
|
|
492
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
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
|
-
|
|
932
|
-
|
|
933
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1628
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1818
|
-
|
|
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
|
-
|
|
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
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
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
|
-
|
|
83
|
-
|
|
84
|
-
|
|
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.
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
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
|
-
#
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
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)
|