require 'git'
require 'KCommercialPipeline/core/version_pipeline/release_branches'
require 'KCommercialPipeline/core/git'
require 'KCommercialPipeline/core/branch_diffs'
require 'KCommercialPipeline/core/kim_cfg'
module KCommercial
module KCPipeline
class AutoCherryPickResult
attr_accessor :conflicts
attr_accessor :target_b
attr_accessor :source_b
attr_accessor :cherry_picks
def initialize(target_b:,source_b:,conflicts:,cherry_picks:)
@conflicts = conflicts
@target_b = target_b
@source_b = source_b
@cherry_picks = cherry_picks
end
end
class AutoCherryPick
attr_accessor :mentioned_list
def run
rs_list = prepare
parse_result(rs_list)
end
def prepare
#忽略由于环境配置造成的变更 不做提交
`git reset --hard`
current_rb = KCGit.git.current_branch
target_branchs = BranchTool.bigger_release_branchs(current_rb)
target_branchs << "develop"
rs_list = []
target_branchs.each do |b|
KCommercial::UI.info"开始向#{b}分支自动cherry-pick"
rs = auto_cherry_pick_in_branch(b,current_rb)
unless rs.nil?
rs_list << rs
end
end
rs_list
end
def mentioned_list
@mentioned_list ||= KimConfig.configs["AutoCherryPick"]['kim']["mentioned_list"] || []
end
def robot_keys
@robot_keys ||= KimConfig.configs["AutoCherryPick"]['kim']["robot_key"] || []
end
def auto_cherry_pick_in_branch(target_b,current_rb)
diffs = KCBranchDiffs.new(current_rb,target_b).diffs
unless diffs.empty?
KCommercial::UI.info"#{current_rb}分支有#{diffs.size}个commit需要cherry--pick到#{target_b}分支"
KCGit.git.checkout(target_b)
result = nil
#尝试整体合入
all_commits = []
diffs.reverse_each do |diff|
all_commits << diff.ori_commit_id
end
rs = KCGit.git.branch.cherry_pick_all(all_commits)
unless rs.code == 0
roll_back_cherry_pick
#尝试单个cherry pick
result = cherry_pick_by_one(diffs,target_b,current_rb)
else
KCommercial::UI.info"开始推送#{all_commits.size}个commit 到#{target_b}分支"
KCGit.git.push("origin",target_b)
result = AutoCherryPickResult.new(target_b:target_b,conflicts:[],cherry_picks:diffs,source_b: current_rb)
end
else
KCommercial::UI.info"不需要自动cherry-pick到#{target_b}分支,退出cherry-pick"
end
result
end
def cherry_pick_by_one(diffs,target_b,current_rb)
conflicts = []
cherry_picks = []
diffs.reverse_each do |diff|
rs = KCGit.git.branch.cherry_pick(diff.ori_commit_id)
unless rs.code == 0
roll_back_cherry_pick
KCommercial::UI.info("commitid = #{diff.ori_commit_id},message = #{diff.message},autho = #{diff.author.author} 自动cherry-pick失败,开始回滚")
conflicts << diff
else
cherry_picks << diff
end
end
KCommercial::UI.info"有#{cherry_picks.size}个已经 cherry-pick 到#{target_b}分支,有#{conflicts.size}个自动cherry-pick到#{target_b}分支失败"
unless cherry_picks.size == 0
KCommercial::UI.info"开始推送#{cherry_picks.size}个commit 到#{target_b}分支"
KCGit.git.push("origin",target_b)
end
result = AutoCherryPickResult.new(target_b:target_b,conflicts:conflicts,cherry_picks:cherry_picks,source_b: current_rb)
result
end
def roll_back_cherry_pick
rs = KCGit.git.branch.roll_back
unless rs.code == 0
KCommercial::UI.error("自动cherry-pick失败,回滚失败,请手动合入!")
exit! -1
end
KCommercial::UI.debug("自动cherry-pick失败,回滚成功")
end
#解析结果,发送通知
def parse_result(results)
results.each do |rs|
unless rs.conflicts.empty?
notify_conflicts(rs)
end
unless rs.cherry_picks.empty?
notify_cherry_picks(rs)
end
end
end
def notify_conflicts(rs)
conflicts__title = "#{rs.target_b}自动cherry-pick有#{rs.conflicts.size}个冲突,请对应开发人工处理!"
msg = diffs_to_markdown(rs.conflicts,conflicts__title)
kim_model = KimModel.new(MessageType::Markdown, "", msg, "", mentioned_list)
robot_keys.each do |robot_key|
kim = Kim.new(robot_key, kim_model)
kim.notifi_kim
end
end
def notify_cherry_picks(rs)
cp__title = "#{rs.target_b}成功自动cherry-pick#{rs.cherry_picks.size}个commit"
msg = diffs_to_markdown(rs.cherry_picks,cp__title)
kim_model = KimModel.new(MessageType::Markdown, "", msg, "", mentioned_list)
robot_keys.each do |robot_key|
kim = Kim.new(robot_key, kim_model)
kim.notifi_kim
end
end
def diffs_to_markdown(conflicts,title)
unless conflicts.empty?
labels = ['commit_msg', 'commit', 'author', "date"]
table = MarkdownTables.make_table(labels, diff_to_data(conflicts), is_rows: true, align: %w[l c c l])
<