gitlab-ci.yml 配置详情

全局关键字

stages

stages用于定义流水线全局可使用的阶段,阶段元素的顺序既是作业执行的顺序。

官方默认预定义的5个阶段(按顺序):.prebuildtestdeploy.post

  • 相同阶段作业并行执行。默认情况下Gitlab Runner运行器只会同时执行一个作业,只有满足以下条件之一时才会真正的并行执行:

    • 作业运行在不同的运行器上
    • 修改Gitlab Runner运行器config.toml concurrent设置,默认是1
  • 默认情况下,上一个阶段作业全部运行成功后,才会运行下一阶段作业

  • 如果作业没定义阶段,则默认使用test阶段

  • 默认情况下,任何一个前置作业失败,commit提交会被标记为fail状态,并且下一阶段作业都不会运行。

  • .pre保证永远是管道中的第一阶段

  • .post保证永远是管道中的最后一个阶段

  • 用户自定义的阶段,在.pre之后,.post之前执行,.pre.post顺序是不可变的,比如以下配置是等同的:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    # 1
    stages:
    - .pre
    - a
    - b
    - .post
    # 2
    stages:
    - a
    - .pre
    - b
    - .post
    # 3
    stages:
    - a
    - b

workflow

include

关键字描述

stage

stage定义每个作业所处的阶段。作业没有第一stage的话,默认是test阶段。

before_script

before_script用于定义在所有作业之前需要执行的命令。比如安装软件、安装依赖、更新代码等。

script

script是定义作业中唯一必须参数,用于配置运行器需要执行的脚本。所有作业都必须有一个script配置,如:

1
2
3
job1:
script:
- echo 'hello world'

表示job1作业需要执行命令输出“hello world”。

after_script

after_script用于定义在所有作业(即使作业执行失败)之后需要执行的命名。比如:清理缓存、清空工作区间等。

如果作业timeoutcancelledafter_script命令不会执行。

image

image是指定作业使用的Docker镜像。

extends

services

services是指定使用Docker镜像服务。

rules

在管道中使用rules来定义包含或排除作业。

rules按顺序计算,直到第一次匹配成功为止。当匹配成功时,在管道中,作业要么被包含或被排除,具体取决于配置。

rules替换only/except,并且它们不能在同一个作业中一起使用。

rules接受一个用下列方法定义的规则数组,可以多个组合在一起使用:

  • if
  • changes
  • exists
  • allow_failuree
  • variables
  • when(未定义时默认为:on_success

rules:if

使用rules:if子句指定何时将作业添加到管道:

  • 如果if语句为true,则将作业添加到管道中。
  • 如果if语句为true,但是与when:never结合使用,则不会将作业添加到管道中。
  • 如果if语句都不为true,则不会将作业添加到管道中。
1
2
3
4
5
6
7
8
9
job:
script: echo "Hello, Rules!"
rules:
- if: '$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME =~ /^feature/ && $CI_MERGE_REQUEST_TARGET_BRANCH_NAME != $CI_DEFAULT_BRANCH'
when: never
- if: '$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME =~ /^feature/'
when: manual
allow_failure: true
- if: '$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME'

其他细节:

  • 如果rule匹配且未定义when,则该规则将为作业定义when,默认为on_success
  • 可以为每个rule定义一次when,或者为将适用于所有规则的job级别定义一次whenjob级别和rule中的when不能混为一谈。
  • script中的变量不同,rule中的变量格式为$VARIABLE

rules:changes

使用rules:changes通过检查对特定文件的更改来指定何时将作业添加到管道中。

仅在branched管道或merge_requests管道中使用rules:changes

1
2
3
4
5
6
7
8
9
10
11
12
docker build:
script: docker build -t my-image:$CI_COMMIT_REF_SLUG .
rules:
# 1、如果是合并请求
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
changes:
# 2、检查Dockerfile是否有更改
- Dockerfile
# 3、作为手动作业添加到管道中
when: manual
# 4、即使作业没有被触发,管道也会继续运行
allow_failure: true

其他细节:

  • rules:changes工作方式与only:changesexcept:changes相同。
  • 你可以使用when:never来实现类似于except:changes的规则。

rules:exists

使用exists用于在存储库中存在某些文件时运行作业。

例子:

1
2
3
4
5
6
job:
script: docker build -t my-image:$CI_COMMIT_REF_SLUG .
rules:
- exists:
# Dockerfile存在于存储库中的任何位置,作业都会运行
- Dockerfile

其他细节:

  • Glob patterns are interpreted with Ruby File.fnmatch with the flags File::FNM_PATHNAME | File::FNM_DOTMATCH | File::FNM_EXTGLOB.
  • 出于性能考虑,GitLab最多匹配10,000个已存在的模式或文件路径。超过10,000个文件时,exists规则总是假定项目中有的匹配。

rules:allow_failure

rules:allow_failure允许作业失败而不停止管道。

allow_failure:truewhen:manual结合使用,管道会继续运行,无需等待手动作业的结果。而allow_failure:falsewhen:manual结合会导致管道等待手动作业运行后再继续。

例子:

1
2
3
4
5
6
job:
script: echo "Hello, Rules!"
rules:
- if: '$CI_MERGE_REQUEST_TARGET_BRANCH_NAME == $CI_DEFAULT_BRANCH'
when: manual
allow_failure: true

rules:variables

rules中使用variables为特定的条件定义变量。

例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
job:
variables:
DEPLOY_VARIABLE: "default-deploy"
rules:
- if: $CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH
variables: # Override DEPLOY_VARIABLE defined
DEPLOY_VARIABLE: "deploy-production" # at the job level.
- if: $CI_COMMIT_REF_NAME =~ /feature/
variables:
IS_A_FEATURE: "true" # Define a new variable.
script:
- echo "Run script with $DEPLOY_VARIABLE as an argument"
- echo "Run another script if $IS_A_FEATURE exists"

only 和 except

onlyexcept用于做限制策略,控制何时向管道添加作业。

  • only用来定义什么时候运行作业。
  • except用来定义什么时候不运行作业。

策略规则:

  • onlyexcept可以同时使用。
  • onlyexcept可以使用正则表达式。
  • onlyexcept可以使用特殊关键字。比如:apibrancheschatexternalexternal_pull_requestsmerge_requestspipelinespushesschedulestagstriggersweb等。
  • onlyexcept允许指定过滤forks作业的存储库路径。

可以使用四个关键词:

  • refs
  • variables
  • changes
  • kubernetes

only:refs/except:refs

使用only:refsexcept:refs关键字来控制什么时候根据分支名称(branches)或管道类型(pipeline types)向管道中添加作业。

  • 分支名称,比如: main or my-feature-branch

  • 匹配分支的正则表达式,比如 /^feature-.*/

  • 以下关键字

关键字 描述
api 用于由管道API触发的管道。理解:当一个pipline被另一个piplines api所触发时(不是触发器API)。
branches 当一个分支被push上来。
chat 用于使用GitLab ChatOps命令创建的管道。
external 当您使用除GitLab之外的CI服务时,比如:Jenkins
external_pull_requests GitHub上的外部拉取请求被创建或更新时。
merge_requests 用于创建或更新合并请求时创建的管道。
pipilines 对于使用带有CI_JOB_TOKENAPItrigger关键字创建的多项目管道。
pushes 用于由git push事件触发的管道,包括用于branchestags
schedules 针对预定好的pipline计划而言。
tags 当一个打了tag标记的Release被提交时。
triggers 用于使用trigger token创建的管道。
web GitLab WEB页面上Pipelines标签页下,按下run pipline的情况。

例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
job1:
script: echo
only:
- main
- /^issue-.*$/
- merge_requests

job2:
script: echo
except:
- main
- /^stable-branch.*$/
- schedules

其他细节:

  • 预定的管道运行在特定的分支上,所以配置了only: braches的作业也会运行在预定的管道上。添加except: schedules以防止只有配置了only: branches的作业在预定的管道上运行。

  • onlyexcept没有使用任何关键字,则等同于only: refsexcept: refs。以下job1job2是等同的:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    job1:
    script: echo 'job1'
    only:
    - branches

    job2:
    script: echo 'job2'
    only:
    refs:
    - branches
  • 如果作业没有使用onlyexcept或者rules,则默认onlybranchestags。以下job1job2是等同的:

    1
    2
    3
    4
    5
    6
    7
    8
    job1:
    script: echo 'job1'

    job2:
    script: echo 'job2'
    only:
    - branches
    - tags

only:variables/except:variables

根据CI/CD variables的状态,使用only:variablesexcept:variables关键字来控制何时向管道中添加作业。

例子

1
2
3
4
5
6
job:
script: echo 'job'
only:
variables:
- $RELEASE == "staging"
- $STAGING

你可以使用except:variables来根据提交消息排除作业

1
2
3
4
5
end-to-end:
script: rake test:end-to-end
except:
variables:
- $CI_COMMIT_MESSAGE =~ /skip-end-to-end-tests/

可以使用&&||来构建更复杂的变量表达式

1
2
3
4
5
6
job1:
script:
- echo This rule uses parentheses.
only:
variables:
- ($CI_COMMIT_BRANCH == "main" || $CI_COMMIT_BRANCH == "develop") && $MY_VARIABLE

only:changes/except:changes

Git push事件修改文件时,使用changes关键字和 only来运行作业,或except来跳过作业。

  • 文件路径。
  • 单个目录的通配符路径,例如path/to/directory/*,或一个目录及其所有子目录,例如path/to/directory/**/*
  • 所有具有相同或多个扩展名的文件的通配符(glob)路径,例如*.mdpath/to/directory/*.{rb、py sh}
  • 用双引号括起来的根目录或所有目录中的文件的通配符路径。例如"*.json""**/*.json"

change可以用于以下refs

  • branches

  • external_pull_requests

  • merge_requests

    1
    2
    3
    4
    5
    6
    7
    8
    docker build service one:
    script: docker build -t my-service-one-image:$CI_COMMIT_REF_SLUG .
    only:
    refs:
    - merge_requests
    changes:
    - Dockerfile
    - service-one/**/*

例子:

1
2
3
4
5
6
7
8
9
10
docker build:
script: docker build -t my-image:$CI_COMMIT_REF_SLUG .
only:
refs:
- branches
changes:
- Dockerfile
- docker/scripts/*
- dockerfiles/**/*
- more_scripts/*.{rb,py,sh}

其他细节

  • 如果使用除branchesexternal_pull_requestsmerge_requests 之外的引用,则changes无法确定给定文件是新文件还是旧文件,因此总是返回true
  • 如果使用only:changes与其他refs配置,则作业会忽略changes且始终运行。
  • 如果使用except:changes与其他refs配置,则作业会忽略changes且永远不会运行。

only:kubernetes/except:kubernetes

needs

使用needs:乱序执行作业。使用needs的作业之间的关系可以可视化为有向无环图。

tags

使用tags从项目可用的所有Gitlab Runner列表中选择特定的运行器。

1
2
3
4
job:
tags:
- ruby
- postgres

allow_failure

让作业失败而不影响CI套件的其他部分时,使用allow_failure,默认:false,除了使用when:manual语法的手动作业。

在使用rules:的作业中,所有作业默认为allow_failure:false,包括when:manual作业。

allow_failure设置为true且作业失败时,作业在UI中显示橙色警告。但是,管道的逻辑流认为作业成功/通过,它是非阻塞。

在下面的例子中,job1job2并行运行。如果job1失败,它不会停止下一个阶段的运行,因为它被标记为allow_failure: true:

1
2
3
4
5
6
7
8
9
10
11
12
13
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

allow_failure:exit_codes

使用allow_failure:exit_codes动态控制是否应该允许作业失败。您可以列出不认为失败的退出码。如果有任何其他退出代码,作业将失败:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
job1:
script:
- echo "Run a script that results in exit code 1. This job fails."
- exit 1
allow_failure:
exit_codes: 137

job2:
script:
- echo "Run a script that results in exit code 137. This job is allowed to fail."
- exit 137
allow_failure:
exit_codes:
- 137
- 255

when

使用when来实现在失败时或失败后运行的作业。

when的有效值为:

  • on_success(默认)-只有当前置阶段的所有作业都成功时才执行作业,或者因为它们具有allow_failure: true而被认为成功时才执行作业。
  • on_failure - 只有在前置阶段至少有一个作业失败时才执行作业。
  • always - 执行作业而不考虑前置阶段作业的状态。
  • manual - 手动执行工作。
  • delayed - 将作业的执行延迟一段指定的时间。GitLab 11.14中新增特性。
  • never
    • 根据作业规则,不执行作业。
    • 根据workflow:rules,不运行流水线。

when:manual

手动作业是一种不会自动执行的作业,必须由用户显式启动。一般在部署到生产环境时使用手动作业。当管道启动时,手动作业显示为跳过,而不会自动运行。

when:delayed

使用when:delayed执行脚本,或者避免作业立即进入挂起状态。

可以使用start_in关键字设置句点。默认start_in的值是以秒为单位的运行时间,除非提供了一个单位。start_in必须小于等于一周。有效值的示例包括:

  • '5'
  • 5 seconds
  • 30 minutes
  • 1 day
  • 1 week

当一个阶段包含一个被延迟的作业时,延迟的作业完成后,管道才会继续运行。

与其他类型的作业类似,延迟作业的计时器只有在前一个阶段通过后才会启动。

下面的示例创建了一个名为job1的作业,在前一个阶段完成30分钟后执行:

1
2
3
4
5
job1:
stage: deploy
script: echo 'job1'
when: delayed
start_in: 30 minutes

environment

cache

使用缓存指定要在作业之间缓存的文件和目录列表。只能使用本地工作副本中的路径。

cache:paths

使用cache:paths关键字选择要缓存的文件或目录。

1
2
3
4
5
6
7
8
9
10
rspec:
script:
- echo "This job uses a cache."
cache:
key: binaries-cache
paths:
# 缓存binaries目录下所有apk文件
- binaries/*.apk
# 缓存 .config 文件
- .config

cache:key

使用cache:key给每个缓存一个唯一的标识键。使用相同cache key的所有作业使用相同的缓存,包括在不同的管道中。

如果不设置,则默认密钥为default。所有带有cache:但没有cache:key的作业都共享default的缓存。

1
2
3
4
5
6
7
cache-job:
script:
- echo "This job uses a cache."
cache:
key: binaries-cache-$CI_COMMIT_REF_SLUG
paths:
- binaries/

其他细节:

  • 如果是windows系统下,需要把$替换成%,比如:%CI_COMMIT_REF_SLUG%
  • cache:key不能包含
    • /符号,等价于URI编码%2F
    • .符号(任何数字),等价于URI编码的%2E
  • 缓存是在作业之间共享的,为不同的作业使用不同的路径,或设置不同的cache:key,否则缓存内容会被覆盖。

cache:key:files

一个两个特定文件发生变化时,使用cache:key:files生成一个新的密钥。cache:key:files允许重用一些缓存,并减少重建的次数,可以加快后续管道运行的速度。

1
2
3
4
5
6
7
8
9
10
11
cache-job:
script:
- echo "This job uses a cache."
cache:
key:
files:
- Gemfile.lock
- package.json
paths:
- vendor/ruby
- node_modules

其他细节:

  • cache key是一个SHA签名,它根据每个列出的更改的文件的最新提交计算得出。如果在提交中没有任何文件变动,则默认为default

cache:key:prefix

使用cache:key:prefixcache:key:files结合计算SHA签名组合。

  • 字符串
  • 预设的variables
  • 二者结合

cache:untracked

使用cache:untracked:true来缓存Git库中所有未被跟踪的文件。

1
2
3
4
5
6
7
8
9
10
11
12
rspec:
script: test
cache:
untracked: true

# 结合 cache:paths 使用
rspec:
script: test
cache:
untracked: true
paths:
- binaries/

cache:when

使用cache:when根据作业的状态,来定义何时需要缓存。

  • on_success - 默认
  • on_failure
  • always

cache:policy

如果要更改cache的上传和下载行为,使用cache:policy。默认情况下,作业在启动时下载缓存,在作业结束时上传更改到缓存。

缓存策略可选项:

  • pull
  • push
  • pull-push - 默认

artifacts

使用artifacts把指定的文件和目录的列表都附加到作业,无论作业返回successfails还是always状态。

作业完成后,artifacts被发送到GitLab。如果大小不大于最大artifacts大小限制(有大小限制,可以手动修改配置支持更大的大小),可以在GitLab UI下载它们。

dependencies

artifacts:exclude

exclude用来防止将文件添加到artifacts存档中。

1
2
3
4
5
artifacts:
paths:
- binaries/
exclude:
- binaries/**/*.o

artifacts:expire_in

使用expire_in指定作业artifacts在过期和删除之前存储的时间。如果未定义过期时间,则默认为:30天。

expire_in设置不生效:

  • Artifacts from the latest job, unless this keeping the latest job artifacts is:
  • Pipeline artifacts. It’s not possible to specify an expiration date for these:
    • Pipeline artifacts from the latest pipeline are kept forever.
    • Other pipeline artifacts are erased after one week.

expire_in默认以为单位。有效值包括:

  • '42'
  • 42 seconds
  • 3 mins 4 sec
  • 2 hrs 20 min
  • 2h20min
  • 6 mos 1 day
  • 47 yrs 6 mos and 4d
  • 3 weeks and 2 days
  • never
1
2
3
4
job:
artifacts:
# 使 artifacts 在上传一周后过期
expire_in: 1 week

要覆盖过期日期并保护工件不被自动删除,可以执行以下操作:

  • 使用Gitlab页面上的Keep按钮。
  • 配置expire_innever

artifacts:expose_as

artifacts:name

使用name指令来定义创建的artifacts存档的名称。

artifacts:paths

paths是相对于项目目录($CI_PROJECT_DIR)的,不接链接到它的外部。

1
2
3
4
5
6
release-job:
script:
- mvn package -U
artifacts:
paths:
- target/*.war

artifacts:public

artifacts:reports

artifacts:untracked

artifacts:when

coverage

retry

使用retry来配置任务在失败时重试的次数。

当作业失败时,将再次处理该作业,直到达到retry指定的限制为止。取值范围0~2(最多重试两次,总共三次)。

1
2
3
test:
script: rspec
retry: 2
1
2
3
4
5
test:
script: rspec
retry:
max: 2
when: runner_system_failur

when 的取值可以是:

  • always: Retry on any failure (default).
  • unknown_failure: Retry when the failure reason is unknown.
  • script_failure: Retry when the script failed.
  • api_failure: Retry on API failure.
  • stuck_or_timeout_failure: Retry when the job got stuck or timed out.
  • runner_system_failure: Retry if there is a runner system failure (for example, job setup failed).
  • missing_dependency_failure: Retry if a dependency is missing.
  • runner_unsupported: Retry if the runner is unsupported.
  • stale_schedule: Retry if a delayed job could not be executed.
  • job_execution_timeout: Retry if the script exceeded the maximum execution time set for the job.
  • archived_failure: Retry if the job is archived and can’t be run.
  • unmet_prerequisites: Retry if the job failed to complete prerequisite tasks.
  • scheduler_failure: Retry if the scheduler failed to assign the job to a runner.
  • data_integrity_failure: Retry if there is a structural integrity problem detected.

timeout

使用timeout为特定作业配置超时时间。

1
2
3
build:
script: build.sh
timeout: 3 hours 30 minutes

parallel

trigger

使用trigger来定义下游管道触发器。当GitLab启动trigger作业时,将创建下游管道。

带有trigger的作业只能使用有限的关键字集合。例如,不能使用scriptbefore_scriptafter_script运行命令。

可以使用trigger创建2中不同类型的下游管道:

多项目管道:基本语法

可以使用trigger来配置一个完成路径的下游项目触发器:

1
2
3
staging:
stage: deploy
trigger: my/deployment

多项目管道:复杂语法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 1、通过分支名称创建下游管道
staging:
stage: deploy
trigger:
project: my/deployment
branch: stable
# 2、通过触发管道的状态创建下游管道
trigger_job:
trigger:
project: my/project
strategy: depend
# 3、通过上游管道状态创建下游管道
upstream_bridge:
stage: test
needs:
pipeline: other/project

父子管道:触发语法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# 1、通过子管道配置的YAML文件的路径
trigger_job:
trigger:
include: path/to/child-pipeline.yml
# 2、通过触发管道的状态创建子管道
trigger_job:
trigger:
include:
- local: path/to/child-pipeline.yml
strategy: depend
# 3、使用(动态生成的)配置文件触发子管道
generate-config:
stage: build
script: generate-ci-config > generated-config.yml
artifacts:
paths:
- generated-config.yml
child-pipeline:
stage: test
trigger:
include:
- artifact: generated-config.yml
job: generate-config
# 4、使用来自另一个项目的文件触发子管道
child-pipeline:
trigger:
include:
- project: 'my-group/my-pipeline-library'
ref: 'main'
file: '/path/to/child-pipeline.yml'

trigger:strategy

默认情况下,一旦创建了下游管道,触发器作业就会以成功状态完成。

使用strategy:depend强制trigger作业等待下游(多项目或父子)管道完成。此设置使trigger作业以running状态等待,知道触发管道完成。此时,trigger作业完成并与下游作业展示相同的状态。

此设置可以帮助您保持管道执行的线性。

通过调用API触发管道

要强制重新构建特定的branchtagcomnit,可以使用trigger token的调用API。更多信息请查看

interruptible

自动取消旧的流水线

interruptible:true表示如果一个正在运行的作业因新的管道运行而变得冗余时,则中断正在运行的作业,去运行新的管道。默认:false(不可中断)。

1
2
3
4
5
6
step-1:
stage: test
script:
# 休眠 120s,可测试中断特性
- sleep 120
interruptible: true

resource_group

安全部署,一个分支只有一个管道在执行。只有前面的管道执行完成了,才会执行新的管道作业。

release

  • 本文作者: forever杨
  • 本文链接: https://blog.yl-online.top/posts/9c6b8737.html
  • 版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。如果文章内容对你有用,请记录到你的笔记中。本博客站点随时会停止服务,请不要收藏、转载!