如何安装 runner?

案例使用的都是 docker 部署,gitlab 使用的是gitlab/gitlab-ce:12.10.14-ce.0所以安装使用的gitlab runner版本是gitlab/gitlab-runner:v12.10.3

查看信息

先在 gitlab 上查看添加 runner 时需要配置的 token(版本不一样,查看位置也会不同)。
image-1662968892463

注册

  1. 运行gitlab-runner register命令进行注册
gitlab-runner register
  1. 输入 gitlab 的 url 地址:
Please enter the gitlab-ci coordinator URL (e.g. https://gitlab.com/):
http://192.168.1.xxxxx/
  1. 输入注册的 token:
Please enter the gitlab-ci token for this runner:
pnsBhDZy_iYH_xxxxxx
  1. 输入对这个Runner的表述(同时也是这个Runner的名字),可以在GitLab page上修改它:
Please enter the gitlab-ci description for this runner:
[96b8ba5db706]: test_runner
  1. 输入Runner的tag,同样可以在GitLab page上修改它:
Please enter the gitlab-ci tags for this runner (comma separated):
test 
  1. 输入Runner的executor:
Please enter the executor: ssh, kubernetes, shell, docker, docker-ssh, parallels, virtualbox, docker+machine, docker-ssh+machine, custom:
docker
  1. 这里选择 docker 那么还需要选择默认的docker image来运行job(可以在.gitlab-ci.yml里修改你需要用的image):
Please enter the default Docker image (e.g. ruby:2.6):
docker:19.03.13

注册完成后,生成 /etc/gitlab-runner/config.toml 文件,该文件是Runner的配置文件.
文件内容如下:

concurrent = 1
check_interval = 0

[session_server]
  session_timeout = 1800

[[runners]]
  name = "test_runner"
  url = "http://192.168.xxxxxxx/"
  token = "jcFVsWbpovxxxxxxxx"
  executor = "docker"
  [runners.custom_build_dir]
  [runners.cache]
    [runners.cache.s3]
    [runners.cache.gcs]
  [runners.docker]
    tls_verify = false
    image = "docker:19.03.13"
    privileged = false
    disable_entrypoint_overwrite = false
    oom_kill_disable = false
    disable_cache = false
    volumes = ["/cache"]
    shm_size = 0

在 gitlab 上查看可以看到刚刚添加的runner信息。
image-1662968910037
至此,runner 就添加完成。
在容器中执行gitlab-runner list 可以看到保存在配置文件中的所有运行程序

root@gitlab-runner:/# gitlab-runner list
Runtime platform                                    arch=amd64 os=linux pid=33 revision=2910048c version=12.10.3
Listing configured runners                          ConfigFile=/etc/gitlab-runner/config.toml
gitlab-runner                                       Executor=docker Token=tGeDQLKwL6********* URL=http://192.168.1.***:*****/

runner 常用命令如下:

gitlab-runner register  #默认交互模式下使用,非交互模式添加 --non-interactive
gitlab-runner list      #此命令列出了保存在配置文件中的所有运行程序
gitlab-runner verify    #此命令检查注册的runner是否可以连接,但不验证GitLab服务是否正在使用runner。 --delete 删除
gitlab-runner unregister   #该命令使用GitLab取消已注册的runner。
 
#使用令牌注销
gitlab-runner unregister --url http://gitlab.example.com/ --token t0k3n
 
#使用名称注销(同名删除第一个)
gitlab-runner unregister --name test-runner
 
#注销所有
gitlab-runner unregister --all-runners

如何配置 runner?

配置 runner,可以通过修改 config.toml 文件。文件更改时不需要重启服务,每隔三秒GitLab Runner 会检查配置修改,并重新加载。

全局配置

配置项 描述
concurrent 限制可以同时运行的作业数量。如果concurrent值为1并且有一个worker已经在工作了,那么即使其他worker达到了可以工作的条件也只能“pending”。
log_level 日志级别
log_format 日志格式
check_interval 检查新作业的间隔长度,默认为3秒。如果有多个
sentry_dsn 启用Sentry错误跟踪
listen_address http服务监听地址

关于check_interval 作用的解释:
如果 config.toml 中存在多个 [[runners]],则对 GitLab 的请求的间隔会比较频繁。
会将 check_interval 的值除以 [[runners]] 的数量。循环遍历所有,为每个部分安排一个请求,并休眠计算的时间量。
如果您设置 check_interval = 10,并且有两个运行器(runners-1 runners-2),则每 10 秒发出一个请求。以下是这种情况下的循环示例:

  1. 获取 check_interval 值(10s)。
  2. 获取跑步者列表(runner-1、runner-2)。
  3. 计算睡眠间隔(10s / 2 = 5s)。
  4. 开始一个无限循环:
    1. 为 runner-1 申请工作。
    2. 睡5秒。
    3. 为 runner-2 申请工作。
    4. 睡5秒。
    5. 重复。

因此,Runner 进程每 5 秒发出一次请求。如果 runner-1 和 runner-2 连接到同一个 GitLab 实例,这意味着对这个 GitLab 实例的请求也会每 5 秒收到一个来自这个 Runner 的新请求。在第一次对 runner-1 的请求和对 runner-1 的第二次请求之间,有两次睡眠需要 5 秒,所以最后在对 runner-1 的后续请求之间大约有 10 秒。 runner-2 也是如此。如果您定义更多的runner,睡眠间隔会更小,但在调用其他 runner 的所有请求+他们的睡眠后,将重复对 runner 的请求。
参考地址:How check_interval works

[session_server]

配置项 描述
listen_address 会话服务器的内部 URL
advertise_address 访问会话服务器的 URL
session_timeout 作业完成后会话可以保持活动状态的秒数,默认值为1800秒

[[runners]]

每个runners部分定义一个runner服务

配置项 描述
name 描述
url GitLab 实例 URL
token runner的的特殊令牌(不是注册令牌)
tls-ca-file 使用 HTTPS 时验证对等方的证书的文件
tls-cert-file 使用 HTTPS 时与对等方进行身份验证的证书的文件
tls-key-file 使用 HTTPS 时要与对等方进行身份验证的私钥的文件
limit 限制同时处理作业数量,0(默认)表示不限制
executor 选择应如何构建项目
shell 生成脚本的 shell 的名称,默认值取决于平台。
builds_dir 构建存储在所选执行程序上下文中的目录的绝对路径。例如,本地、Docker 或 SSH。
cache_dir 构建缓存存储在所选执行程序上下文中的目录的绝对路径。例如,本地、Docker 或 SSH。如果使用dockerexecutor,则需要在其volumes参数中包含该目录
environment 追加或覆盖环境变量。
request_concurrency 限制来自 GitLab 的新作业的并发请求数,默认为1
output_limit 最大构建日志大小,默认值为4096(4MB)
pre_clone_script 在克隆 Git 存储库之前执行的命令
pre_build_script 在克隆 Git 存储库之后但在执行构建之前执行的命令
post_build_script 在执行构建之后执行的命令
clone_url 覆盖 GitLab 实例的 URL
debug_trace_disabled 禁用CI_DEBUG_TRACE特性。当设置为true时,即使用户将CI_DEBUG_TRACE设置为true,调试日志(跟踪)也将保持禁用状态
referees 将结果作为工作工件传递给 GitLab

例子:

[[runners]]
  name = "ruby-2.6-docker"
  url = "https://CI/"
  token = "TOKEN"
  limit = 0
  executor = "docker"
  builds_dir = ""
  shell = ""
  environment = ["ENV=value", "LC_ALL=en_US.UTF-8"]
  clone_url = "http://gitlab.example.local"

tips: 如果想一些固定的变量,比如 registry 仓库地址,可以通过一个变量的形式传递到这个 environment 变量里面,比如 environment = ["CI_REGISTRY=registry.aliyuncs.com"]

executors

executors 简单的解释就是:executors 决定了 runner 用什么方式在什么环境上完成 gitlab 给下来的CI Job。一个觉得挺不错的解释地址:GitLab CI 之 Runner 的 Executor 該如何選擇?

执行者 所需配置 作业运行
shell 默认执行器
docker [runners.docker] and Docker Engine docker容器
docker-windows [runners.docker] and Docker Engine Windows Docker 容器
docker-ssh [runners.docker], [runners.ssh], 和Docker 引擎 Docker 容器,使用 SSH 连接
ssh [runners.ssh] 远程SSH
parallels [runners.parallels] 和 [runners.ssh] Parallels VM,使用 SSH 连接
virtualbox [runners.virtualbox] 和 [runners.ssh] VirtualBox VM,但使用 SSH 连接
docker+machine [runners.docker] 和 [runners.machine] 类似docker,但使用自动缩放的 Docker 机器
docker-ssh+machine [runners.docker] 和 [runners.machine] 类似docker-ssh,但使用自动缩放的 Docker 机器
kubernetes [runners.kubernetes] Kubernetes pods

[runners.custom_build_dir]

设置自定义构建目录参数,如果没有明确配置,对于kubernetes、docker、docker-ssh、docker+machine和docker-ssh+machine执行器将被默认启用。对于所有其他的执行器,它将被默认为禁用。更多细节可以在[runners.custom_build_dir]文档中找到。

参数 类型 描述
enabled 布尔值 允许用户为JOB定义自定义构建目录

[runners.cache]

这定义了分布式缓存功能。更多细节可以在runners autoscale文档中找到。

参数 类型 描述
Type 字符串 s3 和 gcs 两者其中之一。
Path 字符串 附加到缓存 URL 的路径的名称。
Shared 布尔值 启用 runner 之间的缓存共享,默认为 false。

[runners.docker]

定义了 Docker 容器参数

配置项 描述
allowed_images 可以在.gitlab-ci.yml文件中指定的镜像的通配符列表;如果不存在,则允许所有镜像(相当于[“*/ *: *”])
allowed_services 可以在.gitlab-ci.yml文件中指定的服务的通配符列表;如果不存在,则允许所有镜像(相当于[“*/ *: *”])
cache_dir 缓存目录,此路径可以是绝对路径,也可以是路径
cap_add 向容器添加额外的 Linux 功能
cap_drop 从容器中删除其他 Linux 功能
cpuset_cpus 对照组的CpusetCpus
cpu_shares 用于设置相对 CPU 使用率的 CPU 份额数,默认为1024
cpus CPU 数量(在 Docker 1.13 或更高版本中可用)
devices 与容器共享其他主机设备
disable_cache Docker 执行器有两个级别的缓存:全局缓存和基于 Docker 卷的本地缓存,此配置标志仅作用于禁用自动创建(未映射到主机目录)缓存卷的本地配置标志
disable_entrypoint_overwrite 禁用镜像覆盖entrypoint
dns 供容器使用的 DNS 服务器列表
dns_search DNS 搜索域列表
extra_hosts 应该在容器环境中定义的主机
gpus Docker 容器的 GPU 设备使用与dockercli相同的格式查看Docker 文档中的详细信息
helper_image (高级)用于克隆存储库和上传工件的默认帮助程序镜像
host 自定义 Docker 端点默认为DOCKER_HOST环境或unix:///var/run/docker.sock.
hostname Docker 容器的自定义主机名
image 用于运行作业的镜像(也可以在.gitlab-ci.yml里指明你需要用的image)
links 应与运行作业的容器链接的容器
memory 内存限制
memory_swap 总内存限制
memory_reservation 内存软限制
network_mode 将容器添加到自定义网络
oom_kill_disable 如果发生内存不足 (OOM) 错误,不终止容器中的进程
oom_score_adjust OOM 分数调整阳性意味着更早杀死
privileged 使容器以特权模式运行不安全
pull_policy 镜像拉取策略:never,if-not-present或always(默认)查看拉取策略文档中的详细信息您还可以添加多个拉取策略
runtime Docker 容器的运行时
security_opt 安全选项(–security-opt in docker run)获取:分隔键/值的列表
shm_size 镜像的共享内存大小(以字节为单位)
sysctls sysctl选项
tls_cert_path 存储 ca.pem、cert.pem 或 key.pem 的目录,用于与 Docker 建立安全的 TLS 连接。在 boot2docker 中很有用。
tls_verify 启用或禁用对 Docker 守护程序连接的 TLS 验证,默认禁用
userns_mode 启用用户命名空间重新映射选项时,容器和 Docker 服务的用户命名空间模式,在 Docker 1.10 或更高版本中可用
volumes 安装挂载卷与 Docker -v标志的语法相同
volumes_from 从另一个容器继承挂载卷,访问级别默认为读写,但可以手动设置为ro(只读)或rw(读写)
volume_driver 用于容器的挂载卷驱动程序
wait_for_services_timeout 等待 Docker 服务的时间设置0为禁用默认为30

例子:

[runners.docker]
  host = ""
  hostname = ""
  tls_cert_path = "/Users/ayufan/.boot2docker/certs"
  image = "ruby:2.6"
  memory = "128m"
  memory_swap = "256m"
  memory_reservation = "64m"
  oom_kill_disable = false
  cpuset_cpus = "0,1"
  cpus = "2"
  dns = ["8.8.8.8"]
  dns_search = [""]
  privileged = false
  userns_mode = "host"
  cap_add = ["NET_ADMIN"]
  cap_drop = ["DAC_OVERRIDE"]
  devices = ["/dev/net/tun"]
  disable_cache = false
  wait_for_services_timeout = 30
  cache_dir = ""
  volumes = ["/data", "/home/project/cache"]
  extra_hosts = ["other-host:127.0.0.1"]
  shm_size = 300000
  volumes_from = ["storage_container:ro"]
  links = ["mysql_container:mysql"]
  allowed_images = ["ruby:*", "python:*", "php:*"]
  allowed_services = ["postgres:9", "redis:*", "mysql:*"]
  [[runners.docker.services]]
    name = "mysql"
    alias = "db"
  [[runners.docker.services]]
    name = "redis:2.8"
    alias = "cache"
  [[runners.docker.services]]
    name = "postgres:9"
    alias = "postgres-db"
  [runners.docker.sysctls]
    "net.ipv4.ip_forward" = "1"

当我的Runner采用docker作为executor时,无法build docker image
这是个“dind(docker in docker)” 问题,一般pipeline会报如下错误:

Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?
time="2018-12-17T11:12:33Z" level=error msg="failed to dial gRPC: cannot connect to the Docker daemon. Is 'docker daemon' running on this host?: dial unix

有两种解决办法:
第一种解决办法:将本地的docker socket绑定到container里来解决这个问题,具体方法是将volumes = ["/var/run/docker.sock:/var/run/docker.sock"]配置增加到config.toml文件的[runners.docker]里。
第二种解决办法:.gitlab-ci.yml文件中增加如下设置

services:
    - docker:dind

Docker Executor:

所有jobs的执行环境为指定的docker image所生成的container,每个job都会生成一个container并且在job结束后立即销毁。这个说的就是config.toml文件和.gitlab-ci.yml中指定的image。
Docker executor默认将所有的builds存储在/builds/(这里的路径是container里的路径,Runner配置文件config.toml里的build_dir字段可以重新指明build的目录,默认对应于宿主机的目录是在宿主机的docker volume下:/var/lib/docker/volumes/_data/),默认将所有的caches存储在container里的/cache目录(config.toml里的cache_dir字段可以重新指明cache的目录),注意build_dir和cache_dir指向的均是container里的目录,要想将container里的数据持久化,需要用到volumes字段,这个字段的使用和docker volume的使用是类似的,只需在config.toml的[runner.docker]部分添加volumes = [“/cache”, “:rw”]即可实现container里/cache目录数据的永久保存以及将host目录挂载到相应的container目录并具有读写的功能。

参考地址:

https://www.cnblogs.com/sanduzxcvbnm/p/14681532.html
https://www.jianshu.com/p/19fe0ce7ecec
https://docs.gitlab.com/12.10/runner/configuration/advanced-configuration.html


如何使用runner?

.gitlab-ci.yml 用来配置 CI 用你的项目中做哪些操作,这个文件位于仓库的根目录。

当有新内容 push 到仓库,或者有代码合并后, GitLab 会查找是否有 .gitlab-ci.yml 文件,如果文件存在, Runners 将会根据该文件的内容开始 build 本次 commit 。

.gitlab-ci.yml 使用 YAML 语法, 你需要格外注意缩进格式,要用空格来缩进,不能用 tabs 来缩进。
原文档

Job

YAML 文件定义了一系列带有约束说明的 job, job 至少需要要包含 script:

示例:

job1:
  script: "execute-script-for-job1"

job2:
  script: "execute-script-for-job2"

上面这个例子是一个最简单且带有两个 job 的 CI 配置,每个任务分别执行不同的命令。
script 可以直接执行系统命令 (如:./configure;make;make install) 或者直接执行脚本 (test.sh)。
任务是由 CI 接管并且在服务器执行,并且每一个任务的执行都是独立的。
job 的名称具有唯一性在文件中只能出现一次,并且下列词汇被保留不能被使用:

  • image
  • services
  • stages
  • types
  • before_script
  • after_script
  • variables
  • cache
  • include

job 可以配置的参数列表

关键字 描述
script 定义Runner需要执行的脚本或命令
image 需要使用的docker镜像
services 定义了所需的docker服务
before_script 定义在每个job之前运行的命令
after_script 定义在每个job之后运行的命令
stages 定义哪些stage可以被job调用的,相同stage的job可以平行执行,下一个stage的job会在前一个stage的job成功后开始执行。
stage 定义当前 job 运行的阶段名字 (默认: test)
only 定义了job需要执行的所在分支或者标签
except 定义了job不会执行的所在分支或者标签
rules 评估和确定作业的选定属性以及是否创建的条件列表。不能与 only/except 一起使用。
tags 定义了哪些runner适用该job
allow_failure 允许任务失败,但是如果失败,将不会改变提交状态
when 定义 job 在什么时候运行。
environment 用于定义作业部署到特定环境。如果指定了 environment 并且不存在该名称下的环境,则会自动创建一个新环境。
cache 在后续运行之间应该被缓存的文件列表。
artifacts 用于指定一个文件和目录的列表,当作业成功、失败或总是成功时,这些文件和目录应该被附加到作业中。工作完成后,工件将被发送到GitLab,并可在GitLab用户界面上下载。
dependencies 通过提供一个作业列表来限制哪些工件被传递给一个特定的作业,以便从中获取工件。
coverage 可以从作业的输出log中提取代码覆盖率。
retry 当一个作业发生失败时,何时以及有多少次可以自动重试。
timeout 定义一个自定义的作业级超时,它优先于整个项目的设置。
parallel 并行允许您配置并行运行的作业实例数。
trigger 定义下游流水线的触发器。
include 允许此作业包括外部YAML文件。
extends 这个工作要继承的配置条目。
pages 上传GitLab Pages的结果。
variables 定义环境变量。
interruptible 表明该任务是否能够被新的流水线打断,取消。默认为false, 即不可取消,不可被打断。
resource_group 限制工作的并发性,一个环境中同时运行多个作业或管道会导致部署过程中出现错误。

script

script 是作业中唯一必须的关键字参数,是运行器需要执行的脚本,如:

build1:
  script:
    - echo "Do your build here"
    - uname -a

表示build1作业需要执行的命令是输出”Do your build here”。
有时候,script命令需要被单引号或者是双引号包裹起来。举个例子,当命令中包含冒号(:)时,script需要被包在双引号中,这样YAML解析器才可以正确解析为一个字符串而不是一个键值对(key:value)。使用这些特殊字符的时候一定要注意::,{,},[,],&,*,#,?,|,-,<,>,=,!。

image and services

这两个关键字允许使用一个自定义的 Docker 镜像和一系列的服务,并且可以用于整个 job 周期。

  • Image指定了该阶段使用的基础镜像,该镜像为本地手动提前创建并推送;
  • services指定了该阶段依赖使用的服务,比如mongo和redis,该job运行时会初始化指定服务版本的容器,并分别暴露域名为mongo:27017、redis:6379,需要在配置文件中提前配置好CI专用的配置文件供后续使用。

before_script and after_script

before_script 用于定义在所有作业之前需要执行的命令,比如更新代码、安装依赖、打印调试信息之类的事情。job 类型会覆盖掉 global 类型的值
after_script 用于定义在所有作业(即使失败)之后需要执行的命令,比如清空工作空间。job 类型会覆盖掉 global 类型的值

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

stages

stages 定义流水线全局可使用的阶段,阶段允许有灵活的多级管道,阶段元素的排序定义了作业执行的顺序。

  • 相同 stage 的job并行运行。
  • 默认情况下,上一阶段的作业全部运行成功后才执行下一阶段的作业。
  • 默认有三个阶段, build 、test 、deploy 三个阶段,即 构建 、测试 、部署 。
  • 如果一个作业未定义 stage 阶段,则作业使用 test 测试阶段。
  • 默认情况下,任何一个前置的作业失败了,commit提交会标记为failed并且下一个stages的作业都不会执行。

示例:

stages:
  - build
  - test
  - deploy

运行顺序:

  1. 运行所有的 build 。
  2. 如果所有作业都 build 运行成功,那么开始运行所有的 test。
  3. 如果所有作业都 test 运行成功,那么开始运行所有的 deploy。
  4. 如果所有作业都 deploy 成功,则标记 job 为 passed 。
  5. 如果在之前动作中有任何失败,则标记 job 为 failed 并终止 job 执行。
    没有定义时的默认动作:
  6. 如果 .gitlab-ci.yml 文件中没有定义 stages , stages 将会被设置成 build -> test -> deploy.
  7. 如果 job 没有定义 stage, 则 job 的 stage 将会被设置成 test

stage

stage 的值必须定义在 stages 中,可以通过设置 stage 来对 job 进行分组,相同分组的 job 将会并行执行。

stages:
  - build
  - test
  - deploy

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

only 和 except

only 和 except 用于在创建作业时对作业的限制策略。

  • only 定义了哪些分支或标签(branches and tags)的作业会运行

  • except 定义了哪些分支或标签(branches and tags)的作业不会运行
    下面是策略规则:

  • only 和 except 可同时使用,如果在一个作业中同时定义了 only 和 except ,则同时 only except 进行过滤(注意,不是忽略 except 条件) 。

  • only 和 except 可以使用正则表达式。

  • only 和 except 允许指定用于过滤forks作业的存储库路径。

  • only 和 except 中可以使用特殊的关键字,如 branches 、 tags 、 api 、 external 、 pipelines 、 pushes 、 schedules 、 triggers 、 web 、 merge_requests 、 chats 等。

tags

tags可以从允许运行此项目的所有Runners中选择特定的Runners来执行jobs。
在注册Runner的过程中,我们可以设置Runner的标签,比如ruby,postgres,development。
tags可通过tags来指定特殊的Runners来运行jobs:

job:
  tags:
    - ruby
    - postgres

上面这个示例中,需要确保构建此job的Runner必须定义了ruby和postgres这两个tags。

allow_failure

允许 job 失败. job 失败不会影响最终结果
设置 allow_failure 的 job 失败后不会中断 CI 的执行,当你希望一个 job 执行失败之后 CI 仍要继续执行时可以设置这个值为 true 。
如果你设置了 allow_failure 并且 job 执行失败, 这时候 CI 会显示执行成功但是会出现一个警告信息。警告信息用来提示有一个允许失败的任务执行失败。(管理人员可能会执行其他措施。)
下面这个例子中, 当 job1 运行失败, 也不会打断 CI 执行,CI 会继续运行下一阶段,因为它设置了 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 可以设置以下值:

  • on_success :只有前面的阶段的所有作业都成功时才执行,这是默认值。
  • on_failure :当前面阶段的作业至少有一个失败时才执行。
  • always : 无论前面的作业是否成功,一直执行本作业。
  • manual :手动执行作业,作业不会自动执行,需要人工手动点击启动作业。
  • delayed : 延迟执行作业,配合 start_in 关键字一起作用, start_in 设置的值必须小于或等于1小时,start_in 设置的值示例: 10 seconds 、 30 minutes 、 1 hour ,前面的作业结束时计时器马上开始计时。
    示例:
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

示例的执行方式:

  1. cleanup_build_job 只有在 build_job 失败时才会执行.
  2. 不论其他 job 是否执行成功, cleanup_job 总会在最后一个被执行.
  3. 可以通过 Gitlab 控制台手动执行 deploy_job.

environment

environment 用于定义作业部署到特殊的环境中。如果指定了 environment ,并且在该环境列表中没有该名称下的环境,则会自动创建新环境。
在最简单的格式中,环境关键字可以定义为:

deploy to production:
  stage: deploy
  script: git push production HEAD:master
  environment:
    name: production

在上面这个例子中,deploy_to_production作业将会执行部署操作部署到production环境。

environment:name

GitLab 8.11 开始引入。
在GitLab8.11之前,环境名称定义为environment:production。现在推荐的做法是定义为name关键字。

environment 可以设置为:

  • letters(字母)
  • digits(数字)
  • spaces(空格)
  • _
  • /
  • $
  • {
  • }

常用的名称有qa(验证),staging(模拟环境),和production(生产环境),当然你可以在你的工作流中使用任意名字,比如:development(开发环境)、integration(集成环境)

environment:url

这是设置一个可选值,它会显示在按钮中,点击它可以带你到设置的URL页面。

在下面这个例子中,如果job都成功完成了,在environment/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 and environment:action

environment:on_stop 与 environment:action 配合使用。
可以通过 environment:on_stop 关键字定义一个关闭(停止)环境的作业。
action 关键字在关闭环境的作业中定义。

举个例子:

review_app:
  stage: deploy
  script: make deploy-app
  environment:
    name: review
    on_stop: stop_review_app

stop_review_app:
  stage: deploy
  script: make delete-app
  when: manual
  environment:
    name: review
    action: stop

在上面的示例中,设置 review_app 作业用于部署代码到 review 评审环境中,同时在 on_stop 中指定了 stop_review_app 作业。
一旦 review_app 作业成功执行,它将根据 when 下定义的内容触发 stop_review_app 作业。我们把它设置为手动,所以它需要通过GitLab的web界面进行手动操作才能运行。

stop_review_app 作业必须配合定义以下关键字:

  • when : 何时执行删除或停止环境作业
  • environment:name : 环境名称需要与上面的 review_app 作业保持一致,即 review 评审环境
  • environment:action :执行何种执行,stop 停止环境
  • stage :与 review_app 作业的阶段保持一致,都是 deploy

运行完成后,在 stop_review_app 作业界面需要手动点击 停止当前环境 才能启动 stop_review_app 作业的执行。 stop_review_app 作业执行完成后,会停止 review 评审环境,在 环境 –> 已停止 列表中可以看到 review 评审环境。

environment:auto_stop_in

auto_stop_in 关键字用于指定环境的生命周期,当过期时,GitLab 会自动停止它们。
示例:

review_app:
  script: deploy-review-app
  environment:
    name: review/$CI_COMMIT_REF_NAME
    auto_stop_in: 1 day

当review_app工作被执行并创建了一个审查应用程序,环境的生命期被设置为1天。

environment:kubernetes

kubernetes块用于配置部署到与你的项目相关的Kubernetes集群。

deploy:
  stage: deploy
  script: make deploy-app
  environment:
    name: production
    kubernetes:
      namespace: production

这将设置部署作业,以便使用生产的Kubernetes命名空间部署到生产环境。

Dynamic environments

environment也可以是代表配置项,其中包含name和url。这些参数可以使用任何的CI variables(包括预定义、安全变量和.gitlab-ci.yml中的变量)。

举个例子:

deploy as review app:
  stage: deploy
  script: make deploy
  environment:
    name: review/$CI_COMMIT_REF_NAME
    url: https://$CI_ENVIRONMENT_SLUG.example.com/

当$CI_COMMIT_REF_NAME 被Runner设置为environment variable时,deply as review appjob将会被指定部署到动态创建revuew/$CI_COMMIT_REF_NAME的环境中。$CI_ENVIRONMENT_SLUG变量是基于环境名称的,最终组合成完整的URLs。在这种情况下,如果deploy as review appjob是运行在名称为pow的分支下,那么可以通过https"//review-pw.example.com/来访问这个环境。

这当然意味着托管应用程序的底层服务器已经正确配置。

cache

GitLab Runner v0.7.0 引入 cache 缓存机制。
cache 缓存机制,可以在全局设置或者每个作业中设置。
从 GitLab 9.0 开始, cache 缓存机制,可以在不同的的流水线或作业之间共享数据。
从 GitLab 9.2 开始, 在 artifacts 工件之前恢复缓存。

cache用来指定一个文件和目录的列表,这些文件和目录在作业之间被缓存。仅能使用项目工作空间中的路径作为缓存的路径。
如果cache是在作业范围之外定义的,这意味着它是全局设置的,所有作业都会使用这个定义。

cache:paths

缓存二进制文件中以.apk结尾的所有文件和.config文件。

rspec:
  script: test
  cache:
    paths:
    - binaries/*.apk
    - .config

cache:key

key指令允许我们定义缓存的作用域(亲和性),可以是所有jobs的单个缓存,也可以是每个job,也可以是每个分支或者是任何你认为合适的地方。
例如,要启用每个分支缓存:

cache:
  key: "$CI_COMMIT_REF_SLUG"
  paths:
    - binaries/
cache:key :files
cache: key:prefix

artifacts

用于指定一个文件和目录的列表,当作业成功、失败或总是成功时,这些文件和目录应该被附加到作业中。工作完成后,工件将被发送到GitLab,并可在GitLab用户界面上下载。

artifacts:paths

用于指定哪些文件或文件夹会被打包成工件,仅仅项目工作空间的路径可以使用。
下面示例,将目录 binaries/ 和文件 .config 打包成工件:

artifacts:
  paths:
    - binaries/
    - .config

要禁用工件传递,请使用空依赖关系定义作业:

job:
  stage: build
  script: make build
  dependencies: []

你可以仅为打标记的release发布版本创建工作,这样可以避免临时构建产生大量的存储需求:

default-job:
  script:
    - mvn test -U
  except:
    - tags

release-job:
  script:
    - mvn package -U
  artifacts:
    paths:
      - target/*.war
  only:
    - tags

上面的示例中,default-job 作业不会在打标记的release发布版本中执行,而 release-job 只会在打标记的release发布版本执行,并且将 target/*.war 打包成工件以供下载。

artifacts:expose_as

定义展示包的名称
expose_as关键字可用于在合并请求用户界面中公开作业工件。

test:
  script: [ 'echo 1' ]
  artifacts:
    expose_as: 'artifact 1'
    paths: ['path/to/file.txt']

使用此配置,GitLab 会将链接artifact 1 添加到指向 file1.txt 的相关合并请求中。

匹配整个目录:

test:
  script: [ 'echo 1' ]
  artifacts:
    expose_as: 'artifact 1'
    paths: ['path/to/directory/']

请注意以下事项:

  • 每个合并请求最多可以公开 10 个作业工件。
  • 不支持全局模式。
  • 如果指定了一个目录,如果目录中有多个文件,则链接将指向作业工件浏览器。
  • 对于具有 .html、.htm、.txt、.json、.xml 和 .log 扩展名的公开单个文件工件,如果 GitLab Pages 是:
    • 启用后,GitLab 将自动渲染工件。
    • 未启用,您将在工件浏览器中看到该文件

artifacts:name

  • 工件的默认名称是 artifacts ,当下载时名称是 artifacts.zip 。
  • 通过 artifacts:name 关键字可以自定义工件的归档名称,这样你可以为每个工件设置独一无二的名称,归档名称可以使用预定义的变量。
  • 如果分支名称中包含斜杠(比如 feature/my-feature ),推荐使用 $CI_COMMIT_REF_SLUG 代替 $CI_COMMIT_REF_NAME 作为工件名称。

使用作业名称使用工件名称:

job:
  artifacts:
    name: "$CI_JOB_NAME"
    paths:
      - binaries/

使用当前分支或tag版本标签名作为工件名称:

job:
  artifacts:
    name: "$CI_COMMIT_REF_NAME"
    paths:
      - binaries/

同时使用当前作业名称以及当前分支或tag版本标签名作为工件名称:

job:
  artifacts:
    name: "$CI_JOB_NAME-$CI_COMMIT_REF_NAME"
    paths:
      - binaries/

同时使用当前作业阶段名称以及当前分支名称作为工件名称:

job:
  artifacts:
    name: "$CI_JOB_STAGE-$CI_COMMIT_REF_NAME"
    paths:
      - binaries/

如果你使用的 Windows系统的Batch批处理脚本 ,则需要把 $ 替换成 %:

job:
  artifacts:
    name: "%CI_JOB_STAGE%-%CI_COMMIT_REF_NAME%"
    paths:
      - binaries/

如果你使用的 Windows系统的PowerShell脚本 ,则需要把 $ 替换成 $env::

job:
  artifacts:
    name: "$env:CI_JOB_STAGE-$env:CI_COMMIT_REF_NAME"
    paths:
      - binaries/

artifacts:untracked

  • artifacts:untracked 用于将git未加入版本库的文件作为工件文件。
  • artifacts:untracked 将会忽略配置文件 .gitignore。
    将所有的未跟踪文件打包成工件:
artifacts:
  untracked: true

将所有的未跟踪文件以及目录 binaries 中文件打包成工件:

artifacts:
  untracked: true
  paths:
    - binaries/

artifacts:when

  • artifacts:when 用于在作业失败时或者忽略失败时上传工件。

artifacts:when 可以设置以下值:

  • on_success ,默认值,当作业成功上传工件。
  • on_failure ,当作业失败上传工件。
  • always ,无论作业是否成功一直上传工件。
    当作业失败时,上传工件:
job:
  artifacts:
    when: on_failure

artifacts:expire_in

  • artifacts:expire_in 用于设置工件的过期时间。
  • 你可以点击界面上的 Keep 保持按钮,永久保存工件。
  • 工件到期后,默认情况下每小时删除一次工件(通过cron作业),并且后续不能再访问该工件。
  • 工件默认有效期是30天,可以通过 Admin area –> Settings –> Continuous Integration and Deployment 设置默认的有效性时间。
  • 如果你不提供时间单位的话,工作有效性的时间是以秒为单位的时间,下面是一些示例:
  • ‘42’
  • ‘3 mins 4 sec’
  • ‘2 hrs 20 min’
  • ‘2h20min’
  • ‘6 mos 1 day’
  • ‘47 yrs 6 mos and 4d’
  • ‘3 weeks and 2 days’
    下面示例中工件有效期为一周:
job:
  artifacts:
    expire_in: 1 week

artifacts:reports

  • artifacts:reports 用于收集测试报告(report),并在GitLab UI界面中显示出来。
  • 无论作业是否成功,都会收集测试报告。
  • 可以通过设置工件的打包路径 artifacts:paths 添加测试的报告输出文件。
  • artifacts:reports:junit 可以用来收集单元测试的报告,查看 JUnit test reports 获取更详细的信息和示例。
    下面是从Ruby的RSpec测试工具中收集JUnit XML文件的示例:
rspec:
  stage: test
  script:
  - bundle install
  - rspec --format RspecJunitFormatter --out rspec.xml
  artifacts:
    reports:
      junit: rspec.xml

如果你的测试报告是多个XML文件,你可以在一个作业中指定多个单元测试报告,GitLab会自动将他们转换成一个文件,可以像下面这样表示报告的路径:
文件匹配模式: junit: rspec-.xml
文件列表: junit: [rspec-1.xml, rspec-2.xml, rspec-3.xml]
混合模式:junit: [rspec.xml, test-results/TEST-
.xml]

coverage

coverage 可以从作业的输出log中提取代码覆盖率。
仅支持正则表达式方式获取覆盖率。
字符串的前后必须使用/包含来表明一个正确的正则表达式规则。特殊字符串需要转义。
下面是一个简单的例子:

job1:
  coverage: '/Code coverage:\d+\.\d+%/'

如在作业日志中输出了”Code coverage:80.2%”,我们使用上面的正则表达式就可以获取到代码的覆盖率。然后在作业的右上角处就会显示 Coverage:80.2% 。

retry

当一个作业发生失败时,何时以及有多少次可以自动重试。

  • retry 重试关键字用于配置当作业失败时可以重新执行的次数。
  • 当作业失败时,如果配置了 retry ,那么该作业就会重试,直到允许的最大次数。
  • 如果 retry 设置值为2,如果第一次重试运行成功了,那么就不会进行第二次重试。
  • retry 设置值只能是0、1、2三个整数。

下面是一个简单的例子:

test:
  script: rspec
  retry: 2

为了更好的控制重试次数,retry 可以设置以下两个关键字:

  • max : 最大重试次数
  • when : 何时重试

下面这个例子只有当运行器系统出现故障时才能最多重试两次:

test:
  script: rspec
  retry:
    max: 2
    when: runner_system_failure

如果上面例子中出现的是其他故障,那么作业不会重试。

为了针对多种重试情形,我们可以使用矩阵形式罗列出错误情形,如下示例:

test:
  script: rspec
  retry:
    max: 2
    when:
      - runner_system_failure
      - stuck_or_timeout_failure

when 可以是以下值:

  • always : 一直重试,默认值。
  • unknown_failure :当错误未知时重试。
  • script_failure : 脚本错误时重试。
  • api_failure : API调用错误时重试。
  • stuck_or_timeout_failure : 作业卡住或超时错误时重试。
  • runner_system_failure : 运行器系统错误(如设置工作失败)时重试。
  • missing_dependency_failure : 依赖工件丢失错误时重试。
  • runner_unsupported : 运行器不支持错误时重试。
  • stale_schedule : 如果延迟的工作无法执行,则重试。
  • job_execution_timeout : 如果脚本超过了为作业设置的最大执行时间,则重试。
  • archived_failure : 如果作业被归档,无法运行,则重试。
  • unmet_prerequisites : 如果作业未能完成先决条件任务,则重试。
  • scheduler_failure : 如果调度器未能将作业分配给运行器,则重试。
  • data_integrity_failure : 如果检测到有结构完整性问题,则重试。

timeout

timeout允许你为一个特定的工作配置一个超时。
例子:

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

test:
  script: rspec
  timeout: 3h 30m

作业级超时可以超过项目级超时,但不能超过Runner特定的超时。

parallel

并行允许您配置并行运行的作业实例数。该值必须大于或等于2 且小于或等于 50。
这将创建同一作业的N个并行运行的实例。它们按顺序从 job_name 1/N 命名到 job_name N/N。
对于每个作业,CI_NODE_INDEX 和 CI_NODE_TOTAL 环境变量被设置。
标记一个作业为并行运行需要在你的配置文件中添加并行。例如。

test:
  script: rspec
  parallel: 5

trigger

trigger 是应对那些更加复杂的CICD流程,如多流水线,父子流水线 使用它可以定义一个下游的流水线,配置了trigger的任务是不能跑脚本的,就是说不能定义script, before_script, 和 after_script. 项目这个是一个多项目流水线

rspec:
  stage: test
  script: bundle exec rspec

staging:
  stage: deploy
  trigger: my/deployment

流水线执行完test任务后就会去执行my/deployment项目的流水线

配置下游流水线式也可以执行分支

rspec:
  stage: test
  script: bundle exec rspec

staging:
  stage: deploy
  trigger:
    project: my/deployment
    branch: stablez

include

使用include关键字,你可以允许包含外部YAML文件。include要求外部YAML文件的扩展名是.yml或.yaml,否则外部文件将不会被包含。
include中定义的文件是。

  • 与.gitlab-ci.yml中的文件进行深度合并。
  • 总是先评估并与.gitlab-ci.yml中的内容合并,无论include关键字的位置如何

include 支持四种 include 方法:

  • local
  • file
  • template
  • remote

include:local

include:local包括一个与.gitlab-ci.yml相同的存储库的文件。它使用相对于根目录(/)的全路径进行引用。
示例:

include:
  - local: '/templates/.gitlab-ci-template.yml'

include:file

要包含同一GitLab实例下其他私有项目的文件,请使用include:file。这个文件是使用相对于根目录(/)的全路径来引用的。比如:

include:
  - project: 'my-group/my-project'
    file: '/templates/.gitlab-ci-template.yml'

你也可以指定ref,默认是项目的HEAD。

include:
  - project: 'my-group/my-project'
    ref: master
    file: '/templates/.gitlab-ci-template.yml'

  - project: 'my-group/my-project'
    ref: v1.0.0
    file: '/templates/.gitlab-ci-template.yml'

  - project: 'my-group/my-project'
    ref: 787123b47f14b552955ca2786bc9542ae66fee5b # Git SHA
    file: '/templates/.gitlab-ci-template.yml'

include:template

include:template 可用于包含 GitLab 附带的 .gitlab-ci.yml 模板。
示例:

# File sourced from GitLab's template collection
include:
  - template: Auto-DevOps.gitlab-ci.yml

多个include:template文件。

include:
  - template: Android-Fastlane.gitlab-ci.yml
  - template: Auto-DevOps.gitlab-ci.yml

include:remote

include:remote 可用于包含来自不同位置的文件,使用 HTTP/HTTPS,使用完整 URL 引用。远程文件必须可通过简单的 GET 请求公开访问,因为不支持远程 URL 中的身份验证模式。
比如:

include:
  - remote: 'https://gitlab.com/awesome-project/raw/master/.gitlab-ci-template.yml'

extends

extends 扩展用于定义当前作业从哪里继承。
它是使用YAML锚点的替代方案,更加灵活、可读性强。

.tests:
  script: rake test
  stage: test
  only:
    refs:
      - branches

rspec:
  extends: .tests
  script: rake rspec
  only:
    variables:
      - $RSPEC

在上面的例子中,rspec作业继承了.test模板作业。GitLab将根据键值进行反向深度合并。GitLab将:

  • 递归地将rspec的内容合并到.test中。
  • 不合并键的值。
    这会产生以下 rspec 作业:
rspec:
  script: rake rspec
  stage: test
  only:
    refs:
      - branches
    variables:
      - $RSPEC

脚本:rake test 已被脚本:rake rspec 覆盖。

如果您确实想包含 rake 测试,请参阅 before_script 和 after_script。

Using extends and include together

extends 与 include 结合使用跨配置文件。
例如,如果您有一个本地 included.yml 文件:

.template:
  script:
    - echo Hello!

然后,在.gitlab-ci.yml中你可以这样使用它。

include: included.yml

useTemplate:
  image: alpine
  extends: .template

这将运行一个名为useTemplate的作业,运行.template作业中定义的echo Hello!,并使用本地作业中定义的alpine Docker镜像。

pages

pages是一个特殊的作业,用于向GitLab上传静态内容,可以用来为你的网站提供服务。它有一个特殊的语法,所以必须满足以下两个要求。

  • 任何静态内容必须放在public/目录下。
  • 必须定义有通往public/目录的路径的工件。
    下面的例子只是把所有的文件从项目的根部移到public/目录下。.public的变通方法是为了让cp不会在无限循环中把public/复制到自己身上。
pages:
  stage: deploy
  script:
    - mkdir .public
    - cp -r * .public
    - mv .public public
  artifacts:
    paths:
      - public
  only:
    - master

variables

整数(以及字符串)对于变量的名称和值都是合法的。浮点数是不合法的,不能使用。

GitLab CI/CD允许你在.gitlab-ci.yml中定义变量,然后在作业环境中传递。它们可以在全局和每个作业中设置。当变量关键字被用于工作层面时,它将覆盖全局YAML变量和同名的预定义变量。

它们被存储在Git仓库中,旨在存储非敏感的项目配置,例如:

variables:
  DATABASE_URL: "postgres://postgres@postgres/my_database"

这些变量以后可以在所有执行的命令和脚本中使用。YAML 定义的变量也被设置到所有创建的服务容器中,从而可以对它们进行微调。

除了用户定义的变量外,还有一些由Runner本身设置的变量。其中一个例子是CI_COMMIT_REF_NAME,它的值是构建项目的分支或标签名称。除了可以在.gitlab-ci.yml中设置的变量外,还有所谓的变量,可以在GitLab的用户界面中设置。
可用的变量名

interruptible

表明该任务是否能够被新的流水线打断,取消。默认为false, 即不可取消,不可被打断。
当启用时,同一分支上的管道将被取消。

  • 它被一个较新的流水线运行而变得多余了。
  • 要么所有作业都被设置为可中断,要么任何不可中断的作业都没有开始。
    正在进行的作业总是被认为是可中断的。
    一旦一个不可中断的作业正在运行,无论最终作业的状态如何,管道都不会被取消。

将作业设置为可中断的,一旦开始就可以安全地取消的作业(例如,一个构建作业)。

简单例子:

stages:
  - stage1
  - stage2
  - stage3

step-1:
  stage: stage1
  script:
    - echo "Can be canceled."
  interruptible: true

step-2:
  stage: stage2
  script:
    - echo "Can not be canceled."

step-3:
  stage: stage3
  script:
    - echo "Because step-2 can not be canceled, this step will never be canceled, even though set as interruptible."
  interruptible: true

如果仅仅是step-1正在运行或者pending,那么流水线可能会被新流水打断。
但是一旦step-2开始运行后,该流水线就不会再被新的流水线打断。

resource_group

有时在一个环境中同时运行多个作业或管道会导致部署过程中出现错误。
为了避免这些错误,可以使用 resource_group 属性来确保 Runner 不会同时运行某些作业。
当.gitlab-ci.yml中为一个作业定义了resource_group键时,作业的执行在同一项目的不同管道中是相互排斥的。如果属于同一资源组的多个作业同时排队,只有其中一个作业会被Runner选中,其他作业将等待,直到资源_组空闲。
简单例子:

deploy-to-production:
  script: deploy
  resource_group: production

参考地址:
https://meigit.readthedocs.io/en/latest/gitlab_ci_.gitlab-ci.yml_detail.html
https://segmentfault.com/a/1190000010442764
https://blog.csdn.net/JineD/article/details/108742162
https://segmentfault.com/a/1190000011890710
https://ssoor.github.io/2020/03/25/gitlab-ci-config-file/
https://docs.gitlab.com/12.10/ee/ci/yaml/README.html
https://www.hebbao.com/738.html


下一篇gitlab runner 的使用案例中列出了以docker做为runner的使用方法.