-
指定作业何时使用
rules
运行 - 在不同的作业中重用规则
-
指定作业何时以
only
和except
运行 - 创建必须手动运行的作业
- 延迟后运行作业
- 并行化大型作业
- 通过多个并行作业的需求指定并行作业
- 使用预定义的 CI/CD 变量仅在特定流水线类型中运行作业
- 常用表达
- CI/CD 变量表达
- 故障排查
选择何时运行作业
当新流水线启动时,极狐GitLab 检查流水线配置以确定应在该流水线中运行哪些作业。您可以根据变量的状态、流水线类型等配置要运行的作业。
要将作业配置为包含或排除在某些流水线中,您可以使用 rules
。
使用 needs
将作业配置为在其依赖的较早作业完成运行后立即运行。
指定作业何时使用 rules
运行
使用 rules
在流水线中包含或排除作业。
规则按顺序评估,直到第一次匹配。找到匹配项后,该作业将包含在流水线中或从流水线中排除,具体取决于配置。
有关更多详细信息,请参阅 rules
参考。
rules
示例
以下示例使用 if
来定义作业仅在两种特定情况下运行:
job:
script: echo "Hello, Rules!"
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
when: manual
allow_failure: true
- if: $CI_PIPELINE_SOURCE == "schedule"
- 如果流水线用于合并请求,则第一个规则匹配,并将作业添加到合并请求流水线并具有以下属性:
-
when: manual
(手工作业) -
allow_failure: true
(即使没有运行手动作业,流水线也会继续运行)
-
- 如果流水线不是合并请求触发,则第一条规则不匹配,并评估第二条规则。
- 如果流水线是计划流水线,则第二条规则匹配,并将作业添加到计划流水线。没有定义属性,因此添加了:
-
when: on_success
(默认) -
allow_failure: false
(默认)
-
- 在所有其他情况,没有规则匹配,因此作业不添加到任何其他流水线。
或者,您可以定义一组规则以在少数情况下排除作业,但在所有其他情况下运行它们:
job:
script: echo "Hello, Rules!"
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
when: never
- if: $CI_PIPELINE_SOURCE == "schedule"
when: never
- when: on_success
- 如果流水线用于合并请求,则作业不添加到流水线中。
- 如果流水线是计划流水线,则作业不添加到流水线中。
- 在所有其他情况,作业被添加到流水线中,使用
when: on_success
。
when
子句作为最终规则(不包括 when: never
),则可能会同时启动两个流水线。推送流水线和合并请求流水线都可以由同一事件触发(推送到源分支以获取开放合并请求)。
有关更多详细信息,请参阅如何防止重复流水线。为计划流水线运行作业
要将作业配置为仅为计划流水线时执行,请使用 rules
关键字。
在此示例中,make world
在计划流水线中运行,而 make build
在分支和标签流水线中运行:
job:on-schedule:
rules:
- if: $CI_PIPELINE_SOURCE == "schedule"
script:
- make world
job:
rules:
- if: $CI_PIPELINE_SOURCE == "push"
script:
- make build
如果分支为空则跳过作业
使用 rules:changes:compare_to
避免在分支为空时运行作业,从而节省 CI/CD 资源。将分支与默认分支进行比较,如果分支:
- 没有更改的文件,作业不运行。
- 已更改文件,作业运行。
例如,在以 main
作为默认分支的项目中:
job:
script:
- echo "This job only runs for branches that are not empty"
rules:
- if: $CI_COMMIT_BRANCH
changes:
compare_to: 'refs/heads/main'
paths:
- '*'
此作业的规则将当前分支中的所有文件和路径 (*
) 与默认分支 main
进行比较。只有当分支中的文件发生更改时,规则才匹配并且作业运行。
复杂规则
您可以在同一规则中使用所有 rules
关键字,例如 if
、changes
和 exists
。 仅当所有包含的关键字评估为 true 时,规则才会评估为 true。
例如:
docker build:
script: docker build -t my-image:$CI_COMMIT_REF_SLUG .
rules:
- if: $VAR == "string value"
changes: # Include the job and set to when:manual if any of the follow paths match a modified file.
- Dockerfile
- docker/scripts/*
when: manual
allow_failure: true
如果 Dockerfile
文件或 /docker/scripts
中的任何文件发生了变化 和 $VAR
== “string value”`,则该作业手动运行并允许失败。
您可以使用括号、&&
和 ||
来构建更复杂的变量表达式。
引入于 13.3 版本:
job1:
script:
- echo This rule uses parentheses.
rules:
- if: ($CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH || $CI_COMMIT_BRANCH == "develop") && $MY_VARIABLE
||
和 &&
的规则可能会以意外的操作顺序进行评估。防止重复流水线
如果作业使用 rules
,则单个操作(例如将提交推送到分支)可以触发多个流水线。您不必为多种类型的流水线显式配置规则来意外触发它们。
一些可能导致重复流水线的配置,会导致显示流水线警告。 引入于 13.3 版本。
示例:
job:
script: echo "This job creates double pipelines!"
rules:
- if: $CUSTOM_VARIABLE == "false"
when: never
- when: always
当 $CUSTOM_VARIABLE
为 false 时,此作业不会运行,但它确实在 所有 其他流水线中运行,包括推送(分支)和合并请求流水线。使用此配置,每次推送到开放合并请求的源分支都会导致重复的流水线。
为避免重复流水线,您可以:
- 使用
workflow
指定可以运行的流水线类型。 -
重写规则以仅在非常特定的情况下运行作业,并避免最终的
when
规则:job: script: echo "This job does NOT create double pipelines!" rules: - if: '$CUSTOM_VARIABLE == "true" && $CI_PIPELINE_SOURCE == "merge_request_event"'
您还可以通过更改作业规则来避免重复流水线,以避免推送(分支)流水线或合并请求流水线。但是,如果您使用没有 workflow: rules
的 - when: always
规则,系统仍会显示流水线警告。
例如,以下不会触发双流水线,但不建议在没有 workflow: rules
的情况下使用:
job:
script: echo "This job does NOT create double pipelines!"
rules:
- if: $CI_PIPELINE_SOURCE == "push"
when: never
- when: always
如果没有 workflow:rules
防止重复流水线:
job:
script: echo "This job creates double pipelines!"
rules:
- if: $CI_PIPELINE_SOURCE == "push"
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
此外,不要在同一流水线中将 only/except
作业与 rules
作业混合。
它可能不会导致 YAML 错误,但是 only/except
和 rules
的不同默认行为可能会导致难以解决的问题:
job-with-no-rules:
script: echo "This job runs in branch pipelines."
job-with-rules:
script: echo "This job runs in merge request pipelines."
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
对于推送到分支的每个更改,都会运行重复的流水线。一个分支流水线运行单个作业(job-with-no-rules
),一个合并请求流水线运行另一个作业(job-with-rules
)。没有规则的作业默认为 except: merge_requests
,所以 job-with-no-rules
在所有情况下都会运行,除了合并请求。
rules
的常见 if
子句
类似于 only
/except
关键字,您可以检查 $CI_PIPELINE_SOURCE
变量的值:
值 | 描述 |
---|---|
api |
对于由 pipelines API 触发的流水线。 |
chat |
对于使用极狐GitLab ChatOps 命令创建的流水线。 |
external |
当您使用极狐GitLab 以外的 CI 服务时。 |
external_pull_request_event |
在 GitHub 上创建或更新外部拉取请求时。 |
merge_request_event |
对于在创建或更新合并请求时创建的流水线。需要启用合并请求流水线、合并结果流水线和合并队列。 |
parent_pipeline |
对于由带有 rules 的父/子流水线 触发的流水线。在子流水线配置中使用此流水线源,以便它可以由父流水线触发。 |
pipeline |
对于通过[使用带有 CI_JOB_TOKEN 的 API 创建的多项目流水线或 trigger 关键字。 |
push |
对于由 git push 事件触发的流水线,包括分支和标签。 |
schedule |
对于计划流水线。 |
trigger |
对于使用触发器令牌–>创建的流水线。 |
web |
对于使用极狐GitLab UI 中的 运行流水线 按钮创建的流水线,来自项目的 构建 > 流水线 部分。 |
webide |
对于使用 WebIDE 创建的流水线。 |
以下示例在计划流水线或推送流水线(到分支或标签)中将作业作为手动作业运行,使用 when: on_success
(默认)。它不会将作业添加到任何其他流水线类型。
job:
script: echo "Hello, Rules!"
rules:
- if: $CI_PIPELINE_SOURCE == "schedule"
when: manual
allow_failure: true
- if: $CI_PIPELINE_SOURCE == "push"
以下示例在合并请求流水线和计划流水线中将作业作为 when: on_success
作业运行。 它不会在任何其他流水线类型中运行。
job:
script: echo "Hello, Rules!"
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
- if: $CI_PIPELINE_SOURCE == "schedule"
if
子句的其他常用变量:
-
if: $CI_COMMIT_TAG
:如果为标签推送更改。 -
if: $CI_COMMIT_BRANCH
:如果更改被推送到任何分支。 -
if: $CI_COMMIT_BRANCH == "main"
:如果更改被推送到main
。 -
if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
:如果更改被推送到默认分支。当您希望在具有不同默认分支的多个项目中具有相同配置时使用。 -
if: $CI_COMMIT_BRANCH =~ /regex-expression/
:如果提交分支匹配正则表达式。 -
if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH && $CI_COMMIT_TITLE =~ /Merge branch.*/
: 如果提交分支是默认分支并且提交消息标题匹配正则表达式。例如,合并提交的默认提交消息以Merge branch
开头。 -
if: $CUSTOM_VARIABLE !~ /regex-expression/
:如果自定义变量CUSTOM_VARIABLE
不匹配一个正则表达式。 -
if: $CUSTOM_VARIABLE == "value1"
:如果自定义变量CUSTOM_VARIABLE
正好是value1
。
rules:changes
中的变量
您可以在 rules:changes
表达式中使用 CI/CD 变量来确定何时向流水线添加作业:
docker build:
variables:
DOCKERFILES_DIR: 'path/to/files/'
script: docker build -t my-image:$CI_COMMIT_REF_SLUG .
rules:
- changes:
- $DOCKERFILES_DIR/*
您可以将 $
字符用于变量和路径。例如,如果存在 $DOCKERFILES_DIR
变量,则使用其值。 如果它不存在,$
被解释为路径的一部分。
在不同的作业中重用规则
引入于 14.3 版本。
使用 !reference
标签 在不同的作业中重用规则。您可以将 !reference
规则与常规作业定义的规则结合起来:
.default_rules:
rules:
- if: $CI_PIPELINE_SOURCE == "schedule"
when: never
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
job1:
rules:
- !reference [.default_rules, rules]
script:
- echo "This job runs for the default branch, but not schedules."
job2:
rules:
- !reference [.default_rules, rules]
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
script:
- echo "This job runs for the default branch, but not schedules."
- echo "It also runs for merge requests."
指定作业何时以 only
和 except
运行
您可以使用 only
和 except
来控制何时添加作业到流水线。
- 使用
only
来定义作业何时运行。 - 使用
except
定义作业 不 运行的时间。
only:refs
/ except:refs
示例
不使用 refs
时,使用的 only
或 except
与 only:refs
/ except/refs
相同。
在以下示例中,job
仅针对以下情况运行:
- Git 标签
- 触发器
- 计划流水线
job:
# use special keywords
only:
- tags
- triggers
- schedules
要仅为父仓库而不是派生仓库执行作业:
job:
only:
- branches@gitlab-org/gitlab
except:
- main@gitlab-org/gitlab
- /^release/.*$/@gitlab-org/gitlab
此示例为 gitlab-org/gitlab
上的所有分支运行 job
,除了 main
和以 release/
开头的分支。
only: variables
/ except: variables
示例
您可以使用 except:variables
根据提交消息排除作业:
end-to-end:
script: rake test:end-to-end
except:
variables:
- $CI_COMMIT_MESSAGE =~ /skip-end-to-end-tests/
您可以使用括号、&&
和 ||
来构建更复杂的变量表达式:
job1:
script:
- echo This rule uses parentheses.
only:
variables:
- ($CI_COMMIT_BRANCH == "main" || $CI_COMMIT_BRANCH == "develop") && $MY_VARIABLE
当在 only:variables
中指定了多个条目时,作业会在其中至少一个评估为 true
时运行。
当必须同时满足多个条件时,您可以在单个条目中使用 &&
。
only:changes
/ except:changes
示例
如果在仓库根目录中带有.md
扩展名的任何文件中检测到更改,您可以跳过作业:
build:
script: npm run build
except:
changes:
- "*.md"
如果您更改了多个文件,但只有一个文件以 .md
结尾,则仍会跳过 build
作业。该作业不会为任何文件运行。
对于一些使用 changes
的配置,作业或流水线可能会意外运行
将 only:changes
与流水线一起用于合并请求
使用合并请求流水线,可以根据合并请求中修改的文件定义要创建的作业。
将此关键字与 only: [merge_requests]
一起使用,以便系统可以找到源分支的正确基础 SHA。从任何进一步的提交中正确计算文件差异,并且在流水线中正确测试合并请求中的所有更改。
例如:
docker build service one:
script: docker build -t my-service-one-image:$CI_COMMIT_REF_SLUG .
only:
refs:
- merge_requests
changes:
- Dockerfile
- service-one/**/*
在这种情况下,如果合并请求更改了 service-one
目录或 Dockerfile
中的文件,系统会创建 docker build service one
作业。
例如:
docker build service one:
script: docker build -t my-service-one-image:$CI_COMMIT_REF_SLUG .
only:
changes:
- Dockerfile
- service-one/**/*
在此示例中,流水线可能会因更改 service-one/**/*
中的文件而失败。
稍后提交在 service-one/**/*
中没有更改,但确实对 Dockerfile
进行了更改的提交可以通过。该作业仅测试对 Dockerfile
的更改。
系统检查通过的最新流水线。如果合并请求是可合并的,那么早先的流水线由于未更正的更改而失败并不重要。
当您使用此配置时,请确保最近的流水线正确地纠正了先前流水线中的任何故障。
将多个关键字与 only
或 except
组合
如果您将多个关键字与 only
或 except
一起使用,则这些关键字将被评估为单个连接表达式:
-
only
包含作业,如果 all 的键至少有一个匹配的条件。 -
except
如果 any 的键至少有一个匹配的条件,则排除作业。
使用 only
,单个键由 AND
逻辑连接。如果满足以下条件,则将作业添加到流水线中:
(any listed refs are true) AND (any listed variables are true) AND (any listed changes are true) AND (any chosen Kubernetes status matches)
在以下示例中,仅当以下 all 为 true 时才会创建 test
作业:
- 流水线是计划的或运行
main
。 -
variables
关键字匹配。 -
kubernetes
服务在项目中处于活动状态。
test:
script: npm run test
only:
refs:
- main
- schedules
variables:
- $CI_COMMIT_MESSAGE =~ /run-end-to-end-tests/
kubernetes: active
使用except
,各个键由 OR
逻辑连接。如果满足以下条件,则不添加作业:
(any listed refs are true) OR (any listed variables are true) OR (any listed changes are true) OR (a chosen Kubernetes status matches)
在以下示例中,当以下 任何 为 true 时,不创建 test
作业:
- 流水线为
main
分支运行。 - 对仓库根目录中的
README.md
文件进行了更改。
test:
script: npm run test
except:
refs:
- main
changes:
- "README.md"
创建必须手动运行的作业
您可以要求作业在用户启动之前不运行。这称为手工作业。 您可能希望使用手动作业来进行部署到生产之类的工作。
要将作业指定为手动,请将 when: manual
添加到 .gitlab-ci.yml
文件中的作业。
默认情况下,手动作业在流水线启动时显示为已跳过。
您可以使用受保护的分支来更严格地保护手动部署不被未经授权的用户运行。
手动作业类型
手动作业可以是可选的或阻塞的。
可选的手动作业:
-
allow_failure
为true
,这是具有when:manual
且没有rules
的作业的默认设置,或当在rules
之外定义了when:manual
时的设置。 - 该状态不影响整体流水线状态。即使所有手动作业都失败,流水线也可以成功。
阻塞的手动作业:
-
allow_failure
为false
,这是在rules
中定义了when:manual
的作业的默认设置。 - 流水线在定义作业的阶段停止。要让流水线继续运行,请运行手动作业。
- 启用了流水线成功时合并的项目中的合并请求,不能在存在已阻塞的流水线时合并。
- 流水线显示状态为已阻塞。
运行手动作业
要运行手动作业,您必须具有合并到指定分支的权限:
- 转到流水线、作业、环境 或部署视图。
- 在手动作业旁边,选择 运行 ()。
保护手动作业
使用受保护的环境 定义授权运行手动作业的用户列表。您只能授权与受保护环境关联的用户触发手动作业,这可以:
- 更精确地限制可以部署到环境的人员。
- 阻止流水线,直到合资格的用户“批准”它。
要保护手动作业:
-
为作业添加一个
environment
。 例如:deploy_prod: stage: deploy script: - echo "Deploy to production server" environment: name: production url: https://example.com when: manual rules: - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
-
在受保护环境设置中,选择环境(本例中为
production
),添加授权触发手动作业的用户、角色或群组,到 允许部署 列表。只有此列表中的人,以及始终能够使用受保护环境的 GitLab 管理员,才能触发此手动作业。
您可以使用具有阻止手动作业的受保护环境来获得允许批准后期流水线阶段的用户列表。将 allow_failure: false
添加到受保护的手动作业,流水线的下一阶段仅在手动作业由授权用户触发后运行。
延迟后运行作业
使用 when: delay
在等待期后执行脚本,或者如果您想避免作业立即进入 pending
状态。
您可以使用 start_in
关键字设置时间段。start_in
的值是以秒为单位的经过时间,除非提供了单位。最短为一秒,最长为一星期。
有效值的示例包括:
-
'5'
(没有单位的值必须用单引号括起来) 5 seconds
30 minutes
1 day
1 week
当阶段包含延迟作业时,流水线在延迟作业完成之前不会进行。 您可以使用此关键字在不同阶段之间插入延迟。
延迟作业的计时器在前一阶段完成后立即启动。 与其他类型的作业类似,除非前一阶段通过,否则延迟作业的计时器不会启动。
以下示例创建了一个名为 timed rollout 10%
的作业,该作业在前一阶段完成 30 分钟后执行:
timed rollout 10%:
stage: deploy
script: echo 'Rolling out 10% ...'
when: delayed
start_in: 30 minutes
environment: production
要停止延迟作业的活动计时器,请选择 (取消计划) 按钮。 无法再安排此作业自动运行。但是,您可以手动执行作业。
要手动启动延迟作业,请选择 取消计划 () 来停止延迟计时器,然后选择 运行 ()。 很快,GitLab Runner 开始工作。
并行化大型作业
要将大型作业拆分为多个并行运行的较小作业,请在您的 .gitlab-ci.yml
文件中使用 parallel
关键字。
不同的语言和测试套件有不同的方法来实现并行化。 例如,使用 Semaphore Test Boosters 和 RSpec 并行运行 Ruby 测试:
# Gemfile
source 'https://rubygems.org'
gem 'rspec'
gem 'semaphore_test_boosters'
test:
parallel: 3
script:
- bundle
- bundle exec rspec_booster --job $CI_NODE_INDEX/$CI_NODE_TOTAL
然后,您可以导航到新流水线构建的 作业 选项卡,并查看您的 RSpec 作业分为三个独立的作业。
运行并行作业的一维矩阵
引入于 13.5 版本。
您可以创建并行作业的一维矩阵:
deploystacks:
stage: deploy
script:
- bin/deploy
parallel:
matrix:
- PROVIDER: [aws, ovh, gcp, vultr]
environment: production/$PROVIDER
您还可以创建多维矩阵。
运行并行触发作业矩阵
引入于 13.10 版本。
您可以在单个流水线中多次并行运行 trigger 作业,但对于作业的每个实例使用不同的变量值。
deploystacks:
stage: deploy
trigger:
include: path/to/child-pipeline.yml
parallel:
matrix:
- PROVIDER: aws
STACK: [monitoring, app1]
- PROVIDER: ovh
STACK: [monitoring, backup]
- PROVIDER: [gcp, vultr]
STACK: [data]
此示例生成 6 个并行的 deploystacks
触发器作业,每个具有不同的 PROVIDER
和 STACK
值,并且它们使用这些变量创建 6 个不同的子流水线。
deploystacks: [aws, monitoring]
deploystacks: [aws, app1]
deploystacks: [ovh, monitoring]
deploystacks: [ovh, backup]
deploystacks: [gcp, data]
deploystacks: [vultr, data]
为每个并行矩阵作业选择不同的 runner 标签
引入于 14.1 版本。
您可以将 parallel: matrix
中定义的变量与 tags
关键字一起用于动态 runner 选择:
deploystacks:
stage: deploy
parallel:
matrix:
- PROVIDER: aws
STACK: [monitoring, app1]
- PROVIDER: gcp
STACK: [data]
tags:
- ${PROVIDER}-${STACK}
environment: $PROVIDER/$STACK
从 parallel:matrix
作业中获取产物
您可以使用 dependencies
关键字从使用 parallel:matrix
创建的作业中获取产物。使用作业名称作为 dependencies
的值,格式如下:
<job_name> [<matrix argument 1>, <matrix argument 2>, ... <matrix argument N>]
例如,要从具有 2.7
的RUBY_VERSION
和 aws
的 PROVIDER
的作业中获取产物:
ruby:
image: ruby:${RUBY_VERSION}
parallel:
matrix:
- RUBY_VERSION: ["2.5", "2.6", "2.7", "3.0", "3.1"]
PROVIDER: [aws, gcp]
script: bundle install
deploy:
image: ruby:2.7
stage: deploy
dependencies:
- "ruby: [2.7, aws]"
script: echo hello
environment: production
dependencies
条目周围的引号是必需的。
通过多个并行作业的需求指定并行作业
引入于极狐GitLab 16.3。
您可以将 needs:parallel:matrix
中定义的变量与多个并行作业一起使用。
例如:
linux:build:
stage: build
script: echo "Building linux..."
parallel:
matrix:
- PROVIDER: aws
STACK:
- monitoring
- app1
- app2
mac:build:
stage: build
script: echo "Building mac..."
parallel:
matrix:
- PROVIDER: [gcp, vultr]
STACK: [data, processing]
linux:rspec:
stage: test
needs:
- job: linux:build
parallel:
matrix:
- PROVIDER: aws
STACK: app1
script: echo "Running rspec on linux..."
mac:rspec:
stage: test
needs:
- job: mac:build
parallel:
matrix:
- PROVIDER: [gcp, vultr]
STACK: [data]
script: echo "Running rspec on mac..."
production:
stage: deploy
script: echo "Running production..."
environment: production
此示例生成多个作业。每个并行作业都有不同的 PROVIDER
和 STACK
值。
- 3 个并行
linux:build
作业:linux:build: [aws, monitoring]
linux:build: [aws, app1]
linux:build: [aws, app2]
- 4 个并行
mac:build
作业:mac:build: [gcp, data]
mac:build: [gcp, processing]
mac:build: [vultr, data]
mac:build: [vultr, processing]
- 1 个
linux:rspec
作业: - 1 个
production
作业:
这些作业具有三种执行路径:
- Linux 路径:
linux:rspec
作业在linux:build: [aws, app1]
作业运行后立即运行,无需等待mac:build
完成。 - macOS 路径:
mac:rspec
作业在mac:build: [gcp, data]
和mac:build: [vultr, data]
作业完成后立即运行,无需等待linux:build
完成。 - 之前的作业全部完成后,
production
作业就会运行。
使用预定义的 CI/CD 变量仅在特定流水线类型中运行作业
您可以使用预定义 CI/CD 变量来选择运行的管道类型作业,其中:
下表列出了一些您可以使用的变量,以及这些变量可以控制的流水线类型:
- 为 Git
push
事件运行到分支的分支流水线,例如新的提交或标签。 - 仅在将新 Git 标签推送到分支时运行的标签流水线。
- 合并请求流水线 运行以更改合并请求,例如新提交或在合并请求的流水线选项卡中选择 运行流水线 按钮。
- 预定流水线。
变量 | 分支 | 标签 | 合并请求 | 计划流水线 |
---|---|---|---|---|
CI_COMMIT_BRANCH |
Yes | Yes | ||
CI_COMMIT_TAG |
Yes | Yes,如果计划的流水线配置为在标签上运行。 | ||
CI_PIPELINE_SOURCE = push |
Yes | Yes | ||
CI_PIPELINE_SOURCE = scheduled |
Yes | |||
CI_PIPELINE_SOURCE = merge_request_event |
Yes | |||
CI_MERGE_REQUEST_IID |
Yes |
例如,要将作业配置为针对合并请求流水线和计划流水线运行,但不针对分支或标签流水线运行:
job1:
script:
- echo
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
- if: $CI_PIPELINE_SOURCE == "schedule"
- if: $CI_PIPELINE_SOURCE == "push"
when: never
常用表达
@
符号表示引用的仓库路径的开头。
要匹配正则表达式中包含 @
字符的引用名称,您必须使用十六进制字符代码匹配 \x40
。
正则表达式只能匹配标签或分支名称。 仓库路径(如果给定)始终按字面匹配。
要匹配标签或分支名称,pattern 的整个 ref 名称部分必须是一个正则表达式,用 /
包围。
例如,您不能使用 issue-/.*/
来匹配所有以 issue-
开头的标签名称或分支名称,但您可以使用 /issue-.*/
。
正则表达式标志必须附加在结束的 /
之后。默认情况下,模式匹配区分大小写。使用 i
标志修饰符,如 /pattern/i
,使模式不区分大小写:
job:
# use regexp
only:
- /^issue-.*$/i
# use special keyword
except:
- branches
使用锚点^
和$
来避免正则表达式只匹配标签名称或分支名称的子字符串。
例如,/^issue-.*$/
等价于 /^issue-/
,而仅仅 /issue/
也会匹配名为 severe-issues
的分支。
CI/CD 变量表达
使用变量表达式来控制在将更改推送到极狐GitLab 后,在流水线中创建哪些作业。您可以将变量表达式用于:
例如,使用 rules:if
:
job1:
variables:
VAR1: "variable1"
script:
- echo "Test variable comparison
rules:
- if: $VAR1 == "variable1"
将变量与字符串进行比较
您可以使用相等运算符 ==
和 !=
将变量与字符串进行比较。单引号和双引号都有效。顺序无关紧要,因此变量可以是第一个,也可以是字符串的第一个。例如:
if: $VARIABLE == "some value"
if: $VARIABLE != "some value"
if: "some value" == $VARIABLE
比较两个变量
您可以比较两个变量的值。 例如:
if: $VARIABLE_1 == $VARIABLE_2
if: $VARIABLE_1 != $VARIABLE_2
检查变量是否未定义
您可以将变量与 null
关键字进行比较,以查看它是否已定义。例如:
if: $VARIABLE == null
if: $VARIABLE != null
检查变量是否为空
您可以检查变量是否已定义但为空。例如:
if: $VARIABLE == ""
if: $VARIABLE != ""
检查变量是否存在
您可以仅使用表达式中的变量名称来检查变量是否存在。变量不能为空。例如:
if: $VARIABLE
将变量与正则表达式 pattern 进行比较
您可以使用 =~
和 !~
运算符对变量值进行正则表达式模式匹配。
与正则表达式的变量模式匹配使用 RE2 正则表达式语法。
表达式在以下情况下评估为true
:
- 使用
=~
时会找到匹配项。 - 使用
!~
时找不到匹配。
例如:
if: $VARIABLE =~ /^content.*/
if: $VARIABLE !~ /^content.*/
不支持单字符正则表达式,如 /./
,会产生 invalid expression syntax
错误。
默认情况下,pattern 匹配区分大小写。使用 i
标志修饰符使 pattern 不区分大小写。例如:/pattern/i
。
将正则表达式样式存储在变量中
- 引入于 15.0 版本,功能标志为
ci_fix_rules_if_comparison_with_regexp_variable
,默认禁用。- 功能标志
ci_fix_rules_if_comparison_with_regexp_variable
删除于 15.1 版本。
=~
和 !~
表达式右侧的变量被评估为正则表达式。
正则表达式必须用正斜杠 (/
) 括起来。例如:
variables:
pattern: '/^ab.*/'
regex-job1:
variables:
teststring: 'abcde'
script: echo "This job will run, because 'abcde' matches the /^ab.*/ pattern."
rules:
- if: '$teststring =~ $pattern'
regex-job2:
variables:
teststring: 'fghij'
script: echo "This job will not run, because 'fghi' does not match the /^ab.*/ pattern."
rules:
- if: '$teststring =~ $pattern'
用 &&
或 ||
连接变量表达式
您可以使用&&
(和)或||
(或)连接多个表达式,例如:
$VARIABLE1 =~ /^content.*/ && $VARIABLE2 == "something"
$VARIABLE1 =~ /^content.*/ && $VARIABLE2 =~ /thing$/ && $VARIABLE3
$VARIABLE1 =~ /^content.*/ || $VARIABLE2 =~ /thing$/ && $VARIABLE3
运算符的优先级遵循 Ruby 2.5 标准,因此 &&
在 ||
之前评估。
将变量表达式与括号一起分组
您可以使用括号将表达式组合在一起。 括号优先于&&
和||
,所以括号中的表达式首先被计算,结果用于表达式的其余部分。
您可以嵌套括号以创建复杂条件,并首先计算括号中最内层的表达式。
例如:
($VARIABLE1 =~ /^content.*/ || $VARIABLE2) && ($VARIABLE3 =~ /thing$/ || $VARIABLE4)
($VARIABLE1 =~ /^content.*/ || $VARIABLE2 =~ /thing$/) && $VARIABLE3
$CI_COMMIT_BRANCH == "my-branch" || (($VARIABLE1 == "thing" || $VARIABLE2 == "thing") && $VARIABLE3)
故障排查
使用 changes:
时,作业或流水线意外运行
当使用 rules: changes
或 only: changes
没有用于合并请求流水线时,您的作业或流水线可能会意外运行。
与合并请求没有显式关联的分支或标签上的流水线使用以前的 SHA 来计算差异。此计算等效于 git diff HEAD~
并可能导致意外,包括:
- 将新分支或新标签推送到极狐GitLab 时,
changes
规则始终评估为 true。 - 当推送一个新的提交时,更改的文件是通过使用以前的提交作为基本 SHA 计算的。
此外,在计划流水线中,带有 changes
的规则始终评估为 true。
当计划流水线运行时,所有文件都被认为已更改,因此作业可能始终添加到使用 changes
的计划流水线中。
You are not allowed to download code from this project.
错误消息
当极狐GitLab 管理员在私有项目中运行受保护的手动作业时,您可能会看到流水线失败。
CI/CD 作业通常在作业启动时克隆项目,使用运行作业的用户的权限。所有用户(包括管理员)都必须是私有项目的直接成员才能克隆该项目的源。
要运行受保护的手动作业:
- 将管理员添加为私有项目的直接成员(任何角色)
- 模拟作为项目直接成员的用户。