菜单

CI 工作流

相关源文件

本文档描述了 Deno 项目的持续集成(CI)工作流。它解释了如何通过 GitHub Actions 管理自动化构建、测试和发布,工作流的结构以及 CI 管道的关键组件。

有关更广泛的构建系统(包括 Cargo 设置)的信息,请参阅 Cargo 设置

概述

Deno 项目使用 GitHub Actions 来自动执行跨多个平台(Windows、macOS、Linux)和架构(x86_64、aarch64)的测试、代码检查和发布。CI 工作流定义在 .github/workflows/ci.yml 中,该文件由一个 TypeScript 文件(.github/workflows/ci.generate.ts)生成,从而实现更易于维护和程序化的工作流配置。

CI 系统有几个关键目的:

  • 通过自动化测试和代码检查确保代码质量
  • 在各种平台和架构上构建和测试 Deno
  • 创建发布产物
  • 管理缓存以加速构建
  • 支持草稿 PR 处理和基准测试等特殊 CI 功能

来源:.github/workflows/ci.yml1-1180 .github/workflows/ci.generate.ts1-100

工作流架构

CI 管道流程

CI 工作流由三个主要事件触发:

  1. 拉取请求(打开、重新打开、同步、准备审查)
  2. 推送到主分支
  3. 标签推送(用于发布)

工作流具有并发控制,以防止重复构建,尤其是在拉取请求的情况下。

来源:.github/workflows/ci.yml3-20 .github/workflows/ci.generate.ts317-337

草稿 PR 处理

对于草稿 PR,工作流会运行一个 pre_build 作业,检查 PR 是否应该构建。除非满足以下条件之一,否则会跳过草稿 PR 的构建:

  • 提交消息包含 [ci]
  • PR 具有 ci-draft 标签

这样可以避免为正在进行中的 PR 消耗不必要的资源。

来源:.github/workflows/ci.yml22-44 .github/workflows/ci.generate.ts343-362

构建矩阵

CI 使用构建矩阵来跨不同的组合运行作业:

  • 操作系统(Linux、macOS、Windows)
  • 架构(x86_64、aarch64)
  • 作业类型(测试、代码检查、基准测试)
  • 构建配置(debug、release)

某些组合仅在特定触发器上运行

  • 拉取请求上的发布构建仅在 PR 具有 ci-full 标签时运行
  • 拉取请求上的基准测试作业需要 ci-bench 标签
  • Web 平台测试 (WPT) 仅在 Linux x86_64 上运行,并且不针对发布标签运行

来源:.github/workflows/ci.yml45-137 .github/workflows/ci.generate.ts379-449

Runner 选择

CI 工作流根据作业需求使用不同的 runner:

操作系统架构标准 RunnerXL Runner(用于资源密集型作业)
Linuxx86_64ubuntu-24.04ubuntu-24.04-xl
Linuxaarch64ubicloud-standard-16-arm-
macOSx86_64macos-13-
macOSaarch64macos-14cirruslabs/macos-runner:sonoma (自托管)
Windowsx86_64windows-2022windows-2022-xl

对于主分支或标签的 macOS ARM 构建,使用自托管 runner 以提高性能。

来源:.github/workflows/ci.yml55-76 .github/workflows/ci.generate.ts10-63

关键工作流步骤

环境设置

在构建和测试之前,工作流会设置必要的环境:

  1. Git 配置和仓库克隆
  2. 特定测试数据的子模块初始化
  3. Cargo 和构建产物的缓存设置
  4. 工具链安装
    • Rust(通过 rust-toolchain.toml)
    • Deno
    • Python(用于测试和 Windows 构建)
    • Node.js(用于测试和基准测试)

对于主分支或标签上的发布构建,还会进行 Google Cloud 认证以进行发布。

来源:.github/workflows/ci.yml142-252 .github/workflows/ci.generate.ts165-250

Sysroot 构建设置(Linux Release)

Linux 发布构建使用特殊的 sysroot 配置来实现增量链接时优化(LTO)。这包括:

  1. 设置 LLVM/Clang 工具链版本 19
  2. 下载和解压 sysroot
  3. 配置 Rust 的 LTO 标志
  4. 设置链接器缓存目录

此配置可提高发布构建的性能和优化。

来源:.github/workflows/ci.yml259-339 .github/workflows/ci.generate.ts80-162

构建流程

工作流根据配置有不同的构建步骤:

  1. Debug 构建

    cargo build --locked --all-targets
    
  2. Release 构建

    cargo build --release --locked --all-targets
    

对于发布构建,成功编译后,会生成符号缓存以更好地进行调试。

target/release/deno -A tools/release/create_symcache.ts ./deno.symcache

来源:.github/workflows/ci.yml415-448 .github/workflows/ci.generate.ts955-978

测试步骤

不同的作业类型运行不同种类的测试:

  1. 代码检查作业:

    • 检查代码格式(deno run --allow-write --allow-read --allow-run --allow-net ./tools/format.js --check
    • 检查 Rust 和 JavaScript 代码(deno run --allow-write --allow-read --allow-run --allow-net ./tools/lint.js
    • 检查 JSDoc 注释(deno run --allow-read --allow-env --allow-sys ./tools/jsdoc_checker.js
    • 验证 PR 标题格式(针对 PR)
  2. 测试作业:

    • 通过 Cargo 运行 Rust 测试
    • 在特定平台上,运行 Web 平台测试 (WPT)
    • 运行 Node.js 兼容性测试
  3. 基准测试作业:

    • 运行各种性能基准测试
    • 比较 PR 构建的结果

来源:.github/workflows/ci.yml396-412 .github/workflows/ci.generate.ts920-954

产物和发布

对于发布构建(来自主分支或标签),工作流:

  1. 创建特定于平台的二进制文件
  2. 剥离调试信息(用于更小的二进制文件)
  3. 创建 ZIP 存档
  4. 生成 SHA256 校验和
  5. 对于 macOS 构建,使用 Apple 代码签名对二进制文件进行签名
  6. 对于已标记的发布,使用产物创建 GitHub 发布

对于 Linux 构建,还会创建源代码压缩包。

来源:.github/workflows/ci.yml457-520 .github/workflows/ci.generate.ts979-1081

缓存策略

工作流使用缓存来加速构建。

Cargo 缓存

Cargo 缓存使用 cirruslabs/cache@v4 来存储/恢复:

  • Cargo 注册表索引
  • Cargo 注册表缓存
  • Cargo 二进制工具
  • Cargo git 数据库

此缓存由操作系统、架构和 Cargo.lock 哈希值进行键控,并回退到之前的按操作系统和架构的缓存。

来源:.github/workflows/ci.yml177-188 .github/workflows/ci.generate.ts495-514

构建产物缓存

对于 PR 构建,工作流还缓存构建产物,以避免重新构建未更改的代码。

target/
!target/*/gn_out
!target/*/gn_root
!target/*/*.zip
!target/*/*.tar.gz

此外,它还会维护文件修改时间以保留增量构建。

来源: .github/workflows/ci.yml373-389 .github/workflows/ci.generate.ts66-76

CI 配置生成

工作流文件生成

CI 工作流 YAML 文件是从 TypeScript 文件(.github/workflows/ci.generate.ts)生成的,这提供了几个优势

  1. 以编程方式定义复杂的矩阵组合
  2. 更好的代码重用和可维护性
  3. 能够使用 TypeScript 的特性,例如常量、函数和类型检查
  4. 更清晰地管理条件性任务执行

生成脚本定义了

  • 不同平台的运行器配置
  • 缓存键前缀和路径
  • 不同任务类型的步骤
  • 矩阵定义
  • 条件性任务执行逻辑

如 CI YAML 文件顶部的注释所示,在需要更改时,该脚本手动运行以更新工作流文件

# GENERATED BY ./ci.generate.ts -- DO NOT DIRECTLY EDIT

来源: .github/workflows/ci.yml1-2 .github/workflows/ci.generate.ts1-30

矩阵生成逻辑

矩阵配置使用了一个名为 handleMatrixItems 的辅助函数,该函数

  1. 将简写的 skip_pr 属性转换为完整的跳过条件
  2. 为被跳过的任务替换运行器以节省资源
  3. 为某些任务类型应用基于标签的激活

这提供了一种更清晰、更易于维护的方式来定义具有各种跳过条件和条件性运行器选择的复杂构建矩阵。

来源: .github/workflows/ci.generate.ts273-315 .github/workflows/ci.generate.ts379-449

特殊的流程功能

Pull Request 优化

CI 工作流包含多项针对 Pull Request 的优化

  1. 草稿 PR 处理:除非明确要求,否则跳过草稿 PR 的构建
  2. 条件性矩阵任务:某些资源密集型任务(发布构建、基准测试)仅在通过标签请求时运行
  3. 快速失败:在 PR 上,当任何任务失败时,矩阵会快速失败(与主分支构建不同)
  4. 跳过未更改路径:对于某些与子模块相关的步骤,工作流会检查相关路径是否已更改

这些优化有助于节省 CI 资源,同时在需要时提供详尽的测试。

来源: .github/workflows/ci.yml137-146 .github/workflows/ci.generate.ts453-458

发布发布

对于已标记的版本(发布),CI 工作流会

  1. 为所有支持的操作系统/架构组合创建特定于平台的二进制文件
  2. 生成符号缓存以改进调试
  3. 使用 Apple 代码签名对 macOS 二进制文件进行签名
  4. 创建 ZIP 存档和校验和
  5. 将发布资产上传到 GitHub Releases
  6. 将二进制文件上传到 Google Cloud Storage 以供更新检查器使用

此过程确保所有发布工件都已正确构建、签名和发布。

来源:.github/workflows/ci.yml457-520 .github/workflows/ci.generate.ts979-1081

金丝雀版本

对于来自主分支(但非标签)的构建,工作流会设置 DENO_CANARY 环境变量,该变量

  1. 在版本字符串中将构建标记为金丝雀版本
  2. 启用发布到 Google Cloud Storage 的“canary”频道
  3. 允许用户通过更新检查器获取最新的未发布功能

来源: .github/workflows/ci.yml252-258 .github/workflows/ci.generate.ts252-258