pindo 5.13.12 → 5.13.13

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 (50) hide show
  1. checksums.yaml +4 -4
  2. data/lib/pindo/base/funlog.rb +62 -5
  3. data/lib/pindo/base/git_handler.rb +83 -22
  4. data/lib/pindo/base/output_sink.rb +69 -0
  5. data/lib/pindo/command/android/autobuild.rb +57 -8
  6. data/lib/pindo/command/appstore/autobuild.rb +10 -1
  7. data/lib/pindo/command/ios/autobuild.rb +59 -7
  8. data/lib/pindo/command/jps/media.rb +164 -13
  9. data/lib/pindo/command/jps/upload.rb +14 -9
  10. data/lib/pindo/command/unity/autobuild.rb +64 -10
  11. data/lib/pindo/command/utils/tag.rb +9 -1
  12. data/lib/pindo/command/web/autobuild.rb +59 -10
  13. data/lib/pindo/module/android/android_build_helper.rb +6 -7
  14. data/lib/pindo/module/build/git_repo_helper.rb +29 -25
  15. data/lib/pindo/module/pgyer/pgyerhelper.rb +174 -77
  16. data/lib/pindo/module/task/core/concurrent_execution_strategy.rb +237 -0
  17. data/lib/pindo/module/task/core/dependency_checker.rb +123 -0
  18. data/lib/pindo/module/task/core/execution_strategy.rb +61 -0
  19. data/lib/pindo/module/task/core/resource_lock_manager.rb +190 -0
  20. data/lib/pindo/module/task/core/serial_execution_strategy.rb +60 -0
  21. data/lib/pindo/module/task/core/task_executor.rb +131 -0
  22. data/lib/pindo/module/task/core/task_queue.rb +221 -0
  23. data/lib/pindo/module/task/model/build/android_build_dev_task.rb +1 -1
  24. data/lib/pindo/module/task/model/build/android_build_task.rb +6 -2
  25. data/lib/pindo/module/task/model/build/ios_build_dev_task.rb +2 -3
  26. data/lib/pindo/module/task/model/build/ios_build_task.rb +6 -0
  27. data/lib/pindo/module/task/model/build_task.rb +22 -0
  28. data/lib/pindo/module/task/model/git/git_commit_task.rb +11 -2
  29. data/lib/pindo/module/task/model/git_task.rb +6 -0
  30. data/lib/pindo/module/task/model/jps/jps_message_task.rb +9 -11
  31. data/lib/pindo/module/task/model/jps/jps_upload_media_task.rb +204 -103
  32. data/lib/pindo/module/task/model/jps_task.rb +0 -1
  33. data/lib/pindo/module/task/model/unity_task.rb +38 -2
  34. data/lib/pindo/module/task/output/multi_line_output_manager.rb +380 -0
  35. data/lib/pindo/module/task/output/multi_line_task_display.rb +185 -0
  36. data/lib/pindo/module/task/output/stdout_redirector.rb +95 -0
  37. data/lib/pindo/module/task/pindo_task.rb +133 -9
  38. data/lib/pindo/module/task/task_manager.rb +98 -268
  39. data/lib/pindo/module/task/task_reporter.rb +135 -0
  40. data/lib/pindo/module/task/task_resources/resource_instance.rb +90 -0
  41. data/lib/pindo/module/task/task_resources/resource_registry.rb +105 -0
  42. data/lib/pindo/module/task/task_resources/resource_type.rb +59 -0
  43. data/lib/pindo/module/task/task_resources/types/directory_based_resource.rb +63 -0
  44. data/lib/pindo/module/task/task_resources/types/global_exclusive_resource.rb +33 -0
  45. data/lib/pindo/module/task/task_resources/types/global_shared_resource.rb +34 -0
  46. data/lib/pindo/module/xcode/xcode_build_helper.rb +26 -8
  47. data/lib/pindo/options/groups/jps_options.rb +10 -0
  48. data/lib/pindo/options/groups/task_options.rb +39 -0
  49. data/lib/pindo/version.rb +3 -2
  50. metadata +20 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 497b5a13a5d90bf725ce1fbdac76ec095a49dcf200783d0ce5d58949255e6a44
4
- data.tar.gz: 9d0cab4c002042fbac5f6d35d055f326f9c2cfd79713eb9112ac18c92ff5f7dd
3
+ metadata.gz: 44e7745ee889a73f1bfde8da7fdad6248961b0224ca3856e42f5a0556c96c231
4
+ data.tar.gz: 16f43bbe108555f3c831dc987f2d78f7ad5f46a881d6b7d1b0c13c9e47df4e3c
5
5
  SHA512:
6
- metadata.gz: a21ddb1cacb9302d007ee9fd68325e3c5cf5210fc39bb182d8d807b2929a7eb0ba659c7d850a59879b523116ada91da9c640c2837eac73203f9808873f57fd53
7
- data.tar.gz: 944d1f52b0366dcb6c0b333ed0d7c08db1ad2bf4203aaf449492fa911f7a65be9b2c467f37472684049b645fd215da4b2f788c70e4cbfb7b9ed2790df7101e86
6
+ metadata.gz: 1eece9a615272a404bbbb98838465ae501601193a5be99acc95cf5c95a10429ec8decd24a1ccc97c2cea90241d88068ce73c6f1cf94d2110c110a73ca5da7cb5
7
+ data.tar.gz: ff1bb8df725f4b3c6a1196b7e01e3e82538587c5d9000dd4da8f4cf6759d418f767e90c4174f89305866d5969e3d7e2ff2f8b899c279880ae4c6beb7db419a5f
@@ -30,8 +30,17 @@ module Pindo
30
30
 
31
31
  def fancyinfo_update(*args)
32
32
  message = args.join(" ")
33
- spinner_log_handle.update(title:message)
34
- spinner_log_handle.spin
33
+
34
+ # 检查是否在任务上下文中
35
+ if Funlog.in_task_context?
36
+ # 并发模式:不更新终端,只写日志
37
+ Funlog.current_output_sink.log_info(Funlog.current_task_id, message)
38
+ else
39
+ # 串行模式:使用 spinner
40
+ spinner_log_handle.update(title:message)
41
+ spinner_log_handle.spin
42
+ end
43
+
35
44
  @spinner_log
36
45
  end
37
46
 
@@ -62,21 +71,45 @@ module Pindo
62
71
  # @param args [Array] 要输出的消息
63
72
  def info(*args)
64
73
  message = args.join(" ")
65
- puts " ✓ #{message}"
74
+
75
+ # 检查是否在任务上下文中
76
+ if Funlog.in_task_context?
77
+ # 并发模式:路由到输出管理器(只写日志文件)
78
+ Funlog.current_output_sink.log_info(Funlog.current_task_id, message)
79
+ else
80
+ # 串行模式:保持原有行为
81
+ puts " ✓ #{message}"
82
+ end
66
83
  end
67
84
 
68
85
  # 输出静态警告信息(不使用spinner)
69
86
  # @param args [Array] 要输出的消息
70
87
  def warning(*args)
71
88
  message = args.join(" ")
72
- puts "\e[33m ⚠ #{message}\e[0m"
89
+
90
+ # 检查是否在任务上下文中
91
+ if Funlog.in_task_context?
92
+ # 并发模式:路由到输出管理器
93
+ Funlog.current_output_sink.log_warning(Funlog.current_task_id, message)
94
+ else
95
+ # 串行模式:保持原有行为
96
+ puts "\e[33m ⚠ #{message}\e[0m"
97
+ end
73
98
  end
74
99
 
75
100
  # 输出静态错误信息(不使用spinner,对应 fancyinfo_error)
76
101
  # @param args [Array] 要输出的消息
77
102
  def error(*args)
78
103
  message = args.join(" ")
79
- puts "\e[31m ✗ #{message}\e[0m"
104
+
105
+ # 检查是否在任务上下文中
106
+ if Funlog.in_task_context?
107
+ # 并发模式:路由到输出管理器
108
+ Funlog.current_output_sink.log_error(Funlog.current_task_id, message)
109
+ else
110
+ # 串行模式:保持原有行为
111
+ puts "\e[31m ✗ #{message}\e[0m"
112
+ end
80
113
  end
81
114
 
82
115
  #-------------------------------------------------------------------------#
@@ -103,8 +136,32 @@ module Pindo
103
136
  class << self
104
137
  attr_writer :instance
105
138
 
139
+ # ============================================
140
+ # 线程局部上下文支持(并发输出管理)
141
+ # ============================================
142
+
143
+ # 获取当前线程的输出接收器
144
+ # @return [OutputSink, nil] 输出接收器或 nil
145
+ def current_output_sink
146
+ Thread.current[:output_sink]
147
+ end
148
+
149
+ # 获取当前线程的任务 ID
150
+ # @return [String, nil] 任务 ID 或 nil
151
+ def current_task_id
152
+ Thread.current[:task_id]
153
+ end
154
+
155
+ # 检查是否在任务上下文中
156
+ # @return [Boolean] 是否在任务上下文中
157
+ def in_task_context?
158
+ !current_output_sink.nil? && !current_task_id.nil?
159
+ end
160
+
161
+ # ============================================
106
162
  # 类方法委托,简化调用方式
107
163
  # 使用 Funlog.info("消息") 代替 Funlog.instance.info("消息")
164
+ # ============================================
108
165
 
109
166
  def fancyinfo_start(*args)
110
167
  instance.fancyinfo_start(*args)
@@ -505,6 +505,10 @@ module Pindo
505
505
  handle_delete_all(current_project_dir, coding_branch)
506
506
  when 'stash', '保存到stash区域', '保存到stash区域(改代码本次不生效)'
507
507
  handle_stash(current_project_dir, coding_branch)
508
+ when 'skip', '跳过'
509
+ # 跳过处理,不做任何操作
510
+ Funlog.instance.warning("跳过提交,可能导致 build number 与代码仓库不一致")
511
+ return
508
512
  when 'exit', '先退出,手动来处理退出'
509
513
  raise Informative, "请手动处理未提交的文件!!!"
510
514
  else
@@ -547,7 +551,7 @@ module Pindo
547
551
 
548
552
  def handle_commit_all(project_dir, branch, commit_message = nil)
549
553
  # 使用传入的 commit_message,如果没有则使用默认值
550
- message = commit_message || "release code"
554
+ message = commit_message || "build: 构建产生提交"
551
555
 
552
556
  Funlog.instance.fancyinfo_start("开始提交文件...")
553
557
  git! ['add', '-A']
@@ -624,6 +628,68 @@ module Pindo
624
628
  end
625
629
  end
626
630
 
631
+ # 获取最新的符合规范的 commit
632
+ # @param project_dir [String] 项目目录路径
633
+ # @return [Hash] 包含 :commit_id, :commit_time, :commit_desc
634
+ def get_latest_conventional_commit(project_dir:nil)
635
+ result = {
636
+ commit_id: nil,
637
+ commit_time: nil,
638
+ commit_desc: nil
639
+ }
640
+
641
+ return result if project_dir.nil? || !File.exist?(project_dir)
642
+
643
+ Dir.chdir(project_dir) do
644
+ # 获取最近 15 条 commit 历史
645
+ output = `git log -15 --format="%H|%ci|%s" 2>/dev/null`.strip
646
+
647
+ if output.empty?
648
+ Funlog.instance.warning("未找到 git commit 历史")
649
+ return result
650
+ end
651
+
652
+ # 解析 commit 列表
653
+ commits = output.split("\n").map do |line|
654
+ parts = line.split('|', 3)
655
+ {
656
+ commit_id: parts[0],
657
+ commit_time: parts[1],
658
+ commit_desc: parts[2]
659
+ }
660
+ end
661
+
662
+ # 定义符合规范的提交类型
663
+ valid_prefixes = ['feat:', 'fix:', 'docs:', 'style:', 'refactor:', 'perf:', 'test:', 'build:', 'ci:', 'chore:', 'revert:']
664
+
665
+ # 筛选符合规范的提交
666
+ conventional_commits = commits.select do |commit|
667
+ desc = commit[:commit_desc].to_s.strip
668
+ valid_prefixes.any? { |prefix| desc.downcase.start_with?(prefix) }
669
+ end
670
+
671
+ if conventional_commits.empty?
672
+ Funlog.instance.warning("在最近15个提交中未找到符合规范的提交(feat:, fix: 等开头)")
673
+ Funlog.instance.warning("使用最新的提交(HEAD)")
674
+
675
+ # 降级:使用 HEAD
676
+ result[:commit_id] = commits.first[:commit_id]
677
+ result[:commit_time] = commits.first[:commit_time]
678
+ result[:commit_desc] = commits.first[:commit_desc]
679
+ else
680
+ # 使用最新的符合规范的提交(第一个)
681
+ latest = conventional_commits.first
682
+ result[:commit_id] = latest[:commit_id]
683
+ result[:commit_time] = latest[:commit_time]
684
+ result[:commit_desc] = latest[:commit_desc]
685
+
686
+ puts " 找到符合规范的提交: #{result[:commit_desc]}"
687
+ end
688
+ end
689
+
690
+ result
691
+ end
692
+
627
693
  # 创建新的版本标签
628
694
  # @param project_dir [String] 项目目录路径
629
695
  # @param tag_prefix [String] 标签前缀
@@ -718,25 +784,30 @@ module Pindo
718
784
  end
719
785
  end
720
786
 
721
- # 检查并处理未提交的文件(交互式)
787
+ # 获取未提交文件的处理方式
722
788
  # @param project_dir [String] 项目目录路径
723
- # @return [void]
724
- def check_uncommitted_files(project_dir:)
789
+ # @param interactive [Boolean] 是否允许交互,默认为 true
790
+ # @return [String] 处理方式 ('commit', 'skip', 'reset', 'stash', 'exit')
791
+ def get_uncommitted_files_process_type(project_dir:, interactive: true)
725
792
  # 1. 检查是否有未提交的文件
726
793
  uncommitted_files = get_uncommitted_files(project_dir: project_dir)
727
794
 
728
- # 2. 如果没有未提交的文件,直接返回
729
- return if uncommitted_files.nil? || uncommitted_files.empty?
795
+ # 2. 如果没有未提交的文件,默认跳过
796
+ return 'skip' if uncommitted_files.nil? || uncommitted_files.empty?
730
797
 
731
- # 3. 获取当前分支名
732
- current_branch = git!(%W(-C #{project_dir} rev-parse --abbrev-ref HEAD)).strip
798
+ # 3. 如果非交互模式,默认跳过
799
+ unless interactive
800
+ Funlog.instance.info("当前处于非交互模式,默认跳过未提交文件的处理。")
801
+ return 'skip'
802
+ end
733
803
 
734
- # 4. 显示文件状态
804
+ # 4. 获取当前分支名并显示状态
805
+ current_branch = git!(%W(-C #{project_dir} rev-parse --abbrev-ref HEAD)).strip
735
806
  display_file_status(current_branch, uncommitted_files)
736
807
 
737
- # 5. 让用户选择处理方式
808
+ # 5. 交互式选择
738
809
  cli = HighLine.new
739
- process_type = cli.choose do |menu|
810
+ cli.choose do |menu|
740
811
  menu.header = "仓库有未提交的修改,请选择处理方式"
741
812
  menu.prompt = "请输入选项(1/2/3/4/5):"
742
813
  menu.choice("(commit) 全部提交") { 'commit' }
@@ -745,19 +816,9 @@ module Pindo
745
816
  menu.choice("(stash) 保存到stash区域(该部分代码本次不生效)") { 'stash' }
746
817
  menu.choice("(exit) 先退出,手动来处理退出") { 'exit' }
747
818
  end
819
+ end
748
820
 
749
- # 6. 如果用户选择跳过,输出警告信息并返回
750
- if process_type == 'skip'
751
- Funlog.instance.warning("跳过提交,可能导致 build number 与代码仓库不一致")
752
- return
753
- end
754
821
 
755
- # 7. 处理未提交的文件
756
- process_need_add_files(
757
- project_dir: project_dir,
758
- process_type: process_type
759
- )
760
- end
761
822
 
762
823
  # 合并到发布分支
763
824
  # @param project_dir [String] 项目目录
@@ -0,0 +1,69 @@
1
+ module Pindo
2
+ # 输出接收器抽象接口
3
+ # 定义了任务输出管理器必须实现的标准接口
4
+ # 使用依赖倒置原则 (DIP),让 Funlog 等基础模块依赖此抽象而非具体实现
5
+ class OutputSink
6
+ # 记录 INFO 级别日志
7
+ # @param task_id [String] 任务 ID
8
+ # @param message [String] 消息内容
9
+ def log_info(task_id, message)
10
+ raise NotImplementedError, "#{self.class} must implement #log_info"
11
+ end
12
+
13
+ # 记录 WARNING 级别日志
14
+ # @param task_id [String] 任务 ID
15
+ # @param message [String] 警告消息
16
+ def log_warning(task_id, message)
17
+ raise NotImplementedError, "#{self.class} must implement #log_warning"
18
+ end
19
+
20
+ # 记录 ERROR 级别日志
21
+ # @param task_id [String] 任务 ID
22
+ # @param message [String] 错误消息
23
+ def log_error(task_id, message)
24
+ raise NotImplementedError, "#{self.class} must implement #log_error"
25
+ end
26
+
27
+ # 更新任务进度(终端可见)
28
+ # @param task_id [String] 任务 ID
29
+ # @param message [String] 进度消息
30
+ def update_progress(task_id, message)
31
+ raise NotImplementedError, "#{self.class} must implement #update_progress"
32
+ end
33
+
34
+ # 更新当前行(不滚动,用于进度百分比)
35
+ # @param task_id [String] 任务 ID
36
+ # @param message [String] 更新消息
37
+ def update_current_line(task_id, message)
38
+ raise NotImplementedError, "#{self.class} must implement #update_current_line"
39
+ end
40
+
41
+ # 记录详细日志(如命令输出、编译日志)
42
+ # @param task_id [String] 任务 ID
43
+ # @param message [String] 详细日志内容
44
+ def log_detail(task_id, message)
45
+ raise NotImplementedError, "#{self.class} must implement #log_detail"
46
+ end
47
+
48
+ # 任务开始
49
+ # @param task_id [String] 任务 ID
50
+ def start_task(task_id)
51
+ raise NotImplementedError, "#{self.class} must implement #start_task"
52
+ end
53
+
54
+ # 任务成功
55
+ # @param task_id [String] 任务 ID
56
+ # @param message [String, nil] 成功消息
57
+ # @param execution_time [Float, nil] 执行时间(秒)
58
+ def success_task(task_id, message = nil, execution_time: nil)
59
+ raise NotImplementedError, "#{self.class} must implement #success_task"
60
+ end
61
+
62
+ # 任务失败
63
+ # @param task_id [String] 任务 ID
64
+ # @param error_message [String] 错误消息
65
+ def error_task(task_id, error_message)
66
+ raise NotImplementedError, "#{self.class} must implement #error_task"
67
+ end
68
+ end
69
+ end
@@ -13,6 +13,7 @@ require 'pindo/module/task/model/unity/unity_yoo_asset_task'
13
13
  require 'pindo/module/task/model/unity/unity_export_task'
14
14
  require 'pindo/module/task/model/build_task'
15
15
  require 'pindo/module/task/model/jps/jps_upload_task'
16
+ require 'pindo/module/task/model/jps/jps_upload_media_task'
16
17
  require 'pindo/module/task/model/jps/jps_message_task'
17
18
  require 'pindo/options/options'
18
19
 
@@ -44,6 +45,8 @@ module Pindo
44
45
 
45
46
  * 支持Unity和原生Android工程
46
47
 
48
+ * 支持并发任务执行(使用 --multi 参数)
49
+
47
50
  使用示例:
48
51
 
49
52
  $ pindo android autobuild # 编译Debug包
@@ -54,17 +57,24 @@ module Pindo
54
57
 
55
58
  $ pindo android autobuild --send # 编译、上传并发送群组通知
56
59
 
60
+ $ pindo android autobuild --media # 编译、上传并上传媒体附件
61
+
57
62
  $ pindo android autobuild --bundle_name=com.example.app # 使用指定bundle name的配置
58
63
 
59
64
  $ pindo android autobuild --proj="My App" # 指定项目名称
65
+
66
+ $ pindo android autobuild --multi # 使用并发模式执行(速度更快)
67
+
68
+ $ pindo android autobuild --multi --upload # 并发执行并上传
60
69
  DESC
61
70
 
62
71
  # 定义此命令使用的参数项
63
72
  def self.option_items
64
73
  @option_items ||= Pindo::Options::OptionGroup.merge(
65
- Pindo::Options::JPSOptions.select(:proj, :upload, :send),
74
+ Pindo::Options::JPSOptions.select(:proj, :upload, :send, :media),
66
75
  Pindo::Options::UnityOptions.select(:skiplib, :skipyoo),
67
76
  Pindo::Options::UnityOptions.select_with_defaults(skipconfig: true),
77
+ Pindo::Options::TaskOptions.select(:multi),
68
78
  Pindo::Options::GitOptions.all
69
79
  )
70
80
  end
@@ -86,6 +96,11 @@ module Pindo
86
96
  @args_bundle_name = argv.option('bundle_name')
87
97
  @args_skip_lib = @options[:skiplib] || false
88
98
  @args_skip_yoo = @options[:skipyoo] || false
99
+ # media 依赖 upload:如果指定了 media,自动启用 upload
100
+ @args_media_flag = @options[:media] || false
101
+
102
+ # Task 参数
103
+ @args_multi_flag = @options[:multi] || false
89
104
 
90
105
  # Git 参数
91
106
  @args_release_branch = @options[:release_branch] || 'master'
@@ -93,7 +108,7 @@ module Pindo
93
108
  @args_tag_type = Pindo::Options::GitOptions.parse_create_tag_type(@options[:tag_type] || 'new')
94
109
  @args_tag_pre = @options[:tag_pre] || 'v'
95
110
 
96
- if @args_send_flag
111
+ if @args_send_flag || @args_media_flag
97
112
  @args_upload_flag = true
98
113
  end
99
114
 
@@ -117,7 +132,13 @@ module Pindo
117
132
  task_manager = Pindo::TaskSystem::TaskManager.instance
118
133
  task_manager.clear_all
119
134
  tasks.each { |task| task_manager.add_task(task) }
120
- task_manager.start
135
+
136
+ # 执行任务(根据 --multi 参数决定模式)
137
+ if @args_multi_flag
138
+ task_manager.start(mode: :concurrent, max_workers: 3)
139
+ else
140
+ task_manager.start
141
+ end
121
142
 
122
143
  system "open #{pindo_project_dir}"
123
144
  end
@@ -160,12 +181,19 @@ module Pindo
160
181
  tasks = []
161
182
 
162
183
  # 1. Git 提交任务
184
+ # 提前询问用户如何处理未提交的文件
185
+ process_type = Pindo::GitHandler.get_uncommitted_files_process_type(
186
+ project_dir: config[:project_path],
187
+ interactive: true
188
+ )
163
189
  git_commit_task = Pindo::TaskSystem::GitCommitTask.new(
164
190
  config[:project_path],
165
191
  release_branch: @args_release_branch,
166
192
  ver_inc: @args_ver_inc,
167
193
  tag_type: @args_tag_type,
168
- tag_pre: @args_tag_pre
194
+ tag_pre: @args_tag_pre,
195
+ process_type: process_type,
196
+ commit_message: "feat: android autobuild 构建前提交"
169
197
  )
170
198
  tasks << git_commit_task
171
199
 
@@ -260,7 +288,7 @@ module Pindo
260
288
 
261
289
  # 5. 上传和消息发送任务(如果需要)
262
290
  if @args_upload_flag
263
- # 4.1 创建上传任务
291
+ # 5.1 创建上传任务
264
292
  upload_task = Pindo::TaskSystem::JPSUploadTask.new(
265
293
  'apk',
266
294
  File.join(android_project_path, 'build'),
@@ -272,19 +300,40 @@ module Pindo
272
300
  upload_task.dependencies << build_task.id
273
301
  tasks << upload_task
274
302
 
275
- # 4.2 创建消息发送任务(依赖上传任务)
303
+ # 5.2 创建消息发送任务(只依赖上传任务)
276
304
  # app_version_info 将从 upload_task 的数据参数中获取
277
305
  message_task = Pindo::TaskSystem::JPSMessageTask.new(
278
306
  nil, # app_version_info 为 nil,从依赖任务获取
279
307
  app_info_obj: config[:app_info_obj],
280
308
  project_name: @args_proj_name,
281
309
  send_message_type: @args_send_flag ? 'group' : 'self',
282
- data_dependencies: [upload_task.id] # 从 upload_task 获取数据
310
+ dependencies: [upload_task.id] # 从 upload_task 获取数据
283
311
  )
284
- message_task.dependencies << upload_task.id # 执行顺序依赖
285
312
  tasks << message_task
286
313
  end
287
314
 
315
+ # 6. 创建媒体附件上传任务(如果需要,只依赖 Git 提交任务)
316
+ if @args_media_flag
317
+ # 获取 Git 管理类型的工作流(不同于 APK 上传的工作流)
318
+ git_app_info_obj, git_workflow_info = PgyerHelper.share_instace.prepare_upload(
319
+ working_directory: config[:project_path],
320
+ proj_name: @args_proj_name,
321
+ package_type: "", # package_type 在 manage_type=git 时会被忽略
322
+ manage_type: "git"
323
+ )
324
+
325
+ media_upload_task = Pindo::TaskSystem::JPSUploadMediaTask.new(
326
+ [], # 空数组,自动从 JPSMedia/ 目录查找
327
+ config[:project_path], # upload_path
328
+ app_info_obj: git_app_info_obj,
329
+ workflow_info: git_workflow_info,
330
+ project_name: @args_proj_name
331
+ )
332
+ # 只依赖 Git 提交任务
333
+ media_upload_task.dependencies << git_commit_task.id
334
+ tasks << media_upload_task
335
+ end
336
+
288
337
  tasks
289
338
  else
290
339
  raise Informative, "当前目录不是工程目录,不能编译"
@@ -186,12 +186,21 @@ module Pindo
186
186
 
187
187
  # 0. Git 提交任务(使用 IosConfigParser 的版本号)
188
188
  fixed_version = Pindo::IosConfigParser.instance.app_version
189
+
190
+ # 提前询问用户如何处理未提交的文件
191
+ process_type = Pindo::GitHandler.get_uncommitted_files_process_type(
192
+ project_dir: project_path,
193
+ interactive: true
194
+ )
195
+
189
196
  git_commit_task = Pindo::TaskSystem::GitCommitTask.new(
190
197
  project_path,
191
198
  release_branch: @args_release_branch,
192
199
  tag_type: @args_tag_type,
193
200
  tag_pre: @args_tag_pre,
194
- fixed_version: fixed_version
201
+ fixed_version: fixed_version,
202
+ process_type: process_type,
203
+ commit_message: "feat: appstore autobuild 构建前提交"
195
204
  )
196
205
  tasks << git_commit_task
197
206
  last_task = git_commit_task
@@ -15,6 +15,7 @@ require 'pindo/module/task/model/unity/unity_yoo_asset_task'
15
15
  require 'pindo/module/task/model/unity/unity_export_task'
16
16
  require 'pindo/module/task/model/build_task'
17
17
  require 'pindo/module/task/model/jps/jps_upload_task'
18
+ require 'pindo/module/task/model/jps/jps_upload_media_task'
18
19
  require 'pindo/module/task/model/jps/jps_message_task'
19
20
  require 'pindo/options/options'
20
21
  require 'pindo/options/helpers/bundleid_selector'
@@ -50,6 +51,8 @@ module Pindo
50
51
 
51
52
  * 支持CI/CD自动化构建
52
53
 
54
+ * 支持并发任务执行(使用 --multi 参数)
55
+
53
56
  使用示例:
54
57
 
55
58
  $ pindo ios autobuild # 编译Debug包
@@ -58,9 +61,15 @@ module Pindo
58
61
 
59
62
  $ pindo ios autobuild --send # 编译、上传并发送群组通知
60
63
 
64
+ $ pindo ios autobuild --media # 编译、上传并上传媒体附件
65
+
61
66
  $ pindo ios autobuild --bundleid=com.example.app # 指定Bundle ID
62
67
 
63
68
  $ pindo ios autobuild --proj="My App" # 指定项目名称
69
+
70
+ $ pindo ios autobuild --multi # 使用并发模式执行(速度更快)
71
+
72
+ $ pindo ios autobuild --multi --upload # 并发执行并上传
64
73
  DESC
65
74
 
66
75
  # 命令的参数列表
@@ -73,9 +82,10 @@ module Pindo
73
82
  @option_items ||= begin
74
83
  items = Pindo::Options::OptionGroup.merge(
75
84
  Pindo::Options::BuildOptions.select(:bundleid, :build_type),
76
- Pindo::Options::JPSOptions.select(:proj, :upload, :send),
85
+ Pindo::Options::JPSOptions.select(:proj, :upload, :send, :media),
77
86
  Pindo::Options::UnityOptions.select(:skiplib, :skipyoo),
78
87
  Pindo::Options::UnityOptions.select_with_defaults(skipconfig: true),
88
+ Pindo::Options::TaskOptions.select(:multi),
79
89
  Pindo::Options::GitOptions.all
80
90
  )
81
91
 
@@ -111,11 +121,19 @@ module Pindo
111
121
  @args_upload_flag = @options[:send] || @options[:upload]
112
122
  @args_proj_name = @options[:proj]
113
123
  @args_bundle_id = @options[:bundleid]
124
+ # media 依赖 upload:如果指定了 media,自动启用 upload
125
+ @args_media_flag = @options[:media] || false
126
+ if @args_media_flag
127
+ @args_upload_flag = true
128
+ end
114
129
 
115
130
  # Unity 参数
116
131
  @args_skip_lib = @options[:skiplib] || false
117
132
  @args_skip_yoo = @options[:skipyoo] || false
118
133
 
134
+ # Task 参数
135
+ @args_multi_flag = @options[:multi] || false
136
+
119
137
  # Git 参数
120
138
  @args_release_branch = @options[:release_branch] || 'master'
121
139
  @args_ver_inc = Pindo::Options::GitOptions.parse_version_increase_type(@options[:ver_inc] || 'mini')
@@ -148,7 +166,13 @@ module Pindo
148
166
  task_manager = Pindo::TaskSystem::TaskManager.instance
149
167
  task_manager.clear_all
150
168
  tasks.each { |task| task_manager.add_task(task) }
151
- task_manager.start
169
+
170
+ # 执行任务(根据 --multi 参数决定模式)
171
+ if @args_multi_flag
172
+ task_manager.start(mode: :concurrent, max_workers: 3)
173
+ else
174
+ task_manager.start
175
+ end
152
176
 
153
177
  system "open #{pindo_project_dir}"
154
178
  ensure
@@ -175,12 +199,19 @@ module Pindo
175
199
  tasks = []
176
200
 
177
201
  # 1. Git 提交任务
202
+ # 提前询问用户如何处理未提交的文件
203
+ process_type = Pindo::GitHandler.get_uncommitted_files_process_type(
204
+ project_dir: config[:project_path],
205
+ interactive: true
206
+ )
178
207
  git_commit_task = Pindo::TaskSystem::GitCommitTask.new(
179
208
  config[:project_path],
180
209
  release_branch: @args_release_branch,
181
210
  ver_inc: @args_ver_inc,
182
211
  tag_type: @args_tag_type,
183
- tag_pre: @args_tag_pre
212
+ tag_pre: @args_tag_pre,
213
+ process_type: process_type,
214
+ commit_message: "feat: ios autobuild 构建前提交"
184
215
  )
185
216
  tasks << git_commit_task
186
217
 
@@ -276,7 +307,7 @@ module Pindo
276
307
 
277
308
  # 5. 上传和消息发送任务(如果需要)
278
309
  if @args_upload_flag
279
- # 4.1 创建上传任务
310
+ # 5.1 创建上传任务
280
311
  upload_task = Pindo::TaskSystem::JPSUploadTask.new(
281
312
  'ipa',
282
313
  File.join(ios_project_path, 'build'),
@@ -288,19 +319,40 @@ module Pindo
288
319
  upload_task.dependencies << build_task.id
289
320
  tasks << upload_task
290
321
 
291
- # 4.2 创建消息发送任务(依赖上传任务)
322
+ # 5.2 创建消息发送任务(只依赖上传任务)
292
323
  # app_version_info 将从 upload_task 的数据参数中获取
293
324
  message_task = Pindo::TaskSystem::JPSMessageTask.new(
294
325
  nil, # app_version_info 为 nil,从依赖任务获取
295
326
  app_info_obj: config[:app_info_obj],
296
327
  project_name: @args_proj_name,
297
328
  send_message_type: @args_send_flag ? 'group' : 'self',
298
- data_dependencies: [upload_task.id] # 从 upload_task 获取数据
329
+ dependencies: [upload_task.id] # 从 upload_task 获取数据
299
330
  )
300
- message_task.dependencies << upload_task.id # 执行顺序依赖
301
331
  tasks << message_task
302
332
  end
303
333
 
334
+ # 6. 创建媒体附件上传任务(如果需要,只依赖 Git 提交任务)
335
+ if @args_media_flag
336
+ # 获取 Git 管理类型的工作流(不同于 IPA 上传的工作流)
337
+ git_app_info_obj, git_workflow_info = PgyerHelper.share_instace.prepare_upload(
338
+ working_directory: config[:project_path],
339
+ proj_name: @args_proj_name,
340
+ package_type: "", # package_type 在 manage_type=git 时会被忽略
341
+ manage_type: "git"
342
+ )
343
+
344
+ media_upload_task = Pindo::TaskSystem::JPSUploadMediaTask.new(
345
+ [], # 空数组,自动从 JPSMedia/ 目录查找
346
+ config[:project_path], # upload_path
347
+ app_info_obj: git_app_info_obj,
348
+ workflow_info: git_workflow_info,
349
+ project_name: @args_proj_name
350
+ )
351
+ # 只依赖 Git 提交任务
352
+ media_upload_task.dependencies << git_commit_task.id
353
+ tasks << media_upload_task
354
+ end
355
+
304
356
  tasks
305
357
  else
306
358
  raise Informative, "当前目录不是工程目录,不能编译"