读懂配置,答出会跑什么
目标
.gitlab-ci.yml 不是程序,而是声明。因此不能停留在“运行一下就知道”,而必须能通过阅读得出答案。流水线运行结果与预期不符的事故,几乎都源于错误解读这个文件。
本实验不使用 GitLab,只查看配置并得出答案。
材料
/opt/lab/glci/pipeline.yml 잡 다섯 개짜리 파이프라인
/opt/lab/glci/broken.yml 문법은 맞는데 뜻이 틀린 곳이 네 군데
mkdir -p /root/glci && cp /opt/lab/glci/* /root/glci/ && cd /root/glci
需要留下的文件
01-jobs.txt 잡과 템플릿
02-vars.txt 같은 변수의 세 값
03-rules.txt 상황마다 도는 잡
04-broken.txt 틀린 네 군데와 고치는 법
fixed.yml 고친 파일
check.py 같은 실수를 다시 막는 검사
07-notes.md 왜 그런지
区分 job 与非 job
从 pipeline.yml 中找出实际 job 的数量和名称,写入 01-jobs.txt,并另加一行说明 .base 为什么不是 job。
名称以点开头的条目是隐藏模板,不会执行,只会通过 extends 被其他配置引用。
stages、variables 等保留字也不是 job。job 一共有五个。
同名变量的三个值
RETRIES 出现在三个位置。请在 02-vars.txt 中写出 build、unit、lint 各自实际使用的值,并另写一行说明该值为何胜出。
全局 variables 的优先级最低,模板(.base)次之,job 自己的 variables 优先级最高。
build 和 unit 只继承 .base,而 lint 单独设置了自己的值。
什么情况下运行什么
针对 main 分支 push、merge request、tag 三种情况,分别把会运行的 job 写入 03-rules.txt。每种情况用以对应词语(main、머지、태그)开头的一行区分。
rules 会**从上往下检查,并在第一个匹配项处停止。**若没有任何匹配,该 job 就不会运行。
最后一行若只有 when: never,表示“其他情况下不运行”。
deploy-prod 在 tag 情况下设为 when: manual,因此会出现在流水线中,但必须由人工点击。也要把它列入“运行”的 job,并注明为手动。
找出语法正确但含义错误之处
在 broken.yml 中找出四处问题,写入 04-broken.txt,并分别说明如何修复。
这些内容都能被 YAML 正常解析,错误在于违反 GitLab 的规则。
- 一个 job 能否同时使用
only和rules - 使用
stages中不存在的阶段会怎样 - 能否通过
needs等待后续阶段的 job - 在阶段之间传递文件应该使用
cache还是artifacts
实际修复并保存为文件
创建实际修复这四处问题的 fixed.yml。不得删除任何 job。
如果通过删除 job 来修复,检查也许能通过,但流水线的含义会改变。保持原有工作不变,只修正表达方式。
对于 publish,删除 cache,让它接收 build 生成的 artifacts。同一流水线中,前序阶段的 artifacts 会自动下载;只有需要缩小接收范围时才写 dependencies。
让机器阻止同类错误
创建 check.py,使其拦截 broken.yml 并放行 fixed.yml。检查作为参数传入的文件,发现问题时必须以非零状态码退出。
检查四类问题:使用 stages 中不存在的阶段、only/except 与 rules 共存、用 needs 等待后续阶段,以及试图用 cache 在阶段间传递文件。
**无法拦截错误的检查不算检查,而连修复后的文件也拦截的检查不会有人使用。**请用两个文件进行正反双向验证。
写给下一位阅读者
从本实验看到的内容中选择至少四项,整理到 07-notes.md。不要只写做了什么,而要写清楚为什么。
设想这份笔记要留给流水线行为与预期不符时的自己。“查看了 rules”没有帮助;“rules 在首个匹配项处停止,因此若上方条件成立,下方条件永远不会被检查”才有帮助。