流程自动化
为什么要自动化
如果说我在拥有一个开源系统的这些年里学到了什么,那就是你要做的例行事项越少,你就有越多的空闲时间用于实际的工作(比如修复缺陷或者开发新功能)。因此,我们应该力求尽可能自动化。
在实际中,首先检查两个工作流程(非自动化和全自动化),看你有多少时间实际上是花在例行事项上的。然后,我们将探讨如何实现改进的工作流程,让我们有更多的时间来修复缺陷和开发新功能。
最糟糕的情况——没有自动化
graph TD A[Someone creates a PR with a bug fix] -->|Inspect the code| B[You] B -->|Checkout the fork, build and run the tests| C[You] C -->|Approve the PR| D[You] D -->|Merge the PR| E[You] E -->|Checkout the master, build and run the tests| F[You] F -->|Update the change log| G[You] G -->|Bump the version and publish| H[You] H -->|Push the change log to Github and create a Github release| I[You]
如上图,在没有任何自动化的情况下,所有的工作都由你来做。仅仅对于一个缺陷修复来说,你就需要做很多工作,更重要的是,每次修复缺陷或开发新功能时,你都重复进行这些工作!
最好的情况——一切都是自动化的
graph TD PR[Someone creates a PR with a bug fix] -->|Inspect the code| You[You] You -->|Approve the PR| Auto1[Automation] Auto1 -->|Checks out the fork, builds and runs the tests| Auto2[Automation] Auto2 -->|Merges the PR| Auto3[Automation] Auto3 -->|Checks out the master, builds and runs the tests| Auto4[Automation] Auto4 -->|Updates the change log| Auto5[Automation] Auto5 -->|Bumps the version and publishes| Auto6[Automation] Auto6 -->|Pushes the change log to Github and creates Github release| Auto7[Automation]
在这种情况下,你只需要做必须要做的事情——检查代码和(偶尔)批准拉取请求,其他的一切都是自动完成的。这被称为持续集成(continuous integration)和 持续部署(continuous deployment)。在这里,我们并不会深入构建脚本和特定系统配置的细节。相反,我们将会查看让它发挥作用所需的工具,我将会让你自己决定具体细节。
持续集成(CI)
持续集成(CI)是一种自动将代码改动从多个贡献者集成到单个软件项目中的实践。 CI 过程由自动工具组成,这些工具会在集成之前断言新代码的正确性。
一个非常基础的 CI 运行将会包括 构建(build) 和 单元测试(unit tests),但是并不局限于这两种。可能也会包含各种各样的静态代码分析工具、链接器等等。这里的标准由你定。
为什么应该使用 E2E(端到端) 测试?
构建和单元测试可以为你提供有关代码变动的快速反馈,所需时间相对较短,并且在出现问题的时候迅速失败。但是端到端(end-to-end,E2E)测试在 CI 中有着特殊的地位。
端到端测试不仅应该覆盖代码的正确性,还应该覆盖到你的部署流程、包的完整性等等。
这里有一个关键点:端到端测试应该像真实用户使用那样测试你的软件包。
CI 系统是如何工作的
市面上存在很多很多 CI 系统,比如 Travis CI、Circle CI、AppVeyor、Azure Pipelines、GitHub Actions 等等。它们的功能都比较多,做的事情也基本相同:检出你的代码、运行你定义的脚本(通常运行构建和测试),然后向报告成功或失败。
一般 CI 会在每个 PR 上运行,并向 GitHub 报告状态,您需要及时 Review 并处理。具体的构建脚本由你的生态系统、编写项目的语言、你所使用的框架等决定。
持续部署(CD)
持续部署(CD)是一个软件发布过程,它使用自动化测试来验证对代码库的更改是否正确和稳定,以便立即自动部署到生产环境中。
在我们的情况中,生产环境就是程序包在包注册中心中公开可用的时候。这是一个无法返回的阶段,因为一旦发布,就不能取消发布了,因为程序包是公开可用的(因此,它可能正被使用)。
持续部署有多种策略,具体策略取决于项目及其复杂程度。一般情况下,发行(release)只应该基于主干分支,因为这会让工作流变得非常简单。具体做法如下:
- 每个 PR 要么代表一个缺陷修复,要么代表一个新功能。
- 代码在进入主干之前经过了测试(包括端到端测试)。
- 主干分支是受保护的分支,所以只要你不合并失败的 PR,它就会保持稳定。
- 每个合并到主干的 PR 都会触发主干 CI 运行,CI 最终会发布一个新版本。
这将确保所有的发布都是按顺序进行的,并且可以很容易地将某些 PR 与特定的版本联系起来。
为了自动化程序包的发行过程,你需要做几件事情:
- 基于提交信息自动升级版本。
- 基于提交信息自动更新 CHANGELOG。
- 自动发布程序包到公共程序包仓库。
- 自动在 GitHub 上发行。
Semantic-release
semantic-release 自动化整个程序包发行工作流程,包括:确定下个版本号、生成发行说明和发布程序包。这消除了人类感情和版本号之间的直接联系,严格遵循 语义化版本 版本规范。
semantic-release 通过分析提交信息来确定下一个版本号。它使用 Angular Commit Message Conventions 来解析提交信息。这意味着你需要遵循这些规则来提交代码,否则 semantic-release 将无法正常工作。这里不做赘述,你可以在 semantic-release 的文档中找到更多信息。
如何保持项目的更新
如果你的项目没有外部依赖,跳过这一部分。然而,大多数项目都依赖于其它程序包,而其它程序包往往会发生变化。
使项目保持最新的依赖关系很重要,但这很耗时。幸运的是,我们有一个解决方案。实际上,有一些,例如 Greenkeeper、Renovate 和 Dependabot。推荐使用 GitHub 自带的 Dependabot,不过请确保你的 CI 是在发挥作用的情况下再开启使用。