使用 TVM 的 CI

TVM 主要使用 Jenkins 在 Linux 持续集成 (CI) 测试 分支pull requests,通过 Jenkinsfile 中指定的构建配置。Jenkins 是唯一被编纂为阻止合并的 CI 步骤。TVM 也在 GitHub Actions 上进行了针对 Windows 和 MacOS 的最低限度测试。

此页面描述了贡献者和提交者如何使用 TVM 的 CI 来验证他们的代码。您可以在 tlc-pack/ci 仓库中阅读更多关于 TVM CI 设计的信息。

贡献者须知

标准的 CI 运行看起来像这样,在 Jenkins 的 BlueOcean 查看器中查看。CI 运行通常需要几个小时才能完成,并且 pull requests (PR) 在 CI 成功完成之前不能合并。要诊断失败的步骤,请点击失败的 pipeline 阶段,然后点击失败的步骤以查看输出日志。

The Jenkins UI for a CI run

调试失败

当 CI 由于某些原因失败时,有几种方法可以诊断问题。

Jenkins 日志

查找失败的首要位置是 CI 日志,按照失败作业上的红色 X 标记查看日志。注意

  • Jenkins 默认不显示完整日志,在日志查看器的顶部有一个按钮“Show complete log”,点击它将带您到日志的纯文本版本

  • pytest 失败总结在日志的底部,但您可能需要向上滚动才能查看实际的失败信息。

重现失败

大多数 TVM Python 测试在 pytest 下运行,可以按照 测试 中的描述运行。

报告问题

CI 的问题应该在 GitHub 上报告,并附上相关作业、提交或 PR 的链接。

维护者须知

本节讨论 TVM 维护者运行的流程。

保持 CI 绿色的步骤

本节讨论用于保持 CI 通过的常用步骤。

因同时合并导致的 CI 损坏

开发者依赖 TVM CI 来获取其 PR 在合并前的信号。有时,两个不同的 PR 可以单独通过 CI,但在两者都落地时破坏 main 分支。这反过来会导致错误显示在基于损坏提交的不相关的 PR 上。可以通过 GitHub 上的提交状态图标或通过 Jenkins 识别损坏的提交。

在这些情况下,修复 CI 最终是合并 PR 的 TVM Committer 的责任(也鼓励其他人帮忙)。对此情况的典型反应是:1. 回滚有问题的提交 2. 提交向前修复以解决问题。

由 committer 和提交作者决定选择哪个选项。损坏的 CI 会影响所有 TVM 开发者,应尽快修复,而回滚对于有问题的 PR 的作者来说可能尤其痛苦,特别是当该 PR 很大时。

处理不稳定性

如果您注意到 PR 上的失败似乎与您的更改无关,您应该搜索 [最近的与不稳定测试相关的 GitHub issues](https://github.com/apache/tvm/issues?q=is%3Aissue+%5BCI+Problem%5D+Flaky+>) 和 [提交新的 issue](https://github.com/apache/tvm/issues/new?assignees=&labels=&template=ci-problem.md&title=%5BCI+Problem%5D+>),如果您没有看到任何关于该失败的报告。如果某个测试或某类测试影响了 main 分支上的多个 PR 或提交,并且出现不稳定的失败,则应通过 [pytest 的 @xfail 装饰器](https://pytest.cn/en/6.2.x/skipping.html#xfail-mark-test-functions-as-expected-to-fail) 以及 [strict=False](https://pytest.cn/en/6.2.x/skipping.html#strict-parameter) 禁用该测试,并在禁用 PR 中链接相关的 issue。

@pytest.mark.xfail(strict=False, reason="Flaky test: https://github.com/apache/tvm/issues/1234")
    def test_something_flaky():
        pass

然后像往常一样提交 PR

git add <test file>
git commit -m'[skip ci][ci] Disable flaky test: ``<test_name>``

See #<issue number>
'
gh pr create

跳过 CI

对于回滚和简单的向前修复,在回滚 PR 标题中添加 [skip ci] 将导致 CI 快捷方式,仅运行 lint。Committer 应该注意,他们只应合并跳过 CI 的 PR 以修复 main 分支上的失败,而不是在提交者想要快捷方式 CI 以更快地合并更改的情况下。PR 标题在首次运行构建时检查(特别是在 lint 步骤期间,因此之后的更改不会影响 CI,并且需要通过另一个 git push 重新触发作业)。

# Revert HEAD commit, make sure to insert '[skip ci]' at the beginning of
# the commit subject
git revert HEAD
git checkout -b my_fix
# After you have pushed your branch, create a PR as usual.
git push my_repo
# Example: Skip CI on a branch with an existing PR
# Adding this commit to an existing branch will cause a new CI run where
# Jenkins is skipped
git commit --allow-empty --message "[skip ci] Trigger skipped CI"
git push my_repo

Docker 镜像

每个 CI 作业的大部分工作都在 Docker 容器内运行,该容器从 docker/ 文件夹中的文件构建。

更新 Docker 镜像标签

要更新标签,需要构建新的镜像并上传到 Docker Hub,然后需要更新 docker-images.ini 中的镜像标签,以匹配 Docker Hub 上的镜像标签。

Docker 镜像通过 tvm-docker 每晚自动构建,并将构建的镜像上传到 https://hub.docker.com/u/tlcpackstaging,一旦它们通过 CI。合并后在 main 分支上运行的 CI 会临时构建 Docker 镜像,并将它们上传到 tlcpackstaging Docker Hub 帐户。有一个自动提升流程,用于将 tlcpackstaging Docker 镜像移动到 tlcpack 帐户。这意味着来自 tlcpackstaging 的镜像标签可以在 CI 中使用,并且在 main 分支上成功进行合并后 CI 运行后,它们将自动移动到 tlcpack。因此,更新镜像的步骤是

  1. 合并一个 PR,该 PR 更改了 docker/ 下的 Dockerfiles 或 docker/install 中的脚本。

  2. 执行以下任一操作

    1. 等待来自 PR 的合并后 CI 构建完成,并将新构建的镜像上传到 tlcpackstaging Docker Hub。

    2. 等待每晚 Docker 镜像构建完成,并将新构建的镜像上传到 tlcpackstaging Docker Hub。

  3. tlcpackstaging Docker Hub 上找到新上传的镜像标签,例如 20221208-070144-22ff38dff,并更新 ci/jenkins/docker-images.ini 中的标签以使用 tlcpackstaging 标签,但在 tlcpack 帐户下,例如 tlcpack/ci-arm:20221208-070144-22ff38dff。提交包含这些更改的 PR 并等待它完成 CI 运行,以确保新镜像有效。

  4. 合并 docker-images.ini 更新 PR。一旦合并后 CI 完成在 main 分支上的运行,tlcpackstaging 标签将自动重新上传到 tlcpack

添加新的 Docker 镜像

可以添加新的 docker 镜像,以在各种平台上测试 TVM。以下是添加新的 CI 镜像的步骤

  1. docker/ 中定义 docker/Dockerfile.ci_foodocker/install 中的关联脚本。创建一个仅包含这些更改的 PR(没有 Jenkinsfile 更改)。

    示例:https://github.com/apache/tvm/pull/12230/files

  2. Committer 验证镜像在本地构建,然后审查/批准此 PR。

  3. Committer 在 https://hub.docker.com/u/tlcpackhttps://hub.docker.com/u/tlcpackstaging 中创建 ci-foo 仓库。

  4. 创建一个 PR 以在 tlcpack/ci 中为镜像创建 ECR 仓库:https://github.com/tlc-pack/ci/pull/46/files

  5. Committer 创建并合并一个 PR,以将镜像添加到 Jenkinsfile

    示例:https://github.com/apache/tvm/pull/12369/files

    注意:PR 必须从 apache/tvm 中的分支打开,而不是从 fork 仓库中的分支打开。

  6. Committer 将此镜像添加到 tlcpack 中的每日 docker 重建/验证运行中。

ci-docker-staging

ci-docker-staging 分支通常用于测试 Docker 镜像和 Jenkinsfile 更改的更新。当为来自 fork 仓库的普通 PR 运行构建时,Jenkins 使用来自 PR 的代码,但 Jenkinsfile 本身除外,它来自基础分支。当构建分支时,将使用分支中的 Jenkinsfile,因此具有写入权限的 committer 必须将 PR 推送到 apache/tvm 中的分支,以正确测试 Jenkinsfile 更改。如果您的 PR 更改了 Jenkinsfile,请确保 @ 一位 committer 并要求他们将您的 PR 作为分支推送以测试更改。

CI 监控轮换

有些测试也是不稳定的,偶尔会因与 PR 无关的原因而失败。CI 监控轮换 负责监视这些失败,并在必要时禁用测试。编写测试的人员有责任最终修复并重新启用测试。