pindo 5.20.3 → 5.20.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4b1febabe3ba7ca2b2d8bd2e3f005e6aec1226b7d7881b3aebec6b6d5af1c5f0
4
- data.tar.gz: bd12f36dfa900606bb82154406f6d85dbf37bcb1e16abfcd0aaa48341734d20a
3
+ metadata.gz: 51a9e1f1176906c3f5cc98d5c8654bd194c2199eca4d056c5d24b84d321a0e7f
4
+ data.tar.gz: 983e11201e2b488800fb65a745300fc71184e068e01f94255ae29d2f469c3d02
5
5
  SHA512:
6
- metadata.gz: f780b333edd0ae1272d15af1c641e41c481c8ad06ded6bbd7d253f662f54de34b707ccd2e0a91097728da293ead5c053e6d1a8ea652722897a7e572e0c2ec26e
7
- data.tar.gz: 88e50426cfeb85c798610f64935a1e8053d6200da20920a450c2940c79b451e78be918d55d94ea2f186d2a2feb4773b15d6e7221b294d497f4e8470a626c145d
6
+ metadata.gz: 140c5a77bf8ad4e46547a60caef4587e04811450624a0c19213b978fae267078b8d6370486209531d4116ab202670ce12a707edc93c7299df1e4e244f389668d
7
+ data.tar.gz: f646d8f611a70c2ad39bdaa31ef69f55f4a0946ed3e1c90a27d806072ca2484c1bcf7ec8073d9e381031d2ab645aceaf5387cb13b8e90ed6e20070acee5f5a6a
@@ -149,6 +149,21 @@ module Pindo
149
149
  []
150
150
  end
151
151
 
152
+ # 获取仓库当前所在分支名
153
+ # @param local_repo_dir [String] 仓库目录
154
+ # @return [String, nil] 分支名;detached HEAD、非仓库或读取失败时返回 nil
155
+ def current_branch_name(local_repo_dir: nil)
156
+ return nil if local_repo_dir.nil?
157
+
158
+ branch = git!(%W(-C #{local_repo_dir} rev-parse --abbrev-ref HEAD)).strip
159
+ # detached HEAD 时 git 返回字面量 "HEAD",不是分支名
160
+ return nil if branch.empty? || branch == 'HEAD'
161
+
162
+ branch
163
+ rescue StandardError
164
+ nil
165
+ end
166
+
152
167
  # 解析发布分支(当用户未显式指定时给出合理默认):
153
168
  # 1) preferred(用户 --release_branch 或默认值)在远程存在 → 用它(master 仓库、显式指定均走此)
154
169
  # 2) 否则远程有 master → master
@@ -697,12 +712,10 @@ module Pindo
697
712
  Funlog.instance.fancyinfo_success("push文件完成!")
698
713
  end
699
714
 
715
+ # 丢弃工作区全部改动
716
+ # 不在此处二次确认:交互模式下 get_uncommitted_files_process_type 选中 reset 时
717
+ # 已经对着文件清单确认过;非交互模式(--git-commit=reset / CI)本就不该阻塞等待输入。
700
718
  def handle_delete_all(project_dir, branch)
701
- answer = agree("有未提交的文件,确认删除?(Y/n):")
702
- unless answer
703
- raise Informative, "请手动处理未提交的文件!!!"
704
- end
705
-
706
719
  Funlog.instance.fancyinfo_start("开始删除未提交的文件...")
707
720
  git!(%W(-C #{project_dir} reset --hard))
708
721
  git!(%W(-C #{project_dir} clean -df))
@@ -759,13 +772,17 @@ module Pindo
759
772
  end
760
773
  end
761
774
 
762
- # 获取最新的符合规范的 commit
775
+ # 获取本次构建对应的 commit
763
776
  # @param project_dir [String] 项目目录路径
764
- # @param tag_prefix [String] tag前缀,用于检查 HEAD 是否有版本 tag,默认 'v'
777
+ # @param tag_prefix [String] tag前缀,用于识别 HEAD 上的版本 tag,默认 'v'
765
778
  # @return [Hash] 包含 :commit_id, :commit_time, :commit_desc
766
- # 优先级:
767
- # 1. 如果 HEAD 存在版本 tag,直接返回 HEAD(认为有 tag 的 commit 是有效的发布节点)
768
- # 2. 否则,返回最新的符合 Conventional Commits 规范的提交
779
+ #
780
+ # commit_id commit_time 恒为 HEAD:调用方(包绑定、媒体上传、工作流消息)
781
+ # 要的是「本次构建所在的节点」,提交信息是否符合 Conventional Commits
782
+ # 是不是 merge commit,都不改变这一点——沿历史回溯只会关联到与本次构建无关的祖先提交。
783
+ #
784
+ # 只有 commit_desc 会被替换:HEAD 是 merge commit 时其描述通常是无信息量的
785
+ # "Merge branch ...",此时从最近 15 条非 merge 提交中借用一条规范提交的描述。
769
786
  def get_latest_conventional_commit(project_dir:nil, tag_prefix: 'v')
770
787
  result = {
771
788
  commit_id: nil,
@@ -780,75 +797,65 @@ module Pindo
780
797
  return result unless git_root
781
798
 
782
799
  begin
783
- # 优先级 1: 检查 HEAD 是否有版本 tag
784
- if head_has_version_tag?(project_dir: git_root, tag_prefix: tag_prefix)
785
- # HEAD 有版本 tag,直接返回 HEAD 的 commit 信息
786
- head_info = git!(%W(-C #{git_root} log -1 --format=%H|%ci|%s HEAD)).strip
787
- if !head_info.empty?
788
- parts = head_info.split('|', 3)
789
- result[:commit_id] = parts[0]
790
- result[:commit_time] = parts[1]
791
- result[:commit_desc] = parts[2]&.force_encoding('UTF-8')&.scrub('')
792
- puts " HEAD 存在版本 tag,使用 HEAD commit: #{result[:commit_desc]}"
793
- return result
794
- end
795
- end
796
-
797
- # 优先级 2: 获取最近 15 条 commit 历史(排除 merge commits)
798
- output = git!(%W(-C #{git_root} log -15 --no-merges --format=%H|%ci|%s)).strip
799
-
800
- if output.empty?
800
+ # 1. HEAD commit 信息(commit_id / commit_time 以此为准)
801
+ head_info = git!(%W(-C #{git_root} log -1 --format=%H|%ci|%s HEAD)).strip
802
+ if head_info.empty?
801
803
  Funlog.instance.warning("未找到 git commit 历史")
802
804
  return result
803
805
  end
804
806
 
805
- # 解析 commit 列表
806
- commits = output.split("\n").map do |line|
807
- parts = line.split('|', 3)
808
- {
809
- commit_id: parts[0],
810
- commit_time: parts[1],
811
- commit_desc: parts[2]&.force_encoding('UTF-8')&.scrub('')
812
- }
813
- end
814
-
815
- # 定义符合规范的提交类型(Conventional Commits 规范)
816
- valid_types = ['feat', 'fix', 'docs', 'style', 'refactor', 'perf', 'test', 'build', 'ci', 'chore', 'revert']
807
+ parts = head_info.split('|', 3)
808
+ result[:commit_id] = parts[0]
809
+ result[:commit_time] = parts[1]
810
+ result[:commit_desc] = parts[2]&.force_encoding('UTF-8')&.scrub('')
817
811
 
818
- # 筛选符合规范的提交(支持 type: type(scope): 两种格式)
819
- conventional_commits = commits.select do |commit|
820
- desc = commit[:commit_desc].to_s.strip.downcase
821
- # 匹配 "type:" 或 "type(" 格式(允许 scope)
822
- valid_types.any? do |type|
823
- desc.start_with?("#{type}:") || desc.start_with?("#{type}(")
824
- end
812
+ if head_has_version_tag?(project_dir: git_root, tag_prefix: tag_prefix)
813
+ puts " HEAD 存在版本 tag,使用 HEAD commit: #{result[:commit_desc]}"
814
+ return result
825
815
  end
826
816
 
827
- if conventional_commits.empty?
828
- Funlog.instance.warning("在最近15个提交中未找到符合规范的提交(feat:, fix: 等开头)")
829
- Funlog.instance.warning("使用最新的提交(HEAD)")
830
-
831
- # 降级:使用 HEAD
832
- result[:commit_id] = commits.first[:commit_id]
833
- result[:commit_time] = commits.first[:commit_time]
834
- result[:commit_desc] = commits.first[:commit_desc]
835
- else
836
- # 使用最新的符合规范的提交(第一个)
837
- latest = conventional_commits.first
838
- result[:commit_id] = latest[:commit_id]
839
- result[:commit_time] = latest[:commit_time]
840
- result[:commit_desc] = latest[:commit_desc]
841
-
842
- puts " 找到符合规范的提交: #{result[:commit_desc]}"
817
+ # 2. HEAD 不是 merge commit:描述本身有效,直接返回
818
+ head_parents = git!(%W(-C #{git_root} rev-list --parents -1 HEAD)).strip.split(/\s+/)
819
+ unless head_parents.size > 2
820
+ puts " 使用 HEAD commit: #{result[:commit_desc]}"
821
+ return result
843
822
  end
823
+
824
+ # 3. HEAD 是 merge commit:commit 仍用 HEAD,只借用祖先的规范提交描述
825
+ result[:commit_desc] = borrow_conventional_desc(git_root) || result[:commit_desc]
826
+ puts " HEAD 为 merge commit,使用 HEAD commit + 祖先描述: #{result[:commit_desc]}"
844
827
  rescue StandardError => e
845
- Funlog.instance.warning("获取 conventional commit 失败: #{e.message}")
828
+ Funlog.instance.warning("获取 commit 信息失败: #{e.message}")
846
829
  return result
847
830
  end
848
831
 
849
832
  result
850
833
  end
851
834
 
835
+ # 从最近 15 条非 merge 提交中找一条符合 Conventional Commits 规范的描述
836
+ # 仅供 get_latest_conventional_commit 内部使用(本文件的类方法均为 public,
837
+ # 加 private 会影响同块内其它对外方法,故以注释标注)
838
+ # @param git_root [String] git 根目录
839
+ # @return [String, nil] 提交描述;找不到时返回 nil
840
+ def borrow_conventional_desc(git_root)
841
+ output = git!(%W(-C #{git_root} log -15 --no-merges --format=%s)).strip
842
+ return nil if output.empty?
843
+
844
+ descs = output.split("\n").map { |line| line&.force_encoding('UTF-8')&.scrub('') }
845
+
846
+ # 符合规范的提交类型(Conventional Commits 规范),支持 type: 与 type(scope): 两种格式
847
+ valid_types = ['feat', 'fix', 'docs', 'style', 'refactor', 'perf', 'test', 'build', 'ci', 'chore', 'revert']
848
+ conventional = descs.find do |desc|
849
+ normalized = desc.to_s.strip.downcase
850
+ valid_types.any? { |type| normalized.start_with?("#{type}:") || normalized.start_with?("#{type}(") }
851
+ end
852
+
853
+ return conventional if conventional
854
+
855
+ Funlog.instance.warning("在最近15个提交中未找到符合规范的提交(feat:, fix: 等开头),保留 merge commit 描述")
856
+ nil
857
+ end
858
+
852
859
  # 创建新的版本标签
853
860
  # @param project_dir [String] 项目目录路径
854
861
  # @param tag_prefix [String] 标签前缀
@@ -990,16 +997,33 @@ module Pindo
990
997
  display_file_status(current_branch, uncommitted_files)
991
998
 
992
999
  # 5. 交互式选择
1000
+ # 危险选项在这里就地二次确认:此时未提交文件列表还在屏幕上,用户能看着清单做决定。
1001
+ # 若把确认延后到任务执行阶段,中间会隔着任务计划输出,用户看不到自己要丢弃的是哪些文件。
993
1002
  cli = HighLine.new
994
- cli.choose do |menu|
995
- menu.header = "仓库有未提交的修改,请选择处理方式"
996
- menu.prompt = "请输入选项(1/2/3/4/5/6):"
997
- menu.choice("(commit) 全部提交") { Pindo::UncommittedFilesProcessType::COMMIT }
998
- menu.choice("(skip-with-tag) 不提交,但合并分支并打tag") { Pindo::UncommittedFilesProcessType::SKIP_WITH_TAG }
999
- menu.choice("(skip-without-tag) 不提交,不合并分支,不打tag") { Pindo::UncommittedFilesProcessType::SKIP_WITHOUT_TAG }
1000
- menu.choice("(reset) 全部丢弃更改,回滚代码") { Pindo::UncommittedFilesProcessType::RESET }
1001
- menu.choice("(stash) 保存到stash区域(该部分代码本次编译不生效)") { Pindo::UncommittedFilesProcessType::STASH }
1002
- menu.choice("(exit) 先退出,手动来处理退出") { Pindo::UncommittedFilesProcessType::EXIT }
1003
+ loop do
1004
+ choice = cli.choose do |menu|
1005
+ menu.header = "仓库有未提交的修改,请选择处理方式"
1006
+ menu.prompt = "请输入选项(1/2/3/4/5/6):"
1007
+ menu.choice("(commit) 全部提交") { Pindo::UncommittedFilesProcessType::COMMIT }
1008
+ menu.choice("(skip-with-tag) 不提交,但合并分支并打tag") { Pindo::UncommittedFilesProcessType::SKIP_WITH_TAG }
1009
+ menu.choice("(skip-without-tag) 不提交,不合并分支,不打tag") { Pindo::UncommittedFilesProcessType::SKIP_WITHOUT_TAG }
1010
+ menu.choice("(reset) 全部丢弃更改,回滚代码") { Pindo::UncommittedFilesProcessType::RESET }
1011
+ menu.choice("(stash) 保存到stash区域(该部分代码本次编译不生效)") { Pindo::UncommittedFilesProcessType::STASH }
1012
+ menu.choice("(exit) 先退出,手动来处理退出") { Pindo::UncommittedFilesProcessType::EXIT }
1013
+ end
1014
+
1015
+ # reset 会 reset --hard + clean -df,改动无法恢复,必须当场确认
1016
+ if choice == Pindo::UncommittedFilesProcessType::RESET
1017
+ puts
1018
+ puts "⚠️ 以上 #{Array(uncommitted_files).size} 个文件的修改将被永久丢弃,无法恢复".red
1019
+ unless cli.agree("确认删除?(y/n) ")
1020
+ puts "已取消,请重新选择处理方式".yellow
1021
+ puts
1022
+ next
1023
+ end
1024
+ end
1025
+
1026
+ return choice
1003
1027
  end
1004
1028
  end
1005
1029
 
@@ -417,9 +417,13 @@ module Pindo
417
417
  tasks << message_task
418
418
  end
419
419
 
420
- # 6. 创建媒体附件上传任务(如果需要,只依赖 Git 提交任务)
421
- if @args_media_flag
422
- # 获取 Git 管理类型的工作流(不同于 APK 上传的工作流)
420
+ # 6. 获取 Git 管理类型的工作流(media、bind、send 共用,不同于 APK 上传的包工作流)
421
+ # commit 记录挂在 Git 工作流下,媒体附件、包绑定、工作流消息都按它定位
422
+ git_app_info_obj = nil
423
+ git_workflow_info = nil
424
+ if @args_media_flag || @args_bind_flag || @args_send_flag
425
+ # 取不到就让异常冒泡:media/bind/send 都依赖它,静默跳过会让命令
426
+ # 明明没做用户要求的事却以 0 退出
423
427
  git_app_info_obj, git_workflow_info = PgyerHelper.share_instace.prepare_upload(
424
428
  working_directory: config[:project_path],
425
429
  conf: @args_conf,
@@ -427,48 +431,53 @@ module Pindo
427
431
  manage_type: "git"
428
432
  )
429
433
 
434
+ unless git_app_info_obj && git_workflow_info
435
+ raise Informative, "未获取到 Git 类型的工作流;请在 JPS 后台配置 manage_type=git 的工作流"
436
+ end
437
+ end
438
+
439
+ # 7. 创建媒体附件上传任务(如果需要,依赖 Git 提交/打 Tag 任务)
440
+ if @args_media_flag
430
441
  media_upload_task = Pindo::TaskSystem::JPSUploadMediaTask.new(
431
442
  [], # 空数组,自动从 JPSMedia/ 目录查找
432
443
  config[:project_path], # upload_path
433
444
  app_info_obj: git_app_info_obj,
434
445
  workflow_info: git_workflow_info,
435
- project_name: nil
446
+ project_name: nil,
447
+ required: @options[:media] || false # 仅用户显式 --media 时,找不到文件才算失败
436
448
  )
437
449
  # 依赖 Git 提交任务
438
450
  media_upload_task.dependencies << git_commit_task.id
451
+ # 同样依赖 GitTagTask:并发模式下媒体上传可能与 build/tag 并行,
452
+ # 不依赖它就会关联到构建前的 commit,与包绑定的 commit 不一致
453
+ media_upload_task.dependencies << git_tag_task.id if git_tag_task
439
454
  tasks << media_upload_task
440
455
  end
441
456
 
442
- # 7. 创建 Git Commit 绑定任务(如果需要,依赖上传任务)
457
+ # 8. 创建 Git Commit 绑定任务(如果需要,依赖上传任务)
443
458
  bind_package_task = nil # 声明变量以便后续工作流消息任务使用
444
459
  if @args_bind_flag
445
460
  bind_package_task = Pindo::TaskSystem::JPSBindPackageTask.new(
446
461
  nil, # app_version_list 为 nil,从依赖任务获取
447
462
  project_dir: config[:project_path],
448
- app_info_obj: config[:app_info_obj],
449
- workflow_info: config[:workflow_info],
463
+ app_info_obj: git_app_info_obj, # 使用 Git app_info_obj
464
+ workflow_info: git_workflow_info, # 使用 Git workflow_info
450
465
  project_name: nil
451
466
  )
452
- # 依赖上传任务和 Git 提交任务
467
+ # 依赖上传任务和 Git 任务
468
+ # GitTagTask 会提交构建注入文件并移动 HEAD,必须依赖它才能拿到 tag 所在的 commit
453
469
  bind_package_task.dependencies << upload_task.id
454
470
  bind_package_task.dependencies << git_commit_task.id
471
+ bind_package_task.dependencies << git_tag_task.id if git_tag_task
455
472
  tasks << bind_package_task
456
473
  end
457
474
 
458
- # 8. 创建工作流消息任务(如果需要,发送到测试群)
475
+ # 9. 创建工作流消息任务(如果需要,发送到测试群)
459
476
  if @args_send_flag
460
- # 获取 Git 工作流信息
461
- git_app_info_obj, git_workflow_info = PgyerHelper.share_instace.prepare_upload(
462
- working_directory: config[:project_path],
463
- conf: @args_conf,
464
- package_type: nil,
465
- manage_type: "git"
466
- )
467
-
468
477
  workflow_message_task = Pindo::TaskSystem::JPSWorkFlowMessageTask.new(
469
478
  project_id: git_app_info_obj["id"],
470
- workflow_id: git_workflow_info["id"],
471
- branch: 'master',
479
+ workflow_id: git_workflow_info[:workflow_id], # workflow_info 是 symbol key 结构,没有 "id"
480
+ # branch 不传:由任务从 Git 依赖任务取 resolve 之后的真实发布分支
472
481
  single: true,
473
482
  app_info_obj: git_app_info_obj,
474
483
  workflow_info: git_workflow_info
@@ -132,7 +132,7 @@ module Pindo
132
132
  @args_media_flag = @options[:send] || @options[:bind] || @options[:media] || false
133
133
 
134
134
  # send 都依赖 bind:如果指定了任一参数,自动启用 bind
135
- @args_bind_flag = @options[:send] ||@options[:bind] || false
135
+ @args_bind_flag = @options[:send] || @options[:bind] || false
136
136
 
137
137
  @args_send_flag = @options[:send]
138
138
 
@@ -391,66 +391,67 @@ module Pindo
391
391
  tasks << message_task
392
392
  end
393
393
 
394
- # 6. 创建媒体附件上传任务(如果需要,只依赖 Git 提交任务)
395
- if @args_media_flag
396
- begin
397
- # 获取 Git 管理类型的工作流(不同于 IPA 上传的工作流)
398
- git_app_info_obj, git_workflow_info = PgyerHelper.share_instace.prepare_upload(
399
- working_directory: config[:project_path],
400
- conf: @args_conf,
401
- package_type: nil, # package_type 在 manage_type=git 时会被忽略
402
- manage_type: "git"
403
- )
394
+ # 6. 获取 Git 管理类型的工作流(media、bind、send 共用,不同于 IPA 上传的包工作流)
395
+ # commit 记录挂在 Git 工作流下,媒体附件、包绑定、工作流消息都按它定位
396
+ git_app_info_obj = nil
397
+ git_workflow_info = nil
398
+ if @args_media_flag || @args_bind_flag || @args_send_flag
399
+ # 取不到就让异常冒泡:media/bind/send 都依赖它,静默跳过会让命令
400
+ # 明明没做用户要求的事却以 0 退出
401
+ git_app_info_obj, git_workflow_info = PgyerHelper.share_instace.prepare_upload(
402
+ working_directory: config[:project_path],
403
+ conf: @args_conf,
404
+ package_type: nil, # package_type 在 manage_type=git 时会被忽略
405
+ manage_type: "git"
406
+ )
404
407
 
405
- media_upload_task = Pindo::TaskSystem::JPSUploadMediaTask.new(
406
- [], # 空数组,自动从 JPSMedia/ 目录查找
407
- config[:project_path], # upload_path
408
- app_info_obj: git_app_info_obj,
409
- workflow_info: git_workflow_info,
410
- project_name: nil
411
- )
412
- # 依赖 Git 提交任务
413
- media_upload_task.dependencies << git_commit_task.id
414
- tasks << media_upload_task
415
- rescue => e
416
- puts ""
417
- puts " ⚠️ 跳过媒体上传任务: #{e.message}"
418
- puts " 💡 提示: 请在 JPS 后台配置 Git 类型的工作流(manage_type: git)"
419
- puts ""
420
- # 不抛出异常,继续执行后续任务
408
+ unless git_app_info_obj && git_workflow_info
409
+ raise Informative, "未获取到 Git 类型的工作流;请在 JPS 后台配置 manage_type=git 的工作流"
421
410
  end
422
411
  end
423
412
 
424
- # 7. 创建 Git Commit 绑定任务(如果需要,依赖上传任务)
413
+ # 7. 创建媒体附件上传任务(如果需要,依赖 Git 提交/打 Tag 任务)
414
+ if @args_media_flag
415
+ media_upload_task = Pindo::TaskSystem::JPSUploadMediaTask.new(
416
+ [], # 空数组,自动从 JPSMedia/ 目录查找
417
+ config[:project_path], # upload_path
418
+ app_info_obj: git_app_info_obj,
419
+ workflow_info: git_workflow_info,
420
+ project_name: nil,
421
+ required: @options[:media] || false # 仅用户显式 --media 时,找不到文件才算失败
422
+ )
423
+ # 依赖 Git 提交任务
424
+ media_upload_task.dependencies << git_commit_task.id
425
+ # 同样依赖 GitTagTask:并发模式下媒体上传可能与 build/tag 并行,
426
+ # 不依赖它就会关联到构建前的 commit,与包绑定的 commit 不一致
427
+ media_upload_task.dependencies << git_tag_task.id if git_tag_task
428
+ tasks << media_upload_task
429
+ end
430
+
431
+ # 8. 创建 Git Commit 绑定任务(如果需要,依赖上传任务)
425
432
  bind_package_task = nil # 声明变量以便后续工作流消息任务使用
426
433
  if @args_bind_flag
427
434
  bind_package_task = Pindo::TaskSystem::JPSBindPackageTask.new(
428
435
  nil, # app_version_list 为 nil,从依赖任务获取
429
436
  project_dir: config[:project_path],
430
- app_info_obj: config[:app_info_obj],
431
- workflow_info: config[:workflow_info],
437
+ app_info_obj: git_app_info_obj, # 使用 Git app_info_obj
438
+ workflow_info: git_workflow_info, # 使用 Git workflow_info
432
439
  project_name: nil
433
440
  )
434
- # 依赖上传任务和 Git 提交任务
441
+ # 依赖上传任务和 Git 任务
442
+ # GitTagTask 会提交构建注入文件并移动 HEAD,必须依赖它才能拿到 tag 所在的 commit
435
443
  bind_package_task.dependencies << upload_task.id
436
444
  bind_package_task.dependencies << git_commit_task.id
445
+ bind_package_task.dependencies << git_tag_task.id if git_tag_task
437
446
  tasks << bind_package_task
438
447
  end
439
448
 
440
- # 8. 创建工作流消息任务(如果需要,发送到测试群)
449
+ # 9. 创建工作流消息任务(如果需要,发送到测试群)
441
450
  if @args_send_flag
442
- # 获取 Git 工作流信息
443
- git_app_info_obj, git_workflow_info = PgyerHelper.share_instace.prepare_upload(
444
- working_directory: config[:project_path],
445
- conf: @args_conf,
446
- package_type: nil,
447
- manage_type: "git"
448
- )
449
-
450
451
  workflow_message_task = Pindo::TaskSystem::JPSWorkFlowMessageTask.new(
451
452
  project_id: git_app_info_obj["id"],
452
- workflow_id: git_workflow_info["id"],
453
- branch: 'master',
453
+ workflow_id: git_workflow_info[:workflow_id], # workflow_info 是 symbol key 结构,没有 "id"
454
+ # branch 不传:由任务从 Git 依赖任务取 resolve 之后的真实发布分支
454
455
  single: true,
455
456
  app_info_obj: git_app_info_obj,
456
457
  workflow_info: git_workflow_info
@@ -125,6 +125,7 @@ module Pindo
125
125
  git_commit_id = nil
126
126
  git_commit_time = nil
127
127
  git_commit_desc = nil
128
+ git_branch = nil
128
129
 
129
130
  # 1. 检测是否在 Git 仓库中
130
131
  git_root = Pindo::GitHandler.git_root_directory(local_repo_dir: project_path)
@@ -136,6 +137,10 @@ module Pindo
136
137
  git_commit_id = git_info[:commit_id]
137
138
  git_commit_time = git_info[:commit_time]
138
139
  git_commit_desc = git_info[:commit_desc]
140
+ # commit 取的是当前 HEAD,分支就必须配当前分支:
141
+ # 这里没有 autobuild 那样的合并到发布分支流程,用发布分支会发出
142
+ # 「feature 分支的 commit + master 分支名」这种自相矛盾的组合
143
+ git_branch = Pindo::GitHandler.current_branch_name(local_repo_dir: git_root)
139
144
 
140
145
  if git_commit_id
141
146
  puts " └─ Commit: #{git_commit_id[0..7]}"
@@ -145,7 +150,7 @@ module Pindo
145
150
  # 3. 不在 Git 仓库中,获取工作流中最新的 commit id
146
151
  puts " 📡 未检测到 Git 仓库,从工作流获取最新 commit..."
147
152
  git_commit_id = pgyer_helper.get_workflow_latest_commit_id(
148
- workflow_id: git_workflow_info["id"]
153
+ workflow_id: git_workflow_info[:workflow_id] # workflow_info 是 symbol key 结构,没有 "id"
149
154
  )
150
155
 
151
156
  if git_commit_id
@@ -157,11 +162,11 @@ module Pindo
157
162
 
158
163
  workflow_message_task = Pindo::TaskSystem::JPSWorkFlowMessageTask.new(
159
164
  project_id: git_app_info_obj["id"],
160
- workflow_id: git_workflow_info["id"],
165
+ workflow_id: git_workflow_info[:workflow_id], # workflow_info 是 symbol key 结构,没有 "id"
161
166
  git_commit_id: git_commit_id,
162
167
  git_commit_time: git_commit_time,
163
168
  git_commit_desc: git_commit_desc,
164
- branch: 'master',
169
+ branch: git_branch, # 不在 Git 仓库时为 nil,由任务兜底
165
170
  single: true,
166
171
  app_info_obj: git_app_info_obj,
167
172
  workflow_info: git_workflow_info
@@ -154,7 +154,8 @@ module Pindo
154
154
  project_name: nil,
155
155
  git_commit_id: selected_commit_info&.dig(:commit_id),
156
156
  git_commit_time: selected_commit_info&.dig(:commit_time),
157
- git_commit_desc: selected_commit_info&.dig(:commit_desc)
157
+ git_commit_desc: selected_commit_info&.dig(:commit_desc),
158
+ required: true # 本命令就是为上传媒体而执行,没有文件可传即失败
158
159
  )
159
160
  # Media 上传任务依赖 Git 提交任务
160
161
  media_upload_task.dependencies << git_commit_task.id
@@ -353,29 +353,39 @@ module Pindo
353
353
  end
354
354
 
355
355
  # 第五步:获取 Git 工作流信息(如果需要 media、bind 或 send)
356
+ # commit 记录挂在 Git 工作流下,媒体附件、包绑定、工作流消息都按它定位
356
357
  git_app_info_obj = nil
357
358
  git_workflow_info = nil
358
359
  if @args_media_flag || @args_bind_flag || @args_send_flag
359
- # 获取 Git 工作流信息(media、绑定、消息任务都需要)
360
+ # 取不到就让异常冒泡:media/bind/send 都依赖它,静默跳过会让命令
361
+ # 明明没做用户要求的事却以 0 退出
360
362
  git_app_info_obj, git_workflow_info = PgyerHelper.share_instace.prepare_upload(
361
363
  working_directory: Dir.pwd,
362
364
  conf: @args_conf,
363
365
  package_type: nil, # package_type 在 manage_type=git 时会被忽略
364
366
  manage_type: "git"
365
367
  )
368
+
369
+ unless git_app_info_obj && git_workflow_info
370
+ raise Informative, "未获取到 Git 类型的工作流;请在 JPS 后台配置 manage_type=git 的工作流"
371
+ end
366
372
  end
367
373
 
368
- # 第六步:创建媒体附件上传任务(如果需要,只依赖 Git 提交任务)
374
+ # 第六步:创建媒体附件上传任务(如果需要,依赖 Git 提交/打 Tag 任务)
369
375
  if @args_media_flag
370
376
  media_upload_task = Pindo::TaskSystem::JPSUploadMediaTask.new(
371
377
  [], # 空数组,自动从 JPSMedia/ 目录查找
372
378
  Dir.pwd, # upload_path
373
379
  app_info_obj: git_app_info_obj,
374
380
  workflow_info: git_workflow_info,
375
- project_name: all_platform_configs["project_name"]
381
+ project_name: all_platform_configs["project_name"],
382
+ required: @options[:media] || false # 仅用户显式 --media 时,找不到文件才算失败
376
383
  )
377
384
  # 依赖 Git 提交任务
378
385
  media_upload_task.dependencies << git_commit_task.id
386
+ # 同样依赖 GitTagTask:并发模式下媒体上传可能与 build/tag 并行,
387
+ # 不依赖它就会关联到构建前的 commit,与包绑定的 commit 不一致
388
+ media_upload_task.dependencies << git_tag_task.id if git_tag_task
379
389
  all_tasks << media_upload_task
380
390
  end
381
391
 
@@ -389,21 +399,22 @@ module Pindo
389
399
  workflow_info: git_workflow_info, # 使用 Git workflow_info
390
400
  project_name: all_platform_configs["project_name"]
391
401
  )
392
- # 依赖所有平台的上传任务和 Git 提交任务
402
+ # 依赖所有平台的上传任务和 Git 任务
403
+ # GitTagTask 会提交构建注入文件并移动 HEAD,必须依赖它才能拿到 tag 所在的 commit
393
404
  platform_upload_tasks.each do |upload_task|
394
405
  bind_package_task.dependencies << upload_task.id
395
406
  end
396
407
  bind_package_task.dependencies << git_commit_task.id
408
+ bind_package_task.dependencies << git_tag_task.id if git_tag_task
397
409
  all_tasks << bind_package_task
398
410
  end
399
411
 
400
412
  # 第八步:创建工作流消息任务(如果需要,发送到测试群)
401
413
  if @args_send_flag
402
-
403
414
  workflow_message_task = Pindo::TaskSystem::JPSWorkFlowMessageTask.new(
404
415
  project_id: git_app_info_obj["id"],
405
- workflow_id: git_workflow_info["id"],
406
- branch: 'master',
416
+ workflow_id: git_workflow_info[:workflow_id], # workflow_info 是 symbol key 结构,没有 "id"
417
+ # branch 不传:由任务从 Git 依赖任务取 resolve 之后的真实发布分支
407
418
  single: true,
408
419
  app_info_obj: git_app_info_obj,
409
420
  workflow_info: git_workflow_info