GitLab CI Pipeline框架
- 2020.05.20
本文将会介绍一些跟GitLab CI流程相关的知识,方便大家对CI/CD流程的熟悉,设计适合自己项目的流程。
CI/CD 工作流程

Gitlab CI
GitLab CI是GitLab内置的进行持续集成的工具,在你安装好GitLab之后,即同时安装了GitLab CI。只需要在仓库根目录下创建.gitlab-ci.yml文件,并配置GitLab Runner;每次提交的时候,gitlab将自动识别到.gitlab-ci.yml文件,并且使用Gitlab Runner执行该脚本。
Gitlab Runner
GitLab Runner是用来执行.gitlab-ci.yml脚本的工具,从GitLab CI中获取到任务,并按其要求完成任务的执行。可以理解成,Runner就像认真工作的工人,GitLab-CI就是管理工人的中心,所有工人都要在GitLab-CI里面注册,并且表明自己是为哪个项目服务。当相应的项目发生变化时,GitLab-CI就会通知相应的工人执行对应的脚本。
TIP
Runner负责执行.gitlab-ci.yml文件中定义的job,可以是虚拟机、vps、裸机、docker容器或容器集群。
GitLab Runner 是由Go语言编写的,可以运行在 GNU/Linux, macOS 和 Windows上。
如果我们项目中需要使用到Docker的话,最低版本的 Docker 需要 v1.13.0。
我们可以在项目的Settings-->CI/CD-->Runners页面可以查看到是否有可用的Runner。
Runner类型
GitLab-Runner 可以分类两种类型:Shared Runner(共享型)和 Specific Runner(指定型)。
Shared Runner:所有工程都能够用的,且只有系统管理员能够创建。Specific Runner:只有特定的项目可以使用。
Runner安装
以macOs为例子,完整的安装地址参考:官方下载地址
- 方式1
sudo curl --output /usr/local/bin/gitlab-runner https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-darwin-amd64
sudo chmod +x /usr/local/bin/gitlab-runner
cd ~
gitlab-runner install
gitlab-runner start
- 方式2
brew install gitlab-runner
brew services start gitlab-runner
获取Runner注册Token
安装好Runner之后,需要向Gitlab进行注册,注册Runner需要 GitLab-CI 的 url 和 token。可根据需求注册选择所需类型Runner。
- 获取
Shared Runner注册Token:
使用管理员用户登录,进入Admin Area->OverView->Runners界面。
- 获取
Specific Runner注册Token:
进行项目仓库->settings->CI/CD界面
注册Runner
完整的注册文档请参见官方注册文档
执行 gitlab-ci-multi-runner register命令进行 Runner注册,期间会用到前期获取的url及token;注册完成之后,GitLab-CI就会多出一条Runner记录。
gitlab-ci.yml(配置文件)
从
7.12版本开始,GitLab CI使用YAML文件(.gitlab-ci.yml)来管理项目配置。该文件存放于项目仓库的根目录,并且包含了你的项目如何被编译的描述语句。YAML文件使用一系列约束叙述定义了Job启动时所要做的事情。
通过配置gitlab-ci.yml文件我们可以定义Pipeline的结构和执行顺序。
关键字及含义
| 关键字 | 含义 |
|---|---|
before_script | 定义任何 Jobs 运行前都会执行的命令。 |
after_script | 定义任何 Jobs 运行完后都会执行的命令。(要求 GitLab 8.7+ 和 GitLab Runner 1.2+) |
variables && Job.variables | 定义环境变量。如果定义了 Job 级别的环境变量的话,该 Job 会优先使用 Job 级别的环境变量。(要求 GitLab Runner 0.5.0+) |
cache && Job.cache | 定义需要缓存的文件。每个 Job 开始的时候,Runner 都会删掉 .gitignore 里面的文件。如果有些文件 (如 node_modules/) 需要多个 Jobs 共用的话,我们只能让每个 Job 都先执行一遍 npm install。(要求 GitLab Runner 0.7.0+) |
Job.scrip | 定义 Job 要运行的命令,必填项 |
Job.stage | 定义 Job 的 stage,默认为 test |
Job.artifacts | 定义 Job 中生成的附件。当该 Job 运行成功后,生成的文件可以作为附件 (如生成的二进制文件) 保留下来,打包发送到 GitLab,之后我们可以在 GitLab 的项目页面下下载该附件。 |
工作流程

Pipeline(管道)
完整的 pipeline 配置可以参考官方文档
PipeLine即流水线是持续集成、发布、部署的最顶层的组件。由Stage和Job组成,由.gitlab-ci.yml来定义。按触发模式可分为:自动触发和人工触发。
一次 Pipeline 其实相当于一次构建任务,里面可以包含多个流程,比如自动构建、自动进行单元测试、自动进行代码检查等流程 ;
任何提交或者 Merge Request 的合并都可以触发 Pipeline ;
自动触发
- 定时触发
比如我们可以通过配置Pipeline schedules API在每天的0:00进行一次操作。
创建一个新的项目管道计划。
POST /projects/:id/pipeline_schedules
| 属性 | 类型 | 需要 | 描述 |
|---|---|---|---|
id | int / string | 是 | 经过身份验证的用户拥有的项目的ID或URL编码路径 |
description | string | 是 | 管道进度表的描述 |
ref | string | 是 | 分支/标签名称将被触发 |
cron | string | 是 | cron(例如0 1 * * *)(Cron语法) |
cron_timezone | string | 否 | 所支持的时区ActiveSupport::TimeZone(如Pacific Time (US & Canada))(默认值:'UTC') |
active | boolean | 否 | 管道计划的激活。如果假设置,管道计划将首先停用(默认值:true) |
curl --request POST --header "PRIVATE-TOKEN: k5ESFgWY2Qf5xEvDcFxZ" --form description="Build packages" --form ref="master" --form cron="0 0 * * *" --form cron_timezone="UTC" --form active="true" "https://gitlab.example.com/api/v4/projects/29/pipeline_schedules"
执行结果:
{
"id": 14,
"description": "Build packages",
"ref": "master",
"cron": "0 0 * * *",
"cron_timezone": "UTC",
"next_run_at": "2020-05-21T00:00:00.000Z",
"active": true,
"created_at": "2020-05-20T13:43:08.169Z",
"updated_at": "2020-05-20T13:43:08.169Z",
"last_pipeline": null,
"owner": {
"name": "Administrator",
"username": "root",
"id": 1,
"state": "active",
"avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
"web_url": "https://gitlab.example.com/root"
}
}
Merge请求触发
此功能在
GitLab 11.6版本中引入。
在基础配置中,每次提交一个更改到分支的时候,GitLab都会运行一个管道。要在merge的时候触发需要配置CI/CD配置文件。
例如使用only或except运行管道以进行合并请求:
build:
stage: build
script: ./build
only:
- master
test:
stage: test
script: ./test
only:
- merge_requests
deploy:
stage: deploy
script: ./deploy
only:
- master
WARNING
使用此方法时,必须only: - merge_requests为每个作业指定。
在此示例中,管道包含test配置为在合并请求上运行的作业,在build与deploy工作没有only: - merge_requests参数,所以他们不会合并请求运行。
人工触发
手动去触发打包
Stages
stages表示构建阶段,一个Pipeline中可以定义多个stage,包括了build、test和deploy等阶段。
stages有如下特点 :
所有
stages会按照顺序运行,即当一个stage完成后,下一个stage才会开始只有当所有
stages成功完成后,该构建任务 (Pipeline) 才算成功如果任何一个
stage失败,那么后面的stages不会执行,该构建任务 (Pipeline) 失败
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
Stages执行顺序
以图中所示为例,整个 CI 环节包含三个 Stage:build、test 和deploy。
build被首先执行。如果发生错误,本次 CI 立刻失败;test在 build 成功执行完毕后执行。如果发生错误,本次 CI 立刻失败;deploy在 test 成功执行完毕后执行。如果发生错误,本次 CI 失败。
Jobs
Job是.gitlab-ci.yml文件中最基本的元素,表示某个stage里面执行的工作。一个stage中用户可以创建任意个任务;每个任务必须有一个独一无二的名字,但有一些保留keywords不能用于Job名称。
保留关键字:
image,services,stages,types,before_script,after_script,variables,cache,include。
Job被定义为顶级元素,并且至少包括一条script语句,如果一个 Job 没有显式地关联某个 Stage,则会被默认关联到 test Stage。
jobs有如下特点 :
相同
stage中的jobs会并行执行相同
stage中的jobs都执行成功时,该stage才会成功如果任何一个
job失败,那么该stage失败,即该构建任务 (Pipeline) 失败
Job执行流程


Script
script是一段由Runner执行的shell脚本。
job:
script:
- uname -a
- bundle exec rspec
image and services
这两个选项允许开发者指定任务运行时所需的自定义的docker镜像和服务。
#为每个作业定义不同的映像和服务
test:2.1:
image: ruby:2.1
services:
- postgres:9.3
script:
- bundle exec rake spec
test:2.2:
image: ruby:2.2
services:
- postgres:9.4
script:
- bundle exec rake spec
before_script和after_script
before_script是用于定义一些在所有任务执行前所需执行的命令, 包括部署工作,可以接受一个数组或者多行字符串。after_script用于定义所有job执行过后需要执行的命令,可以接受一个数组或者多行字符串。
#定义全局 before_script:
default:
before_script:
- global before script
#覆盖全局before_script
job:
before_script:
- execute this instead of global before script
script:
- my command
after_script:
- execute this after my script
配置示例
before_script:
# 激活 nodeenv 虚拟环境
- source /data/gitlab-runner/paas-webfe/bin/activate
# 查看 node 版本
- which node && node --version
# 为了能方便使用 npm ,给它取一个别名
- alias npm="/data/gitlab-runner/node/bin/npm"
- which npm && npm --version
stages:
- build
build-test-webpack:
variables:
# 需要修改为项目的 GitLab 地址格式
CI_REPOSITORY_URL:
http://$GIT_USERNAME:$GIT_PASSWORD@gitlab.xxx.com/$CI_PROJECT_PATH.git
# 打包生成的文件存放目录
OUT_PUT_DIR:
test
stage: build
# 允许在 GitLab 页面上,直接下载 $OUT_PUT_DIR 内容
artifacts:
paths:
- $OUT_PUT_DIR
# 没有 Git 版本的文件,设置缓存,可以避免每次 npm install 重复安装
cache:
untracked: true
script:
# 开始执行打包编译命令,并提交到当前的 Git 仓库,具体的命令,需要根据项目编写,也可以放在一个 shell 文件,执行
- echo "start build test"
- rm -rf $CI_PROJECT_NAME $OUT_PUT_DIR
- cd ./webpack && tnpm install && tnpm run build-test && cd ..
- git clone $CI_REPOSITORY_URL
- rm -rf $CI_PROJECT_NAME/$OUT_PUT_DIR && cp -r $OUT_PUT_DIR $CI_PROJECT_NAME/
- cd $CI_PROJECT_NAME
- git add $OUT_PUT_DIR
- git status >> build.log
- date >> build.log
- git add build.log
- git commit -m "auto build-test[ci skip]"
- git push $CI_REPOSITORY_URL master
- echo "end build test"