Gitlab持续集成-(.gitlab-ci.yml)

从7.12版本开始,GitLab CI使用YAML文件(.gitlab-ci.yml)来管理项目配置。该文件存放于项目仓库的根目录,它定义该项目如何构建。

stages

stages用来定义可以被job调用的stages。stages的规范允许有灵活的多级pipelines。stages中元素的顺序决定了对应job的执行顺序:

  • 相同stage的job是并行执行的;
  • 下一个stage的job在前一个stage的job成功完成后才开始执行;
  • 如果.gitlab-ci.yml中没有定义stages,那么stages默认定义为build、test和deploy;
  • 如果一个job没有指定stage,那么这个任务会分配到test stage。

variables

variables用来定义变量,全局变量作用于所有job,也可以在指定的job中定义变量(优先级高于全局变量)
如果在job中想禁用全局定义的变量,可通过variables: {}定义一个空的哈希值。

GitLab CI/CD内置变量

variables 变量值
CI_JOB_NAME 对应的job_name
GIT_STRATEGY 指定git获取代码的方式(clone,fetch,none)

jobs

jobs用来定义了一组作业,其中必须包含script语句。

job.stage(默认:test

job中指定的stage必须是stages中存在的元素

job.tags

指定该job所允许运行的Runner,必须在注册Runner时设置Runner的tag

job.allow_failure

用于指定该job允许执行失败,则如果执行失败也不会影响下一个stage的执行。

job.script

script是job中必须指定的语句,指定Runner所要执行的命令

job.before_script、job.after_script

指定script执行前/后所执行的命令,也可定义在全局模式,则在所有job中的script执行前/后都会执行。

job.artifacts

用于指定job执行成功后,将会被发送到Gitlab中的文件,且默认情况下job之间会根据stage的优先级自动下载之前所有stage中的artifacts。

  • artifacts.paths:必选
  • artifacts.name:指定artifact的名称,同时Gitlab上下载的文件名即为artifact_name.zip
  • artifacts.when:指定artifact上传到Gitlab的条件(on_success[默认],on_failure,always)
  • artifacts.expire_in:指定artifact的过期时间(默认为30天),使用keep可永久保存

job.dependencies

dependencies用于指定在不同的job之间传递artifacts,(默认情况下当前的job都会自动下载之前stage中所有job定义的artifacts),指定dependencies: []可禁止该job下载artifacts

job.only、job.except

onlyexcept是两个参数用分支策略来限制jobs构建

  • onlyexcept可同时使用。如果在一个job配置中同时存在,则同时有效;
  • onlyexcept可以使用正则表达式;
  • onlyexcept允许使用特殊的关键字:branchestagstriggers

job.environment

environment用于定义job部署到指定的运行环境中。

  • environment.name:必选,指定environment名称
  • environment.url:可选,指定environment对应的URL,将在指定的environment页面中添加一个链接按钮指向该URL

job.when

when用于指定job执行的条件。

  • when.on_success:只有之前所有的stage成功才执行(默认);
  • when.on_failure:只有之前的stage至少有一个job失败才执行;
  • when.always:总是执行;
  • when.manual:需要手动在Gitlab Pipeline中点击play按钮才执行。manual中allow_failure默认为true

特殊的YAML特性

Hidden keys(jobs)

如果想临时disable某个job,不必注释整个job定义的行,只需在job name前加一个.即可

1
2
3
4
5
6
.compile_centos:
stage: build_centos
tags:
- centos
script:
- echo "##### build library"

Anchors

锚点可用于在文件中复制或继承配置,一般与Hidden keys(jobs)提供的job模版搭配使用。

1
2
3
4
5
6
7
8
9
10
11
12
13
.job_template: &job_definition  #job中定义一个anchor:job_definition
image: ruby:2.1
services:
- postgres
- redis
test1:
<<: *job_definition #合并anchor:job_definition中的模版内容
script:
- test1 project
test2:
<<: *job_definition
script:
- test2 project

最终实现的效果如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
.job_template:
image: ruby:2.1
services:
- postgres
- redis
test1:
image: ruby:2.1
services:
- postgres
- redis
script:
- test1 project
test2:
image: ruby:2.1
services:
- postgres
- redis
script:
- test2 project

Skipping jobs

如果你的commit信息中包含[ci skip]或者[skip ci],不论大小写,那么这个commit将会创建但是jobs也会跳过。


example:

以下示例为编译nginx的上传模块nginx-upload并测试验证上传功能,验证成功后将自动将编译好的文件打包通过curl上传到指定的文件服务器。其中只有在非master的branches中提交代码才会执行build和test的stage,只有在打tag后才会执行deploy,且需要手动在gitlab上执行。

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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
variables:
DIR: nginx
TOPNODE: package

.function: &function |
function build() {
echo "execute function:build"
chmod +x auto/configure
sh build.sh
}

function changelog() {
echo "execute function:changelog"
git log --graph -n 3 --name-status --pretty="%h -[%cd] - <%an> %s" > CHANGELOG
}

function test() {
echo "execute function:test"

sudo \cp modules/nginx-upload-module-master/nginx.conf /etc/nginx/nginx.conf
sudo sed -i '/error_log/,/working_directory/d' /etc/nginx/nginx.conf
if [ -f /run/nginx.pid ];then sudo nginx -s reload;else sudo nginx;fi
sudo rm -rf /tmp/{0,1,2,3,4,5,6,7,8,9} && sudo mkdir /tmp/{0,1,2,3,4,5,6,7,8,9} && sudo chown -R nginx. /tmp/{0,1,2,3,4,5,6,7,8,9}
sudo echo nginx_upload > test && curl -F "filename=@test" http://localhost/upload
sudo find /tmp/{0,1,2,3,4,5,6,7,8,9} -type f -exec grep nginx_upload {} \;
}

function artifacts() {
echo "execute function:artifacts"
URL="https://xxx.com/upload?dir=${DIR}/${VERSION}&override=1&topNode=${TOPNODE}"

echo "push the artifacts:nginx_${VERSION}.tar.gz to $URL"
tar zcf /tmp/nginx_${VERSION}.tar.gz --exclude=".git*" --exclude=build .
curl -F "filename=@/tmp/${DIR}_${VERSION}.tar.gz" "$URL"

echo "push the CHANGELOG to $URL"
curl -F "filename=@CHANGELOG" "$URL"
}

function deploy() {
echo "execute function:deploy"
}

function clean() {
echo "execute function:clean"
if [ -f /run/nginx.pid ];then sudo kill `cat /run/nginx.pid`;fi
sudo rm -rf /tmp/{0,1,2,3,4,5,6,7,8,9} /tmp/nginx_${version}.tar.gz
}

#########only the section above need to be modify #################
before_script:
- VERSION=`head -n1 version`
- *function

stages:
- build
- test
- deploy

build:
stage: build
only:
- branches
except:
- master
script:
- build
- changelog

test:
stage: test
variables:
GIT_STRATEGY: none
only:
- branches
except:
- master
script:
- test
- artifacts
- clean

.job_template: &deploy_template
stage: deploy
variables:
GIT_STRATEGY: none
only:
- tags
script:
- deploy
- delete
when: manual

staging:
<<: *deploy_template
environment:
name: staging

production:
<<: *deploy_template
environment:
name: production
坚持原创技术分享,您的支持将鼓励我继续创作!
0%