Submodule Checker 开发笔记

背景

为了让多个服务互相通讯,拥有强类型的消息类型定义、服务接口定义非常有必要。 同时我们需要将一份定义配置(如 Protobuf,GRPC)在多个项目中使用,最终选择了用 Git Submodule

在比较标准的 git 协作流程中,我们希望所有合并到 master 分支的提交,submodule 也是指向子项目的 master 分支的。 同时我们 pr 使用 squash 合并,分支中的所有提交都被压成一个提交进入 master。

假设我们有 parent 和 child 两个项目,其中 child 是 parent 的一个子模块,两个项目都需要使用 pr 做协作。

考虑如下的工作流程:

  1. 修改 child 项目,提出 pr,review 后合并至 master
  2. 更新 parent 项目,指向最新的 child 提交,开发 parent 项目提 pr 并 review

在这种两个项目没有同时开发的过程中,此流程没有明显问题,但事实上 child 作为一份消息格式定义,不可避免的要在开发过程中修改定义, 如果每次修改都先等待 child 发 pr 合并会浪费很多时间,并且让提交日志混乱。因此一般都会在 child 改一些内容后,先开发 parent,在过程中同时修改两个项目,最后一起发 pr。也就是如下的工作流程:

  1. child 开新分支,做出初步的修改
  2. parent 开新分支,根据新的定义写代码,同时将 child 的子模块指向新分支的新提交
  3. 两边同时推上去,等 CI,根据测试结果、覆盖率情况修改
  4. 随着开发的过程修改 child 和 parent,分别提交到各自分支
  5. 在 child 项目开 pr 等后合入主分支
  6. 在 parent 中将 child 指向刚刚合进去的新分支,开 pr

如果在以上过程最后两步中,没有将 parent 指向 child,最终合并后 parent 就指向了一个在分支上的提交,等 child 项目提交被 squash,分支删除后,parent 的主分支将处于找不到 submodule commit 的尴尬境地。

设计与实现

所有项目的主分支都保证了严格向前,只需要保证 parent 对 child 的指针一定是在一个 child 的主分支上的提交即可,每个 PR 在合并前都检查是否已经将 submodule 指向了 master 分支。

因此我开发了一个用来检查这一状态,并会设置 github commit status 的小程序:https://github.com/richard1122/submodule-checker

首先需要配置 parent 项目中都有哪些子项目,分别位于那个路径中,程序会分别用 Github API 查看这个路径的内容。 Github 对于 Submodule 已经做了处理,可以得到其项目地址等信息,再使用 Github 比较提交 API, 获取 Submodule 的指针与默认分支的比较结果,Github 会返回对应的状态,如 ahead,identical 等,根据这个状态就可以知道当前提交和某个分支的头指针的关系了。

使用方式请参考项目连接,目前已经配置了 Github APP,可以在此安装:https://github.com/apps/submodule-checker