Back

GitHub Actions 调试技巧与窍门

GitHub Actions 调试技巧与窍门

昨天还能正常运行的工作流现在却因为一个晦涩的错误而失败。你没有改动任何东西。日志中显示一堆折叠的步骤,而真正的问题就隐藏在其中某处。这种场景让每一位维护 CI/CD 流水线的工程师都感到沮丧。

有效的 GitHub Actions 调试需要了解哪些工具可用以及何时使用它们。本指南涵盖了稳定、经久不衰的技术,帮助你快速诊断工作流失败问题——而不会在无效的方法上浪费时间。

核心要点

  • 通过 ACTIONS_STEP_DEBUGACTIONS_RUNNER_DEBUG secrets 启用调试日志,以更深入地了解工作流失败原因
  • 添加诊断步骤来输出环境详情,并临时使用 continue-on-error: true 来隔离不稳定的步骤
  • 在推送前使用 actionlint 和 nektos/act 在本地验证工作流,以便及早发现错误
  • 将 action 版本固定到特定标签或 SHA,以防止上游更改导致的意外中断

启用调试日志以获得更深入的可见性

当标准的 GitHub Actions 日志无法提供足够的细节时,启用调试日志。两个仓库 secrets 控制此行为:

  • ACTIONS_STEP_DEBUG: 设置为 true 可查看每个步骤的详细输出
  • ACTIONS_RUNNER_DEBUG: 设置为 true 可获取 runner 级别的诊断信息

你也可以在不修改 secrets 的情况下触发调试模式。重新运行失败的工作流时,选择”Re-run jobs”并勾选”Enable debug logging”选项。这将为该特定运行提供详细跟踪信息,而不会影响后续执行。

GitHub 的日志查看器支持实时流式传输和展开最近的日志显示,使跟踪长时间运行的作业变得更容易。在展开的步骤中使用搜索功能来定位特定错误,而不是滚动浏览所有内容。

向工作流添加诊断步骤

有时你需要自定义调试信息。在关键操作之前添加输出环境详情的步骤:

- name: Debug environment
  run: |
    echo "Node version: $(node --version)"
    echo "Working directory: $(pwd)"
    echo "Event: ${{ github.event_name }}"
    env | sort

对于不可预测地失败的步骤,临时使用 continue-on-error: true。这允许后续步骤运行,从而暴露失败是级联的还是孤立的:

- name: Potentially flaky step
  id: tests
  continue-on-error: true
  run: npm test

- name: Capture state after tests
  if: always()
  run: echo "Tests completed with status ${{ steps.tests.outcome }}"

一旦确定了根本原因,就移除 continue-on-error

在推送前本地验证工作流

仅仅为了测试工作流语法而推送提交会浪费时间并使你的历史记录变得混乱。使用 actionlint 在错误到达 GitHub 之前捕获 YAML 错误和表达式错误:

actionlint .github/workflows/

对于更全面的本地测试,nektos/act 在 Docker 容器中运行工作流,这些容器近似于 GitHub 的 runner 环境。它不会复制所有内容——制品保留和确切的软件版本有所不同——但它验证步骤执行顺序并捕获明显的配置问题。

act -P ubuntu-latest=catthehacker/ubuntu:act-latest

这两个工具都提供快速反馈循环,显著减少工作流故障排查周期。

理解制品(Artifact)行为

GitHub Actions 中的制品是作业范围的。在 v4 系统下,多个作业不能上传到同一个制品名称——尝试这样做会导致冲突而不是合并。始终为每个作业提供唯一的制品名称,特别是在矩阵或并行构建中,以避免上传失败并确保可预测的检索。

使用可复用工作流减少不稳定性

跨仓库复制工作流逻辑会引入不一致性。当相同的步骤存在于多个位置时,调试变得更加困难,因为修复必须传播到各处。

可复用工作流集中了常见模式。当你在一个地方修复错误或提高可靠性时,所有调用工作流都会受益。这种方法还使 CI/CD 调试更容易在整个组织中一致应用。

固定 Action 版本并避免使用已弃用的 Actions

通过 SHA 或特定版本标签引用 actions,而不是 @main@master。未固定的引用可能在上游更改发生时破坏工作流:

# 推荐这样做
uses: actions/checkout@v4

# 避免这样做
uses: actions/checkout@main

许多较旧的调试辅助 actions 使用已弃用的 Node.js 版本。GitHub 会在工作流日志中对此发出警告。用维护良好的替代方案替换它们,以避免当 GitHub 最终移除对旧版运行时的支持时出现意外失败。

在调试输出中保护 Secrets

调试日志会暴露更多信息,这会带来风险。即使在调试步骤中也不要直接回显 secrets。GitHub 会掩盖已知的 secrets,但派生值或部分匹配可能会泄露。在公开共享日志或在问题报告中共享之前,请检查调试输出。

结论

当你掌握正确的技术时,工作流故障排查就会变得可管理。启用调试日志以获得可见性,策略性地添加诊断步骤,使用 actionlint 或 act 在本地验证,并通过可复用工作流保持一致性。这些 GitHub Actions 最佳实践无论平台如何演变都适用——它们是使 CI/CD 调试更快、更少挫折的基础。

常见问题

随机失败通常源于外部依赖项的更改,例如未固定的 action 版本更新、包注册表问题或速率限制。共享 runner 上的网络超时和资源限制也可能导致间歇性失败。启用调试日志并检查失败是否与特定时间或外部服务可用性相关。

使用带有步骤 id 属性的 steps 上下文。首先,为你的步骤分配一个 id,然后使用语法 steps.step_id.outputs.output_name 引用其输出。对于带有 continue-on-error 的步骤结果,使用 steps.step_id.outcome,它返回 success、failure、cancelled 或 skipped。

可以。使用 actionlint 在本地验证 YAML 语法和表达式。对于更彻底的测试,nektos/act 在模拟 GitHub runner 环境的 Docker 容器中运行工作流。虽然 act 无法复制每个 GitHub 功能,但它能捕获大多数配置错误并在推送前验证步骤执行顺序。

ACTIONS_STEP_DEBUG 为单个工作流步骤启用详细输出,显示每个 action 执行的详细信息。ACTIONS_RUNNER_DEBUG 提供关于 runner 本身的更低级别诊断信息,包括环境设置和内部操作。对于大多数调试场景,ACTIONS_STEP_DEBUG 提供足够的详细信息。

Understand every bug

Uncover frustrations, understand bugs and fix slowdowns like never before with OpenReplay — the open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data. Check our GitHub repo and join the thousands of developers in our community.

OpenReplay