去年,当我在为 SciPy重新设计 CI/CD 管道时,我有机会使用GitHub Actions。 GitHub Actions 是GitHub 的内部 CI/CD 服务,希望能够说服许多项目维护人员和开发人员从外部CI/CD服务(如TravisCI中的TravisCI)转移到 GitHub Actions希望有一个可以构建、测试和部署的中央服务。

然而,与其他 CI/CD 服务(如CircleCI)不同,它具有使用CLI和SSH 机制的适当调试机制,GitHub Actions 不提供任何调试工具失败的工作流程。它通常会导致开发人员多次提交,以触发和重新触发 CI/CD 工作流,以确保他们的提交旁边有一个绿色的勾号。有效调试 GitHub Actions 工作流程的要求让我陷入了困境。

显示两个面板的模因。在顶部,一个男人指着相机说“生活是美好的”。在底部面板中,同一个人微笑着说“但它可以更好”。在顶部,我们看到了 CircleCI、TravisCI 和 AppVeyor 的徽标。在底部,我们看到了 GitHub Actions 的标志。

使用 GitHub Actions 最好的部分是GitHub API的可用性,我们可以从我们的工作流程本身使用它。 GitHub Actions 还具有一个充满活力的市场,其中的应用程序旨在让开发人员更直接地使用 GitHub Actions。更有意义的是,一定有人已经解决了这个问题,而且我发现的解决方案不是一两个,而是多个!

在本博客中,我们将探讨几种有效调试 GitHub Actions 工作流程的方法。其中一些方法已经过实战测试(在调试许多项目的工作流程时),而有些方法对我来说是新的尝试并开始使用!

创建 GitHub Actions 工作流

我将使用一个简单的Flask 应用程序和一个返回Hello World消息的 API 端点来开始。我还为其添加了一个测试,以确保我们可以安装所有依赖项并在 CI 管道上运行测试以及使用Flake8进行一些 linting。测试我们的应用程序的最基本工作流程类似于以下内容:

# Path: .github/workflows/ci.yml

name: Flask CI

on:
  push:
    branches:
      - master
  pull_request:
    branches:
      - master

jobs:
  build:
    runs-on: ubuntu-latest

    steps:

      - uses: actions/checkout@v2

      - name: Setup Python 3.8
        uses: actions/setup-python@v2
        with:
          python-version: 3.8

      - name: Install dependencies
        run: |
          python -m pip install --upgrade pip
          pip install -r requirements.txt

      - name: Run tests
        run: |
          python -m pytest

      - name: Run Flake8
        run: |
          pip install flake8
          flake8 .

工作流用YAML编写,然后作为项目.github/workflows目录中存储库的一部分提交。一旦代码被推送,GitHub 将根据它们包含的指令检测需要触发和处理的工作流。

上面的工作流程启动了一个工作流程,每个推送和拉取请求都会触发该工作流程,并在 Ubuntu 运行器上检查代码。它将进一步安装依赖项、运行测试并检查代码库以确保样式检查到位。现在我们有了一个基本的工作流程设置,这就是它在推送后的样子:

GitHub 操作面板显示整个工作流程在 GitHub UI 上运行的每一步

让我们检查一下如何进一步深入研究这些工作流程。

使用act在本地运行工作流

act是Nektos提供的一个工具,它提供了一种在本地运行 GitHub Actions 的便捷方式。它提供了一种快速的方法来在本地验证您对 CI 的更改,而无需将更改提交/推送到工作流以触发和验证它们。作为本地任务运行程序,它可以带来快速反馈和兼容性,以验证我们所有的 CI 作业。

在内部,act通过构建和运行执行作业的 Docker 容器来模拟我们想要运行的工作流。act将市场操作作为单独的 Docker 镜像拉取,并允许我们以优雅的方式在 Docker 容器中使用它们。虽然内部实现很复杂,但act为您提供了一种简洁的方式,只需一个命令即可在本地运行 GitHub Actions 工作流!

可以使用Homebrew、Chocolatey甚至是简单的 BASH 脚本在本地设置 act。要使用 BASH 脚本进行设置,请在终端上推送以下命令:

curl https://raw.githubusercontent.com/nektos/act/master/install.sh | sudo bash

如果您有可用的 Homebrew,请使用以下命令安装它:

brew install act

下一步是定义我们可以用来在本地运行工作流的自定义图像。act为 Ubuntu GitHub runner 提供了一个微型、中型和更大的 Docker 镜像。但是,act还不支持 Windows 和 macOS 镜像。第一次运行 act 时,我们可以定义要用于本地 CI 运行的图像。配置保存在~/.actrc文件中。您可以选择直接从 GitHub Container Registry 拉取镜像:

docker pull ghcr.io/catthehacker/ubuntu:act-latest

在 GitHub 存储库中,第一次运行act时,它会找到./.github/workflows和所有存在的工作流。要签出作为 GitHub Actions CI 的一部分列出的作业,请推送以下命令:

act -l

它返回以下内容:

$ act -l

Stage  Job ID  Job name  Workflow name  Workflow file  Events
0      build   build     Flask CI       ci.yml         push,pull_request

您现在可以通过指定act来运行工作流,或者如果有多个工作流,您可以通过指定act -j <job_name>调用单个工作流:

act -j build

成功完成工作流后,您将看到✅ Success表示工作流已成功执行!

来自 Warp 的快照,展示了使用本地操作来测试 GitHub Action 工作流程。

但是如果工作流运行失败怎么办?在这种情况下,最好使用-v, --verbose标志添加详细选项,以尽可能多地获取有关act运行时发生的工作流运行的信息。

您还可以使用以下命令获取 shell 访问权限,因为act实际上是 GitHub Action 工作流程的本地复制,尽管位于 Docker 容器内:

docker run -it -v $(pwd):/app/ ghcr.io/catthehacker/ubuntu:act-latest

由于本地项目文件映射到/app/目录,您可以开始运行 apt 命令、编辑文件以及确保工作流有效运行所需的任何操作!如果镜像标签不可用,请使用docker images检查您机器上可用的镜像标签(对于中等大小的镜像,默认为act-latest)。

查看法案的综合文档了解更多配置细节。

使用tmate获取SSH访问

虽然大多数 CI 服务,例如 CircleCI 或 TravisCI,都有一个特色调试模式,可以让你的 SSH 在运行的实例(VM 或容器)中,但 GitHub Actions 没有这样的功能(还没有!)。要在正在运行的操作中进行 SSH,您可能会发现tmateGitHub 操作对您的用例很有用。

此 GitHub Action 允许您访问正在运行的 GitHub Actions 运行程序。一旦 Action 到达此步骤,就会调用 SSH 服务器,并且每隔 5 秒将连接信息打印到 Checks 选项卡的输出中。您可以为您的用例打开一个 Web 终端,也可以使用 SSH 直接从您的终端验证和调试您的工作流程。

要开始,请在您的工作流作业中添加此步骤:

- name: Setup tmate session
   uses: mxschmitt/action-tmate@v3

触发工作流后,您现在会注意到 tmate 会话可用于您的 GitHub Action 运行器:

来自 GitHub Action 运行器日志的快照,显示 tmate 打开 SSH 会话以及访问运行器内的 SSH 的 Web shell 并调试任何问题

你可以打开你的终端(我使用Warp)并输入:

ssh 6EJCQMtC5ET9RaPhVu3DCwfnj@nyc1.tmate.io

但是 tmate 是如何工作的呢? tmate 是一个终端多路复用器,具有即时终端共享功能,您可以通过 SSH 将终端访问权限共享给多个用户。您可以与希望一起调试失败的工作流的各种用户共享上述 Web shell 链接和 SSH 访问权限。

为了充分利用它,建议将它与${{ failure() }}的 if 条件一起使用,以确保仅在上述任何步骤失败时才调用 tmate。它确保您在不需要时不会调用 tmate。还建议添加timeout-minutes以减少 GitHub Action 运行器的使用,并且不让它在运行器超时之前占用整个持续时间。

为确保您是唯一能够获得 SSH 访问权限的人(如果它是公共项目),请使用您在 GitHub 上注册的公共 SSH 密钥向运行器进行身份验证。为此,请添加:

with: 
    limit-access-to-actor: true

这也确保了在工作流运行时不会有人访问您的GITHUB_TOKEN,并且您可以安全地调试失败的工作流。

如果您不是 tmate 的忠实粉丝,您可以选择使用Debug via SSH操作,该操作使用 Ngrok。但是,请记住在问题解决后删除调试步骤,并且您的 CI 状态为绿色!

使用 Foresight 调试工作流

我遇到的一个新工具是Thundra 的 Foresight,它有助于调试和分析你的 GitHub Actions 工作流程。 Foresight 为 GitHub Actions 工作流提供监控/调试功能,并支持跨 Java、JavaScript (Jest) 和 Python (PyTest) 的测试。虽然Thundra不适合上述两个用例,但它允许大型组织批判性地分析其失败的测试套件并显着降低 CI 成本和构建时间。

首先,我们需要在 Thundra 上创建一个帐户并选择 Foresight 作为我们希望使用的产品。我们现在可以继续创建一个新项目。通过项目设置,获取Thundra API 密钥和 Thundra 项目 ID,这是在我们的工作流程中配置 Foresight 所必需的。添加以下步骤作为工作流作业的一部分:

- name: Install Thundra Python Agent
  uses: thundra-io/thundra-foresight-python-action@v1
  with:
    apikey: ${{ secrets.THUNDRA_APIKEY }}
    project_id: ${{ secrets.THUNDRA_PROJECT_ID }}
    command: pytest

您也可以单独运行pytest命令。您现在可以在相应的小部件上查看最新的测试运行详细信息。 Foresight 可以向您显示整体测试运行时间,并帮助您发现不稳定、跳过或非常慢的测试。

显示 GitHub Action 运行的 Foresight 面板,该面板被持续分析,可以帮助您识别错误和易碎测试

通过 Foresight,您可以查看更多 CI 可观察性数据,例如测试套件的性能指标、失败的频率、操作日志,并通过创建“快照”帮助您跟踪错误并找出特定测试失败的原因。与启用本地运行的act相比,Foresight 提供回放功能来帮助您指出失败的测试,从而确保时间旅行调试。

结论

在此博客中,我们发现了许多调试、模拟和分析 GitHub Actions 工作流程以确保它们正常工作的方法。不再需要通过随机修复进行连续提交,以确保您的 CI 是绿色的并且部署成功! GitHub Actions 还具有更多附加功能,允许您跨多个场景、架构和环境测试您的部署,使其成为可靠测试和部署的协作工具,而不仅仅是简单的 CI/CD 工具。

谢谢阅读!查看Pajamas 2021 存储库,其中托管 Flask 应用程序和 GitHub Actions 工作流程的源代码,我在睡衣会议 2021期间介绍了这些源代码。

Logo

Python社区为您提供最前沿的新闻资讯和知识内容

更多推荐