{{< details >}}
- Tier: 基础版, 专业版, 旗舰版
- Offering: JihuLab.com, 私有化部署
{{< /details >}}
你可以通过使用以下功能减少极狐GitLab CI/CD 配置文件中的复杂性和重复配置:
- YAML 特定功能如 anchors (
&
), aliases (*
), 和 map merging (<<
)。 - 使用更灵活和可读的
extends
关键字。你应该尽可能使用extends
。
锚点
YAML 有一个称为“锚点”的功能,可以用来在文档中复制内容。
使用锚点来复制或继承属性。将锚点与 隐藏的任务 一起使用,为你的任务提供模板。当有重复的键时,最新包含的键将覆盖其他键。
在某些情况下(见 YAML 锚点的脚本),你可以使用 YAML 锚点来构建具有多组件的数组,这些组件在其他地方定义。例如:
.default_scripts: &default_scripts
- ./default-script1.sh
- ./default-script2.sh
job1:
script:
- *default_scripts
- ./job-script.sh
当使用 include
关键字时,你不能跨多个文件使用 YAML 锚点。锚点仅在它们定义的文件中有效。要重用来自不同 YAML 文件的配置,请使用 !reference
标签 或 extends
关键字。
以下示例使用锚点和 map 合并。它创建了两个任务,test1
和 test2
,继承了 .job_template
配置,每个都有其自定义的 script
定义:
.job_template: &job_configuration # 隐藏的 yaml 配置,定义了一个名为 'job_configuration' 的锚点
image: ruby:2.6
services:
- postgres
- redis
test1:
<<: *job_configuration # 添加 'job_configuration' 别名的内容
script:
- test1 project
test2:
<<: *job_configuration # 添加 'job_configuration' 别名的内容
script:
- test2 project
&
设置锚点的名称(job_configuration
),<<
意味着“将给定的哈希合并到当前的哈希中”,而 *
包含命名的锚点(再次是 job_configuration
)。此示例的 扩展版 是:
.job_template:
image: ruby:2.6
services:
- postgres
- redis
test1:
image: ruby:2.6
services:
- postgres
- redis
script:
- test1 project
test2:
image: ruby:2.6
services:
- postgres
- redis
script:
- test2 project
你可以使用锚点定义两组服务。例如,test:postgres
和 test:mysql
共享在 .job_template
中定义的 script
,但使用不同的 services
,分别在 .postgres_services
和 .mysql_services
中定义:
.job_template: &job_configuration
script:
- test project
tags:
- dev
.postgres_services:
services: &postgres_configuration
- postgres
- ruby
.mysql_services:
services: &mysql_configuration
- mysql
- ruby
test:postgres:
<<: *job_configuration
services: *postgres_configuration
tags:
- postgres
test:mysql:
<<: *job_configuration
services: *mysql_configuration
扩展版 是:
.job_template:
script:
- test project
tags:
- dev
.postgres_services:
services:
- postgres
- ruby
.mysql_services:
services:
- mysql
- ruby
test:postgres:
script:
- test project
services:
- postgres
- ruby
tags:
- postgres
test:mysql:
script:
- test project
services:
- mysql
- ruby
tags:
- dev
你可以看到隐藏的任务被方便地用作模板,并且 tags: [postgres]
覆盖了 tags: [dev]
。
YAML 锚点的脚本
{{< history >}}
- 在极狐GitLab 16.9 中,引入了对
stages
关键字的锚点支持。
{{< /history >}}
你可以在 script、before_script
和 after_script
中使用 YAML 锚点,以在多个任务中使用预定义命令:
.some-script-before: &some-script-before
- echo "Execute this script first"
.some-script: &some-script
- echo "Execute this script second"
- echo "Execute this script too"
.some-script-after: &some-script-after
- echo "Execute this script last"
job1:
before_script:
- *some-script-before
script:
- *some-script
- echo "Execute something, for this job only"
after_script:
- *some-script-after
job2:
script:
- *some-script-before
- *some-script
- echo "Execute something else, for this job only"
- *some-script-after
使用 extends
复用配置部分
你可以使用 extends
关键字 在多个任务中重用配置。它类似于 YAML 锚点,但更简单,并且你可以 将 extends
与 includes
一起使用。
extends
支持多级继承。由于额外的复杂性,你应该避免使用超过三级的继承,但最多可以使用十一级。以下示例有两级继承:
.tests:
rules:
- if: $CI_PIPELINE_SOURCE == "push"
.rspec:
extends: .tests
script: rake rspec
rspec 1:
variables:
RSPEC_SUITE: '1'
extends: .rspec
rspec 2:
variables:
RSPEC_SUITE: '2'
extends: .rspec
spinach:
extends: .tests
script: rake spinach
从 extends
中排除一个键
要从扩展内容中排除一个键,你必须将其分配为 null
,例如:
.base:
script: test
variables:
VAR1: base var 1
test1:
extends: .base
variables:
VAR1: test1 var 1
VAR2: test2 var 2
test2:
extends: .base
variables:
VAR2: test2 var 2
test3:
extends: .base
variables: {}
test4:
extends: .base
variables: null
合并后的配置:
test1:
script: test
variables:
VAR1: test1 var 1
VAR2: test2 var 2
test2:
script: test
variables:
VAR1: base var 1
VAR2: test2 var 2
test3:
script: test
variables:
VAR1: base var 1
test4:
script: test
variables: null
一起使用 extends
和 include
要重用不同配置文件中的配置,结合使用 extends
和 include
。
在以下示例中,一个 script
在 included.yml
文件中定义。然后,在 .gitlab-ci.yml
文件中,extends
引用 script
的内容:
-
included.yml
:.template: script: - echo Hello!
-
.gitlab-ci.yml
:include: included.yml useTemplate: image: alpine extends: .template
合并细节
你可以使用 extends
合并哈希,但不能合并数组。用于合并的算法是“最接近的范围获胜”。当有重复的键时,极狐GitLab 基于键进行反向深度合并。最后一个成员的键总是覆盖在其他层次上定义的任何东西。例如:
.only-important:
variables:
URL: "http://my-url.internal"
IMPORTANT_VAR: "the details"
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
- if: $CI_COMMIT_BRANCH == "stable"
tags:
- production
script:
- echo "Hello world!"
.in-docker:
variables:
URL: "http://docker-url.internal"
tags:
- docker
image: alpine
rspec:
variables:
GITLAB: "is-awesome"
extends:
- .only-important
- .in-docker
script:
- rake rspec
结果是这个 rspec
任务:
rspec:
variables:
URL: "http://docker-url.internal"
IMPORTANT_VAR: "the details"
GITLAB: "is-awesome"
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
- if: $CI_COMMIT_BRANCH == "stable"
tags:
- docker
image: alpine
script:
- rake rspec
在这个例子中:
-
variables
部分合并,但URL: "http://docker-url.internal"
覆盖了URL: "http://my-url.internal"
。 -
tags: ['docker']
覆盖了tags: ['production']
。 -
script
不合并,但script: ['rake rspec']
覆盖了script: ['echo "Hello world!"']
。你可以使用 YAML 锚点 合并数组。
!reference
标签
使用 !reference
自定义 YAML 标签从其他任务部分选择关键字配置,并在当前部分中重用它。与 YAML 锚点 不同,你还可以使用 !reference
标签重用来自 包含的 配置文件的配置。
在以下示例中,test
任务中重用了来自两个不同位置的 script
和 after_script
:
-
configs.yml
:.setup: script: - echo creating environment
-
.gitlab-ci.yml
:include: - local: configs.yml .teardown: after_script: - echo deleting environment test: script: - !reference [.setup, script] - echo running my own command after_script: - !reference [.teardown, after_script]
在以下示例中,test-vars-1
重用了 .vars
中的所有变量,而 test-vars-2
选择了一个特定变量,并将其重用为新的 MY_VAR
变量。
.vars:
variables:
URL: "http://my-url.internal"
IMPORTANT_VAR: "the details"
test-vars-1:
variables: !reference [.vars, variables]
script:
- printenv
test-vars-2:
variables:
MY_VAR: !reference [.vars, variables, IMPORTANT_VAR]
script:
- printenv
在使用 !reference
标签与 parallel:matrix
关键字 时,存在一个 已知问题。
在 script
、before_script
和 after_script
中嵌套 !reference
标签
{{< history >}}
- 在极狐GitLab 16.9 中,引入了对
stages
关键字的!reference
支持。
{{< /history >}}
你可以在 script
、before_script
和 after_script
部分中嵌套 !reference
标签多达 10 级。使用嵌套标签在构建更复杂的脚本时定义可重用的部分。例如:
.snippets:
one:
- echo "ONE!"
two:
- !reference [.snippets, one]
- echo "TWO!"
three:
- !reference [.snippets, two]
- echo "THREE!"
nested-references:
script:
- !reference [.snippets, three]
在这个例子中,nested-references
任务运行所有三个 echo
命令。
配置你的 IDE 支持 !reference
标签
流水线编辑器 支持 !reference
标签。然而,像 !reference
这样的自定义 YAML 标签的模式规则可能会被你的编辑器默认视为无效。你可以配置一些编辑器以接受 !reference
标签。例如:
-
在 VS Code 中,你可以在
settings.json
文件中设置vscode-yaml
以解析customTags
:"yaml.customTags": [ "!reference sequence" ]
-
在 Sublime Text 中,如果你正在使用
LSP-yaml
包,你可以在你的LSP-yaml
用户设置中设置customTags
:{ "settings": { "yaml.customTags": ["!reference sequence"] } }