Gitlab的Pipeline执行机制

Gitlab的Pipeline执行机制

从gitlab 8.0开始,就可以通过.gitlab-ci.yml定义流水线的构建过程。所有分支互不影响,只有当前分支上存在这个文件才能够触发流水线的构建。

Pipeline基本概念

在gitlab上project->settings->CI/CD中可以设置提交以及MR时触发Pipeline构建。

一个流水线构建任务中有若干个构建阶段(stage),这些阶段都是按序进行构建的,根据在yaml文件中定义的顺序进行串行构建。在阶段下又有若干个构建任务(job),而这些构建任务在阶段中是并行运行的

在一个流水线中,前项stage构建失败时,整个流水线失败,且后向的stage都不会再进行构建。在一个阶段中,如果任意一个job失败,则该阶段失败。

gitlab runner

gtilab并不会负责任务的构建,它只负责分发任务以及回显构建结果。构建的事情由gitlab runner负责,装载gitlab runner的机器将会是处理构建任务的计算机器。

注册runner

gitlab runner安装完成后,只需要运行注册命令:$ gitlab-runner register进行runner的注册即可。可以反复使用该命令为一个runner注册多次。在gitlab的project->settings->CI/CD->runner下能够看到gitlab给出的URL以及token,用于连接gitlab与gitlab runner。

具体步骤可以如下:

  • 运行 sudo gitlab-runner register
  • 输入 CI URL
  • 输入 Token
  • 输入 Runner 的标签
  • 选择 Runner 的类型,简单起见还是选 Shell

其他一些比较通用的命令如:

$ gitlab-runner list #列出当前机器上注册的所有runner及其状态

$ gitlab-runner restart #重启runner

$ gitlab-runner unregister –url URL –token tokenNum #注销某个runner

.gitlab-ci.yml的编写

不同于python,yaml通过空格来区分代码块。将空格写成tab是不行滴。直接上代码吧:

# 定义 stages(阶段)。任务将按此顺序执行。
stages:
  - build
  - test
  - deploy

# 定义 job(任务)
job1: #job的名称
  stage: test
  tags:
    - XX #只有标签为XX的runner才会执行这个任务
  only:
    - dev    #只有dev分支提交代码才会执行这个任务。也可以是分支名称或触发器名称
    - /^future-.*$/ #正则表达式,只有future-开头的分支才会执行
  script:
    - echo "I am job1"
    - echo "I am in test stage"

# 定义 job
job2:
  stage: test    #如果此处没有定义stage,其默认也是test
  only:
    - master
  script:
    - echo "I am job2"
    - echo "I am in test stage"
  allow_failure: true #允许失败,即不影响下步构建

# 定义 job
job3:
  stage: build
  except:
    - dev #除了dev分支,其它分支提交代码都会执行这个任务
  script:
    - echo "I am job3"
    - echo "I am in build stage"
  when: always #不管前面几步成功与否,永远会执行这一步。它有几个值:on_success (默认值)\on_failure\always\manual(手动执行)

# 定义 job
.job4:    #对于临时不想执行的job,可以选择在前面加个".",这样就会跳过此步任务
  stage: deploy
  script:
    - echo "I am job4"

# 模板,相当于公用函数,有重复任务时很有用
.job_template: &job_definition  # 创建一个锚,'job_definition'
  image: ruby:2.1
  services:
    - postgres
    - redis

test1:
  <<: *job_definition           # 利用锚'job_definition'来合并
  script:
    - test1 project

#下面几个都相当于全局变量,都可以添加到具体job中,这时会被子job的同名变量覆盖

before_script:
  - echo "每个job之前都会执行"

after_script:
  - echo "每个job之后都会执行"

variables:    #变量
  DATABASE_URL: "postgres://postgres@postgres/my_database"  #在job中可以用${DATABASE_URL}来使用这个变量。常用的预定义变量有CI_COMMIT_REF_NAME(项目所在的分支或标签名称),CI_JOB_NAME(任务名称),CI_JOB_STAGE(任务阶段)
  GIT_STRATEGY: "none" #GIT策略,定义拉取代码的方式,有3种:clone/fetch/none,默认为clone,速度最慢,每步job都会重新clone一次代码。我们一般将它设置为none,在具体任务里设置为fetch就可以满足需求,毕竟不是每步都需要新代码,那也不符合我们测试的流程

cache:    #缓存
  #因为缓存为不同管道和任务间共享,可能会覆盖,所以有时需要设置key
  key: ${CI_COMMIT_REF_NAME}  # 启用每分支缓存。
  #key: "$CI_JOB_NAME/$CI_COMMIT_REF_NAME" # 启用每个任务和每个分支缓存。需要注意的是,如果是在windows中运行这个脚本,需要把$换成%
  untracked: true    #缓存所有Git未跟踪的文件
  paths:    #以下2个文件夹会被缓存起来,下次构建会解压出来
    - node_modules/
    - dist/

像stage、only、except等等都是yml的关键字,更多关键字的用法可以参考官方文档

关键字needs:能够无序执行作业,无需按照阶段顺序运行某些作业,可以让多个阶段同时运行。比如阶段3的作业1可以在阶段1的作业2执行完成后就可执行,不需要等到阶段2执行完才能执行。

stages:
  - build
  - test

job1: 
  stage: build
  needs: []
  script:
    - echo "I am job1"

job2:
  stage: test
  needs: []
  script:
    - echo "I am job2"

job3:
  stage: test    #如果此处没有定义stage,其默认也是test
  needs: [job2]
  script:
    - echo "I am job3"

job1和job2将会并行,job3将在job2完成后立即执行,不需要等到build阶段的所有任务都完成才能执行。

YAML数据结构

yaml支持的数据结构有:对象(映射)、数组、纯量(scalars)。

对象

像stage: build就是一种对象,需要注意的是,冒号后面需要跟着一个空格。

对象还可以写成:hash: {stage: build, name: Jane}

数组

一组中划线组成的行,构成一个数组。

script:
 -
  - ele1
  - ele2
  - ele3
 - outside

一个数组下有一个数组元素和一个名为outside的元素,数组元素中又有三个元素。

数组还可以写成:

script: [[ele1, ele2, ele3], outside]

纯量

数值直接以字面量的形式呈现。

布尔值可以直接使用true和false。

null用~表示。

yaml允许使用两个感叹号进行数据的强制转换:e: !!str 123 #将数值123转为字符串

字符串

字符串默认不使用引号表示

如果字符串中包含空格或其他特殊字符如冒号,则需要用引号包含起来(单双引号都可以)。如e: ‘123 : 456’

若字符串中存在单引号,则需要用两个单引号进行转义。

字符串可以写成多行,但是从第二行开始,必须有单空格缩进。换行符会被转为空格。

sss: line1
 line2
 line3

引用

锚点&和别名*可以用于yaml的引用。

defaults: &defaults-anchor
  adapter:  postgres
  host:     localhost

development:
  database: myapp_development
  <<: *defaults-anchor

test:
  database: myapp_test
  <<: *defaults-anchor

公司的CI配置遇到了几个小坑:

ci的构建实际上是在每个runner机器上,用固定用户加sudo去执行每条指令。拿我司来说,代码会下到/home/gitlab-runner/下的某个子目录(Ubuntu),并在项目目录下执行自动化构建脚本。那么执行的用户就是gitlab-runner。Linux下的软件安装和下载都是分用户的,如果工具链装在了管理员用户的/root/下,那么其他普通用户将无法使用该工具链。

普通用户下的$HOME是/home/username,而管理员用户下的$HOME是/root/,不一样,在配置环境变量时如果输入了$HOME的话,可能结果和预期的不同。

所以需要用到的工具链最好安装在一些公用目录上,如/usr/local/bin,这样任意一个用户都能够访问到。

参考:持续集成之.gitlab-ci.yml篇 – SegmentFault 思否


本文为原创内容,遵循CC BY-ND 4.0协议,署名-禁止演绎。
转载请注明出处:https://tis.ac.cn/blog/yexin/gitlab%e7%9a%84pipeline%e6%89%a7%e8%a1%8c%e6%9c%ba%e5%88%b6/

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注