持续交付(continuous delivery)是持续集成理念的简单延伸。这种软件工程方法旨在
确保应用程序可以随时可靠地发布。持续交付的目标是在短时间内发布软件。它通常允许
在生产中对应用程序进行更改,从而降低发布软件的成本和风险。
构建成功的持续交付流程的主要先决条件如下。
● 可靠的持续集成过程。
● 部署到生产环境的自动过程(如果项目具有生产环境的概念)。
● 定义良好的版本控制系统工作流程和分支策略,这可以让你轻松定义什么软件版本
代表可发布的代码。
在许多项目中,自动化测试不足以可靠地断定给定版本的软件是否真的准备好发布。
在这种情况下,额外的手动用户验收测试通常由熟练的 QA 工作人员执行。根据你的项目
管理方法,这可能还需要客户的一些批准。如果一些验收测试必须由人手动执行,这并不
意味着你不能使用 Git 工作流,GitHub 工作流,或类似的分支策略。这只会更改稳定和发
布分支的语义,从准备好部署到准备好用户验收测试和批准。
此外,前一段并不改变代码部署应始终自动化的事实。我们已经在第 6 章中讨论了自
动化的一些工具和好处。如上所述,它将始终降低新版本的成本和风险。此外,大多数可
用的 CI 工具允许你设置特殊的构建目标,而不是测试,将为你执行自动部署。在大多数持
续交付过程中,当确定有必须的批准并且所有验收测试都成功结束时,这通常是由授权的
员工手动(按需)触发。
持续部署
持续部署(continuous deployment)是一个比持续交付更高级别的过程。这是一个完美
的方法,其中所有验收测试是自动化的,不需要客户的手动批准。简而言之,一旦代码被合并到稳定分支(通常是 master),它就被自动部署到生产环境中。
这种方法似乎非常好并且非常强大,但不常用,因为很难找到一个项目,在新版本发
布之前,不需要手动 QA 测试和某人的批准。无论如何,它绝对是可行的,一些公司声称
它们就是这样工作的。
为了实现持续部署,你需要与持续交付流程有相同的基本先决条件。另外,通常需要一个
种更加仔细地合并到稳定分支中的方法。在持续集成中被合并到主分支中的代码通常立即部署
到生产环境。因此,将合并任务切换到 CI 系统是合理的,正如使用 CI 测试合并部分所述。
常用的持续集成工具
当今,CI 工具有很多种选择。它们在易用性和可用功能上差别很大,几乎每个工具都
有一些独特的其他工具缺乏的功能。因此,很难给出一个好的一般性建议,因为每个项目
都有完全不同的需求和不同的开发工作流程。当然,有一些伟大的免费或者开源项目,即
使付费的托管服务也值得研究。这是因为 Jenkins 或 Buildbot 这些开源软件,它们可以免费
安装使用,人们才错误的认为它们可以免费使用。硬件和维护都增加了拥有自己的 CI 系统
的成本。在某些情况下,支付这样的服务可能不那么昂贵,而不是支付额外的基础设施和
花费时间来解决开源 CI 软件中的任何问题。不过,你需要确保将代码发送到任何第三方服
务符合公司的安全策略。
在这里,我们将回顾一些流行的免费开源工具,以及付费的托管服务。我真的不想
宣传任何供应商,所以我们将只讨论那些可用的没有任何费用的开源项目,以证明这个
相当主观的选择。没有给出最佳建议,但我们将指出任何解决方案的好和坏两方面。如
果你仍然有疑问,下一节将描述常见的持续集成的陷阱,应该有助于你做出正确的决定。
Jenkins
Jenkins 似乎是最流行的持续集成工具,如图 8-7 所示。它也是这个领域最古老的开源
项目之一,与 Hudson 配对(这两个项目的开发是分开的,Jenkins 是 Hudson 的一个派生)。
Jenkins 是用 Java 编写的,最初设计主要用于构建用 Java 语言编写的项目。这意味着
对于 Java 开发人员来说,它是一个完美的 CI 系统,但是如果你想在其他技术栈中使用它,
你需要做一些额外的工作。
Jenkins 的一个很大的优点是其已经实现了非常广泛的功能列表。最重要的是,从 Python
程序员的角度来看,是理解测试结果的能力。Jenkins 不是提供关于构建成功的纯二进制信
息,而是能够以表和图形的形式呈现在运行期间执行的所有测试的结果,如图 8-8 所示。
这当然不是自动工作的,你需要在构建期间提供特定格式(默认情况下,Jenkins 理解 JUnit
文件)的结果。幸运的是,许多 Python 测试框架能够以机器可读的格式导出结果。
令人惊讶的是,Jenkins 的大部分功能不是来自其内置的功能,而是来自一个巨大的免
费插件库。可以纯净地安装这对 Java 开发人员来说是很棒的,但使用不同技术的程序员可
能需要花费大量的时间,使其适合他们的项目。甚至支持 Git 是由一些插件提供的。
Jenkins 有着良好可扩展性,这真的很棒,但这也有一些严重的缺点。你最终将依赖已
安装的插件来驱动你的持续集成过程,这些都是独立于 Jenkins 核心开发的。大多数流行插
件的作者试图保持它们的最新版本,并与最新版本的 Jenkins 兼容。然而,具有较小社区的
扩展不能太频繁地更新,并且有一天你可能被迫卸载它们或推迟核心系统的更新。当紧急
需要更新(例如,安全修复)时,这可能是一个真正的问题,但是对于 CI 过程至关重要的
一些插件可能无法与新版本配合使用。
Buildbot
Buildbot(http://buildbot.net/)是一个用 Python 编写的软件,可以自动化任何类型的软
件项目的编译和测试周期。它是可配置的,在源代码库上进行的每个更改都生成一些构建
并启动一些测试,然后提供一些反馈,如图 8-10 所示。
例如,这个工具被 CPython 核心使用,请参阅 http://buildbot.python.org/all/waterfall?
&category=3.x.stable。
默认的 Buildbot 的构建结果的表示是一个瀑布视图,如图 10 所示。每个列对应于一个
由步骤(step)组成的构建(build),并与一些从构建器(build slaves)关联。整个系统由主构建器(build master)驱动。
● 主构建器控集中和驱动一切。
● 一次构建是一系列构建应用程序的步骤和其上运行的测试。
● 一个步骤是一个原子命令,例如:
○ 检查项目的文件。
○ 构建应用程序。
○ 运行测试。
构建器是一个负责运行构建的机器。它可以位于任何地方,只要它可以达到主构建器。
由于这种架构,Buildbot 的扩展非常好。所有的繁重工作都是从构建器完成,你可以根据
需要使用足够多的从构建器。
非常简单和明确的设计使 Buildbot 非常灵活。每个构建步骤只是一个命令。Buildbot 是用
Python 编写的,但它完全是语言不可知的。所以构建步骤绝对可以是任何东西。进程退出代码
用于决定步骤是否以成功结束,并且默认情况下捕获步骤命令的所有标准输出。大多数测试工具
和编译器遵循良好的设计实践,并且它们通过适当的退出代码指示故障,并在 sdout 或 stderr 输出流上返回可读的错误/警告消息。如果它不是这样,你通常可以轻松地用 Bash 脚本包装它们。
在大多数情况下,这是一个简单的任务。由于这一点,很多项目可以很容易地与 Buildbot 集成。
Buildbot 的下一个优点是它支持许多版本控制系统,而不需要安装任何额外的插件:
● CVS;
● Subversion;
● Perforce;
● Bzr;
● Darcs;
● Git;
● Mercurial;
● Monotone。
Buildbot 的主要缺点是缺乏用于呈现构建结果的更高级别的演示工具。例如,其他项
目,如 Jenkins,可以在构建期间运行单元测试。如果你向它们提供合适的格式(通常是
XML)的测试结果数据,它们可以以可读形式(如表格和图形)呈现所有测试。Buildbot
没有这样的内置功能,这是它的灵活性和简单付出的代价。如果你需要一些额外的功能,
你需要自己构建它们或搜索一些自定义扩展。另一方面,由于这种简单性,更容易推理
Buildbot 的行为并维护它。所以,总是有一个权衡。
Travis CI
Travis CI(https://travis-ci.org/)是以软件即服务形式出售的持续集成系统,如图 8-11
所示。企业需要付费使用此服务,但是 GitHub 上托管的开源项目可以完全免费使用。
当然,正是它的定价计划中的免费部分,使其非常受欢迎。目前,它是 GitHub 上托管
的项目中最受欢迎的 CI 解决方案之一。但是相比那些比较古老的项目,如 Buildbot 或
Jenkins,它最大的优势是存储构建配置的方式。所有构建定义都放在项目仓库的根目录中
的.travis.yml 文件中。Travis 只能和 GitHub 一起使用,所以如果你已经启用了这样的
集成,只需要有一个.travis.yml 文件,你的项目的每一次提交都将被测试。
Travis 的另一个主要的优点是它强调在干净的环境中运行构建。每个构建都在一个全新
的虚拟机中执行,因此不会有影响构建结果的持久状态的风险。Travis 使用了相当大的虚拟
机映像,所以你可以有很多开源软件和编程环境,而不需要额外的安装。在此隔离环境中,
你具有完全的管理权限,因此你可以下载和安装执行构建所需的任何内容,.travis.yml
文件的语法使这些事情变得很容易。不幸的是,对于作为测试环境的操作系统,你没有太多
选择。Travis 不允许提供你自己的虚拟机映像,所以你必须依赖它提供的非常有限的选项。
通常没有选择,所有的构建必须在 Ubuntu 或 Mac OS X(仍然在编写本书时的实验)的一些版本中进行。有时,有一个选项可以选择一些旧版本的系统或新的测试环境的预览版,但这
种可能性总是临时的。总是有一种方法绕过这个。你可以在 Travis 提供的虚拟机中运行另一
个虚拟机。这允许你在项目源中很容易地编码虚拟机配置(如 Vagrant 或 Docker)。但这会给
你的构建增加更多的时间,所以它不是你会采取的最好的方法。如果你需要在不同的操作系
统下执行测试,以这种方式堆叠虚拟机可能不是最好和最有效的方法。如果这是一个重要的
功能,那么这说明,对你来说,Travis 不是一个合适的服务。
Travis 的最大缺点是它完全锁定到 GitHub。如果你想在你的开源项目中使用它,那么
这不是一个大问题。对于企业和封闭源项目,这是一个难以解决的问题。
GitLab CI
GitLab CI 是庞大的 GitLab 项目的一部分。它可用作付费服务(企业版),同时也是一
个开源项目,你可以在自己的基础架构上托管(社区版)。开源版本缺少一些付费服务功能,但在大多数情况下,公司可以从软件管理版本控制仓库和持续集成中获取类似的服务。
GitLab CI 在功能设置上非常类似于 Travis。它使用非常类似与 YAML 语法的方式进行配置,
这些配置存储在.gitlab-ci.yml 文件中的。最大的区别是,GitLab 企业版定价模式不为你提
供开源项目的免费帐户。社区版本是开源的,但是你需要有一些自己的基础设施才能运行它。
与 Travis 相比,GitLab 具有对执行环境有更多控制的明显优势。不幸的是,在环境隔离领
域,GitLab 中的默认构建运行器有点处于劣势。这个过程称为 Gitlab 运行器,它在它运行的同
一环境中执行所有的构建步骤,所以它的工作方式更像 Jenkins 或 Buildbot 的从服务器。幸运的
是,它可以和 Docker 一起很好的工作,所以你可以轻松地添加更多的基于容器的虚拟化隔离,
但这将需要做一些额外的工作和设置。在 Travis 中,你得到的是完全开箱即用的隔离。
Python 高手编程系列七百七十二:持续交付
最新推荐文章于 2024-09-09 00:00:00 发布