如何基于$jobs变量按组控制GitLab CI/CD作业执行顺序?
问题描述
我有3组作业,当前配置下同一stage的所有作业会并发执行。希望基于$jobs变量按以下顺序执行:
- prep(始终最先执行)
- 若
$jobs字符串变量中包含build1,则执行build1 build1执行完成后执行deploy1- 若
$jobs中包含build2,则执行build2 build2执行完成后执行deploy2- 若
$jobs中包含build3,则执行build3 build3执行完成后执行deploy3
补充规则:若build1不存在则跳过build1直接执行build2;若build2不存在则跳过build2,先执行build1再执行build3。
现有CI配置如下:
stages: - prep - build - deploy getjobs stage: prep script: <script assigns string value with jobs to be ran to $jobs global variable> rules: - if: $CI_COMMIT_MESSAGE =~ /See merge request/ when: on_success build1 stage: build needs: [getjobs] script: ... rules: - if: $CI_COMMIT_MESSAGE =~ /See merge request/ when: on_success deploy1 stage: deploy needs: [build1] script: ... rules: - if: $CI_COMMIT_MESSAGE =~ /See merge request/ when: on_success build2 stage: build needs: [getjobs] script: ... rules: - if: $CI_COMMIT_MESSAGE =~ /See merge request/ when: on_success deploy2 stage: deploy needs: [build2] script: ... rules: - if: $CI_COMMIT_MESSAGE =~ /See merge request/ when: on_success build3 stage: build needs: [getjobs] script: ... rules: - if: $CI_COMMIT_MESSAGE =~ /See merge request/ when: on_success deploy3 stage: deploy needs: [build3] script: ... rules: - if: $CI_COMMIT_MESSAGE =~ /See merge request/ when: on_success
想了解在保留当前stage结构的前提下,是否能实现这种作业顺序依赖。
解决方案
可以实现,核心是通过**needs控制作业执行顺序**,结合**rules基于$jobs变量判断作业是否触发**,同时利用GitLab CI中needs对未触发作业的自动忽略特性(需GitLab 13.10+版本支持)。以下是修改后的完整配置:
stages: - prep - build - deploy getjobs stage: prep script: <script assigns string value with jobs to be ran to $jobs global variable> rules: - if: $CI_COMMIT_MESSAGE =~ /See merge request/ when: on_success # 将$jobs变量传递给后续作业 artifacts: reports: dotenv: jobs.env build1 stage: build needs: [getjobs] script: ... rules: - if: $CI_COMMIT_MESSAGE =~ /See merge request/ && $jobs =~ /build1/ when: on_success deploy1 stage: deploy needs: [build1] script: ... rules: - if: $CI_COMMIT_MESSAGE =~ /See merge request/ && $jobs =~ /build1/ when: on_success build2 stage: build # 依赖getjobs和build1(若build1触发则等待其完成,未触发则直接执行) needs: - getjobs - job: build1 optional: true script: ... rules: - if: $CI_COMMIT_MESSAGE =~ /See merge request/ && $jobs =~ /build2/ when: on_success deploy2 stage: deploy needs: [build2] script: ... rules: - if: $CI_COMMIT_MESSAGE =~ /See merge request/ && $jobs =~ /build2/ when: on_success build3 stage: build # 依赖getjobs、build1和build2(已触发的作业需等待完成,未触发则跳过) needs: - getjobs - job: build1 optional: true - job: build2 optional: true script: ... rules: - if: $CI_COMMIT_MESSAGE =~ /See merge request/ && $jobs =~ /build3/ when: on_success deploy3 stage: deploy needs: [build3] script: ... rules: - if: $CI_COMMIT_MESSAGE =~ /See merge request/ && $jobs =~ /build3/ when: on_success
关键修改说明:
- 传递
$jobs变量:在getjobs作业中添加artifacts:reports:dotenv,确保$jobs变量能被后续作业读取使用(GitLab 12.0+支持)。 - 基于
$jobs触发作业:所有build/deploy作业的rules中添加$jobs =~ /buildX/判断,只有当变量包含对应作业标识时才触发。 - 控制作业执行顺序:
build2的needs中添加可选依赖build1:若build1被触发,则build2会等待build1完成后再执行;若build1未触发,build2直接执行。build3的needs中添加可选依赖build1和build2:确保build3在build1、build2(如果触发)完成后才执行,符合要求的顺序逻辑。
- deploy作业依赖对应build:保持原有
needs: [buildX],确保只有对应build完成后才执行deploy,且仅当$jobs包含对应build时触发。
这样既保留了原有的prep/build/deploy stage结构,又完全实现了要求的作业执行顺序规则。
内容的提问来源于stack exchange,提问作者annyka
相关产品推荐
相关产品推荐

