自动化部署
---

优化开发流程有一个很重要的步骤就是：让部署自动化。通过部署自动化，我们可以大大缩减开发周期，加快软件交付流程。下图是一个自动化部署的流程图：

![自动化部署](assets/article/chapter4/auto-deployment.png)

从下图中我们可以得到下面的五个步骤：

 - 获取源码
 - 获取依赖
 - 构建软件包
 - 生成/上传安装包
 - 目标平台安装/配置

这个过程可能和之前的 Web 项目构建过程差不多，然而却多了好几步。

在前面的章节里，我们已经使用了版本管理系统来管理我们的源码。因此，在这里对于获取源码的介绍就比较简单了——我们只需要在我们的 CI（持续集成）服务器上使用 ``git clone`` 这一类的方法来获取我们的源码即可。

###依赖与包仓库

获取完源码后，我们就需要开始下载软件包依赖。无论是 Python、Ruby、Java，还是 JavaScript 都需要这样的一个过程。软件开发已经从大教堂式的开发走向了集市——开源软件改变了这一切。

![大教堂与集市](assets/article/chapter4/hierarchy-vs-graph.png)

过去我们需要在大系统的内部构建所使用的依赖，现在我们更多地借助于外部的库来实现这些功能。这也意味着，如果在这一个节点里出现了意外——软件被删除，那么这个系统将陷入瘫痪的状态。如之前在 NPM 圈发生了“一个 17 行的模块引发的血案”——即 left-pad 工具模块被作者从 NPM 上撤下，所有直接或者间接依赖这个模块的 NPM 的软件包都挂掉了。因为我们依赖于公有的包服务，所以系统便严重依赖于外部条件。

这时候一种简单、有效的方案就是搭建自己的包服务。如使用 Java 技术栈的项目，就会使用 Nexus 搭建自己的 Maven 私有服务。我们的软件依赖包将会依赖于我们自己的服务，此时会产生的主要问题可能就是：我们的软件包不是最新的。但是对于追求稳定的项目来说，这个并不是必须的需求，反而是个优势。

###构建软件包

在一些编译型语言里，在我们运行包测试后，将会得到一个软件包。如 Jar 包，它是 Java 所特有的一种压缩文档。Jar 包无法直接安装使用，虽然我们可以直接运行这个 Jar 包，但是我们需要通过一些手段将这个 Jar 包拷贝到我们的服务器上，然后运行。在特定的时候，我们还需要修改配置才能完成我们的工作。

因此，使用 RPM 或者 DEB 包会是一种更好的选择。RPM 全称是 Red Hat Package Manager（Red Hat包管理器），它工作于 Red Hat Linux 以及其它 Linux 和 UNIX 系统，可被任何人使用。如下图是 RPM 包的构建过程：

![RPM Build Process](assets/article/chapter4/rpm-deploy.jpg)

要构建一个标准的 RPM 包，我们需要创建 .spec文件，这个文件包含软件打包的全部信息——如包的 Summary、Name、Version、Copyright、Vendor 等等。在产生完这一个配置文件后，执行 rpmbuild 命令，系统会按照步骤生成目标 RPM 包。

###上传和安装软件包

生成对应的软件包后，我们就可以将其上传到 Koji 上，它是 Fedora 社区的编译系统。如下图所示：

![RPM Build Process](assets/article/chapter4/rpm-koji.jpg)

如果我们已经对我们的所有目标操作系统配置过，即配置好了软件源，那么我们就可以直接在我们的服务器上使用包管理工具安装，如``yum install``。
