虽然许多指南都介绍了如何配置持续集成管道,但很少有指南会告诉你在遇到问题时该如何进行调试——尤其是当问题涉及到多个环节时。

在参与开源项目时,这种情况很常见:你进行了一些小的修改,提交了拉取请求,结果突然一切都出错了。

不是某一项检查出现了问题,而是多项检查都出了问题:

  • 代码格式检查错误

  • YAML格式验证失败

  • 构建过程失败

  • 部署过程中出现故障

更令人困惑的是,你可能会在那些自己并没有修改的代码部分看到错误信息。

在本文中,你将学习如何一步步地调试这些问题。我们的目标不仅仅是修复某个拉取请求中的错误,而是要真正理解持续集成系统是如何验证你的修改的。

本指南是根据我在参与一个开源文档项目时所积累的实际调试经验编写而成的。

虽然这个例子来自一个文档项目,但这种调试流程适用于许多使用持续集成管道、代码格式检查工具以及自动化构建流程的仓库。

目录:

先决条件

要阅读本指南,你需要具备以下条件:

  • 对Git及拉取请求有基本的了解

  • 拥有一个GitHub账户

  • 了解持续集成/持续部署的相关概念(了解这些知识会有帮助,但不是必需的)

了解持续集成管道的工作原理

在许多项目中,你会看到“CI/CD”这个术语,它代表的是持续集成和持续部署。

在本指南中,我们将重点介绍CI部分,也就是持续集成。这意味着当您提交代码或发起拉取请求时,会自动运行一系列检查。这些检查会在您的更改被合并到主代码库之前对其进行验证。

而CD(持续部署/交付)则通常负责处理这些检查通过之后的环节,比如应用程序的实际部署工作。

理解这一区别非常重要,因为我们在本指南中要解决的大多数问题都发生在持续集成阶段。

当您发起拉取请求时,大多数代码仓库都会运行多项自动化检查:

  • 代码格式检查工具(例如markdownlint、yamllint)会确保代码格式符合规范。

  • 构建系统(例如mdBook)会验证代码结构并生成相应的输出文件。

  • 部署检查工具(例如Netlify)会确保网站能够正常构建和运行。

  • 合并控制机制(例如Tide)会执行审批流程,确保变更符合规定才能被合并。

需要记住的一点是:持续集成系统会验证您提交的所有文件,而不仅仅是您修改过的那些部分。

持续集成管道如何处理您的拉取请求

当您提交代码或发起拉取请求时,持续集成管道会依次运行多项检查。

让我们来看看在典型的持续集成管道中,这些检查是如何相互关联的。

持续集成管道示意图,展示了代码格式检查、构建过程及部署环节,其中失败情况会促使您返回并修复问题后再继续流程。

图示:简化版的持续集成管道流程,展示了代码格式检查、构建及部署环节是如何依次执行的。

上图展示了一个包含反馈循环的持续集成管道流程:如果在任何阶段出现错误,系统会要求您先修复问题后再继续后续步骤。

让我们详细分析一下这个图示所表达的内容:

  1. 首先,您需要提交代码或发起拉取请求。

  2. 随后,持续集成管道会开始运行自动化检查。

  3. 最初的检查通常包括代码格式检查工具,如markdownlint或yamllint。

    • 如果格式检查失败,管道流程会停止,您需要先修复格式问题才能继续。

    • 如果格式检查通过,管道会进入构建阶段(例如在文档项目中使用mdBook进行构建)。

    • 如果构建失败,通常说明存在结构上的问题,比如重复条目或无效引用等。

  4. 构建成功后,接下来会进行部署检查(例如使用Netlify进行预览测试)。

    • 如果部署失败,问题往往出在配置设置或构建结果上。

  5. 如果所有步骤都通过,拉取请求就可以进入审核阶段了。

实用的调试工作流程

步骤 1:解决认证和权限问题

在持续集成流程运行之前,由于认证错误,你的代码推送操作很可能会失败。

示例错误信息:

拒绝允许个人访问令牌创建或更新工作流程

出现这种问题的原因是,当你的提交中包含以下路径下的文件时,GitHub会要求具备特殊的权限:

.github/workflows/

解决办法是重新生成个人访问令牌,确保该令牌具有以下权限:

  • 对“仓库”有访问权限

  • 具有操作“工作流程”的权限

步骤 2:在本地运行代码检查工具

如果只依赖持续集成系统的反馈,会大大降低工作效率,因为你需要先推送更改,然后等待整个流程完成才能查看错误信息。

在本地进行代码检查可以让你在推送代码之前立即发现存在的问题。

实际上,你应该同时采用这两种方法:

  • 在本地运行检查工具,以便尽早发现问题并减少迭代次数

  • 利用持续集成系统作为最终验证手段,确保你的更改符合仓库的标准

可以把本地检查看作是第一道防线,而持续集成系统则是代码被接受之前的最后一道关卡。

以下是一个示例(用于检查Markdown格式的正确性):

npm install -g markdownlint-cli2
markdownlint-cli2 docs/**/*.md

步骤 3:修复常见的Markdown格式错误

以下是一些你可能会遇到的常见问题:

像“here”这样的非描述性链接无法让读者了解链接指向的具体位置,这使得文档更难理解,尤其是对于依赖屏幕阅读器的用户来说。

正确的写法应该是:

[命令帮助文档](https://example.com)

而不是这样写:

[here](https://example.com)

2. 行长度违规

许多项目都会规定最大的行长度(通常约为80个字符),这样可以提高代码在不同设备和编辑器中的可读性。

如果某一行过长,你可以将其拆分成多行,而不会影响代码的含义。

进行分割时,应选择单词之间的空格或标点符号后的位置作为分割点。避免拆分单词或破坏句子结构。
例如:

这是一个过长的句子,应该将其拆分成多行才能符合格式要求。

3>列表缩进问题

<列表缩进错误通常发生在嵌套列表项的排列方式不一致时。这种情况会破坏格式规范,从而导致代码检查工具报错。

为避免这种情况,请确保使用统一的间距格式(通常每级使用2个空格)。

错误示例:

- Item 1
 - Subitem

正确版本:

- Item 1
  - Subitem

步骤4:修复Markdown代码块中的YAML格式错误

YAML具有严格的格式要求,包括正确的缩进、键值对结构以及统一的间距格式。

即使YAML内容位于Markdown代码块中,像yamllint这样的工具仍会检查其结构是否正确。

错误示例:

metadata:
annotations:

正确版本:

metadata:
  annotations:
    capi.metal3.io/unhealthy: "true"

在错误示例中,annotations并没有正确地嵌套在metadata下,也没有定义任何键值对。

在正确版本中:

  • annotations被正确地缩进在metadata下面

  • 添加了一个有效的键值对(capi.metal3.io/unhealthy: "true"

这种结构符合YAML对于层次结构和格式的要求。

步骤5:在lint检查通过后修复构建错误

即使lint检查通过了,也不能保证构建过程一定会成功。

这是因为lint检查主要关注语法和格式问题,而构建过程则会验证整个项目的结构是否完整。

构建失败通常由以下原因导致:

  • 导航文件中存在重复条目

  • 缺少文件或引用文件错误

  • 配置设置无效

即使语法没有问题,构建系统也会确保所有组件能够正确连接。

例如,在使用mdBook等工具的文档项目中,如果SUMMARY.md文件中存在重复条目,那么即使所有文件都通过了lint检查,构建过程仍然会失败。

步骤6:排查连续出现的CI构建失败问题

CI流程是分层的,一个环节的错误可能会引发多个后续环节的故障。

例如,假设存在YAML缩进错误:

YAML格式错误 → 构建失败 → 部署失败 → 多个检查步骤也失败

为了解决这个问题,可以按照以下步骤操作:

  1. 在CI日志中找出第一个出现故障的环节

  2. 修复该问题

  3. 重新运行整个流程

在这个例子中,YAML缩进错误是根本原因。一旦修复了这个格式问题,lint检查就会通过,构建过程也会顺利完成,部署步骤也会成功。

因此,及时解决流程中的第一个故障非常重要,而不应该试图一次性处理所有错误。

步骤7:在CI调试过程中处理Git相关问题

在处理更新后的分支时,你可能会遇到以下问题:

  • 分支分歧

  • 重新基定的冲突

  • 推送失败

为了解决这些问题,通常需要使用以下两种方法之一来更新你的分支:

选项1:重新基底(清除历史记录)

git pull --rebase

重新基底会修改你的提交历史记录,使你的更改显示在该分支的最新版本之上。

使用时请注意:

  • 仅对自己的分支进行重新基底操作

  • 避免对共享分支进行重新基底操作

选项2:合并(更安全的方式)

git pull --no-rebase

合并会保留完整的提交历史记录,在与他人协作时更为安全,但可能会产生额外的合并提交。

安全地推送你的更改

更新分支后,你可能需要将更改推送到远程仓库:

git push --force-with-lease

请避免使用:

git push --force

`–force`选项会覆盖其他贡献者的工作。`–force-with-lease`选项更为安全,因为它只有在远程分支没有发生意外变化时才会执行推送操作。

关键要点

  • 持续集成系统会验证你的所有提交内容,而不仅仅是你修改的特定代码行

  • 代码检查工具和构建系统遵循不同的规则

  • Markdown格式中的YAML文件必须结构正确

  • 由于结构问题,文档生成过程可能会失败

  • 在本地运行检查可以显著减少调试时间

结论

调试失败的拉取请求并不仅仅是修复语法错误而已。

你还需要了解各种系统之间的交互方式:

  • 版本控制系统

  • 持续集成管道

  • 代码检查工具

  • 构建流程

一旦理解了这些系统的协同工作原理,你就可以有条不紊地解决问题,而不会盲目猜测。

下次你的拉取请求再次失败时,你就会知道应该从哪里开始着手以及如何解决它。

起初调试持续集成相关的问题可能会让人感到无从下手,但只要采用科学的方法,这些故障就能变成提升代码质量的契机。

Comments are closed.