stage 的排队与 needs 的 DAG
一句话总结
stages是排列成抓取格子的,前一个格子结束后,下一个格子才能开始,needs无视那个栏壁,只指定“我实际上需要等待的东西”,将管道转换为DAG。
为什么需要这个?
阶段模型有一个很大的优点,就是很容易理解。build结束后开始test,test结束后开始deploy。问题是这种简单性很快就会变成浪费。
在test阶段有五个任务,其中一个是12分钟的综合测试。其余四个任务只要1分钟就能完成,但要等待deploy阶段的12分钟全部完成。实际上,部署可能只需要综合测试结果,但阶段模型没有表达这一事实的方法。任务之间的真正依赖关系比单元格更紧密,单元格将这种紧密的关系四舍五入为紧密。
更令人沮丧的情况是相反的。仅仅因为源代码就可以的lint抓取在build阶段后面,所以直到build结束都无法开始。开发者为了知道一个错误而等待build时间。如果整个管道时间超过15分钟,人们就不等结果而去做其他事情,反馈循环就会崩溃,这种浪费时间占了15分钟的大部分。
怎么行动
needs在抓取中写上,忽略抓取的阶段顺序,只等待列出的抓取。此时,三个规则同时起作用。
第一,needs完全保持了抓到的以前的样子。只有在自己面前的舞台上的所有抓取完成后才能出发。所以一个文件中可以混合舞台方式和DAG方式。
第二,needs: []意思是“什么都不等”。没有高度和空列表具有完全相反的意义。这一行将Lint捕获的管道拉到了最前面。
第三,needs虽然是前阶段,但不能指明。可以指明同阶段的杂项,然后在同一个格子里也会形成顺序。相反,如果指明后阶段的杂项,就会形成循环,GitLab会拒绝设置。
将这三条规则加起来,管道就会变成有方向的非循环图,执行顺序由图的相位排序决定。如果你想用眼睛看到执行计划,可以用波浪来表示。没有任何事情要等待的杂事在第一波一起出发,只有他们完成后才能出发的杂事才是第二波。波浪数是管道的最小深度,无论增加多少跑者,都不会减少的时间下限。
有一个实际上的限制。可能会遇到一些麻烦的needs数量有上限(基本50),所以试图将数百个管道变成完整的DAG的尝试一般在中间停止。那样的时候,只选择几个成为瓶颈的。needs最好把挂起来的部分交给舞台,剩下的交给舞台处理。
在现场相遇的样子
换成DAG的团队首先经历的惊讶不是时间减少,而是依赖关系被文档化。needs要写的话,必须回答这个杂事为什么要等待,但当真正想写的时候,出现了很多没有人知道原因的等待。这些等待大部分是可以抹去的。
也有相反方向的交通事故。needs正在使用向前推进的抓取的前抓取的产出物,那个依赖needs写了很多,说没有文件,所以失败了。这种失败在跑者空闲的时候不会重现,只有忙的时候才会出现,所以很容易被误认为是播放器测试。
接下来要看的
即使是同一个管道,也要根据分支,根据是否是合并请求,做出不同的选择。负责那个选择的rules在下一篇文章中看到。