持续集成,让很多开发团队又 「 爱 」 又 「 恨 」 。爱,在于整个流程对项目的交付价值大有裨益,尽最大可能地减少不必要的加班;恨,在于成本过大,部署的困难、工程文化的隔阂。
首先看下,持续集成,持续交付,持续部署的概念
持续集成
持续集成强调开发人员提交了新代码之后,立刻进行构建、(单元)测试。根据测试结果,我们可以确定新代码和原有代码能否正确地集成在一起。 持续交付
持续交付在持续集成的基础上,将集成后的代码部署到更贴近真实运行环境的「类生产环境」(production-like environments)中。比如,我们完成单元测试后,可以把代码部署到连接数据库的 Staging 环境中更多的测试。如果代码没有问题,可以继续手动部署到生产环境中。 持续部署
持续部署则是在持续交付的基础上,把部署到生产环境的过程自动化。
互联网软件的开发和发布,已经形成了一套标准流程,最重要的组成部分就是持续集成(Continuous integration,简称CI)。下面来详细的进行讲解
一、持续集成
持续集成(Continuous integration,简称CI)指的是,频繁地(一天多次)将代码集成到主干。
它的好处主要有两个。
(1)快速发现错误。每完成一点更新,就集成到主干,可以快速发现错误,定位错误也比较容易。 (2)防止分支大幅偏离主干。如果不是经常集成,主干又在不断更新,会导致以后集成的难度变大,甚至难以集成。
持续集成的目的,就是让产品可以快速迭代,同时还能保持高质量。它的核心措施是,代码集成到主干之前,必须通过自动化测试。只要有一个测试用例失败,就不能集成。
Martin Fowler说过,"持续集成并不能消除Bug,而是让它们非常容易发现和改正。"
与持续集成相关的,还有两个概念,分别是持续交付和持续部署。
二、持续交付
持续交付(Continuous delivery)指的是,频繁地将软件的新版本,交付给质量团队或者用户,以供评审。如果评审通过,代码就进入生产阶段。
持续交付可以看作持续集成的下一步。它强调的是,不管怎么更新,软件是随时随地可以交付的。
三、持续部署
持续部署(continuous deployment)是持续交付的下一步,指的是代码通过评审以后,自动部署到生产环境。
持续部署的目标是,代码在任何时刻都是可部署的,可以进入生产阶段。
持续部署的前提是能自动化完成测试、构建、部署等步骤。它与持续交付的区别,可以参考下图。
四、流程
根据持续集成的设计,代码从提交到生产,整个过程有以下几步。
4.1 提交
流程的第一步,是开发者向代码仓库提交代码。所有后面的步骤都始于本地代码的一次提交(commit)。
4.2 测试(第一轮)
代码仓库对commit操作配置了钩子(hook),只要提交代码或者合并进主干,就会跑自动化测试。
测试有好几种。
- 单元测试:针对函数或模块的测试
- 集成测试:针对整体产品的某个功能的测试,又称功能测试
- 端对端测试:从用户界面直达数据库的全链路测试
第一轮至少要跑单元测试。
4.3 构建
通过第一轮测试,代码就可以合并进主干,就算可以交付了。
交付后,就先进行构建(build),再进入第二轮测试。所谓构建,指的是将源码转换为可以运行的实际代码,比如安装依赖,配置各种资源(样式表、JS脚本、图片)等等。
常用的构建工具如下。
- Jenkins
- Travis
- Codeship
- Strider
- gitlab-ci
Jenkins和Strider是开源软件,Travis和Codeship对于开源项目可以免费使用。它们都会将构建和测试,在一次运行中执行完成。
4.4 测试(第二轮)
构建完成,就要进行第二轮测试。如果第一轮已经涵盖了所有测试内容,第二轮可以省略,当然,这时构建步骤也要移到第一轮测试前面。
第二轮是全面测试,单元测试和集成测试都会跑,有条件的话,也要做端对端测试。所有测试以自动化为主,少数无法自动化的测试用例,就要人工跑。
需要强调的是,新版本的每一个更新点都必须测试到。如果测试的覆盖率不高,进入后面的部署阶段后,很可能会出现严重的问题。
4.5 部署
通过了第二轮测试,当前代码就是一个可以直接部署的版本(artifact)。将这个版本的所有文件打包( tar filename.tar * )存档,发到生产服务器。
生产服务器将打包文件,解包成本地的一个目录,再将运行路径的符号链接(symlink)指向这个目录,然后重新启动应用。这方面的部署工具有Ansible,Chef,Puppet等。
4.6 回滚
一旦当前版本发生问题,就要回滚到上一个版本的构建结果。最简单的做法就是修改一下符号链接,指向上一个版本的目录。
五,持续集成的原则
业界普遍认同的持续集成的原则包括:
- 需要版本控制软件保障团队成员提交的代码不会导致集成失败。常用的版本控制软件有 git、svn 等;
- 开发人员必须及时向版本控制库中提交代码,也必须经常性地从版本控制库中更新代码到本地;
- 需要有专门的集成服务器来执行集成构建。根据项目的具体实际,集成构建可以被软件的修改来直接触发,也可以定时启动,如每半个小时构建一次;
- 必须保证构建的成功。如果构建失败,修复构建过程中的错误是优先级最高的工作。一旦修复,需要手动启动一次构建。
六,持续集成系统的组成
由此可见,一个完整的构建系统必须包括:
- 一个自动构建过程,包括自动编译、分发、部署和测试等。
- 一个代码存储库,即需要版本控制软件来保障代码的可维护性,同时作为构建过程的素材库。
- 一个持续集成服务器。
七,持续集成CI实战
Jenkins
Jenkins作为老牌的持续集成框架,在这么多年的发展中,积累很多优秀的plugin工具,对进行持续集成工作带来很大的便利。
gitlab-ci
gitlab-ci作为gitlab提供的一个持续集成的套件,完美和gitlab进行集成,gitlab-ci已经集成进gitlab服务器中,在使用的时候只需要安装配置gitlab-runner即可。 gitlab-runner基本上提供了一个可以进行编译的环境,负责从gitlab中拉取代码,根据工程中配置的gitlab-ci.yml,执行相应的命令进行编译。
下面就gitlab-ci进行一个简单的介绍
Gitlab CI介绍
GitLab提供可持续集成服务。只要在你的仓库根目录 创建一个.gitlab-ci.yml 文件, 并为该项目指派一个Runner,当有合并请求或者 push的时候就会触发build。
这个.gitlab-ci.yml 文件定义GitLab runner要做哪些操作。 默认有3个[stages(阶段)]: build、test、deploy。
当build完成后(返回非零值),你会看到push的 commit或者合并请求前面出现一个绿色的对号。 这个功能很方便的让你检查出来合并请求是否会导致build失败, 免的你去检查代码。
大部分项目用GitLab's CI服务跑build测试, 开发者会很快得到反馈,知道自己是否写出了BUG。
所以简单的说,要让CI工作可总结为以下几点:
- 在仓库根目录创建一个名为.gitlab-ci.yml 的文件
- 为该项目配置一个Runner
完成上面的步骤后,每次push代码到Git仓库, Runner就会自动开始pipeline。
基于Gitlab CI快速搭建持续集成环境
开启 Gitlab CI 功能
开启 Gitlab CI 功能
在自己的Gitlab中打开CI界面,比如迅雷的Gitlab,地址是 https://gitlab.xunlei.cn/ci/projects,找到自己项目后选择 “Add project To CI”
项目 Gitlab CI 配置
项目 Gitlab CI 配置
可以对项目的构建进行详细配置,比如构建的时间表及需要 CI 进行持续集成的分支等,这里配置了 对master和develop分支进行持续集成。
配置一个 Runner
GitLab CI 中,runner 是一个隔离的虚拟机器,用来配合 Gitlab CI 进行构建。
安装 GitLab-Runner
安装gitlab-ci-multi-runner
环境:centos 7, 使用了清华大学的镜像
新建 gitlab-ci-multi-runner.repo
代码语言:javascript复制touch /etc/yum.repos.d/gitlab-ci-multi-runner.repo
将以下内容写入文件
代码语言:javascript复制[gitlab-ci-multi-runner]
name=gitlab-ci-multi-runner
baseurl=http://mirrors.tuna.tsinghua.edu.cn/gitlab-ci-multi-runner/yum/el7
repo_gpgcheck=0
gpgcheck=0
enabled=1
gpgkey=https://packages.gitlab.com/gpg.key
执行
代码语言:javascript复制sudo yum makecache
sudo yum install gitlab-ci-multi-runner
其他系统安装
https://docs.gitlab.com/runner/install/
Gitlab CI Multi Runner 国内镜像
https://mirrors.tuna.tsinghua.edu.cn/help/gitlab-ci-multi-runner/
Runner 的区分
Runner 的区分
- 指定 Runner: 可以指定运行某一个Gitlab CI 的项目
- 共享 Runner:可以运行所有的 CI 项目
Gitlab Runner 和 Gitlab 不能安装在同一个机器
注册一个指定的runner
代码语言:javascript复制注册共享的Runner 需要 gitlab 的 admin 权限
sudo gitlab-ci-multi-runner register
- 输入Gitlab CI地址, (e.g. https://gitlab.xunlei.cn/ci)
- 输入项目CI token
- 输入 Runner 描述(e.g. home.xl9.xunlei.com 测试runner)
- 输入 Runner 标签,可以多个,用逗号隔开(e.g. 10.10.34.91-dev)
- 输入 Runner 执行的语言 (e.g. shell)
注册完成之后,GitLab-CI立刻就会多出一条Runner记录
启动 runner
这里把批量运行Runner这个功能安装为一项服务
代码语言:javascript复制# Install runner as service and start it:cd ~
gitlab-ci-multi-runner install
gitlab-ci-multi-runner start
创建.gitlab-ci.yml
.gitlab-ci.yml
文件是什么
.gitlab-ci.yml
用来配置 CI 用你的项目中做哪些操作,这个文件位于仓库的根目录。
当有新内容push到仓库后,GitLab会查找是否有.gitlab-ci.yml文件,如果文件存在, Runners 将会根据该文件的内容开始build 本次commit。
.gitlab-ci.yml
使用YAML语法, 你需要格外注意缩进格式,要用空格来缩进,不能用tabs来缩进。
创建.gitlab-ci.yml
代码语言:javascript复制stages: - test - deploy# 变量variables: DEV_RSYNC_PATH: "/data/deploy/xunlei.com/misc.xl9.xunlei.com/d/"# 所有 stage 之前的操作before_script: - npm set registry http://xnpm.sz.xunlei.cn - npm install# 代码检查lint: stage: test script: npm run lint# 单元测试unit: stage: test script: npm run unit# 部署测试服务器deploy_dev: stage: deploy tags: - 10.10.34.91-dev only: - develop script: - rsync -av --delete-after --exclude-from=/data/shell/home.xl9.xunlei_exclude.list . $DEV_RSYNC_PATH - chmod -R 755 $DEV_RSYNC_PATH - chown -R nobody:nobody $DEV_RSYNC_PATH - find $DEV_RSYNC_PATH -type f -exec chmod 644 {} ; - cd $DEV_RSYNC_PATH - npm install
推送构建配置文件
配置好.gitlab-ci.yml
文件之后,只要把它加入git后然后推送到远程仓库,CI就会开始自动化集成
查看可视化的构建过程
Gitlab CI 提供了可视化的构建过程的显示可以随时查看。
查看可视化的构建过程
启用构建邮件通知
Gitlab CI提高了一些 Service, 比如邮件通知,可以配置一系列接受邮件的地址和是否只有失败的时候才发送邮件。
启用构建邮件通知
邮件内容
徽章
徽章,当Pipelines执行完成,会生成徽章,你可以将这些徽章加入到你的README.md文件或者你的网站。
整体来说,持续集成为我们带来了以下好处:
尽早暴露问题,把握开发节奏
在团队开发中,问题暴露的越早,修复代码的成本越低,成功部署的胜算就越大。持续集成高频率地编译、测试、审查、部署项目代码,这其中代码集成是主要的风险来源。要想规避这个风险,只有提早集成,持续而有规律的集成,以此来确保当前代码库的质量,把握开发的进程和节奏。
当然发现问题代码,也不要一味地坠入快速的简单修复之中,要投入时间和精力保持代码的整洁、敞亮。
很明显的一点,使用持续集成后,程序员们提交代码也会变得更加小心谨慎。想想应该没人乐意让其他同事不停地见到自己的分支上 CI 失败的通知邮件吧:)
避免重复操作,让流程自动化
工具环境的滞后,加上工作的重复枯燥,让开发者对写程序失去新鲜感。
在持续集成过程,一步一步的编译、测试、审查、部署,牵扯大量重复的工作。搭建持续集成环境,可以让开发人员不再需要手动地 checkout 代码,节省大量的时间和避免不必要的压力,把精力放在更多有价值的事情上,这样也可以形成良性的循环。
保持随时部署,简化发布流程
每日高频率的集成保证了项目随时处于可部署运行的状态,如果没有持续集成,项目发布之前将不得不手动地集成,然后花费大量精力修复集成问题,弄的团队成员疲惫不堪。
使用持续集成,帮助我们跨越频繁部署的障碍。大家都知道,只有保持频繁部署,让用户看到产品的新特性, 才能不断地磨合优化构建和发布流程,让反馈周期更短更有效。
增强团队信心,建立工程师文化
无论什么样的工程师,都会对存在大量 bug 的代码产生恐惧心理,这就是心理学上的的 Broken Windows 综合症(Broken Windows syndrome)。CI 可以有效防止破窗综合症,让开发团队一点点积累起对产品的信心,对使用技术的保持成就感。
与此同时,持续集成让每个人都能看到良好的界面和视图来了解项目的成熟度,让所有人都知道正在发生什么。也许更容易增强开发信心,培养团队良好的工程文化,齐心协力向目标前进。
文章参考出处:
https://www.zhihu.com/question/23444990
http://www.ruanyifeng.com
http://www.jianshu.com/p/705428ca1410
http://blog.flow.ci/ci_benefits/