Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

多项目下CI管理方案的设计与实现 #249

Closed
WGrape opened this issue Aug 9, 2022 · 0 comments
Closed

多项目下CI管理方案的设计与实现 #249

WGrape opened this issue Aug 9, 2022 · 0 comments

Comments

@WGrape
Copy link
Owner

WGrape commented Aug 9, 2022

前言

本文原创,著作权归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代码。

image

当每次需要变动的时候,都会把远程通用的CI代码拷贝到本地各个单项目中,然后本地的各个项目再单独修改并提交,完成CI的执行。

image

2、远程管理

远程管理的设计思想是基于WORA,即write once, run anywhere(一次编写,到处运行)

image

(1) 一次编写

只维护一套通用的CI代码CIManager

(2) 到处运行

每个代码库只需要有自己的一个.gitlab-ci.yml文件,且这个文件内容会保持精简而通用,如下所示

image: golang:1.17

before_script:
  - echo '====== CIManager Start Running ========='

after_script:
  - echo '====== CIManager Stopped Successfully ========='

stages:
  - CIManager

CIManager:
  stage: CIManager
  script:
    - git clone https://github.com/wgrape/CIManager.git ; cp -an ./CIManager/. ./ ; rm -rf ./CIManager ; bash start.sh

当提交代码时,在远程的Runner机器上,会自动拉取CIManager代码库并运行start.sh脚本,完成CI的执行。

三、通用CI的设计

多项目下CI管理方案的一个重要思想,就是设计一个通用的CI逻辑。这个CI逻辑寄托在一个叫做CIManager的代码库中。

image

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_NAME}}
  PROJECT_ID: {{PROJECT_ID}}
  PROJECT_PATH: {{PROJECT_PATH}}
  DING_NOTICE_KEYWORD: {{DING_NOTICE_KEYWORD}}
  GITLAB_API_TOKEN: {{GITLAB_API_TOKEN}}
  GITLAB_HOST: {{GITLAB_HOST}}
  DING_ACCESS_TOKEN: {{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管理方案,本文设计并实现了本地管理和远程管理者两种方案。根据自己的需要选择合适的方案即可,不过无论使用哪种方案,都可以简单高效解决我们的问题。

@WGrape WGrape changed the title 多项目的CI管理方案设计与实现 多项目下CI管理方案的设计与实现 Aug 16, 2022
@WGrape WGrape closed this as completed Aug 26, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant