Gitlab CI/CD 官方文档学习篇 之 Pipeline Configuration Reference

官网文档:GitLab CI/CD 之 Pipeline Configuration Reference

什么是GitLab CI/CD

GitLab CI/CD is configured by a file called .gitlab-ci.yml placed at the repository’s root. This file creates a pipeline, which runs for changes to the code in the repository. Pipelines consist of one or more stages that run in order and can each contain one or more jobs that run in parallel. These jobs (or scripts) get executed by the GitLab Runner agent.

Concepts/概念

Concepts Description
Pipelines 通过pipeline来构建我们的CI/CD流程
Environment variables 全局变量,定义一些重复使用的变量
Environments 将我们的项目部署到不同的环境当中(开发、测试、正式环境等)
Job artifacts 我们build完项目的jar包、跑完UT得到的report等,都可以放到这里面。以供我们后续的使用
Cache dependencies 将我们下载的资源进行缓存
GitLab Runner 定义我们自己的Gitlab Runner来执行我们的脚本/流程

GitLab CI/CD Pipeline Configuration Reference/GItLab Pipeline配置参考

GitLab CI/CD pipelines是通过每个项目中一个叫做:.gitlab-ci.yml 的文件进行配置的。

Introduction/介绍

Pipeline configuration begins with jobs. Jobs are the most fundamental element of a .gitlab-ci.yml file.

什么是Jobs
  • 定义了在执行时,应该遵守的限制
  • 具有任意名称的顶级元素,并且必须至少包含script子句
  • 没有数量限制
    Jobs是在Runner所处的环境下执行的,并且每个job之间的运行是独立的
例如
job1:
  script: "execute-script-for-job1"

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

不可以用作jobs的名字列表

每一个job必须有唯一的名字,同时一些保留字是不能够用作jobs的名字的

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

配置参数

一个Job定义了一系列的参数来定义job的行为(job里面的参数,而不是job的名字),如下:

Keyword Description
script 用于在Runner中执行的Shell脚本
image 使用docker的镜像,支持的参数:image:name, image:entrypoint
services 使用docker的服务镜像,支持的参数:services:name, services:alias, services:entrypoint, services:commond
before_script 定义一些命令,使得它们在每次执行job之前会执行一遍
after_script 定义一些命令,使得它们在每次执行job之后会执行一遍
stage Defines a job stage (default: test). (不知道应该怎么翻译,看例子可能会更好理解一点)
only jobs执行的限制条件,支持的参数:only:refs, only:kubernetes, only:variables, only:changes
except jobs创建前的限制条件,支持的参数:except:refs, except:kubernetes, except:variables, except:changes
rules 设定一系列的规则,以此来判断是否能够创建/执行这个job,不能够与only / except共用
tags 用来选定使用的是哪一个Runner(一个GitLab中,可以创建多个Runner,有私有的和公共的)
allow_failure 允许这个job执行失败,且不会影响正常的流程
when 什么时候去执行这个job,支持的参数:when:manual, when:delayed
environment 这个job具体部署的环境的名称,支持的参数:environment:name, environment:url, environment:on_stop, environment:auto_stop_in, environment:action
cache 需要被缓存的文件,能够被后续的jobs所引用,支持的参数:environment:name, environment:url, environment:on_stop, environment:auto_stop_in, environment:action
artifacts 当这个job执行成功后,其结果所保存的地方,支持的参数:artifacts:paths, artifacts:expose_as, artifacts:name, artifacts:untracked, artifacts:when, artifacts:expire_in, artifacts:reports, artifacts:reports:junit, artifacts:reports:cobertura, and artifacts:reports:terraform.
dependencies 定义这个job所依赖的job是哪一个,例如:我们先build项目,然后再deploy项目。那么deploy就依赖于build,如果build失败了,那么deploy也不会执行
coverage Code coverage settings for a given job/允许您配置如何从作业输出中提取代码覆盖率(看了具体的说明,也没有很懂具体的作用是什么 (TODO)
retry 设定job失败后,可以重新执行的次数
timeout 定义job执行的超时时间,此优先级比项目中设定的pipelines timeout要高(项目中,pipelines默认的超时时间是1小时。修改路径:Settings > CI/CD > General pipelines settings)
parallel 定义这个job会被多少个线程并行执行
trigger Defines a downstream pipeline trigger(不懂具体的作用(TODO)
include 允许这个job包含其他的YAML文件,支持的参数:include:local, include:file, include:template, and include:remote.
extends 将会继承整个对象job的配置
pages 将job执行的结果,上传到执行的位置
variables 定义job level的变量
interruptible Defines if a job can be canceled when made redundant by a newer run(不懂具体的作用(TODO)
resource_group 限制job的并发执行。(官方进一步解释:在.gitlab-ci中为作业定义resource_group键时。yml中,作业执行在同一项目的不同管道中是互斥的。如果属于同一资源组的多个作业同时进入队列,则运行程序只会选择其中一个作业,而其他作业将一直等待,直到resource_group空闲。)

全局参数

一些参数可以用于全局定义,以达到影响所有jobs的执行

全局默认值

可以使用 default: 关键字将某些参数全局设置为所有jobs的默认值。这种设置,可以在特定的job中被重新定义。
相关的参数有:

  • image
  • services
  • before_script
  • after_script
  • tags
  • cache
  • artifacts
  • retry
  • timeout
  • interruptible

如:
ruby:2.5只会作用于rspec job中,rspec将会使用ruby:2.6

default:
  image: ruby:2.5

rspec:
  script: bundle exec rspec

rspec 2.6:
  image: ruby:2.6
  script: bundle exec rspec

inherit/继承

我们可以使用inherit:参数,在某个job中决定使用/不使用全局定义的variables: & default: 参数

全盘肯定/否定的写法

inherit:
  default: true
  variables: true

inherit:
  default: false
  variables: false

部分肯定/否定的写法:

inherit:
  default: [parameter1, parameter2]
  variables: [VARIABLE1, VARIABLE2]

或者

inherit:
  default:
    - parameter1
    - parameter2
  variables:
    - VARIABLE1
    - VARIABLE2

例子:

# default 定义了image & before_script
default:
  image: 'ruby:2.4'
  before_script:
    - echo Hello World

# variables 定义了DOMAIN & WEBHOOK_URL两个变量
variables:
  DOMAIN: example.com
  WEBHOOK_URL: https://my-webhook.example.com

# rubocop的inherit中,default & variables 都为false,所以将不会用到上面全局定义的变量
rubocop:
  inherit:
    default: false
    variables: false
  script: bundle exec rubocop

# rspec 继承default:image & variables:WEBHOOK_URL两个变量
rspec:
  inherit:
    default: [image]
    variables: [WEBHOOK_URL]
  script: bundle exec rspec

# capybara 继承default定义的所有变量,不会继承variables定义的变量
capybara:
  inherit:
    variables: false
  script: bundle exec capybara

# capybara 继承default定义的所有变量,以及variables的DOMAIN变量,不会继承variables的WEBHOOK_URL变量
karma:
  inherit:
    default: true
    variables: [DOMAIN]
  script: karma

stages

stages中定义了哪些stages可以在jobs中使用
需要注意的是:

  1. 如果jobs用了相同的stage,那么它们将会并行执行
  2. jobs的执行顺序,是根据在stages中编写的顺写而定的
  3. 除非自己定义允许某个job执行失败,否则,顺序执行过程中,某个job失败将会影响后面jobs的执行

例如:

stages:
	- build
	- test
	- deploy

build_project:
	stage: build
	script: build_project

unit_test:
	stage: test
	script: run unit test

int_test:
	stage: test
	script: run int test

deploy_project:
	stage: deploy
	script: deploy project
  1. unit_test & int_test两个job,将并行执行
  2. 整个的执行顺序为:build_project -> (unit_test + int_test) -> deploy_project
  3. 期间,如果build/test失败了,那么deploy就不会执行

rules

定义自己的规则,以此来判断这个job是否执行。
rules 支持定义一些列的判断条件,运行时将会根据顺序做判断,直到找到符合条件的那个。

rules 不能同时和 only/except 一起使用。如果一起使用的话,将会抛出异常:key may not be used with rules

目前支持的配置选项

  • if:定义一个规则,类似于:only:variables
  • when:目前只支持alwaysnever,如果没有设置,则默认为always
  • changes:类似于:only:changes
  • exists

例子:

job:
  script: "echo Hello, Rules!"
  rules:
  	# 假如第一个 if 匹配上的话,这个stage就always执行
    - if: '$CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "master"'
      when: always
    # 如果第一个 if 条件没有匹配上,则会判断第二个 if 条件。
    # 如果第二个 if 条件匹配上的话,这个stage将不会自动结束,直到我们手动触发且成功  
    - if: '$VAR =~ /pattern/'
      when: manual
    # 最后,如果上面的两个 if 条件都没有匹配上的话,则会自动执行这个stage,因为没有if条件了
    - when: on_success

rules:if

rules:ifonly:variables 的区别仅在于,rules:if只支持单个表达式判断,后者支持数组
rules:if 只能通过 && 或者 ** || ** 进行结合判断

例子

job:
  script: "echo Hello, Rules!"
  rules:
    - if: '$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME =~ /^feature/ && $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "master"' # 这个rules将会被匹配上
      when: always
    - if: '$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME =~ /^feature/' # 主要当目标分支不是master时,才会匹配此规则
      when: manual
    - if: '$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME' # 如果前两个判断条件都不匹配,且这个 if 条件只有简单的变量,那么它将默默认为:on_success

如果所有条件都不匹配,则默认为:when:never

rules:change

rules:changeonly:changes, except: changes的用法是一样的,都能够接受数组路径

例子

docker build:
  script: docker build -t my-image:$CI_COMMIT_REF_SLUG .
  rules:
    - changes: # 当Dockerfile发现改变时,stage将会转成手动触发
      - Dockerfile
      when: manual
    - when: on_success

rules:exists

rules:exists 接受数组路径,任意一个文件匹配上即可

例子

job:
  script: docker build -t my-image:$CI_COMMIT_REF_SLUG .
  rules:
    - exists:
      - Dockerfile

# 也可以使用模糊匹配路径,看匹配此路径下的所有*.rb文件
job:
  script: bundle exec rspec
  rules:
    - exists:
      - spec/**.rb

为了考虑效率问题,使用 exist 将会默认匹配10000次。超过10000次后,都将算是匹配成功

rules:allow_failure

我们可以使用 rules:allow_failure 命令,它允许我们的job执行失败,或者让一个需要手动触发的job进行等待,而无需停止整个pipeline的执行。
如果没有定义这个配置的话,所有的job默认 allow_failurefalse

例子

job:
  script: "echo Hello, Rules!"
  rules:
    - if: '$CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "master"'
      when: manual
      allow_failure: true
综合运用
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.

# 上面这个例子,当 $VAR == "string value 且 (Dockerfile 文件 或者 docker/scripts/* 匹配到的文件,有改动时),此stage将会转成手动触发。否则的话,这个stage将不会被执行

关于rules与only/except的区别

官网给出的解释是:A very important difference between rules and only/except, is that jobs defined with rules trigger merge request pipelines by default, but only/except jobs do not((⊙o⊙)…不太懂,官网给的例子网页也打不开…)

include

使用include配置,可以引入外部的YAML文件。这么做有两个好处:

  1. 可以将配置文件拆分开来。当步骤、脚本过多时,按照类型拆分,这样子有助于关于YAML文件。
  2. 可以将一些比较通用的变量定义在一个全局YAML文件中,不同的项目都可以引入这个全局的YAML文件,也就不需要维护多份全局变量。

要求:
include:需要外部的YAML文件是以:.yml 或者 .yaml 结尾的,否则将不会被引入。

支持的参数

Method Description
local 引入同一个项目中的文件
file 引入不同项目的文件
remote 引入一个可访问的远程文件
template 引入GitLab提供的模板文件

例子:

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

# 或者,更简便的写法

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

# 也可以使用 ref 来指定branch
include:
  - project: 'my-group/my-project'
    ref: master
    file: '/templates/.gitlab-ci-template.yml'
# include:remote
include:
  - remote: 'https://gitlab.com/awesome-project/raw/master/.gitlab-ci-template.yml'
# include:template
# File sourced from GitLab's template collection
include:
  - template: Auto-DevOps.gitlab-ci.yml

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

image

指定docker的image,用于job的执行

格式:
image

script

script 是一个job必须要有的参数,它里面定义的是可以在Runner中执行的 shell脚本

例子

job:
  script: "bundle exec rspec"
 
# 一个job执行多个脚本时
job:
  script:
    - uname -a
    - bundle exec rspec

当任何脚本命令返回的结果不为0时,这个job将会失败且影响到接下来的其他job的运行
官网:可以定义一个为0的全局变量来避免这种情况(我:没有特殊情况的话,我使用allow_failure是不是也可以达到同样的效果?)

例子

job:
  script:
    - false || exit_code=$?
    - if [ $exit_code -ne 0 ]; then echo "Previous command failed"; fi;

before_script & after_script

before_script: 定义执行命令,在每个job执行前执行
after_script:定义执行命令,在每个job执行后执行(包括跑失败的job)。
after_script:是在一个新的shell中执行,与 before_scriptscript 相隔离开来

  • 将当前的路径设置回默认路径
  • 没有权限更改 before_scriptscript 中的:
    1. script脚本中定义的命令别名和变量
    2. before_scriptscript所下载的软件等
  • 拥有独立的timeout设置时间,默认是5分钟
  • 即使after_script执行失败了,也不会影响正常的job流程

例子

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

stage

每个job都会定义 stagestage 所使用的变量是 stages 全局定义的变量。这让Runner可以执行不同 stage 的脚本,以及能够让相同 stage 的job并行执行。

例子

stages:
  - build
  - test
  - deploy

# job1 & job2会并行执行
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

Runner有分私有的公共的,当你使用私有的Runner时,它每次只会执行一个job。
Jobs只有在一下的情况会并行执行:

  1. 执行于不同的Runners
  2. Runner的并发设置被更改了

.pre & .post

.pre.post被允许执行于所有的pipeline

  1. .pre,将会先于其他stage被pipeline所执行
  2. .post,将会后于其他stage被pipeline所执行

只要定义了 .pre.post,它们在stages中定义的顺序,并不会影响它们在首尾执行的顺序

例子

stages:
  - .pre
  - a
  - b
  - .post

# 和

stages:
  - a
  - .pre
  - b
  - .post

# 所执行的顺序是一样的:.pre > a > b > .post

如果一个pipeline只有 .pre 和 .post,则这个pipeline将不会创建/执行

extends

extends 可以将其他的job继承到自身job内

例子

# 定义了一个.tests的stage
.tests:
  script: rake test
  stage: test
  only:
    refs:
      - branches

# 这里用extends: .tests,继承了.tests里面的配置
rspec:
  extends: .tests
  script: rake rspec
  only:
    variables:
      - $RSPEC

# 最终的结果为:
rspec:
  script: rake rspec
  stage: test
  only:
    refs:
      - branches
    variables:
      - $RSPEC

# 可以看到,script执行的是:rake rspec,这是因为被script: rake rspec给重写了。(感觉就像Java的抽象类,子类继承父类,相同的方法名、参数将会被重写)

extends支持嵌套继承,官方不建议超过3层嵌套。嵌套最多可支持10层。

例子

.tests:
  only:
    - pushes

# 这里继承了.tests
.rspec:
  extends: .tests
  script: rake rspec

# 这里继承了.rspec
rspec 1:
  variables:
    RSPEC_SUITE: '1'
  extends: .rspec

# 结果是:
rspec 1:
	variables:
		RSPEC_SUITE: '1'
	script: rake rspec
	only:
		- pushes

extends也支持同时继承多个stage

.only-important:
  only:
    - master
    - stable
  tags:
    - production

.in-docker:
  tags:
    - docker
  image: alpine

rspec:
  extends:
    - .only-important
    - .in-docker
  script:
    - rake rspec

# 结果为:
rspec:
  only:
    - master
    - stable
  tags:
    - docker
  image: alpine
  script:
    - rake rspec

小插曲

extends的例子中,官网使用了 .xxx 开头的stage名字。官网也是有对其做解释的:

如果你想要暂时的停掉某个stage的运行,那么有两种方式:

# 整段注释掉(简单粗暴)
#hidden_job:
#  script:
#    - run test

# 使用.xxx的命名方式(优雅)
.hidden_job:
  script:
    - run test

extends 和 include 的强强联合

上面提到:
include可以引入同项目、不同项目、远程、GitLab官方提供的YAML模板
extends可以继承其他stage的配置

例子

# 假设这是一个待被引入的yaml文件,称之为:include.yml
# 同时这里定义的是“被注释”的stage
.template:
  script:
    - echo Hello!

# 在我们本地的.gitlab-ci.yml文件中
# 先将同项目中的yml文件引入
include: included.yml

# 使用继承
useTemplate:
  image: alpine
  extends: .template

# 结果为:
useTemplate:
  image: alpine
  script:
    - echo Hello!  

only/except(basic)

官方推荐:rules 能够更好、更强大的定义何时执行一个job。尽可能地使用 rules 来代替 only/except

onlyexcept 是两个用来定义是否创建 job 的参数

  1. only 用来定义 job 只会在规定下的 branchestags 的名称下执行
  2. except 用来定义 job 只会在规定下的 branchestags 的名称下执行

关于 only 与 except 的一些使用规则

  • only 和 except 可以共同在一个job中使用
  • only 和 except 允许使用正则表达式
  • only 和 except 允许指定项目路径来作用于fork项目

only 和 except 允许使用的关键字

Value Description
branches 当管道的Git引用是一个分支时
tags 当管道的Git引用是一个tag时,即一个被打了tag的分支
api 当这个pipeline被其他pipeline所触发时
external 当使用GitLab以外的CI服务时
pipelines 对于多项目触发器,使用带有CI_JOB_TOKEN的API创建
pushes 当一个pipeline被用户用 git push 提交时
schedules 用于特定的某个时间段触发的pipeline
triggers 作用于使用trigger token创建的pipeline
web 在GitLab UI中使用Run pipeline按钮创建的管道
merge_requests 当创建/修改一个merge request
external_pull_requests 当在GitHub上创建或更新外部pull request
chat 当jobs是被 GitLab ChatOps 命令 所创建时

例子

# Case#1
job:
  # 使用了正则表达式匹配,匹配以:issue- 开头的branchs, tags..
  only:
    - /^issue-.*$/

# Case#2
# 正则表达式匹配默认是区分大小写的,使用 i 可以使得忽略大小写而进行匹配
job:
  only:
    - /^issue-.*$/i

# Case#3
# 这个例子只能作用于主项目,而不能作用于fork的项目,以及主项目的master分支
job:
  only:
    - branches@gitlab-org/gitlab
  except:
    - master@gitlab-org/gitlab
    - /^release/.*$/@gitlab-org/gitlab

如果一个job没有设置任何的 only 规则,那么默认会设置为:only: [‘branches’, ‘tags’]
如果没有 except 规则,那么将什么都不会默认设置。

例子

job:
  script: echo 'test'

# 将会转化成:
job:
  script: echo 'test'
  only: ['branches', 'tags']
正则表达式

因为 @ 被用来表示项目的根目录,所以使用正则表达式中包含 @ 字符的路径,则需要使用 \x40 代替。
只有 tagbranch 能够使用正则表达式匹配。
使用正则表达式时,需要用 / 包裹着整个正则表达式。像:issue-/.*/ 没有被包裹住,所以它并不会起到作用。

only/except(advanced)

Warning: 这是测试版本的功能,官方随时会进行修改!
GitLab supports both simple and complex strategies, so it’s possible to use an array and a hash configuration scheme.

有4个可用参数

  • refs
  • variables
  • changes
  • kubernetes

onlyexcept 下有多个条件时,表现形式为:
例子

test:
  script: npm run test
  only:
    refs:
      - master
      - schedules
    variables:
      - $CI_COMMIT_MESSAGE =~ /run-end-to-end-tests/
    kubernetes: active

# only
# (any of refs) AND (any of variables) AND (any of changes) AND (if Kubernetes is active) 

test:
  script: npm run test
  except:
    refs:
      - master
      - schedules
    variables:
      - $CI_COMMIT_MESSAGE =~ /run-end-to-end-tests/
    kubernetes: active

# except
# NOT((any of refs) AND (any of variables) AND (any of changes) AND (if Kubernetes is active)) 

only:refs/except:refs

在GitLab 10.0 版本引进 refs
例子

deploy:
  only:
    refs:
      - master
      - schedules

# 这个job只有在,branch = master 或者 这个job由 scheduled 触发时,才会执行

only:kubernetes/except:kubernetes

在GitLab 10.0 版本引进 kubernetes

kubernetes 仅支持 active 参数
例子

deploy:
  only:
    kubernetes: active

# 这个job只有在,kubernetes服务在运作时,才会执行

only:variables/except:variables

在GitLab 10.7 版本引进 variables

variables 关键字,是用于定义变量的。我们可以通过定义一些全局变量,搭配上 only:variables/except:variables,来最终决定是否创建和执行这个job。
例子

deploy:
  script: cap staging deploy
  only:
    refs:
      - branches
    variables:
      - $RELEASE == "staging"
      - $STAGING

only:changes/except:changes

在GitLab 11.4 版本引进 changes

onlyexcept 上定义 changes,可以通过每一次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}

# 当Dockerfile发生改变时
# 当任何在docker/scripts/ 路径下的文件发生改变时
# 当任何在dockerfiles路径下、子目录下的文件发生改变时
# 当任何在more_scripts路径下,以rb, py, sh结尾的文件发生改变时

我们也可以使用全局定义的方式,但是需要使用双引号(" ")包裹住匹配路径
例子

# only example
test:
  script: npm run test
  only:
    changes:
      - "*.json"
      - "**/*.sql"

# except example
build:
  script: npm run build
  except:
    changes:
      - "*.md"

使用 only:changes 当我们提交merge_requests

例子

# 当我们提交的merge_requests中,包含了对:Dockerfile 或者 service-one目录下的文件 的改动
# 那么将会执行script中的脚本
docker build service one:
  script: docker build -t my-service-one-image:$CI_COMMIT_REF_SLUG .
  only:
    refs:
      - merge_requests
    changes:
      - Dockerfile
      - service-one/**/*

needs

needs 允许无序的执行jobs。
needs 可以让我们忽视jobs的执行顺序,以达到多个步骤可以并发的执行。

例子

  1. lint 将会立刻执行,不会等linux:build & mac:build 两个job的执行完成。这是因为,needs: [ ],没有任何的依赖。
  2. linux:rspec & linux:rubocop 将在 linux:build执行完后立刻执行,并且不会考虑mac:build的执行情况。
  3. 同理,mac:rspec & mac:rubocop 将在 mac:build 执行完后立刻执行,同样不会考虑 linux:build的执行情况。
  4. 最后,production job 将会等上面的步骤执行完后才开始执行。
linux:build:
  stage: build

mac:build:
  stage: build

lint:
  stage: test
  needs: []

linux:rspec:
  stage: test
  needs: ["linux:build"]

linux:rubocop:
  stage: test
  needs: ["linux:build"]

mac:rspec:
  stage: test
  needs: ["mac:build"]

mac:rubocop:
  stage: test
  needs: ["mac:build"]

production:
  stage: deploy

needs的一些限制

  • 如果 needs 指向了一个因为 only/except 或者其他的因素导致这个job没有被实例化,则会报错
  • 对于单个job,needs 中的参数数组大小是有限制的
    • 对于Gitlab.com,它的限制是:10个
    • 对于自己搭建的Gitlab平台,它的限制是:
      • 10个,如果ci_dag_limit_needsfeature = enabled。(默认是:enabled)
      • 50个,如果ci_dag_limit_needsfeature = disabled
  • 如果 needs 指向的job是并行的,那么当前的这个job将依赖于所有并行的jobs

修改needs的数量限制

For Omnibus installations

sudo gitlab-rails console
# 设置为50个
Feature::disable(:ci_dag_limit_needs)
# 设置为10个
Feature::enable(:ci_dag_limit_needs)

For installations from source

sudo -u git -H bundle exec rails console -e production
# 设置为50个
Feature::disable(:ci_dag_limit_needs)
# 设置为10个
Feature::enable(:ci_dag_limit_needs)

Artifact downloads with needs

当某个job使用了needs,是否下载它所依赖job的Artifact将由 artifacts: true || artifacts: false 控制,默认是:true

例子

build_job:
  stage: build
  artifacts:
    paths:
      - binaries/

# rspec将会下载build_job中的artifact
rspec:
  stage: test
  needs:
    - job: build_job
      artifacts: true

# rubocop将不会下载build_job中的artifact
rubocop:
  stage: test
  needs:
    - job: build_job
      artifacts: false

# rspec2将会下载build_job的artifact,因为其中的artifacts是默认为true的
rspec2:
  needs:
    - job: build_job_1

Cross project artifact downloads with needs

needs依赖于不同项目的jobs

build_job:
  stage: build
  script:
    - ls -lhR
  needs:
    - project: group/project-name
      job: build-1
      ref: master
      artifacts: true

tags

使用tags选择项目可使用的Runner
当我们注册Runner过程中,会要求我们输入Runner对应的tags。具体注册Runner操作,可参考Gitlab runner的注册 & 使用

在下面的例子中,job这个步骤将会在被定义了ruby & postgres 两个tags下的Runner中执行。

job:
  tags:
    - ruby
    - postgres

我们也可以使用tags来实现让不同步骤在不同的平台上执行。例子如下:

windows job:
  stage:
    - build
  tags:
    - windows
  script:
    - echo Hello, %USERNAME%!

osx job:
  stage:
    - build
  tags:
    - osx
  script:
    - echo "Hello, $USER!"

allow_failure

当执行CI/CD过程中,我们允许某一个步骤失败时,可以使用allow_failure。这样,即使这个步骤执行失败了,也不会影响接下来的其他步骤继续执行。allow_failure默认值为:false

正如下面的例子:job1job2 并行执行时,如果job1执行失败了,它不会影响到接下来的其他步骤。

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可以用于设置以下的变量

  1. on_success:(默认值) - 只有当之前的步骤都执行成功了,或者是之前的步骤设置了allow_failure: true 时。会执行此步骤。
  2. on_failure:当之前的步骤至少有某一步失败了,才会执行此步骤。
  3. always:不管前面的步骤成功与否,都会执行此步骤。
  4. manual:手动执行此步骤。
  5. delayed:延迟执行此步骤。
  6. never
    • With rules, don’t execute job.
    • With workflow:rules, don’t run pipeline.

例子:

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. 只有build_job执行失败时,cleanup_build_job会执行。
  2. cleanup_job无论如何都会执行
  3. deploy_job只有当我们在Gitlab UI上手动触发时会执行。

when:manual

当使用了rules:allow_failure将默认为:false,包括manual jobs
只有当用户拥有merge的权限,才能够触发manual job。我们可以使用protected branches功能来防止未授权的用户随意触发manual job

Protecting manual jobs

使用Protected Environments可以定义一组有权限操作manual job的用户。

when:delayed

使用when:delayed让步骤等待一段时间再执行。
可以通过start_in的方式,设置等待时间。默认是:,或者主动提供时间单位start_in设置的时间必须小于等于一个星期
可以设置的值的例子:

  • ‘5’
  • 5 seconds
  • 30 minutes
  • 1 day
  • 1 week

看官网文档进行学习、实践的过程。尽可能地记下自己觉得有用的内容,及翻译。
尽量地强迫自己看官方/英文文档,学习一手资料。

你可能感兴趣的:(gitlab,ci/cd)