.gitlab-ci.yml是GitLab CI/CD管道(Pipeline)使用的配置文件,该文件定义了管道的结构和执行顺序。本文件参考GitLab官方文档,简单翻译及整理。
- 介绍
- 配置参数
- 设置默认参数
- 详细参数
scriptimageservicesbefore_script和after_scriptstagesstageonly/except(基本)- 支持的
only/except正则表达式语法 only/except(高级)rulestagsallow_failurewhenenvironmentcacheartifactsdependenciesneedscoverageretrytimeoutparalleltriggerinterruptibleincludeextends- 同时使用
extends和include pagesvariables
- 不推荐使用的参数
- 自定义构建目录
- YAML的特殊功能
- 触发器(Trigger
- 处理Git推送
- 跳过Job
在每个项目中,使用名为.gitlab-ci.yml的YAML文件配置GitLab CI/CD管道。.gitlab-ci.yml文件定义了管道的结构和顺序,并确定:
- GitLab Runner执行的内容
- 遇到特定条件时所要做的操作。如:当一个过程成功或失败时
本文内容涵盖了CI/CD管道配置。其它CI/CD相关配置,请参阅:
- GitLab CI/CD变量,用于配置运行管道的环境
- GitLab Runner高级配置,用于配置GitLab Runner
以下是几个GitLab提供的配置管道的完整示例:
- 有关GitLab CI的快速介绍,请参考:快速入门指南
- 有关示例的集合,请参考:GitLab CI/CD示例
- 在大型企业项目中使用
.gitlab-ci.yml文件,请参阅:GitLab的.gitlab-ci.yml文件
注意:如果你有一个GitLab拉取镜像的存储库,那么可能需要在“设置”>“存储库”>“从远程存储库中提取”>“触发管道更新镜像”(Settings > Repository > Pull from a remote repository > Trigger pipelines for mirror updates.)中启用管道触发。
1. 介绍
管道配置都是从作业(Job)开始的。作业是.gitlab-ci.yml文件的最基本元素。作业应该有以下特点:
- 定义了约束,指出应在什么条件下执行它们
- 具有任意名称的顶级元素,并且必须至少包含
script子句 - 不限制可以定义多少个
示例如下:
job1: script: "execute-script-for-job1" job2: script: "execute-script-for-job2"
以上的示例中定义了尽可能简单的CI/CD配置两个单独的作业(job1、job2),其中,每个作业的执行的命令不同。命令可以是直接执行代码(如:./configure;make;make install)或运行在存储库中脚本(如:test.sh)。
作业由会Runner提取并在Runner环境中执行。重要的是,每个作业彼此独立运行。
1.1 验证.gitlab-ci.yml
GitLab CI的每个实例都有一个称为“Lint”的嵌入式调试工具,该工具可以验证.gitlab-ci.yml文件的内容。可以在项目名称空间的ci/lint页下找到Lint。例如,https://gitlab.example.com/gitlab-org/project-123/-/ci/lint。
1.2 不可用的Job名
每个作业都要有唯一的名称,但以下保留关键字能用做作业名:
imageservicesstagestypesbefore_scriptafter_scriptvariablescache
1.3 使用保留关键字
如果使用某些特殊值(如true和false)出现验证错误时,请尝试以下操作:
- 引用它们
- 将其改为其它形式,如:
/bin/true
2. 配置参数
每个Job其行为由参数列表定义。以下是Job可用的参数:
| 关键字 | 说明 |
|---|---|
script |
由Runner执行的Shell脚本 |
image |
所使用的Docker镜像。也可以用:image:name和image:entrypoint |
services |
使用Docker服务镜像。也可以用:services:name、services:alias 、services:entrypoint和services:command |
before_script |
覆盖作业之前执行的一组命令 |
after_script |
覆盖作业之后执行的一组命令 |
stages |
定义管道中的阶段 |
stage |
定义一个工作阶段(默认:test ) |
only |
限制创建作业的时间。也可以用:only:refs、only:kubernetes、only:variables和only:changes |
except |
限制不创建作业的时间。也可以用:except:refs、except:kubernetes、except:variables和except:changes |
rules |
评估和确定作业的选定属性,以及是否创建作业的条件列表。不能only/except一起使用 |
tags |
用于选择Runner的标签列表 |
allow_failure |
允许作业失败。失败的工作不会影响提交状态 |
when |
什么时候执行作业。也可以用:when:manual和when:delayed |
environment |
作业部署到的环境的名称。也可以用:environment:name、environment:url、environment:on_stop和environment:action |
cache |
在后续运行之间应缓存的文件列表。也可以用:cache:paths、cache:key、cache:untracked和cache:policy |
artifacts |
成功时附加到作业的文件和目录列表。也可以用:artifacts:paths、artifacts:expose_as、artifacts:name、artifacts:untracked、artifacts:when、artifacts:expire_in、artifacts:reports和artifacts:reports:junit。在GitLab Enterprise Edition中可用: artifacts:reports:codequality、artifacts:reports:sast、artifacts:reports:dependency_scanning、artifacts:reports:container_scanning、artifacts:reports:dast、artifacts:reports:license_management、artifacts:reports:dast、artifacts:reports:license_management、artifacts:reports:dast、artifacts:reports:performance和artifacts:reports:metrics |
dependencies |
通过提供要从中获取工件(artifacts)的作业列表,限制将哪些工件传递给指定作业 |
coverage |
指定作业的代码覆盖率设置 |
retry |
发生故障时可自动重试作业的重试次数 |
timeout |
定义优先于项目范围设置的自定义作业级别的超时 |
parallel |
可并行运行作业实例数 |
trigger |
定义下游管道触发器 |
include |
当前作业所包括的外部YAML文件。也可以用:include:local、include:file、include:template和include:remote |
extends |
该作业所要继承的配置项 |
pages |
上传作业结果,以用于GitLab Pages |
variables |
在作业级别上定义的作业变量 |
interruptible |
定义在通过新的运行(run)使其冗余时是否可以取消作业 |
注意:types和type参数不建议使用。
3. 设置默认参数
可以使用default:关键字,将某些参数全局设置为所有Job的默认设置。然后,特定于Job的配置可以覆盖默认参数。
以下参数可以在default:块内定义:
以下示例中,将ruby:2.5镜像设置为所有Job的默认参数,而rspec 2.6Job除外,其使用ruby:2.6镜像:
default: image: ruby:2.5 rspec: script: bundle exec rspec rspec 2.6: image: ruby:2.6 script: bundle exec rspec
4. 详细参数
以下是用于配置CI/CD管道参数的详细说明。
script
是Job所需的唯一必需关键字。它是一个由Runner执行的shell脚本,例如:
job: script: "bundle exec rspec"
备注:有时,timeout命令需要用单引号或双引号引起来。例如,包含冒号(:)的命令就需要用引号引起来,以便YAML解析器知道将整个内容解释为字符串而不是“键: 值”对。使用特殊字符时要小心:
:, {, }, [, ], ,, &, *, #, ?, |, -, <, >, =, !, %, @, `。
script的YAML锚点
在GitLab 12.5中引入
可以将YAML锚点与脚本一起使用,从而可以在多个Job中所包括的预定义命令列表。例如:
.something: &something
- echo 'something'
job_name:
script:
- *something
- echo 'this is the script'
image
用于指定Job所使用的Docker镜像。
示例:
- 简单示例,请参阅:从
.gitlab-ci.yml定义image和services - 详细的使用信息,请参阅:Docker集成文档
image:name
更多相关信息,请参阅:image有效设置。
image:entrypoint
更多相关信息,请参阅:image有效设置。
services
用于指定服务Docker镜像,该镜像链接到image中指定的基本image。
- 简单示例,请参阅:从
.gitlab-ci.yml定义image和services - 详细的使用信息,请参阅:Docker集成文档
services使用示例,请参阅: GitLab CI Services。
services:name
更多相关信息,请参阅:services有效设置。
services:alias
更多相关信息,请参阅:services有效设置。
services:entrypoint
更多相关信息,请参阅:services有效设置。
services:command
更多相关信息,请参阅:services有效设置。
before_script 和 after_script
GitLab 8.7中引入,且要求GitLab Runner v1.2
before_script用于定义应在所有作业,包括部署作业之前;但在在还原工件(artifacts)之后运行的命令。必须是一个数组。
after_script用于定义将在所有作业,包括失败的作业之后运行的命令。必须是一个数组。
before_script中指定的脚本:
- 与主脚本中指定的
script串联。当与script定义串联时,Job级的before_script定义将覆盖全局级的before_script定义
与主script脚本一起作为一个脚本,在单个shell上下文中执行
after_script中指定的脚本:
- 将当前工作目录重新设置为默认目录
- 在与
before_script和script脚本,在分开的shell上下文中执行 - 由于上下文分开,因此无法查看由
before_script或script脚本中定义的脚本所做的更改:- 在shell中。例如,
script脚本中导出的命令别名和变量 - 在工作树之外(取决于Runner执行程序)。例如,由
script或code>script脚本安装的软件
- 在shell中。例如,
如果按Job设置全局定义的before_script和after_script则有可能覆盖它们:
default:
before_script:
- global before script
job:
before_script:
- execute this instead of global before script
script:
- my command
after_script:
- execute this after my script
before_script和after_script的YAML锚点
GitLab 12.5 引入
你可以将YAML锚点与before_script和after_script结合使用,从而可以在多个Job中包含预定义的命令列表。
示例:
.something_before: &something_before
- echo 'something before'
.something_after: &something_after
- echo 'something after'
job_name:
before_script:
- *something_before
script:
- echo 'this is the script'
after_script:
- *something_after
stages
stages用于定义Job可以使用的阶段,并且是全局定义的。
stages的规范允许有灵活的多阶段管道。stages中元素的顺序定义了作业执行的顺序:
- 同一阶段的Job并行运行
- 前一阶段的Jon成功完成后,运行下一阶段的Job
参考以下示例,该示例定义了3个阶段:
stages: - build - test - deploy
- 首先,所有
buildJob并行执行 - 如果所有
buildJob都并行执行成功,则testJob将并行执行 - 如果所有
testJob都并行执行成功,则并行执行deployJob - 如果所有
deployJob都并行执行成功,则将提交标记为passed - 如果先前的任何Job执行失败,则将提交标记为
failed并且不再执行后续Job
还有两个边界情况值得注意:
- 如果
.gitlab-ci.yml中未定义任何stages,则默认允许将build、test和deploy用作Job的阶段 - 如果作业未指定
stages,则为该Job分配test阶段
.pre和.post
在GitLab 12.4中引入
每个管道都可以使用以下阶段:
.pre,它始终是管道中的第一个阶段.post,它始终是管道中的最后一个阶段
用户定义的阶段都在.pre之后且.post之前执行。
即使.gitlab-ci.yml定义不正确,>.pre和.post的顺序也无法更改。例如,以下配置是等效的:
- 按顺序配置:
stages: - .pre - a - b - .post
- 乱序配置:
stages: - a - .pre - b - .post
- 未明确配置:
stages: - a - b
stage
stage被定义为每个Job,并且依赖于全局定义的stages。它允许将Job分为不同的阶段,并且可以并行执行同一stage的Job(取决于特定条件)。例如:
stages: - build - test - deploy job 0: stage: .pre script: make something useful before build stage job 1: stage: build script: make build dependencies job 2: stage: build script: make build artifacts job 3: stage: test script: make test job 4: stage: deploy script: make deploy job 5: stage: .post script: make something useful at the end of pipeline
使用你自己的Runner
当>使用你自己的Runner,默认情况下,GitLab Runner一次仅运行一个Job(更多相关信息,请参见Runner全局设置中的concurrent标志)。
仅在以下情况下,Job会在你自己的Runner上并行运行:
- 在不同Runner上运行
- Runner的
concurrent设置已修改
only/except (基本)
注意:这些参数将很快被弃用,以支持rules,因为它提供了更强大的语法。
only和except两个参数用于设置Job策略以限制Job的创建时间:
only:定义要运行Job的分支和标签的名称except:定义不运行Job的分支和标签的名称
以下是一些可用于作业策略的规则:
only和except同时包括。如果Job中同时定义了only和except,则引用(ref)将被only和except过滤。only和except允许使用正则表达式(支持的正则语法)only和except允许指定存储库路径以过滤派生Job。
此外,only和except允许使用特殊关键字:
| 关键字 | 说明 |
|---|---|
branches |
当管道的Git引用是分支时 |
tags |
当管道的Git引用是标签时 |
api |
当第二个管道API触发了管道(不是触发器API)时 |
external |
使用GitLab以外的CI服务时 |
pipelines |
对于多项目触发器,使用带有CI_JOB_TOKEN的API创建 |
pushes |
管道由用户的git push触发 |
schedules |
用于定时计划的管道 |
triggers |
用于使用触发令牌(token)创建的管道 |
web |
用于使用GitLab UI中的"运行管道"(Run pipeline)按钮创建的管道(在项目的Pipelines下) |
merge_requests |
创建或更新合并请求时(请参阅:合并请求管道) |
external_pull_requests |
在GitHub上创建或更新外部拉取请求时(请参阅:外部拉取请求的管道) |
chat |
用于使用GitLab ChatOps命令创建的Job |
在以下示例中,job将只运行了以issue-开头的引用,而所有分支(branches)将被忽略:
job:
# use regexp
only:
- /^issue-.*$/
# use special keyword
except:
- branches
模式匹配默认情况下区分大小写。可以使用i标志修饰符,以使模式匹配不区分大小写,例如/pattern/i:
job:
# use regexp
only:
- /^issue-.*$/i
# use special keyword
except:
- branches
以下示例中,job将仅对标签(tags)引用运行,或者通过API触发器或Pipeline Schedule显示请求构建时,Job将运行:
job:
# use special keywords
only:
- tags
- triggers
- schedules
存储库路径仅对父存储库执行的Job可用,但不能用于派生Job:
job:
only:
- branches@gitlab-org/gitlab
except:
- master@gitlab-org/gitlab
- /^release/.*$/@gitlab-org/gitlab
以上示例中,会为gitlab-org/gitlab上的所有分支运行job,但master和其它以release/开头的分支除外。
如果job没有only规则,则默认将设置为only: ['branches', 'tags'];如果没有except规则,则默认将为空。
例如:
job: script: echo 'test'
可转换为:
job: script: echo 'test' only: ['branches', 'tags']
常用表达式
因为@用于表示引用的存储库路径的开头,所以匹配正则表达式中如果包含@字符的引用名称,则需要使用十六进制字符\x40代替。
正则表达式只能匹配标签(tags)或分支(branches)名称。如果指定了存储库路径,则始终以字面量形式匹配。
如果必须使用正则表达式来匹配标签或分支名称,则模式匹配的整个引用名称部分必须是正则表达式,并且必须用/括起来(在结束符/后面附加正则表达式标志)。所以,issue-/.*/并不能匹配所有以issue-开头的标签名或分支名。
提示使用定位符^和$避免正则表达式仅匹配标签名称或分支名称的子字符串。例如,/^issue-.*$/等效于/^issue-/,而仅/issue/也会匹配一个名为severe-issues的分支。
支持的only/except正则表达式语法
注意:这是GitLab 11.9.4引入的重大更改.
在GitLab 11.9.4中,GitLab开始内部将only和except 参数中使用的正则表达式转换为RE2。
这意味着仅支持Ruby Regexp提供的功能子集。由于计算复杂性,RE2限制了所提供的功能集,也就是说某些功能在GitLab 11.9.4中会变得不可用。
对于从11.9.7到GitLab 12.0的GitLab版本,GitLab提供了一个功能标记,管理员可以启用它,从而允许用户使用不安全的正则表达式语法。这带来了与以前允许的语法版本的兼容性,并允许用户正常迁移到新语法。
Feature.enable(:allow_unsafe_ruby_regexp)
only/except (高级)
注意:这是Alpha版功能,如有更改,恕不另行通知!
GitLab支持简单策略和复杂策略,因此可以使用数组和哈希配置方案。有四个键可用:
refsvariableschangeskubernetes
如果在only和except下使用多个键,则这些键将被视为单个联合表达式。其为:
only:表示“如果所有条件都匹配,则包括此Job”only:表示“如果符合任何条件,则排除此Job
使用only,各个键在逻辑上由AND联接:
(任何引用) AND (任何变量) AND (任何更改) AND (如果Kubernetes是可用的)
except实现如下:
NOT((任何引用) AND (任何变量) AND (任何更改) AND (如果Kubernetes是可用的))
或者,可以更直观的用OR来表达:
(任何引用) OR (任何变量) OR (任何更改) OR (如果Kubernetes是可用的)
only:refs/except:refs
refs策略在GitLab 10.0中引入
refs策略采用与简化的only/except配置相同的值。
以下示例中,仅在master分支计划或运行管道时才创建deployJob:
deploy:
only:
refs:
- master
- schedules
only:kubernetes/except:kubernetes
kubernetes策略在GitLab 10.0中引入
kubernetes策略仅接受active关键字。
以下示例中,仅当项目中的Kubernetes服务处于活动状态时,才创建deployJob:
deploy:
only:
kubernetes: active
only:variables/except:variables
variables策略在GitLab 10.0中引入
variables关键字用于定义变量表达式。也就是说,你可以使用预定义变量/项目/组或环境范围的变量来定义GitLab将要评估的表达式,以决定是否应创建Job。
使用示例:
deploy:
script: cap staging deploy
only:
refs:
- branches
variables:
- $RELEASE == "staging"
- $STAGING
另一个示例,根据提交消息排除Job:
end-to-end:
script: rake test:end-to-end
except:
variables:
- $CI_COMMIT_MESSAGE =~ /skip-end-to-end-tests/
更多关于变量表达式的相关信息
only:changes/except:changes
changes策略在GitLab 11.4中引入
使用changes关键字与only和except,能够基于通过Git推送(push)操作事件修改的文件中定义,以确一个Job是否应被创建。
示例:
docker build:
script: docker build -t my-image:$CI_COMMIT_REF_SLUG .
only:
changes:
- Dockerfile
- docker/scripts/*
- dockerfiles/**/*
- more_scripts/*.{rb,py,sh}
在上述示例中,当将提交推送到GitLab中的现有分支时,它会创建并触发docker build作业,只要提交中包含对以下任何一项的更改:
Dockerfile文件docker/scripts/目录中的任何文件dockerfiles目录中的任何文件和子目录more_scripts目录中具有rb、py、sh扩展名的more_scripts文件
注意:如果使用only:changes仅允许在管道成功的情况下合并合并请求,则如果不同时使用only:merge_requests,则可能导致一些异常行为。
还可以使用全局模式来匹配存储库根目录中或存储库中任何目录中的多个文件,但是它们必须用双引号括起来,否则GitLab将无法解析.gitlab-ci.yml。例如:
test:
script: npm run test
only:
changes:
- "*.json"
- "**/*.sql"
如果在.md的根目录中检测到任何扩展名为.md文件更改,则以下示例将跳过build作业:
build:
script: npm run build
except:
changes:
- "*.md"
注意:此功能与不带合并请求管道的新分支或标签一起使用时,需要注意一些要点。
在合并请求的管道中使用only:changes
使用用于合并请求的管道,可以根据在合并请求中修改的文件来定义要创建的Job。
为了推断出源分支的正确基础SHA,建议将此关键字与only: merge_requests结合使用。这样,可以从任何进一步的提交中正确计算出文件差异,因此可以在管道中正确测试合并请求中的所有更改。
例如:
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,则GitLab会创建并触发docker build service oneJob。
请注意,如果合并请求的管道与only: change和only: change组合使用,但only: merge_requests被省略,则可能会发生有害行为。
例如:
docker build service one:
script: docker build -t my-service-one-image:$CI_COMMIT_REF_SLUG .
only:
changes:
- Dockerfile
- service-one/**/*
在上面示例中,管道可能由于对service-one/**/*中的文件的更改而失败。然后可以推送之后的提交,该提交不包括对该文件的任何更改,但包括对Dockerfile的更改,并且该管道可以通过,因为它仅测试对Dockerfile的更改。GitLab会检查“通过”的“最新管道”,并将合并请求显示为可合并,尽管之前的管道失败是由于尚未更正的更改引起的。
使用此配置时,必须注意检查最新的管道是否正确地纠正了先前管道的任何故障。
使用不带管道的only:changes合并请求
如果没有用于合并请求的管道,则管道会在与合并请求没有明确关联的分支或标签上运行。在这种情况下,将使用先前的SHA来计算diff,这等效于git diff HEAD~。这可能会导致某些意外行为,包括:
- 当将新分支或新标签推送到GitLab时,该策略始终评估为
true。 - 推送新提交时,将使用先前的提交作为基础SHA来计算更改的文件。
rules
在GitLab 12.3中引入
rules允许按顺序评估临时规则对象的列表,直到有一个匹配的并为Job动态提供属性。
可用规则如下:
if(类型only:variables)changes(与only:changes相同)exists
例如,使用if,以下配置指定针对master分支的合并请求为每个管道构建并运行job,而不考虑其他的构建状态:
job:
script: "echo Hello, Rules!"
rules:
- if: '$CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "master"'
when: always
- if: '$VAR =~ /pattern/'
when: manual
- when: on_success
在此示例中,如果第一个规则:
- 如果匹配,则将分配
when: always属性 - 如果不匹配,将依次评估第二和第三条规则,直到找到匹配项。也就是说,将为作业分配以下任一项
- 如果第二条规则匹配,则分配
when: manual属性 - 如果第二个规则不匹配,则为
when: on_success属性。由于没有条件子句,因此第三条规则始终会匹配。
- 如果第二条规则匹配,则分配
rules:if
rules:if与only:variables略有不同,它仅接受单个表达式字符串,而不接受它们的数组。应使用&&或||将要求值的任何表达式集合并为一个表达式。例如:
job:
script: "echo Hello, Rules!"
rules:
- if: '$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME =~ /^feature/ && $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "master"' # This rule will be evaluated
when: always
- if: '$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME =~ /^feature/' # This rule will only be evaluated if the target branch is not "master"
when: manual
- if: '$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME' # If neither of the first two match but the simple presence does, we set to "on_success" by default
如果提供的规则都不匹配,则Job将设置为when:never,并且不包含在管道中。如果在配置中根本不包含rules:when,则行为默认为job:when,其继续默认为on_success。
rules:changes
changes的工作方式与only/except相同,其接受路径数组。
docker build:
script: docker build -t my-image:$CI_COMMIT_REF_SLUG .
rules:
- changes: # Will include the job and set to when:manual if any of the follow paths match a modified file.
- Dockerfile
when: manual
- if: '$VAR == "string value"'
when: manual # Will include the job and set to when:manual if the expression evaluates to true, after the `changes:` rule fails to match.
- when: on_success # If neither of the first rules match, set to on_success
在以上示例中,job设置为:
- 如果
Dockerfile已更改或$VAR == "string value"则手动运行 when:on_success遵循最后一条规则,在此规则中,没有任何较早的条件为true
rules:exists
在GitLab 12.4中引入
exists接受路径数组,如果这些路径中的任何一个作为存储库中的文件存在,则将匹配。
job:
script: docker build -t my-image:$CI_COMMIT_REF_SLUG .
rules:
- exists:
- Dockerfile
还可以使用全局模式来匹配存储库中任何目录中的多个文件。例如:
job:
script: bundle exec rspec
rules:
- exists:
- spec/**.rb
注意:出于性能原因,使用exists与模式限制为10000个检查。第10000次检查后,规则将始终匹配
复杂的规则条款
要使用AND将if、changes和exists子句结合在一起,请在同一规则中使用它们。
在以下示例中:
- 如果
Dockerfile或docker/scripts/中的任何文件已更改并且$VAR == "string value"则手动运行作业 - 否则,作业将不包含在管道中
docker build:
script: docker build -t my-image:$CI_COMMIT_REF_SLUG .
rules:
- if: '$VAR == "string value"'
changes: # Will include the job and set to when:manual if any of the follow paths match a modified file.
- Dockerfile
- docker/scripts/*
when: manual
# - when: never would be redundant here, this is implied any time rules are listed.
当前可用的唯一子句是:
ifchangesexists
例如branches或refs当前仅可用于only/except关键字在rules中还不可用,在此情况下,它们的用法和行为会被单独考虑。
允许的属性
rules当前唯一可用属性是:
whenstart_in,如果when被设置为delayed
如果when被评估为除never以外的值,则when作业将包含在管道中。
延迟作业需要一个start_in值,所以规则对象也如此。例如:
docker build:
script: docker build -t my-image:$CI_COMMIT_REF_SLUG .
rules:
- changes: # Will include the job and delay 3 hours when the Dockerfile has changed
- Dockerfile
when: delayed
start_in: '3 hours'
- when: on_success # Otherwise include the job and set to run normally
tags
tags用于从允许运行此项目的所有Runner列表中选择指定的Runner。
在注册Runner期间,可以指定Runner的标签,如:ruby
、postgres、development。
tags允许您使用已为其分配了指定标签的Runner运行Job:
tags允许使用已为其分配了指定标签的Runner运行Job:
job:
tags:
- ruby
- postgres
以上示例中,会确保job由定义为ruby和postgres标签的Runner构建。
标签是在不同平台上运行不同作业的好方法。如,可以指定带有osx标签的OS X Runner和带有windows标签的Windows Runner,以下作业将在各自的平台上运行:
windows job:
stage:
- build
tags:
- windows
script:
- echo Hello, %USERNAME%!
osx job:
stage:
- build
tags:
- osx
script:
- echo "Hello, $USER!"
allow_failure
allow_failure用于定义允许Job失败,而不会影响其余CI套件。手动作业除外,默认值为false
启用后,如果作业失败,该作业将在用户界面中显示橙色警告。但是,管道的逻辑流程将认为作业成功/通过(success/passed),并且不会被阻塞。
假设所有其它作业均成功,则该作业的阶段( Stages)及其管道将显示相同的橙色警告。但是,关联的提交将被标记为"通过"(passed),而不会发出警告。
在下面的示例中,job1和job2会并行运行,但是如果job1失败,则不会停止下一阶段的运行,因为它标记为allow_failure: true:
job1:
stage: test
script:
- execute_script_that_will_fail
allow_failure: true
job2:
stage: test
script:
- execute_script_that_will_succeed
job3:
stage: deploy
script:
- deploy_to_staging
when
when用于指定在发生故障或已经发生故障的情况下所要执行的作业。
when可以设置为以下值:
on_success- 仅当先前阶段中的所有作业都成功(或由于标记为allow_failure而被视为成功)时才执行作业。这也是默认值。on_failure- 仅当至少一个先前阶段的作业失败时才执行作业。always- 执行作业,而不管先前阶段的作业状态如何。manual- 手动执行作业(添加于 GitLab 8.10)。相关信息参考下面的manual部分。
stages:
- build
- cleanup_build
- test
- deploy
- cleanup
build_job:
stage: build
script:
- make build
cleanup_build_job:
stage: cleanup_build
script:
- cleanup build when failed
when: on_failure
test_job:
stage: test
script:
- make test
deploy_job:
stage: deploy
script:
- make deploy
when: manual
cleanup_job:
stage: cleanup
script:
- cleanup after jobs
when: always
以上脚本将:
- 仅当
build_job失败时执行cleanup_build_job。 - 无论是否成功,总是执行
cleanup_job作为管道的最后一步。 - 允许从GitLab的UI手动执行
deploy_job。
when:manual
手动操作是一种特殊的Job,其不会自动执行,需要用户手工启动。手动操作的示例用法,是将部署到生产环境。可以从管道(Pipelines)、作业(Jobs)、环境(Environments)和部署视图手工启动。更多相关内容,请参考:环境文档。
手动操作可以是可选的或阻塞的。阻塞的手动操作将在定义该操作的阶段阻止管道的执行。当有人通过单击Play按钮执行阻塞的手动Job时,可以恢复管道的执行。
当管道被阻塞时,如果设置了"管道成功时合并"(Merge When Pipeline Succeeds),则不会合并。阻塞的管道也确实有特殊状态,称为“手动”(manual)。默认情况下,手动操作是非阻塞的。如果要阻塞手动操作,则必须在.gitlab-ci.yml的作业定义中添加allow_failure: false。
可选的手动操作默认情况下设置为allow_failure: true ,其状态不会对整体管道状态产生影响。因此,如果手动操作失败,则管道最终是成功的。
手动操作被视为写操作,因此当用户想要触发操作时,将使用受保护分支的权限。换句话说,为了触发分配给正在为其运行管道的分支的手动操作,用户需要有合并到该分支的能力。可以使用受保护的环境来更严格地保护手动部署,以防止未经授权的用户运行该部署。
注意:同时使用when:manual和trigger导致jobs:#{job-name} when should be on_success, on_failure or always错误,是因为when:manual阻止了使用触发器。
受保护的手动Job
可以使用受保护的环境来定义授权用户执行手动作业的精确用户列表。通过仅允许与受保护环境关联的用户触发手动作业,可以实现一些特殊用例,例如:
- 更精确地限制可以部署到环境的人员。
- 允许阻塞管道,直到获得相关用户“批准”为止。
为此,必须要:
- 为job添加
environment。例如:deploy_prod: stage: deploy script: - echo "Deploy to production server" environment: name: production url: https://example.com when: manual only: - master - 在“受保护的环境”设置中,选择环境(上例中为
production),然后将被授权触发手动作业的用户,角色或组添加到“允许部署”(Allowed to Deploy)列表中。只有该列表中的人员以及始终能够使用受保护环境的GitLab管理员才能触发此手动作业。
此外,如果通过添加allow_failure: false将手动作业定义为阻塞,则直到触发手动作业后,管道的下一阶段才会运行。这可以作为一种方法,使定义的用户列表可以通过触发阻止的手动作业来“批准”(approve)后续的管道阶段。
when:delayed
在GitLab 11.4中引入
延迟的Job用于在一定时间后执行脚本。如果要避Job立即进入pending状态,此功能很有用。
可以使用start_in键设置时间段。除非提供了单位,否则start_in的值是以秒为单位的经过时间。start_in键必须小于或等于一小时。有效值的示例包括:
10 seconds30 minutes1 hour
当阶段(stage)中有延迟(delayed)的作业时,直到延迟的作业完成,管道才会继续进行。这意味着此关键字也可以用于在不同阶段之间插入延迟。
上一阶段完成后,延迟作业的计时器立即启动。与其他类型的作业类似,延迟的作业计时器不会启动,除非上一个阶段已通过。
下面的示例创建一个名为timeout rollout 10%的作业,该作业在上一阶段完成后30分钟执行:
timed rollout 10%: stage: deploy script: echo 'Rolling out 10% ...' when: delayed start_in: 30 minutes
可以通过点击“取消调度”(Unschedule)按钮停止延迟工作的活动计时器。除非你手动执行该作业,否则该作业以后将永远不会执行。
可以通过单击Play按钮立即开始延迟的工作。GitLab Runner会很快选择你的Job并开始Job。
environment
environment用于定义作业部署的特定环境。如果指定了environment,但不存在该名称下的环境,则将自动创建一个新环境。
最简单的形式,可以将environment关键字定义为:
deploy to production:
stage: deploy
script: git push production HEAD:master
environment:
name: production
在上述示例中,deploy to production作业将被标记为在production环境中进行部署。
environment:name
environment的名称可以包含:
- 字母
- 数字
- 空格
-_/${}
通用名称是qa、staging和production ,但是也可以使用任何适用于你的工作流程的名称。
deploy to production:
stage: deploy
script: git push production HEAD:master
environment:
name: production
environment:url
这是一个可选值,设置该值时,它将在GitLab中的各个位置显示按钮,单击这些按钮会跳转到所定义的URL。
下面的示例中,如果Job成功完成,它将在合并请求和环境/部署(vironments/deployments)页面中创建按钮,这些页面将指向https://prod.example.com。
deploy to production:
stage: deploy
script: git push production HEAD:master
environment:
name: production
url: https://prod.example.com
environment:on_stop
通过在environment定义on_stop关键字,可以实现关闭(停止)环境。
请参考environment:action章节,获取相关示例。
environment:action
在GitLab 8.13中引入
action关键字与on_stop结合使用,并在调用关闭环境的Job中定义。示例如下:
review_app:
stage: deploy
script: make deploy-app
environment:
name: review
on_stop: stop_review_app
stop_review_app:
stage: deploy
variables:
GIT_STRATEGY: none
script: make delete-app
when: manual
environment:
name: review
action: stop
上面示例中,我们设置了review_app作业以部署到review环境,并且在on_stop下定义了一个新的stop_review_app作业。一旦rreview_app作业成功完成,它将根据when下定义的内容触发stop_review_app作业。在这种情况下,我们将其设置为manual,因此需要通过GitLab的Web界面手工操作才能运行。
同样在示例中,GIT_STRATEGY设置为none,所以会在自动触发stop_review_app作业删除分支后,GitLab Runner将不会尝试检出代码。
stop_review_app作业必须定义以下关键字:
-
when- 参考 environment:nameenvironment:action-
stage应该与review_app相同,以便在删除分支时自动停止环境
动态环境
示例:
deploy as review app:
stage: deploy
script: make deploy
environment:
name: review/$CI_COMMIT_REF_NAME
url: https://$CI_ENVIRONMENT_SLUG.example.com/
deploy as review app作业将被标记为部署,以动态创建review/$CI_COMMIT_REF_NAME环境,其中$CI_COMMIT_REF_NAME是运行程序所设置的环境变量。$CI_ENVIRONMENT_SLUG变量基于环境名称,但适合包含在URL中。这种情况下,如果deploy as review app作业在名为pow的分支中运行,则可以使用https://review-pow.example.com/之类的URL访问此环境。
当然,这意味着托管应用程序的基础服务器已正确配置。
常见的用例是为分支创建动态环境并将其用作Review Apps。可以在https://gitlab.com/gitlab-examples/review-apps-nginx/上查看使用Review Apps的简单示例。
cache
更多信息:了解缓存工作原理及一些好的做法,请参考缓存依赖项文档。
cache用于指定应在Job之间缓存的文件和目录的列表。只能使用本地工作副本中的路径。
如果在Job范围之外定义了cache,则意味着它是全局设置,所有Job都将使用该定义。
cache:paths
通过paths指令选择要缓存的文件或目录。只能在$CI_PROJECT_DIR中指定路径。可以遵循使用glob模式和filepath.Match。
如,将所有文件缓存在以.apk和.config文件结尾的binaries中:
rspec:
script: test
cache:
paths:
- binaries/*.apk
- .config
本地定义的缓存将覆盖全局定义的选项。以下rspec作业将仅缓存binaries/:
cache:
paths:
- my/files
rspec:
script: test
cache:
key: rspec
paths:
- binaries/
需要注意,由于缓存是在作业之间共享的,因此如果为不同的作业使用不同的路径,则还应该设置不同的cache:key,否则缓存内容可能会被覆盖。
cache:key
在GitLab v1.0.0中引入
由于缓存是在作业之间共享的,因此如果为不同的作业使用不同的路径,则还应该设置一个不同的cache:key,否则缓存内容可能会被覆盖。
key指令允许你定义作业之间缓存的相似性,从而允许为所有作业使用单个缓存、按作业缓存、按分支缓存或适合你工作流程的任何其他方式。这样,你可以微调缓存,从而允许你在不同作业甚至不同分支之间缓存数据。
cache:key变量可以使用任何预定义的变量,并且默认key(如果未设置)只是字面的default,这意味着从GitLab 9.0开始,默认情况下,所有内容在每个管道和作业之间共享。
注意:cache:key变量不能包含/字符,或等效的URI编码的%2F;也禁止仅由点(.、%2E)组成的值。
例如,要启用每分支缓存:
cache:
key: "$CI_COMMIT_REF_SLUG"
paths:
- binaries/
如果使用Windows Batch运行Shell脚本,则需要将$替换为%:
cache:
key: "%CI_COMMIT_REF_SLUG%"
paths:
- binaries/
cache:key:files
在GitLab v12.5中引入
如果添加了cache:key:files,则必须用它定义一个或两个文件。缓存key将是根据更改了指定文件的最新提交(一次或两次)计算得出的SHA。如果两个文件在任何提交中均未更改,则key为default。
cache:
key:
files:
- Gemfile.lock
- package.json
paths:
- vendor/ruby
- node_modules
cache:key:prefix
在GitLab v12.5中引入
prefix参数允许key由指定的prefix与cache:key:prefix计算的SHA组合而成,从而为key:files增加了额外的功能。例如,添加rspec的prefix,将使key看起来像:rspec-feef9576d21ee9b6a32e30c5c79d0a0ceb68d1e5。如果两个文件在任何提交中均未更新,则前缀将添加到default,则示例中的key将是rspec-default。
prefix遵循与与key相同的限制,因此它可以使用任何预定义变量。同样的,/字符或等效URI编码的%2F;也禁止仅由点(.、%2E)组成的值,是不允许的。
cache:
key:
files:
- Gemfile.lock
prefix: ${CI_JOB_NAME}
paths:
- vendor/ruby
cache:untracked
设置cache:untracked将缓存Git存储库中所有未跟踪的文件:
rspec:
script: test
cache:
untracked: true
将所有Git未跟踪的文件和缓存在binaries中的文件:
rspec:
script: test
cache:
untracked: true
paths:
- binaries/
cache:policy
在GitLab v9.4中引入
缓存Job的默认是在执行开始时下载文件,并在结束时重新上传文件。这样可以将Job所做的任何更改保留下来,以备将来运行,这被称为pull-push缓存策略。
如果你确认该Job不会更改缓存的文件,则可以通过设置policy: pull来跳过上传步骤。通常,这会在早期阶段与普通的缓存作业结合在一起,以确保不时更新缓存:
stages:
- setup
- test
prepare:
stage: setup
cache:
key: gems
paths:
- vendor/bundle
script:
- bundle install --deployment
rspec:
stage: test
cache:
key: gems
paths:
- vendor/bundle
policy: pull
script:
- bundle exec rspec ...
这有助于加快Job的执行速度并减少缓存服务器上的负载,尤其是有大量并行使用缓存的作业时。
此外,如果有一项Job可以无条件地重新创建缓存而不参考其先前的内容,则可以使用policy: push设置该Job跳过下载步骤。
artifacts
artifacts用于指定文件\目录的列表,这些文件应在成功(succeed)、失败(fail)或总是(always)时附加到Job
Job完成后,工件(artifacts)将被发送到GitLab,并可在GitLab UI中下载
artifacts:paths
artifacts:expose_as
artifacts:name
artifacts:untracked
artifacts:when
artifacts:expire_in
artifacts:reports
artifacts:reports:junit
artifacts:reports:codequality
artifacts:reports:sast
artifacts:reports:dependency_scanning
artifacts:reports:container_scanning
artifacts:reports:dast
artifacts:reports:license_management
artifacts:reports:performance
artifacts:reports:metrics
dependencies
当依赖的Job执行失败
needs
要求和限制
coverage
retry
timeout
parallel
trigger
简单的trigger语法
复杂的trigger语法
interruptible
include
include:local
include:file
include:template
include:remote
嵌套包含(include)
include示例
单个字符串或多个值的数组
重用before_script模版
覆盖外部模板值
使用嵌套包含
extends
同时使用extends和include
pages
variables
Git策略(strategy)
Git子模块策略
Git 检出(checkout)
Git 清除(clean)标志
Job 阶段尝试
浅克隆
5. 不推荐使用的参数
5.1 全局定义的types
5.2 Job定义的type
5.3 全局定义的image、services、cache、before_script、after_script
typestypeimage、services、cache、before_script、after_script