一本好书使您改变。它将改变您的思想,您看待问题的角度和方式,最终,它将改改您的行为。然而,所有具有重要意义的改变都不会是在一夜之间发生的,如果您相信这种变革必会发生,不妨朝着这个方向去努力,经常改变,每次改变一点点。
——《持续集成:软件质量改进和风险降低之道》
CI的价值:
减少风险:缺陷的检测与修复变得更快;通过持续测试与持续审查,软件的健康程度可以测量;可以减少不实的假定。
减少重复过程
在任何时间、任何地点生成可部署的软件
增强项目的可见性
对开发团队的软件产品建立起更强大的产品信心
CI的阻碍:
增加了维护开销
团队变化太大
失败的构建太多
额外的软硬件成本
团队中7项好的CI实践:
经常提交代码
不要提交无法构建的代码
立即修复无法集成的构建
编写自动化的开发者测试
必须通过所有的测试和审查
执行私有构建
避免签出无法构建的代码
持续构建:
每次代码变更均进行自动化构建
将构建过程控制在单行命令下
将构建脚本从IDE中分离,避免与IDE产生耦合
集中放置软件资产
创建一致的目录结构
让构建快速失败
针对所有环境构建
使用专门的集成构建计算机
使用CI服务器
执行快速构建:分离较慢的构建,让集成构建少于10分钟
分阶段构建
持续数据库集成:
进行数据库自动化集成
使用本地数据库沙盒
将数据库资产放入版本控制库
让开发者能够修改数据库
让开发者成为开发团队的一员
持续测试:
线性系统的可靠性是每个系统组件的可靠性的乘积,因此特别需要保证底层组件的可靠性
进行自动化单元测试、组件测试、系统测试、功能测试,优先运行测试速度快的测试
为缺陷编写测试
让测试组件可以重复
尽量将测试限制为一个断言
进行代码持续审查,对代码的复杂度、耦合度、重复度等进行持续审查(sonarQube)
持续部署:
为每一个构建打上标签
执行测试
创建构建反馈报告
回滚构建的过程能力
持续反馈:
不要让您的团队习惯于忽略来自CI构建过程的消息
需要尽快反馈:持续集成的核心是减少缺陷引入、发现和修复之是的时间间隔
《持续交付:发布可靠软件的系统方法》
软件交付:
每次修改都应该触发反馈流程
必须尽快接收反馈
交互团队必须接收反馈并作出反应
无论部署到什么样的目标环境,都使用相同的部署方法
软件交付的原则:
为软件的发布创建一个可重复且可靠的过程
将几乎所有的事情自动化:配置管理自动化、验收测试自动化、数据库升降级自动化,对于硬件可采用虚拟化技术和像puppet这样的工具支撑自动化
将所有的东西都纳入版本控制
提前并频繁地做让你感到痛苦的事
内建质量:一旦发现缺陷,就要马上着手修复,交付团队中的每个人都应该对应用程序的质量负责
Done意味着已发布
交付过程是每个成员的责任
持续改进:团队应定期召开会议,反思过去的一段时间哪边做得好,哪边需要改进。
配置管理:
对所有内容进行版本控制,包括应用程序的软件、硬件及基础设施,与项目相关的所有东西都在版本控制库中(但是不推荐将源代码编译后的二进制文件也纳入版本控制中)
频繁提交代码到主干,尽量减少分支
使用意义明显的提交注释
以对待代码的方式来对待你的系统配置,使其受到正常的管理和测试
将特定于测试环境或生产环境的实际配置存放于与源代码分离的单独代码库中
应该严格控制生产环境,进行变更过程管理
高效配置管理策略:将二进制文件与配置信息分离;将所有的配置信息保存在一处。
基础设施应该具有自治特性,且非常容易重新搭建
保证配置管理是声明式且幂等的,即无论基础设施的初始状态是什么样,执行了配置操作后,基础设施或系统所处的状态就一定是你所期望的状态。
如果版本控制系统允许,尽量选择乐观锁(编辑本地工作副本的一个文件时不会阻止其它成员对其进行修改)
康威法则:设计系统的组织不可避免地要产生与其组织的沟通结构一样的设计,即由都坐在一起的小团队开发出来的产品更趋向于紧耦合、非模块化特点
持续集成:
一、良好的实践:
构建失败之后不要提交新代码
提交前在本地运行所有的提交测试,或者让持续集成服务器完成此事
等提交测试通过后再继续工作
回家之前,构建必须处于成功状态
时刻准备着回滚到前一个版本
回滚之前规定一个修复时间
不要将失败的测试注释掉
为自己导致的问题负责
测试驱动的开发
二、推荐的实践:
极限编程开发实践
若违背架构原则,就让构建失败
若测试运行变慢,就让构建失败
若有编译警告或代码风格问题,就让测试失败
测试策略:
一旦同一个测试重复做过多次手工操作,并确信不会花太多时间来维护时,就要把它自动化
单元测试不应该访问数据库、使用文件系统、与外部系统交互
尽可能频繁地向客户演示功能
建立一些基本的非功能测试,如容量测试、安全性测试。
提交测试应该避免复杂的数据准备,而是用尽量少的测试数据来断言被测试的单元正确地完成了所期望的功能
尽可能使用应用程序的公共API为测试创建正确的初始状态
部署流水线:
只生成一次二进制包,并将生成的二进制包存入于制品库中,之后的测试、部署均基于此二进制包
对不同环境采用同一种部署方式
对部署进行冒烟测试,这个冒烟测试还应该检查一下应用程序所依赖的服务是否都已启动
向生产环境的副本中部署,即先向类生产环境中部署
每次变更都要立即在流水线中传递
只要有环节失败,就停止整个流水线
为尽快加快反馈过程,增加提交阶段的测试
通常都应该使用增量的方法来实现部署流水线:构建、部署、单元测试、代码审查、验收测试、发布等步骤,部署流水线也应该不断变化,不断改善与重构
做整体优化,不断缩短周期时间,即修改一行代码到最终部署至线上并生效的时间
确保构建时尽量使用相对路径
应该尽量将需要管理的构建数量最少化
验收测试:
写应用程序验收条件时必须想着如何使其自动化,并遵循INVEST原则(independentnegotiable valuable estimable small testable)
尽量与GUI解耦
尽量使测试具有原子性,即与测试的执行顺序无关
单个测试范围内,应该避免所有异步情况,也要避免跨越测试边界情况
尽早修复失败的验收测试
当验收测试时间需要很长时,考虑使用虚拟化技术进行多环境并行测试
进行容量测试,但需要先进行度量,找到解决方案之前,必须先找出问题的根源,过早的优化是所有罪恶的根源
对于容量测试环境可以采用缩放后的类生产环境,而不是整个集群
把自动化容量测试作为部署流水线中的一个完成独立的阶段
部署与发布:
真正执行部署操作的人应该参与部署过程的创建
记录部署活动
不要删除旧文件,而是移动到别的位置
部署是整个团队的责任
服务器应用程序不应该有GUI
为新部署留预热期
快速失败
不要直接对生产环境进行修改