文章内容更新请以 WGrape GitHub博客 : 多项目下CI管理方案的设计与实现 为准
前言
本文原创,著作权归WGrape所有,未经授权,严禁转载
一、背景介绍
在团队开发中,工作并不只是分而治之,而是分、治以及集成。基于CI可以实现强大且深度定制的服务自动化,现在已经越来越多的团队开始重视并投入到CI建设的工作中。
大部分公司的CI建设是基于Gitlab CI
,在项目根目录下创建.gitlab-ci.yml
文件即可简单快速的实现,项目结构如下所示
- .gitlab
- check_code.sh
- unit_test.sh
- cmd
- app
- api
- define
- service
- AService
- BService
- .gitignore
- .gitlab-ci.yml
在单体架构下,上面这种基于单项目下的CI建设没有任何问题。但是在微服务架构下,就会遇到非常棘手的多项目下CI管理的问题。
由于微服务架构下,一套代码被划分到多个代码库中,多个代码库下都有自己的CI代码,一旦CI中任意一个流程有变动,那么所有项目都需要配合修改,造成的整体联动调整过大。
所以本文会设计并实现一种简单易用的方式,以解决微服务架构下多项目的CI管理问题。
二、设计方案
1、本地管理
本地管理的设计思想是基于快拷贝。即仍然使用单项目下的CI代码,但是远程的一个仓库中会存储所有项目通用的CI代码。
当每次需要变动的时候,都会把远程通用的CI代码拷贝到本地各个单项目中,然后本地的各个项目再单独修改并提交,完成CI的执行。
2、远程管理
远程管理的设计思想是基于WORA
,即write once, run anywhere(一次编写,到处运行)
。
(1) 一次编写
只维护一套通用的CI代码CIManager
(2) 到处运行
每个代码库只需要有自己的一个.gitlab-ci.yml
文件,且这个文件内容会保持精简而通用,如下所示
image: golang:1.17
variables:
PROJECT_NAME:
before_script:
- echo '====== CI Start Running ========='
- cd /temp && git clone git.xxx.com/xxx/CIManager && cd CIManager && cp -r . /yourproject && cd /yourproject && bash remote_mgr.sh runci
after_script:
- echo '====== CI Stopped Successfully ========='
当提交代码时,在远程的Runner机器上,会自动拉取CIManager
代码库并运行start.sh
脚本,完成CI的执行。
三、通用CI的设计
多项目下CI管理方案的一个重要思想,就是设计一个通用的CI逻辑。这个CI逻辑寄托在一个叫做CIManager的代码库中。
1、目录结构
CIManager代码库的目录结构如下所示
.gitlab
目录 :存放与CI相关的脚本逻辑.gitlab/hook
目录 :存放与git相关的钩子.gitlab/include
目录 :存放需要引入的脚本.gitlab/apidoc_gen.sh
文件 :文档自动生成脚本.gitlab/check_code.sh
文件 :代码检查脚本.gitlab/config_check.sh
文件 :配置检查脚本.gitlab/godep_check.sh
文件 :依赖检查脚本.gitlab/unit_test.sh
文件 :单元测试脚本.gitlab/pre_install.sh
文件 :预安装脚本.gitlab/print_env.sh
文件 :打印环境和本地变量脚本.gitlab/mock_ci.sh
文件 :本地CI模拟执行脚本.golangci.yml
文件 :代码检查的配置文件.gitlab-ci.yml
文件 :gitlab CI
配置文件
2、接入Web Hook
CIManager项目内部接入了不同的Web Hook,通过接入Web Hook实现各种场景需求,如钉钉消息通知。
curl -H 'Content-type: application/json' -d "{\"msgtype\":\"text\", \"text\": {\"content\":\"${MESSAGE}\"}}" "https://oapi.dingtalk.com/robot/send?access_token=${DING_ACCESS_TOKEN}"
3、消息通知
为了方便知道CI的内部执行过程,在CI中的任何一个过程,如果出现失败,都会发出详细的失败通知。包括失败原因、操作人等。基于这个场景需求,在CIManger内部定义了一个简单的CI消息通知,其字段结构和含义如下所示
字段 | 值 | 含义 |
---|---|---|
操作 | - | 根据分支不同,生成不同的操作名,如请求合并到主分支 |
项目 | ${CI_PROJECT_NAME} |
项目的名称 |
操作人 | ${GITLAB_USER_EMAIL} |
提交这个请求的操作人 |
失败原因 | ${FAILURE_REASON} |
执行CI失败的原因 |
查看详情 | ${CI_PIPELINE_URL} |
执行Pipeline的地址 |
实现原理是通过Gitlab系统变量和自定义变量实现脚本间信息的传递。
四、如何实现
1、本地管理的实现
在项目根目录下有一个local_mgr.sh
脚本,它会提供一系列的命令实现对多个项目的管理。它的.gitlab-ci.yml
配置内容如下 :
# could not use go:1.13
# Using Docker executor with image go:1.13 ...
# Pulling docker image go:1.13 ...
# ERROR: Job failed: Error response from daemon: pull access denied for go, repository does not exist or may require 'docker login': denied: requested access to the resource is denied (executor_docker.go:188:3s)
# Variables: https://docs.gitlab.com/ee/ci/variables/index.html
image: golang:1.17
variables:
GOPATH: /go
PROJECT_NAME:
PROJECT_ID:
PROJECT_PATH:
DING_NOTICE_KEYWORD:
GITLAB_API_TOKEN:
GITLAB_HOST:
DING_ACCESS_TOKEN:
before_script:
- echo '====== CI Stage Start Running ========='
- bash .gitlab/print_env.sh
after_script:
- echo '====== CI Stage Stopped Successfully ========='
stages:
- detect_project
- godep_check
- config_check
- apidoc_gen
detect_project:
stage: detect_project
script:
- bash .gitlab/pre_install.sh
- bash .gitlab/check_code.sh
- bash .gitlab/unit_test.sh
only:
- merge_requests
- master
- test
godep_check:
stage: godep_check
script:
- bash .gitlab/godep_check.sh
only:
- merge_requests
- master
- test
config_check:
stage: config_check
script:
- bash .gitlab/config_check.sh
only:
- merge_requests
- master
- test
apidoc_gen:
stage: apidoc_gen
script:
- bash .gitlab/pre_install.sh
- bash .gitlab/apidoc_gen.sh
only:
- merge_requests
- test
(1) fastcopy命令
bash local_mgr.sh fastcopy ${sourceDir} ${targetDir}
实现原理是先将远程通用的CI代码拉到本地,然后全量覆盖到本地项目内。这一系列操作被封装集成在fastcopy
命令中。
2、远程管理的实现
在项目根目录下有一个remote_mgr.sh
脚本,它会提供一系列的命令实现对多个项目的管理。
(1) runci命令
注意事项 :此命令只允许Runner调用和执行
实现原理是每一个项目都有一个自己的.gitlab-ci.yml
配置文件,当提交代码触发CI后,在Runner机器上执行before_script
中的脚本,完成在Runner机器上执行CIManager
中通用的CI逻辑。
3、开源项目CIManager
开源项目CIManager正是基于远程管理方式实现的多项目CI管理框架,更多请查看原项目。
4、使用CIManager的项目例子
基于CIManager项目构建的apimock-example,轻松实现更加快速高效的CI管理方案,在这里查看Pipline运行示例。
五、总结
对于多项目下的CI管理方案,本文设计并实现了本地管理和远程管理者两种方案。根据自己的需要选择合适的方案即可,不过无论使用哪种方案,都可以简单高效解决我们的问题。