当前位置: 首页 > Web前端 > HTML

CI-CD必知:master分支检测背后的

时间:2023-03-28 00:10:00 HTML

背景我在公司一年多了,业余时间一直在参与BU自己的前端发布平台;以前我们的构建底层(CI/CD)大多依赖于组的能力,所以往往一个应用的某个迭代发布后,其他迭代构建部署,就会报错。这时候需要打开群系统的构建日志,会看到类似如下的错误提示:master分支有新的提交,请合并分支后继续部署。由于今年有新的业务系统要接入,我们需要有自己的CI/CD底层。为了集成这个能力,一开始我也走了很多弯路,所以记录一下。为什么后向检测很重要目前,大多数简单的前端建设部署都是由分支机构管理的;例如,当我们完成一个需求时:我们会从master主干拉取一个迭代分支,然后我们会在开发-测试环境中使用这个分支我们做一个构建部署,然后我们将变更合并回之前的主干在线发布它们。上面的过程是一个很笼统的过程,但是可能还有其他的方法,比如一个特别前沿的:每次从master主干拉取部署分支,然后合并迭代分支,然后部署。这种情况不在今天的讨论范围之内,因为这个策略没有这个落后的麻烦。回到前面,为什么要做后向检测呢?因为在很多情况下,一个应用会由多人维护,有多次迭代(A,B),这里我们假设10.10的两个分支是从主干的同一个节点拉取的。A和B自己正常开发部署,然后A的迭代在10.22上线。发布后,代码合并到master;但是B的迭代是10.24上线的,不知道A已经发布了。如果此时部署系统没有master分支,如果检测落后,B会顺利上线分支B。这会造成什么后果?B上线后,分支合并回主分支,报错(大概率)。后续迭代没有这个功能,导致以后失败;A迭代上的功能没了,上线事故(比较严重,3.25)。是谁的锅?作为?乙?还是平台?在我看来,锅就是平台。也许你会问,为什么上线前不合并master,然后在线构建部署呢?我们平台这边,有两个考虑:上线前有一个灰度阶段。如果先合并master,如果发现灰度有bug,或者需要先启动其他迭代,退出灰度会很麻烦。这时,主枝也会被污染;重新从master上拉取分支,合并代码构建部署,如果是手动操作,对开发者来说会很麻烦;如果平台自己做这个操作,是有代价的,这个能力是集成的,你可以再往前建一点,走前面提到的前沿计划##我们的做法首先要明白,什么是这种情况,我们称之为滞后于master,上图:feat/1.0.0发布后合并到master,导致feat/1.0.1滞后于master分支。这个滞后与1.0.1提交的commit数量无关,只与是否与master分支的commit信息同步有关。其实在网上查了一下分支比较的资料,发现基本都是用shell脚本处理的。stackoverflow上有一篇帖子和我的说法基本一致:链接地址有没有办法在我的分支和master之间做一个diff,排除master中还没有合并到我的分支中的变化?高度赞扬答案,其中提到:gitdiffbranch...master,并请给出官方链接进行解释;里面提到了一个概念,叫做merge-base,相当于两个分支的共同起点,比如上面的两个分支,这个点就是X;gitdiffmaster...feat/1.0.1相当于gitdiff$(gitmerge-basemasterfeat/1.0.1)feat/1.0.1相当于gitdiffcommitXcommitF所以在运行时:gitdifffeat/1.0.1...master,可以看到:从上图的结果可以看出,列出的差异点只有A/B的两次提交;所以两次差异比较等价于:gitdiffXB;就这样,我明白了!!!但是我们的平台是基于gitlab的API,直接运行这种命令行是不可能的。幸运的是,互联网是无所不能的。这个API是:gitlab.Repositories.compare//Repositories.compare(projectId:string|number,from:string,to:string,options?:Sudo)constinfo:any=awaitgitlab.Repositories.compare(projectId,commitId,'掌握');注意from和to的位置,from是feat/1.0.1,to是master,这个很重要;结果信息是这样的:{"commit":{},"commits":[],"diffs":[],"compare_timeout":false,"compare_same_ref":false,"web_url":"https://gitlab.example.com/thedude/gitlab-foss/-/compare/ae73cb07c9eeaf35924a10f713b364d32b2dd34f...0b4bc9a49b562e85de7cc8682"82e8634"所以如果分支不在master之后,即master分支没有新的commit,那么commit和iffcom都是空值,是一个空数组;另外,注意compare_timeout的值。如果分支比较的工作量过大,可能会导致超时。这四个参数是一个选项。当option.straight为true时,此时的diff结果不是我们预期的,调用时要注意野鹿子分享说,事情并没有像上面描述的那么顺利。一开始我们因为时间关系没有找到compareAPI,而是采用了递归的方式,就是不断的回到分支节点,试图找到和当前master相同的commitId。节点,最大搜索范围向下8层。如果超过8层还没有找到,则判断在master分支后面,否则就是安全的。我个人认为这个算法不低于leetCode的中题;在一些简单的迭代分支管理方面,上述算法仍然可以工作,但是对于过于复杂的分支,它要么超时,要么超过8层;超时是因为如果一个节点不匹配,需要调用API获取下一堆子节点,API调用过程非常耗时://部分代码实现if(level>MaxLevel||this.globalFinish){returnfalse;}constreocords=[]for(leti=0;i