OpenStack 如何在不到三个月的时间内合并超过 900 个文档更改?我们将文档视为代码,并持续发布来自多个 git 存储库的经过审查的内容。
CI 代表持续集成。通常,CI 意味着代码持续测试、与其他代码更改集成,然后合并。持续交付 (CD) 意味着代码在每次补丁后持续部署到整个代码库。对于文档而言,这意味着内容持续测试、与每个补丁合并并部署。对于文档,部署意味着发布。例如,部署文档意味着输出文件被复制到 Web 服务器,供所有人查看。
文档的 CI/CD
对任何 OpenStack 存储库(包括我们的文档存储库)的更改只能使用 Gerrit 代码审查系统完成。Gerrit 是我们为代码协作和审查而设置的附加的基于 Web 的审查工具,由 OpenStack 基础设施团队运行。基本工作流程是,文档贡献者检出文档存储库,对文档进行更改,在本地进行测试,提交到 git(我们的源代码控制修订系统),然后将其上传到 OpenStack 的 Gerrit 实例。然后,Gerrit 发送通知,告知 Jenkins 有新的更改,Jenkins 为软件开发提供持续集成服务。一旦收到来自 Gerrit 的通知,Jenkins 就会运行为存储库配置的各种测试套件。实际上,OpenStack 并行运行八个 Jenkins 实例,并使用名为 Zuul 的自制工具进行协调。您可以在 Zuul 网站上查看任何给定构建的状态。
一旦更改上传到 Gerrit,审查者就可以看到更改并开始评论。Gerrit 的 Web 用户界面允许逐行审查更改。因此,审查者可以直接评论在源文件中发现的任何问题。我们还实施了构建文档的测试,以便审查者可以在适用时看到 HTML 或 PDF 格式的已构建文档。一旦审查者评论了更改,她还可以对更改进行投票。这里的投票不是民主过程,而更多是对补丁是否应该被采纳的评估。审查者可以投赞成票(是的,应该采纳)或反对票(这需要更多工作)——或者只评论而不投票。
每个人都可以在 OpenStack 的 Gerrit 中使用这些投票进行审查
- 0:无评分
- +1:对我来说看起来不错,但需要其他人批准
- -1:此补丁在合并之前需要进一步工作
我们还需要对补丁进行评论,说明其错误原因、提出澄清问题,或说明其良好之处。这些评论有助于原始作者和其他审查者更新和评估更改。
一组特殊的资深审查者,即所谓的“核心审查者”,也可以投 +2(或 -2)票并批准更改,以便可以发布。这些审查用以下任一符号表示
- +2:对我来说看起来不错(核心审查者)
- -2:不要合并
一旦两位核心审查者都给出了 +2 票,一位核心审查者——通常是第二个给出 +2 票的人——批准更改,然后它就会合并并发布。带有负面审查评论的更改不会被批准,因此文档将不会发布,直到达成共识并获得适当的批准。
Jenkins 的自动测试也会在审查阶段产生投票。一旦更改获得批准,Jenkins 会再次运行测试——对与当时最新的、更新的 git 存储库合并的更改进行测试——以确保不会出现任何回归。只有 Jenkins 对更改进行积极审查,更改才能合并。
所有这些自动更改都在 HP 和 Rackspace 公有云中运行。OpenStack 项目目前为此使用了多达 950 台虚拟机。对于每个测试作业,都会启动一台机器,检出其中经过测试的更改的存储库,安装测试套件的任何依赖项,然后执行测试套件。是的,我们正在使用云来编写关于云的文档。
我们目前运行的测试在下面的章节中列出。
为文档使用 CI/CD 有什么好处?
OpenStack 每天有多个项目合并多个更改,因此文档系统也需要能够跟上如此多的更改。持续集成和交付实现了这一点,因此这不仅是一个好处,而且是我们环境中的一项要求。编写者拥有与开发人员相同的工作流程,并获得与开发人员贡献者相同的认可和奖励。
我们还发现,它减轻了本地编写者环境构建文档的负担,尽管贡献者仍然需要能够在本地构建文档。通过拥有可供审查的已构建草稿,临时贡献者和审查者避免了下载补丁、复制构建环境然后构建文档的开销。由于系统中的自动化,我们可以审查源代码和输出。
构建速度加快,因为编写者可以同时处理多个补丁,而基于云的 CI/CD 继续运行。
在 OpenStack 中,基础设施团队也将许多相同的技术用于服务器管理。
由于测试脚本,编写者始终从工作状态开始,并且主分支始终构建。如果文档在本地或其他环境中无法构建,编写者可以确信这是他自己的错误,而不是已经损坏的树。
构建和发布草稿文档允许审查者快速检查更改在发布时的呈现方式。他们不需要下载并在本地构建,因此可以更快地进行审查。
我们还使用了 OpenStack 开发人员和基础设施团队使用的工作流程,这使得开发人员可以轻松地为文档做出贡献。随着我们最近转向 RST 格式,它变得更加容易,因为 RST 是 OpenStack 中使用的通用标记语言。
自动化风险和陷阱
考虑到写作既是一门艺术又是一门手艺,我们确实尝试在应该自动化的内容和仍然需要大师级工匠的内容之间取得平衡。早期的担忧之一是发布过快或发布不完整的文档。我们发现,只要审查者有诸如“它比我们现在拥有的更好”或“我已经测试过它并且知道它可以工作”或“此文档修复与我调查的已报告错误相符”之类的指导原则,那么每天发布 50-100 次更新的风险就会降低。
我们必须在审查者之间建立信任,而且我们仍然在每六个月一次的峰会上就审查进行深入讨论。我们编写了一份审查指南,并尝试培训审查者在使用最佳判断力审查补丁。我们还编写了一套审查指南。持续集成不仅是我们发布速度的一部分,而且拥有值得信赖的审查者使用良好的判断力,同时让机器人测试审查给他们信心,他们不必担心文档无法构建或者我们会在一夜之间破坏整个文档站点。
我们有一些与版本无关的手册,以及记录当前版本的手册。对于记录特定版本的手册,如安装指南,我们会为每个新版本更新它们并在分支中工作。已发布文档会使用关键更改进行更新,下一个版本的文档会获得大部分更改,并发布在隐藏位置,以便轻松审查当前草稿。一旦软件版本发布,我们就会公开发布这些特定版本的指南,然后开始更新下一个版本。
文档测试
Jenkins 允许执行脚本,文档团队有自己的包含测试脚本的存储库,主要用 Python 编写。我们使用与文档相同的工作流程来开发这些脚本。一旦我们进行了重大更改,就会发布测试工具的版本,然后该版本将用于测试任何文档更改。在文档存储库中,我们使用 Python 的 test-requirements.txt 文件约定,该文件指示哪个版本的 openstack-doc-tools 适用于给定的文档源文件集。
为了让审查者专注于内容,而不必在形式上吹毛求疵,自动测试为我们处理了大部分吹毛求疵的工作。但是,我们不要求所有自动测试都通过才能发布文档。有些测试被标记为“投票”,这意味着除非通过所有这些测试,否则文档将不会合并。其他测试被标记为“非投票”,这意味着即使测试失败,我们也允许补丁落地。自动测试包括
- 检查单个文件的语法。这有助于快速定位语法错误。可以测试 DocBook XML、WADL XML、RST 和 JSON 格式的语法,但我们只测试 DocBook XML 和 RST。JSON 的格式是否正确在不同的测试中检查。
- 检查文档是否可以构建。这样做的一个附带好处是,生成的指南会上传到草稿服务器,以便审查者可以轻松审查新生成的书籍,并查看更改在 HTML 和 PDF 中的外观。
- 检查翻译后的手册是否可以通过工具链构建。
- 检查文件是否“整洁”。这会检查——取决于文件类型(XML、RST 或 JSON)——多余的空格、过长的行、一些不需要的 Unicode 字符或正确的格式 (JSON)。额外的空格和过长的行会使并排审查源文件变得更加困难。我们的工具链无法输出某些 Unicode 字符,并且 JSON 文件应符合格式标准。
- 检查指向外部网站的链接是否有效。这会检查更改的 DocBook XML 文件中的所有 URL 是否可访问。由于网站可能会宕机,因此此更改被标记为“非投票”。
- 检查是否没有删除其他手册使用的 XML 文件。这很重要,因为我们只构建更改的手册,因此我们必须检查如果删除一个文件,是否仍然可以构建所有手册。
我们还在测试脚本中进行了一些优化。例如,由于构建 DocBook XML 文件的成本很高,因此小型依赖项构建器会检查哪些文件已更改以及哪些指南包含这些文件,然后仅构建这些指南。其他测试(如语法或 URL 检查)也仅在更改的文件上运行。没有理由一遍又一遍地检查未更改的文件,虽然测试单个文件可能很快,但测试近千个 XML 文件却很慢。
这些优化目前在 RST 文件上没有完成,因为 RST 文件更容易解析,并且指南的构建也更快。
我们不运行任何语法或拼写检查器,因为投票检查需要始终准确。我们已经就自动化拼写检查进行了大量讨论,但这确实需要人眼进行判断。
CI 基础设施的其他用途
我们使用它与我们的翻译服务器对话。翻译团队使用翻译服务器(目前是 Transifex)来翻译手册。每当合并更改时,CI 基础设施会自动将当前文本上传到翻译服务器,以便翻译人员可以直接翻译并始终拥有最新的字符串。每天,CI 基础设施上都会运行一个所谓的“定期”作业,从翻译服务器下载所有翻译后的字符串到文档存储库,然后提出一个包含任何新字符串的更改。这使我们有机会通过 CI 基础设施和人工审查来运行翻译导入。
此外,我们使用 CI 基础设施将一些共享文件从一个存储库同步到其他几个存储库。这些文件是我们的共享词汇表和共享的“支持附录”及其翻译。在对这些文件的主存储库合并更改后,会检查其他存储库中的文件是否需要更新,如果是,则会为该存储库提出更改。同样,这允许在导入时运行测试套件和最终人工审查。
总结
希望本文能为您提供关于我们如何在 OpenStack 文档流程中使用持续集成和交付的想法。我们发现这种方法的好处远远超过任何风险。我们与其他团队保持一致的需求意味着我们采用了持续的心态,以便尽早且频繁地交付。着眼于自动化来查看您的开源文档,看看有什么启发。
本文由 Anne Gentle 与 Andreas Jaeger 合作撰写。Anne 和 Andreas 都是 OpenStack 文档团队的成员。Andreas 也参与 OpenStack CI 基础设施。他在过去 20 多年中消费并贡献了各种开源项目,并在 SUSE 工作。
1 条评论