Skip to content

Git push 后生成 Changes 流程 18.5

重点

# app/workers/update_merge_requests_worker.rb

主要看看这个

生成 MR Changes(代码变更/diff) 的完整流程。

生成 Changes 的核心流程

1. UpdateMergeRequestsWorker (主要入口)

# app/workers/update_merge_requests_worker.rb
  • 触发时机: 在 BranchPushService#enqueue_update_mrs 中被调度
  • 队列: update_merge_requests
  • 功能: 当 push 影响到 MR 的分支时触发

2. MergeRequests::RefreshService (协调服务)

# app/services/merge_requests/refresh_service.rb
# 第 151-185 行:reload_merge_requests 方法

关键代码(第 164 和 175 行):

merge_request.reload_diff(current_user)  # 重新加载 diff

3. MergeRequests::ReloadDiffsService (重载 Diff 服务)

# app/services/merge_requests/reload_diffs_service.rb
# 第 16 行
new_diff = merge_request.create_merge_request_diff(preload_gitaly: true)
  • 创建新的 MergeRequestDiff 记录
  • 清除旧的缓存
  • 更新讨论位置

4. MergeRequestDiff Model (核心模型)

# app/models/merge_request_diff.rb

关键回调(第 248 行):

after_create :save_git_content, unless: :importing?

save_git_content 方法(第 273-287 行):

def save_git_content
  ensure_commit_shas  # 确保 commit SHA
  save_commits        # 保存 commits
  save_diffs          # ⭐ 生成并保存 diff files
  save
end

save_diffs 方法(第 918-945 行):

def save_diffs
  # 1. 比较 commits
  diff_collection = compare_diffs_preloaded
  
  # 2. 构建 diff files
  rows = build_merge_request_diff_files(diff_collection)
  
  # 3. 批量创建 diff files 到数据库
  create_merge_request_diff_files(rows)
  
  # 4. 设置状态为 'collected' 或 'overflow'
  new_attributes[:state] = :collected
end

完整的调用链

git push

PostReceive Worker

BranchPushService

UpdateMergeRequestsWorker  ⭐ (异步队列任务)

MergeRequests::RefreshService

merge_request.reload_diff(user)

MergeRequests::ReloadDiffsService

merge_request.create_merge_request_diff

MergeRequestDiff.create! (触发 after_create 回调)

save_git_content

save_diffs  ⭐ (生成 diff)

create_merge_request_diff_files  ⭐ (保存到数据库)

数据库表

生成的 Changes 数据主要存储在:

  • merge_request_diffs: diff 的元数据(head_commit_sha, base_commit_sha 等)
  • merge_request_diff_files: 每个文件的具体变更内容
  • merge_request_diff_commits: 包含的 commits

总结

生成代码变更的核心任务UpdateMergeRequestsWorker,它通过调用一系列服务和模型方法,最终在 MergeRequestDiff 模型的 save_git_content 方法中:

  1. 从 Git 仓库获取 diff 数据
  2. 解析并构建 diff files
  3. 批量插入数据库
TianLu 编辑于