workflow
workflow 关键字适用于整个管道,并将确定是否创建管道。when
:可以设置为always
或never
. 如果未提供,则默认值always
- if:定义变量条件
- when:只有两个值,always 和 nevel
if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
|
合并请求时运行流水线 |
if: '$CI_PIPELINE_SOURCE == "psuh"'
|
提交代码运行流水线 |
workflow: rules: - if: '$CI_PIPELINE_SOURCE == "push"' # 当为 push 的时候才会触发,其他情况下不会触发该流水线 when: never # 上面的条件为 true 时,永远不执行 - when: always # 上面的条件为 false 时,永远执行 stages: # 指定运行的步骤,没有指定就顺序执行 - build - deploy - test - rebase build1: # job 的名称 tags: - k8s # 指定运行的 runner 标签 stage: build # stage 的名称 script: - echo "Do your build here" test1: stage: test script: - echo "Do a test here" - echo "For example run a test suite" rebase: stage: rebase script: - echo "Do another parallel test here" - echo "For example run a lint test" deploy1: tags: - k8s stage: deploy script: - echo "Do your deploy here"
当上面执行 push 操作时,才会运行流水线,否则不会运行流水线
rules
rules 可以按照设置的规则来判断是否执行流水线,也可以设置以什么样的方式执行(when)
rules 有三个关键字
- if:判断条件,如果条件满足时执行该 job,不满足时不执行 job
- changes:某个或多个文件改变时执行该 job,没有改变时不执行 job
- exists:文件存在时执行该 job,不存在时不执行 job
if
if 可以使用多条件,&& 所有条件满足时才会执行该 job,|| 某个条件满足时就会执行该 job
stages: # 指定运行的顺序 - test - deploy variables: name: zouzou deploy: tags: - k8s stage: deploy retry: parallel: 3 # 要并行运行的作业实例数 rules: - if: '$name == "zouzou"' # 如果变量名等于 zouzou,则运行流水线,将流水线设置为手动执行 when: manual - if: '$name == "haha"' # 如果变量名等于 haha,则延迟 10 秒执行 when: delayed start_in: "10" - when: on_success # 上面两个条件都不满足的话,则上个流水线成功时该流水线触发 script: - echo "我是部署阶段" test: stage: test script: - echo "我是测试阶段"
现在 name 的值是等于 zouzou的,查看流水线
将 name 的值改为 haha,在来查看流水线
changes
接受文件路径数组。 如果提交中Dockerfile
文件发生的变化则为 true。触发流水线
先在项目下创建一个 Dockerfile 的文件,随便写点内容
修改 .gitlab-ci.yml 文件内容,修改后的如下
stages: # 指定运行的顺序 - test - deploy variables: name: haha deploy: tags: - k8s stage: deploy retry: parallel: 3 # 要并行运行的作业实例数 rules: - changes: # 当 Dockerfile 或者 Jenkinsfile 里的文件内容改变时,才会执行 deploy 的 job - Dockerfile - Jenkinsfile script: - echo "我是部署阶段" test: stage: test script: - echo "我是测试阶段"
触发流水线查看下,可以看到,只有 test 的 job 触发了
这时候只有 Dockerfile 或者 Jenkinsfile 里的文件没有发生改变,deploy 的 job 都不会触发
接下来我们修改一下 Dockerfile 的内容,然后提交
提交后查看流水线
exists
接受文件路径数组。当仓库中存在指定的文件时操作
stages: # 指定运行的顺序 - test - deploy variables: name: haha deploy: tags: - k8s stage: deploy retry: parallel: 3 # 要并行运行的作业实例数 rules: - exists: # 当项目中存在 Dockerfile 或者 Jenkinsfile 文件时,才会执行 deploy 的 job - Dockerfile - Jenkinsfile script: - echo "我是部署阶段" test: stage: test script: - echo "我是测试阶段"
实际项目中使用 rules 的场景
下面几个例子是我们公司实际项目中 gitlab ci 的场景
例子一:在合 pr 的时候触发 job
static_check: rules: - if: '$CI_PIPELINE_SOURCE == "merge_request_event"' # 是合 pr 的时候才执行该 job tags: - docker stage: verify script: # 执行的操作 - make clean - make genproto - go mod vendor - make lint interruptible: true verify_import_alias: rules: - if: '$CI_PIPELINE_SOURCE == "merge_request_event"' # 是合 pr 的时候才执行该 job stage: verify tags: - k8s script: - make verify-import-alias interruptible: true
演示
在我们的 main 分支下的 .gitlab-ci.yml 里写入下面内容
stages: # 指定运行的顺序 - test - deploy variables: name: haha deploy: tags: - k8s stage: deploy retry: rules: - if: '$CI_PIPELINE_SOURCE == "merge_request_event"' # 合 pr 时触发 script: - echo "我是部署阶段" test: stage: test script: - echo "我是测试阶段"
基于 main 分支创建一个 demo 分支,修改 demo 分支上的文件,然后提交到 demo 分支上,也可以使用 git 提交
提交后查看流水线,发现只有一个 test 的 job 触发了(要保证 demo 分支的和 main 分支的 .gitlab-ci.yml 里的文件内容一样,如果不一样会以 demo 分支的为准)
这时候我们在提交一个 pr 到 main 分支
可以看到,提交 pr 只会跑'$CI_PIPELINE_SOURCE == "merge_request_event"'
的 job ,我们的 test job 没有触发
例子二:满足某个条件时执行
unit_test: rules: # 合 pr 或者提交到的分支是 main 分支。或者是创建 tag,只要满足某一个,都会触发该 job - if: '$CI_PIPELINE_SOURCE == "merge_request_event" || $CI_COMMIT_BRANCH == "main" || $CI_COMMIT_TAG' stage: test tags: - docker script: - make genproto - go mod vendor - make test interruptible: true coverage: '/total:\s+\(statements\)\s+\d+.\d+%/'
例子三:当往 main 分支 push 时触发
build_to_release_ci: rules: # 提交的分支是 main 分支并且是 push 操作时才触发该流水线,&& 条件都要满足 - if: '$CI_COMMIT_BRANCH == "main" && $CI_PIPELINE_SOURCE == "push"' # trigger when a branch was merged into main retry: max: 2 tags: - docker before_script: - docker -v #override the global before_script - make genall - go mod vendor stage: build script: - | # set envirment varible when new release publish by new tag created export REGISTRY_USER_NAME=$CI_REGISTRY_USER_NAME export REGISTRY_PASSWORD=$CI_REGISTRY_PASSWORD export REGISTRY_REPO="release-ci.daocloud.io/amamba" export REGISTRY_SERVER_ADDRESS="release-ci.daocloud.io" export HELM_REPO="https://release-ci.daocloud.io/chartrepo/amamba" make release -j2 #REGISTRY_USER_NAME and REGISTRY_PASSWORD config as Gitlab Variables export NPM_TOKEN=$NPM_TOKEN;make push-grpc-ts #NPM_TOKEN has been configured as Gitlab Variable
例子四:创建 tag 或者往 main 分支上 merge 时触发
build_to_release_ci: rules: # 往 main 分支上 merge 或者创建 tag 的时候触发 - if: '($CI_COMMIT_BRANCH == "main" && $CI_PIPELINE_SOURCE == "merge_request_event") || $CI_COMMIT_TAG' tags: - docker before_script: - docker -v stage: build script: - | # set envirment varible when new release publish by new tag created export REGISTRY_USER_NAME=$CI_REGISTRY_USER_NAME export REGISTRY_PASSWORD=$CI_REGISTRY_PASSWORD export REGISTRY_REPO="release-ci.daocloud.io/amamba" export REGISTRY_SERVER_ADDRESS="release-ci.daocloud.io" make release #REGISTRY_USER_NAME and REGISTRY_PASSWORD config as Gitlab Variables