为什么要做 deepin-code-release 呢?其实我们在 deepin-code-release 的 README.md 中写得挺详细了:
从deepin项目启动开始,伴随着越来越多的deepin子项目产生,不同开源/商业定制版本的分割加剧,项目间的版本依赖问题、上游项目的patch丢失问题和系统环境无法恢复问题越来越严重,我们迫切需要一个统一的系统来帮助我们记录不同版本的ISO/软件仓库的状态,做各个子项目版本的版本控制和patch的版本控制,以达到快速恢复开发/系统环境,进而使针对不同系统版本的开发更加高效。
deepin release系统就是这样一个辅助系统,它的目标在于将它的每一个状态都对应到我们所有发布的ISO/软件仓库状态、每一个针对ISO/软件仓库的改动都能反映到这个仓库的改动上。
简而言之,deepin-code-release 是版本的版本控制管理工具,用来管理 deepin 众多“轮子”项目的版本号的,每次系统发布都需要进行一次记录,方便以后开发修问题的时候能找到当时的代码进行bug修复。
为了确保记录的准确,它的想法是这样的,每次(系统)发布前,深度的程序员各自检查一下自己负责的项目,如果需要跟随系统进行发布,就提交 CL 到 deepin-code-release 项目,这个 CL 会自动触发项目在对应仓库的打包,并且将打包结果反馈到 CL 的 Code Review 评分上,+1 分的就进行合并,反之闭门思过解决问题后再次提交,直到成功合并。
问题 Link to heading
以上需求还是听简单明确的,但是在目前的实现上却有一个问题:使用了 git-submodule 进行子项目的管理,再加上其他几个没有考虑的情况,这导致了好多小问题,以至于推行到现在还是阻碍重重:
1. 使用起来比较麻烦 Link to heading
deepin 的项目都是放在 gerrit 上的,它并没有一个统一的 git 用户(类似git@github.com中的git),所以同一个项目在不同开发人员的机器上的项目地址是不一样的,当成 submodule 放到 deepin-code-release 这个项目中以后,必须驱动项目地址中的用户名部分,再在 ~/.config/ssh
中添加一些额外的配置(参见 README.md )。
2. submodule 用起来比较别扭 Link to heading
最直接、也是抱怨最多的一点,是大家平常使用 git submodule
系列的命令并不多,所以对操作 git submodule
有不太习惯,而且就算是我比较熟练了,也总觉得 git submodule update
这个有点反直觉,感觉上应该是类似 git pull --recurse-submodules
的功能,但是实际上并不是这样。以至于很多人一不小心,把别个辛辛苦苦提交的更新又给退回去了。
3. 多了一个额外的仓库 Link to heading
原本的打算是每个开发都只需要克隆一个 deepin-code-release 项目,然后在其中 init 自己负责的项目并进行提交,需要关注多个项目的就按需 init 多个项目即可,但是实际推行的过程中还是发现大家并不是特别关注自己项目外的项目,deepin-code-release 里面就一个自己的项目初始化了,而且用着还挺别扭,还不如自己单独克隆一份,结果就每个开发上面既有一个自己项目的仓库,还要有一个包含了自己项目仓库的 deepin-code-release 项目,也是抱怨声颇多。
4. 严重降低工作效率 Link to heading
每次系统发布前,都有统一的 ”冻结代码“ 时刻,这个时候大家都向 deepin-code-release 提交代码,就造成了拥堵,因为每个CL都是需要打包验证过没有问题才能合并的,所以大家的CL都在等打包完成,然而一旦其中某个项目打包完成合并了,其他 CL 都需要进行 rebase
操作才能合并,rebase
又会触发打包……本来每个项目应该一次打包的时间,硬生生的被进行了翻倍。
本来只是想着让工作流程更加清晰,增加工作效率的东西,反而严重降低了工作效率,这也是这次痛定思痛准备重新设计这个系统的原因了。
解决办法 Link to heading
既然有问题,那就需要想办法解决啦,以下就是解决方案的草案:
首先,要排除 “万恶之源” 的 git submodule
,其实在设计之初就应该遵照产品上 MVP 的思路,用最简单的方式进行尝试,比如这次就回归为只使用一个简单的 projects.json 文件来进行项目 metadata 的记录,包括项目地址、版本号(可以是tag或者commit)等等。
去掉 git submodule
之后,其实前三个问题自然而然地也就解决了。
在此基础之上,要解决“ CL 拥堵问题”,解决方案其实蛮简单的,就是抛弃原来的那套方案,不再通过提交 CL 来触发打包和记录操作,而是搭建一个服务,提供 LDAP 登录验证和简单的操作界面,一个worker负责接收更新版本的请求,接到请求以后只是简单的把请求丢到“请求队列”中,其余的什么也不做;另外一个worker则不停地尝试从队列中获取请求信息,先触发打包开始等待结果,如果打包失败,直接发邮件或者IM信息通知请求的发起人;如果打包成功,则将更新的内容修改至相应的 projects.json 文件中,然后尝试从队列中获取另外一个更新请求;系统闲时或者定期将本地提交推送到 git 远程仓库即可,这样就完全没有重复打包的情况出现了。
至于说以前有的需求,比如需要把所有被管理子项目的代码拉到本地进行处理,就只需要将dcr
工具做一下简单的修改,就可以很方便地满足。
这么简单的解决方案为什么就一直没有想到呢?最主要的原因就是总是觉得程序员应该是万能的,一点不太熟悉的工具不应该成为做事的阻碍,但是慢慢地发现这种想法非常错误,当所有人都觉得这个事情有问题的事情,这个事情多半是有问题的,也就妥协了。