​Gitlab CI持续集成可以这样用

750次阅读  |  发布于2年以前

前言

每个公司内部都有自己的DevOps平台,来规范需求创建、开发编译、部署、测试、上线等等流程。Beetle是转转内部的DevOps平台,很好地加强了产品的开发效率及发布质量。其中为了实现通用性,Beetle对持续集成(CI)部分的构建命令,做了一定的强制规范。但是魔方项目(内部低代码搭建平台)的构建比较复杂,不能完全符合规范及其他原因,造成这个平台不能接入,导致在开发编译部署上线阶段还经常出现问题。最后,我们尝试用Gitlab的CI/CD来先行解决这些问题。

简述Gitlab-CI流程

1、仓库根目录增加.gitlab-ci.yml文件

2、监听.gitlab-ci.yml文件内配置的触发时机

3、触发(例如push)并执行配置的job

设计思路

通常情况,每个仓库下都需要配置.gitlab-ci.yml文件。

但是因为业务关系,我们并不在每个仓库下都放置一个配置文件,我这里新建了一个仓库,这个仓库用来集成所有魔方项目的构建部署工作。

这种设计并非常规设计,只是提供一种思路,大家慎重使用。

以下为详细设计思路:

1、创建一个CI/CD仓库,添加.gitlab-ci.yml文件

2、分别创建多个仓库项目的JOB,并且将具体逻辑放到子yml文件中

3、每个JOB的触发时机为,正则匹配特定分支变量的push

4、特定分支或变量规则:需要部署的项目名+是否需要安装依赖+部署分支

5、以上操作都通过api传入变量来触发

大致流程图如下:

安装配置

仅以Linux环境为例:

1、在项目编译的物理机上安装gitlab-runner

https://mp.weixin.qq.com/s/qG3XhYB1zbYKZztJcWtkcw

2、授权

sudo chmod +x /usr/local/bin/gitlab-runner

3、创建一个gitlab-ci用户

sudo useradd --comment 'GitLab Runner' --create-home gitlab-runner --shell /bin/bash

4、安装,并作为服务启动

sudo gitlab-runner install --user=gitlab-runner --working-directory=/home/gitlab-runner
sudo gitlab-runner start

5、注册

sudo gitlab-runner register

命令展示:

注册需要的信息获取路径:

Project → Setting → CI/CD → Runner → Expand

如图:

配置信息:

注册后状态(待激活):

6、激活

sudo gitlab-runner verify

激活后:

创建配置文件

创建仓库并创建.gitlab-ci.yml文件,因为我们部署多个项目,所以配置比较多,我们对这些任务进行拆分。其中用到include关键字来实现拆分,最后我们的仓库结构如下图:

配置文件代码预览

.gitlab-ci.yml 文件

stages:
  - module-publish
  - install
  - build
variables:
  NODE_VERSION: "12.22.4"

  # 以下为接口传入的参数
  # $TRIGGER_JOB_NAME  # api触发的job名

include:
  - '.gitlab-ci.install.yml'

.gitlab-ci.install.yml文件

.script-common-install: &script-common-install
  - |
    nvm use $NODE_VERSION

dev-install-package-common:
  stage: install
  resource_group: dev-install-package-common
  script:
    - *script-common-install
    - echo "通用依赖安装完成"
  only:
    refs:
      - /^.*\+module\+.*$/
    variables:
      - $TRIGGER_JOB_NAME =~ /^.*magic-common-component.*$/
  tags:
    - magic-work

配置文件分析

简单描述一下:

1、定义这个Pipeline执行阶段及相应的全局变量,并引入外部YAML文件。

2、监听当包含+module+的分支名发生push,或者trigger中变量包含magic-common-component时,执行名为dev-install-package-common的JOB,先检查其他Pipeline中是否已经存在dev-install-package-common任务,如果有,则进入pending,如果没有则,在相应的stage阶段,在magic-work这个runner中执行这个job中的script。

关键字stages

描述:用于定义JOB的执行组,并且JOB将在定义的stage阶段运行。

如果stages未在.gitlab-ci.yml文件中定义,则默认管道阶段为:

.pre → build → test → deploy → .post

特点:

同一阶段的作业并行运行。

下一阶段的作业在上一阶段的作业成功完成后运行。

我定义了三个阶段:

1、组件publish到npm库

2、安装依赖

3、编译代码

关键字variables

描述:定义变量,可以在全局和JOB中使用。

特点:

如果在全局进行了定义,则在创建管道时,每个变量都会复制到每个JOB配置中。

如果JOB已经定义了该变量,则作业级变量优先。

关键字include

描述:模块化,引入外部 YAML 文件

特点:

.gitlab-ci.yml文件中的内容合并

无论include位置在哪里,都会先进行合并

最多嵌套100个

.gitlab-ci.yml会覆盖include引入的相同关键字

include的文件类型包括以下几种:

include:local
include:file
include:remote
include:template

创建JOB

描述:Pipeline配置都是从JOB开始的, 其中JOB是.gitlab-ci.yml最基本的元素

特性:

1、相同stage中的job会并行执行 2、相同stage中的job都执行成功时,stage才会成功 3、任何一个job失败,该 stage 失败,pipeline也会失败 4、可定义的数量不受限制

JOB内stage

描述:定义作业在哪个阶段运行

特点:

如果stage未定义,则默认在test阶段执行

如果JOB在不同的runner上运行,它们可以并行运行(我试了下好像不太行,可能打开方式不对...)

如果在一个runner运行,想并行运行,则需要设置concurrent来实现

resource_group

描述:用于resource_group创建资源组,以确保同一项目的不同管道之间的作业互斥。

例如,如果属于同一资源组的多个作业同时排队,则只有一个作业启动。其他作业等到resource_group空闲为止。

parallel

描述:在单个管道中并行运行作业多次,并行作业从job_name 1/N到依次命名job_name N/N。

这个属性很有用,我们可以将一个大的任务,拆分成多个小任务并行执行,来节约执行时间

JOB内script

描述:指定运行器要执行的命令,我们这里用的shell

特点:

可执行单行命令

可输入多行命令,借助- |来实现

支持YAML锚点:通过&来定义复用script,通过*来引入复用的script。

only

描述:使用only来控制何时将作业添加到管道

支持类型:

  only:refs
  only:variables
  only:changes
  only:kubernetes

我们这里用了ref(分支)和variables(变量)

当匹配到的分支被push时触发或当匹配到传入的变量时被触发

条件支持:正则表达式和一些条件判断方法

tags

描述:选择特定运行器来执行script,即在注册runner时定义的tag

执行

我们已经定义完我们的配置,我们这里通过push分支来触发,接下来看下我们执行的Pipeline

Project → CI/CD → Pipelines

如图:

上图我们发现,有两个任务,但是第二个任务一直处于pending状态,要等到第一个任务完成后,才会执行第二个任务。

这是我们无法接受的,这会严重影响我们的效率。

前边提到JOB应该是并行执行的,那为什么还会一直pending呢?

其实默认情况下,gitlab-runner每次运行的job数量是1,我们这里需要修改一下,路径:

vi /etc/gitlab-runner/config.toml

修改执行数值

concurrent=20

再次运行,则并行处理

API触发

通过以上我们实现,通过分支push来触发JOB,但是还是需要一些操作成本的,为了更易用,我们决定通过api来触发。

开启API

获取Token

开启后,我们就可以通过接口来触发Pipeline了

主要分为4种:

1、Use cURL

curl -X POST \
     -F token=TOKEN \
     -F ref=REF_NAME \
     http://gitlab.xxx.com/api/v4/projects/id/trigger/pipeline

2、Use .gitlab-ci.yml

trigger_build:
  stage: deploy
  script:
    - "curl -X POST -F token=TOKEN -F ref=REF_NAME http://gitlab.xxx.com/api/v4/projects/id/trigger/pipeline"

3、Use webhook

http://gitlab.xxx.com/api/v4/projects/id/ref/REF_NAME/trigger/pipeline?token=TOKEN

4、Pass job variables 传入变量

curl -X POST \
     -F token=TOKEN \
     -F "ref=REF_NAME" \
     -F "variables[RUN_NIGHTLY_BUILD]=true" \
     http://gitlab.xxx.com/api/v4/projects/id/trigger/pipeline

之前我们一直都是通过不同分支名push来触发的,现在我们就可以通过api传入不同变量,来触发不同的JOB,分别执行不同的项目部署了。

总结

以上为我们实现的基本原理,还有一些很强大的功能文中没有提到,例如cache、Kubernetes及更全面的api等等功能。如果大家感兴趣,可以进一步查看官方文档,写的很详细。

通过持续集成帮助我们减少大量重复工作,减少风险,快速构建等等优点,大家也快快用起来吧。就先写到这里,不对的地方也希望大家多多指正,一起进步~

Copyright© 2013-2020

All Rights Reserved 京ICP备2023019179号-8