【译】如何开始CI

banner

开始学习持续集成所要了解的知识:分支策略,测试自动化,工具和最佳实践。git

目标:快速且安全地交付工做代码

持续集成的目的是将代码传递到存储库的主分支:github

  • 快速地:从将新代码推送到存储库以及将其合并到主分支的事情,应该在几分钟内完成。
  • 安全地:咱们怎么知道新代码生效呢?持续集成会设置正确的检查项以顺利地自动合并代码。

持续集成有点关于工具以及团队中的思惟方式和文化。你但愿在开发的过程当中可以保持主分支的同时快速集成新代码。此工做主分支将在以后启用持续交付或持续部署(的操做)。可是,这些不是本文的内容。让咱们先来关注下持续集成。后端

实现持续集成有两大支柱。缓存

以小块工做

想象一下,一个五人组成的团队致力于一个SaaS产品。每一个人都开发一个单独的新功能。每一个功能的工做量大约是1或2周。有两种方式能够实现这个目标。安全

  • 团队能够选择(一个)功能分支。每一个开发人员都将在这个"功能分支"上工做。一旦每一个人对本身的工做感到满意,此分支将被被合并到主分支。
  • 团队(仍然)可使用分支机构,可是每次推送时,将他们的工做集成到主分支。即便事情仍然在进行中!正在进行的工做对主分支的任何最终用户或测试者来讲仍然是不可见的。

你认为哪一种方法效果最好?服务器

第一种方法最终将致使**“不可预测的释放综合症”**。长时效的特征分支为每一个开发人员创造了一种虚假的安全感和温馨感。因为分支分离了很长一段时间,没办法衡量将它们合并(到主分支)的难度。其最好的状况是出现些少的代码冲突,在最坏的状况下,基本的设计假设将受到挑战,事情将不得不从新进行...这是艰难的方式。架构

返工的工做将在时间压力下进行,致使质量降低和技术债务积累。这是个恶性循环。并发

请参考关于为什么不该该使用特性分支来处理脏细节的文章。工具

第二种方法是咱们实现持续集成所须要的方法。每一个开发人员都在本身的分支上工做。差别是:布局

每次推送都会将其更改合并到主分支,每一个开发人员天天会将其分支与最新的主分支版本同步几回。

经过这种方式,团队能够更快且轻松地修复冲突并协调设计假想。**早期发现五个小问题比发布日前发现1个大问题更好。**查看下面的“功能切换”部分,了解如何将“正在进行的工做”集成到主分支。

带有自动检查功能的安全性

以前的软件开发工程基于构建周期,而后是测试周期。这可能仍然适用“特征分支”方法(法一)。若是咱们天天数十次集成和合并代码,那么,手动测试就没有意义了。这将花费太长的时间。咱们须要自动检查以验证代码是否正常工做。咱们须要一个CI工具,帮助开发人员自动推送并运行构建和测试。

测试类型和内容应该为:

  • 足够快,能在几分钟内向开发人员提供反馈
  • 足够完全,可以安全放心地将代码合并到主分支

不幸的是,没有一种方式适合全部测试类型和内容。这要根据你的项目适当平衡。在CI阶段,不要运行大而耗时的测试套件。虽然这些测试提供了更好的安全性,但它们的代价就是对开发人员的延迟反馈。这将致使上下文工做切换,纯粹就是浪费时间。

优化开发者时间并减小上下文切换

长时间CI检查,个人意思是超过3分钟的(CI),消耗团队中的每一个开发人员的大量时间。

让咱们来比较下“好”和”坏“的工做流程。“好”的工做流程:

  • 你提交并推送你的代码
  • CI构建和测试运行1到3分钟
  • 在这1到3分钟内,你能够查看下手头的任务,在某些管理工具中查看状态,或者再次查看代码
  • 在3分钟内,你得到CI(返回的)成功状态:你能够继续执行下一部分任务。若是你的构建失败:你能够当即解决问题

“坏”的工做流程:

  • 你提交并推送你的代码
  • CI构建和测试运行15分钟
  • 你在这15分钟内作什么?
    • 你能够和团队一块儿喝杯咖啡。这很公平,可是你天天有多少这些时间呢?
    • 你可能会开始关注管道(工做流)中的下一个任务
  • 15分钟以后,你收到构建失败的通知。你须要切回到上一个任务,尝试解决问题...并再循环一次15分钟...
  • 那时你可能想:我是否应该再次回到下一个任务呢,仍是再等15分钟,心平气和地去完成当前的任务...

这糟糕的工做流程不只仅是浪费时间。对开发人员来讲也是使人沮丧的。高效的开发会使得开发人员很开心的。

你须要调整工具和工做流程以保证开发人员的满意度。

工具

分支

持续集成是指未来自不一样开发人员分支的代码集成到配置管理系中的公共分支。有可能你正在使用git。在git中,存储库中的默认主分支称为"master"。一些团队建立了一个名为"develop"的分支做为(开发时)持续集成的主分支。他们使用"master"来跟踪交付和部署(develop分支将合并到master分支)。

你(的项目中)可能已经有了一个主分支,你的团队将代码推送或合并到那里。坚持(这样作)下去。

每一个开发人员都应该在本身的分支上工做。若是同时处理许多不一样的功能内容,可使用多个分支。虽然这多是"不专心"工做的标志。只要代码连贯部分准备就绪,就能够推送到你的存储库。若是成功,CI将检查、启动并将代码合并到主分支。若是检查失败,您仍然在本身的分支上,能够修复须要的任何内容并再次推送。

上述过程当中的关键语是你代码连贯的部分。那么,你怎么知道它是连贯的?简单。

若是你可以轻松地想出一个好的提交信息,那就是连贯的。

另外一方面,若是你提交的信息须要分三次且带有许多形容词或副词,那可能并很差。屡次拆分你的工做内容,连贯的提交,而后推送代码。连贯的提交有助于代码的审查,且能让仓库的历史记录更容易被遵循。

不要乱推送任何东西,由于这(有可能)意味着一天的结束!

拉取请求

pull request (拉取请求)是什么呢?拉取请求是种概念,其要求团队将你的分支合并到主分支。接受你的请求应该经过你的CI工具提供的状态和潜在代码审查。最终由负责合并拉取请求的人手动合并。

拉取请求诞生于开源项目中。维护者须要一种结构化的方式来评估合并以前的贡献。拉取请求并非Git的一部分。他们受到任何Git提供程序的支持(GitHub, BitBucket, GitLab, ...)。

请注意,在持续集成中,拉取请求并非必须的。而拉取请求的主要好处是支持代码审查过程,这过程没法经过设计自动化。

若是你正在使用拉取请求,适用(下面)相同的原则或(上面提到的)“分块工做”和“优化开发者时间”:

  • 保持每一个拉取请求内容很小,并有一个明确的目的(它将使代码审查更容易)
  • 快速完成CI检查

自动检查

持续过程的核心是自动检查。它们确保在合并代码后,主分支代码能正常工做。若是它们失败,则代码不会合并。至少代码应该编译或转换,或者你的技术堆栈应该作点什么以使其为运行时作好准备。

在编译之上,你应该运行自动化测试以确保软件正常工做。测试覆盖率越高,在将新代码合并到主分支时你就越有信心。注意了!更好的覆盖率意味着更多测试和更长的执行时间。你须要找到正确的权衡。

当你彻底没有测试或者须要减小一些长时间运行的测试时,你要从哪里开始呢?专一于你项目或产品的相当重要的事项。

若是你要构建一个SaaS应用,则应该检查用户是否能够注册或登陆,以及执行SaaS提供的最基本操纵。除非你正在开发Salesforce竞争产品,不然你应该可以在几分钟内运行测试,若是不是立刻运行。若是要构建繁重的数据处理后端:使用有限的数据集来运行不一样的构建块。在持续集成中保持大型数据集的长时间运行。合并代码以后,能够触发长时间运行的测试。

专业提示

功能切换

持续集成的关键概念是尽快将代码放在主分支中,甚至工做正在进行中。若是功能不彻底正常,或者你不但愿暴露给测试的人员或终端用户。实现这一目标的方法就是功能切换。在启用/禁止切换下启用新功能。这切换能够是编译时布尔标志,环境变量或运行时事物。正确的方法取决于你想要 实现的目标。

功能切换的第一个主要好处是,你能够根据需求将它们投入生产并启用/禁止新功能。你可使用更改的环境变量来从新启动服务器,或者切换打开/关闭一个新的UI仪表盘的布局。经过这种方式,你能够灵活地推出功能。若是在线上中致使意外问题,请将其禁用。或容许终端用户选择加入或退出该功能(使用UI切换)。

功能切换的第二个主要好处是它们会强制你考虑你正在执行的操纵与现有代码之间的界限。这是一个好的练习,如论什么时候,每次添加到现有系统时,都应该从这里开始。功能切换步骤使得该过程的这一步更加明显。

功能切换的惟一缺点是你须要按期从环境和代码中清除它们。一旦功能通过实测并被用户采用,它应该是默认(成功的)。应该清理切换的代码和旧版本的东西(若是有的话)。不要陷入“配置为切换”系统的陷阱。你没法维护和测试切换的全部组合,(带来的缺点是)你最终拥有一个脆弱的架构。

保持CI构建时间不超过3分钟

谨记本文中的“好”和“坏”工做流程。咱们但愿避免开发人员的上下文切换工做(的状况)。拿起你的手机,并开启3分钟的计时器。看看你等待构建完的时间有多长!3分钟应该是个绝对最大值,你能够集中精力并安全有效地从一个任务移动到另外一个任务。

对一些团队来讲,3分钟内的构建可能看起来很疯狂,但这绝对能够实现的。它和你组织工做的方式有关,而不是你使用的工具。优化构建的方法有:

  • 使用更多构建容纳能力:若是你的CI工具上没有足够的并发构建和构建事件排队,开发人员就会浪费时间
  • 利用缓存:大多数技术堆栈须要在运行新构建时安装和配置依赖项。当依赖项未更改,你的CI工具应该可以缓存这些步骤,以优化构建时间。
  • 检查你的测试:检查你的测试是否通过时间优化。删除超时和“漫长地安全”等待步骤。若是要运行繁重的测试套件,请考虑在合并到主分支以后,在运行的单独构建中移除它们。它们再也不是持续集成保护措施的一部分,可是不管如何都不该该进行繁重的测试。
  • 拆分你的代码库:你必须在一个存储库中存储全部东西吗?你是否必须在全部内容上构建和运行测试,即便某些小部分发生了变化?这里可能就是突破点。
  • 有条件地运行测试:仅在某些目录发生更改时运行测试。若是你的代码库组织得很好,这将是重大的成功。

强制缩短期来限制你的CI检查的好处在于它使你从根本上改善整个开发过程。

正如Jim Rohn所说:

“成为一个百万富翁,不是为了百万美圆,而是为了实现这一目标会让你很成功”

虚拟合并:没必要全凭你的代码

大多数持续集成工具在你的分支上运行CI构建,以确保它是否能够合并。可是这不是咱们感兴趣的内容。若是你知道本身在作什么,那么你推送的代码已经颇有可能生效了。你的CI工具应该验证的是你的分支和主分支合并正常。

你的CI工具应该执行分支到主分支的本地合并,并针对该分支来运行构建和测试。若是主分支在此期间没有变化,则能够自动合并你的分支。若是确实发生了更改,则应该再次运行CI检查,直到你的代码能够安全合并为止。若是你的CI工具不支持此类工做流程,请换一个工具。

邪恶的任务管理

有种误解是,可以跟踪Agile板或像JIRA之类的bug跟踪器中相关的代码是件很酷的(事情)。这是一个很好的教科书概念,可是对开发的过程的影响确定不值得付出努力。任务管理器提供了“功能和错误”的视图。代码以很是不一样的方式构建和分层。尝试协调任务管理器中的项目和一组提交是没有意义的。若是你想知道为何编写一段代码,你应该可以从上下文和注释中获取信息。

后绪

工具仅仅是工具而已。设置工具多是(花费)一个小时的事情。若是你错误的使用工具,你将没法获得预期的效果。

谨记咱们为持续集成设定的目标:

  • 快速且安全的传输工做代码
  • 优化开发人员的时间并减小上下文切换

真正的意义是将你的思惟方式转变为“不断为你的项目或产品提供价值”

将你的软件开发过程视为硬件生产设施。开发人员的代码表明可移动的部件。主要分支就是组装产品。

更快地将不一样部分集成在一块儿并检查其能正常工做,你最终将得到更好的工做产品。

一些实操例子:

  • 你正在开发一项新功能,而且必须更改其余人最有可能使用的低级别组件。为该公共组件进行相关的提交并将其合并。而后继续处理你的其它功能。其它开发人员将可以当即根据你的更改来开展工做。
  • 你正在开发一项耗时和须要编码的大型功能?(这时)使用功能切换。不要孤立的工做,永远都不要!
  • 你正在等待代码审核,可是没人能够执行此操做。若是你的代码正在经过CI检查,那么只须要合并它并在以后进行代码审查。这听起来好像是打破了既定的过程,可是请记住“完成比完美更好”。若是它正常工做,它在主分支中提供的价值比停滞在一旁几天要好。

后话

原文:fire.ci/blog/how-to…

文章首发:github.com/reng99/blog…

更多内容:github.com/reng99/blog…

相关文章
相关标签/搜索