首页 > 代码库 > CI-持续集成

CI-持续集成

1   概述

持续集成(Continuous Integration)是一种软件开发实践。

2   主要环境及工具

  • Git代码管理系统(如:GitOSC)
  • Linux操作系统(Ubuntu)
  • Jenkins系统软件安装包
  • Jenkins的Python语言的SDK
  • Python及 Tornado Web 框架

以上的技术选型,都是尽量使用 开源 且 主流 的系统,这样的好处如下:

  • 节省软件购置成本
  • 有丰富的参考资料
  • 有能力的企业或者个人可以按照需求做自定义扩展

3   原理分析

在上一篇文章里面,对持续集成绘制过一个基本的结构图,如下:

技术分享

基本流程如下:

  1. 开发人员推送代码到Git

  2. Git通知Jenkins

  3. Jenkins开启构建

  4. 构建完成开启后续任务
    • 自动化测试
    • 自动化部署
  5. Jenkins通知自动化发布系统

  6. 发布系统持续后续的任务……

这里面涉及的系统有:

  1. 代码版本管理系统
  2. 自动化构建系统
  3. 自动化测试系统
  4. 自动化发布系统

关于 自动化发布系统 这个基本上属于运维方面的内容,在互联网产品领域情形和技术需求比较复杂,暂时不列入本部分的内容。但是Jenkins 能够有接口去通知相应的发布系统,以达到 事件信息流的连续性

本文则主要从技术角度来将这些系统联合起来。

4   Jenkins安装及配置

4.1   下载和安装

关于 Jenkins 的下载及安装,可以参考其官网。

1
https://jenkins-ci.org/

直接下载Ubuntu/Debian版本,在Ubuntu服务器上安装即可。

由于过程比较简单,网上相关教程很多,此处也不再赘述。但是一般Jenkins安装完毕后,最初的权限配置会比较繁琐,所以本文重点从相应的使用场景出发,实现一个完整的带权限配置的解决方案。

5   内网持续集成系统

对于只是在 内网 使用持续集成的团队来说,权限的配置就相对简单一些。因为只是在内网,所以可以将权限的要求放松,只要保证公司网络之外的人无法访问到 Jenkins 服务即可。

注意:如果要和git服务的webhook形成完整的事件流,则git服务也需要在内网,否则 构建事件 无法被 代码推送事件 给触发。

5.1   权限配置

对 Jenkins 进行如下操作:

[系统管理]->[Configure Global Security]->[访问控制]->[授权策略]->[项目矩阵授权策略]

对 匿名用户 进行如下配置:

  • Overall: Read -> Enabled
  • Job: Read -> Enabled

具体配置界面如下:

技术分享

注意:如果不这样配置,则后面提到的基于git的构建触发器将无法通过调用指定的url接口来触发构建。因为webhook只能构造 单次 简单的http请求,无法构造由多个请求组成的会话,故而无法调用需要身份授权的接口。

5.2   构建触发器

一般情况下,构建都是以代码的发布作为起始事件点,所以需要和git服务器建立事件关联,在Jenkins具体的项目的配置界面中,对 构建触发器 进行配置。

技术分享

目前网络上一般都是介绍的这种方式,具体的细节,此处就不再赘述,感兴趣的同学可以自行在网络上搜索。

基本原理图如下:

技术分享

5.3   最终效果

可以达到如下效果:

  • 开发人员向内网的git服务器推送代码
  • git服务的webhook向内网jenkins发送消息并 触发构建
  • Jenkins执行构建相关命令

以上的内网方案的特点如下:

  • 优点:
    • 配置简单
    • 不需要配置人员进行任何的开发活动
  • 缺点
    • 无法限制匿名用户的权限
    • 出于安全考虑,只能在内网使用

当然,对于 开发资源相对匮乏 的小团队而言,推荐通过以上方法 快速搭建 自己的内部的持续集成系统,毕竟先快速生产自己的特色产品才是最重要的事情。

6   公网持续集成系统

对于前面的 内网持续集成系统 的优点和缺点都介绍之后,作为一个以 开放为主要精神 的互联网团队来说,肯定是无法满足这样一个 封闭的内部网络 系统的,所以下面就要隆重介绍 公网持续集成系统 。

对于 内网系统 在配置上进行了 偷懒 ,但是实际上却在其它地方付出了 巨大的代价 ,这些代价包括:

  • 无法使用市场上已经成熟的公网git服务(包括但不限于:bitbucket,github,git@osc)
  • 团队成员的工作地点将受到限制,必须局限于同一个内网环境中

所以,如果配置人员拥有一定的系统设计能力和开发能力,还是建议搭建 公网持续集成系统 。

公网方案具有如下特点:

  • 缺点:
    • 需要配置人员具备系统设计能力和开发能力
  • 优点:
    • 能够将系统以登录授权的方式部署在公网
      • 未登录的匿名用户无法查看任何项目信息
      • 登录用户可以配置不同的权限
    • 能够作为服务器来接受来自事件来触发构建
      • 可以通过公网git服务的webhook触发
      • 可以通过自定义的任何公网IT系统触发(按钮,短信,微信等等)
    • 可扩展性强,理论上可以和任何的公共互联网服务进行对接

6.1   权限配置

公网持续构建系统对权限控制有如下要求:

  • 未登录的匿名用户无法查看任何项目信息
  • 登录用户可以配置不同的权限

对 Jenkins 进行如下操作:

[系统管理]->[Configure Global Security]->[访问控制]->[授权策略]->[项目矩阵授权策略]

技术分享

可以建立三类用户并进行权限配置:

  • 普通用户

    登录后,可以查看相应的项目的名称及构建的状态(主要是基本的查看功能)

  • 管理员用户

    登录后,可以进行构建操作,对任务进行增加及删除等等高级操作(主要是项目管理功能)

  • 匿名用户

    未登录用户,不具备任何权限,只呈现登录界面

有了这样的登录授权机制,就不用再使用网络进行隔离了,此系统就可以放心地放到公网服务器上了。

前面提到的内网系统的解决方案,主要原因是:

  1. 基于git的webhook无法对需要认证的 构建触发器 接口请求发起有效构建请求
  2. 将 构建触发器 接口设置为不需要认证,会导致匿名用户的权限过大

如果部署到公网,则需要解决如上的矛盾之处。一个比较好的思路就是:

  1. 按照要求配置好相应的用户权限(见公网权限配置方案)
  2. 开发中间件来完成 构建API 的用户登录认证

6.2   构建触发器

在兼顾Git的webhook的特点和Jenkins构建特性的情况下,可以提出如下所描述的解决方案:

使用web服务作为中间件,来模拟用户登录:将本来需要多个请求组成的会话变成单一的Http请求(可以在单次请求的url里面加入授权的token),这样就可以被Git的webhook所调用。

基本原理图如下:

技术分享

主要的通讯过程为:

  1. Git Server 接收代码并向 Web Server 发起单次Http请求(参数带上token)
  2. Web Server 先向 Jenkins Server 发起认证授权请求
  3. Web Server 再向 Jenkins Server 发起构建请求,触发构建

当然,由于 Jenkins 提供了Pyhon语言的SDK,所以以上 步骤2和3其实可以简化为对其SDK的调用了。

安装方法:

1
pip install python-jenkins

最简单的使用示例如下:

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
# coding:utf-8
"""
jenkins相关的工具函数及配置
"""
from dtlib.dtlog import dlog
import jenkins
 
__author__ = ‘harmo‘
 
 
jenkins_url =‘http://jenkins.xxxx.com‘
jenkins_user = ‘jenkins_user‘
jenkins_passwd =‘jenkins_user_password‘
 
 
def build_job(project_name):
    """
    构建项目
    :param project_name: 项目名称
    :return:
    """
    jen =jenkins.Jenkins(jenkins_url, username=jenkins_user, password=jenkins_passwd)
    jen.build_job(project_name)
    print("build %s succeed" %project_name)
 
if __name__ == ‘__main__‘:
    build_job("your-project-name")

开发人员只需要在自己的web程序里面集成此SDK,并进行参数化,即可完成webhook和jenkins的中间件。

6.3   最终效果

可以达到如下效果:

  • 接收git服务的webhook请求
  • 解析请求中代码提供信息,包括但不限于:提交时间,提交人,分支,备注,项目名称等等
  • 进行条件过滤,并触发 Jenkins 进行自动构建(例如:本文是对release分支进行监控,来触发构建)

使用中间件的好处是,对构建的事件有很好的订制性,包括分支监控,提交人权限等等。当然,也可以只使用最简单的功能:只要有人向 release 分支提交了代码,那么就会触发自动构建流程,这样就完成了整个流程了。

当然,构建成功之后到发布还有一些后续的流程,比如:

  1. 开发人员完成代码,自测完毕后,推送代码到 release 分支

  2. 触发自动构建,构建成功,并生成构建产物

  3. 将构建产物发布到 测试服务器

  4. 触发自动化测试脚本
    • 如果测试不通过,发送消息给相关人员,终止后续流程
    • 如果测试通过,通知 自动化发布系统
  5. 由 自动化发布系统 完成构建产物向生产服务器发布的过程

6.4   其它说明

在得知Jenkins有Python语言的SDK之前,其实还有个其它方法也能够完成登录授权并调用构建接口。直接通过接口来模拟用户登录行为(因为Jenkins登录处不需要验证码),然后获取登录成功的sessionid ,以此作为授权token来调用构建的接口。

具体的技术实现的代码细节不在本文的讨论内容中出现,只要了解登录的原理,很容易就开发出来。

此处做一些说明的目的是,其实只要了解原理,即使官方没有提供一些工具,仍然也是有办法完成想要的功能的。

7   持续集成的应用场景

持续集成的平台搭建完毕后,关于其可应用的项目也进行一些简单的介绍。

基本上任何的软件项目,从生产到最终发布都可以划分为如下几个过程:

  1. 代码开发
  2. 构建生成发布产物
  3. 发布上线

不同类型项目,无非就是构建过程不同而已,本文也简单的列举一下几类项目的应用方式的流程,关于具体的技术手段就由各人根据各自的项目去做相应的订制开发了。

7.1   脚本类服务端项目

主要的代表有:Php,Python等等。

它们的构建产物就本身的源代码,所以整个持续集成的过程如下:

  1. 开发人员发布代码到Git仓库
  2. Jenkins同步代码到本地(做好发布产物的备份,方便回滚)
  3. 部署好测试服务器
  4. 执行自动化测试脚本
  5. 发布到生产服务器或者驳回

7.2   需要编译的服务端项目

主要的代表有:Java等。

过程如下:

  1. 开发人员发布代码到Git仓库
  2. Jenkins同步代码到本地,并使用构建工具(如:Ant等)生成字节码的构建产物
  3. 将构建产物统一备份到相应目录,做好发布产物的备份,方便回滚
  4. 部署测试服务器
  5. 测试……
  6. 发布……

7.3   Web前端项目

主要代表有:Javascript,css等。

过程如下:

  1. 开发人员发布代码到Git仓库
  2. Jenkins同步代码到本地,并使用前端构建工具(如:Grunt等)生成构建产物
  3. 将构建产物统一备份到相应目录,做好发布产物的备份,方便回滚
  4. 部署测试服务器
  5. 测试……
  6. 发布……

7.4   移动端App项目

主要代表有:Android等。

过程如下:

  1. 开发人员发布代码到Git仓库

  2. Jenkins同步代码到本地,并使用构建工具生成构建产物Apk

  3. 将构建产物统一备份到相应目录,做好发布产物的备份,方便回滚

  4. 安装到设备,执行测试

  5. 测试
    • 如果测试通过,发布到各大应用市场
    • 如果测试未通过,发现bug后驳回

8   运行效果

Jenkins系统运行界面:

技术分享

Jenkins本身可以实现如下功能:

  • 完成项目持续集成及持续发布
  • 对构建过程进行记录
  • 构建完毕后可以发邮件或者微信通知相应的人员,形成良好的反馈机制

再通过文章前半部分提到的系统,团队就可以达到 持续交付 和 持续部署 的目的,从而实现项目的 快速迭代 。

持续交付:

技术分享

持续部署:

技术分享

当然,还有后续的更多的扩展功能,就需要测试开发人员去实现了。

9   小结

此文作为 持续集成 系列文章的具体技术实现部分,介绍了一个通用的技术框架的解决方案。剩下的就是各种针对自己的工程特性是编写各种脚本和安装各种环境了。这样 理论加实践,就构成了能够提供生产力的 持续集成 系统,大家Enjoy it吧。

目前以 Google 为代表的大型的互联网公司,基本上都是保持着这样的开发节奏。《Google软件测试之道》里面提到了这样的生产方式,但是没有给出具体的技术解决方案,本文则将这种构想进行技术落地,并发布此方案,希望能够给后来者一些帮助吧。

(如果大家有兴趣,后面可以针对某个具体的项目,来一个完整的持续集成示例,包括构建代码的编写,及过程的截图等等。但是如果反响不大,就不再浪费时间了)

CI-持续集成