ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Aspire CI Pipeline 优化实践:按依赖与 OS 拆分构建测试车道,缩短首信信号与墙钟时间

Aspire CI Pipeline 优化实践:按依赖与 OS 拆分构建测试车道,缩短首信信号与墙钟时间 Aspire CI Pipeline 优化实践按依赖与 OS 拆分构建测试车道缩短首信信号与墙钟时间【免费下载链接】aspireAspire is the tool for code-first, extensible, observable dev and deploy.项目地址: https://gitcode.com/GitHub_Trending/as/aspire本文基于 Aspire 仓库的 CI Pipeline Optimizations 文档结合 .github/workflows/tests.yml、eng/scripts/split-test-matrix-by-deps.ps1 等真实工作流与脚本源码讲解 Aspire 主测试流水线的优化目标、作业拆分策略与产物依赖设计。读完后你可以掌握如何在 GitHub Actions 中通过“多车道并行 精确 needs 依赖”平衡首信信号时间与总耗时以及如何验证一次 CI 结构改动没有破坏产物生产与消费的一致性。优化目标为什么不做单一串行大作业Aspire 的测试流水线被明确优化为三个目标缩短首个可用测试信号的时间Short time to first useful test signal缩短总墙钟时间Short total wall-clock time共享产物与测试作业之间保持清晰的依赖边界Clear dependency boundaries between shared artifacts and test jobs。这三条目标直接决定了工作流的组织方式它偏好多个“感知依赖”的小作业而不是单一的“构建 测试”串行大车道。这样纯单元测试车道可以在任何构建产物就绪之前就开始运行而各平台的测试只等待本平台真正需要的产物避免被最慢的平台拖住。当前结构tests.yml 的五个阶段主测试工作流 .github/workflows/tests.yml 被组织成以下阶段setup_for_tests枚举测试并产出 OS 展开后的all_tests矩阵然后调用 eng/scripts/split-test-matrix-by-deps.ps1 将矩阵切分为按依赖划分的桶。见 tests.yml 中 “Split matrix by dependency type” 步骤。build_packages构建共享 Aspire 包源package feed供需要 NuGet 包的测试使用通过-p:SkipBundleDepstrue避免重复构建由 CLI archive 作业负责的 RID 专属 DCP/Dashboard 包。build_cli_archive_linux/build_cli_archive_windows/build_cli_archive_macos以及当前代码中的 arm64/x64 变体按 RID 构建原生 CLI 归档在本地用BuildBundleDepsOnly构建对应的 RID 专属 DCP 与 Dashboard 包上传built-nugets-for-{rid}工件供下游测试消费上传cli-native-archives-{rid}工件供 polyglot validation 等归档消费者使用。测试执行车道tests_no_nugets、tests_requires_nugets_linux、tests_requires_nugets_windows、tests_requires_nugets_macos、tests_requires_cli_archive、polyglot_validation、extension_tests_win。results在所有必需车道完成后汇总整个工作流的最终状态。从当前源码结构看tests.yml 中的构建车道比文档描述的基线更细除了文档提到的三个 x64 主车道还有build_cli_archive_linux_arm64、build_cli_archive_windows_arm64、build_cli_archive_macos_x64等按架构细分的作业见 tests.yml。它们的拆分原则与文档完全一致——每个 RID 对应一个独立的构建作业下游只声明自己实际需要的needs。为什么这样拆分作业1. 包构建与 CLI archive 构建并行build_packages与各 CLI archive 作业有意并行执行。如果没有这个拆分CLI archive 的创建将被迫排在共享包构建之后——尽管 archive 的大部分工作其实是独立的。现在 archive 工作流在本地构建自己所需的 RID 专属 DCP 和 Dashboard 包build-cli-native-archives.yml 中显式传入/p:BuildBundleDepsOnlytrue注释明确写道 “This allows the CLI archive build to run in parallel with build_packages”因此没有必要串行等待build_packages。这缩短了以下对象的产物就绪时间CLI archive 的消费者、polyglot validation、以及任何需要 RID 专属 DCP/Dashboard 包的测试。2. CLI archive 构建按 OS 独立工作流对每个平台使用一个独立的 CLI archive 作业而不是一个合并的矩阵依赖。这样下游作业只需要等待与自身 runner 和 RID 匹配的那个 archiveLinux 测试等待build_cli_archive_linuxWindows 测试等待build_cli_archive_windowsmacOS 测试等待build_cli_archive_macos在 tests.yml 中可以看到每段作业都带有同样的设计注释“Split by OS so that test jobs can depend on just their platforms archive, allowing Linux tests to start as soon as the Linux archive completes without waiting for the slower Windows/macOS builds.” 如果这些作业被合并到单一逻辑依赖后面最慢的平台会拖慢所有依赖它的测试车道。3.requires_nugets测试按 OS 拆分需要构建包的测试同时需要正确 RID 的 DCP/Dashboard 包而这些包由同一 OS 的 CLI archive 作业产出。因此工作流把requires_nugets桶拆成 Linux、Windows、macOS 三条车道使依赖图与产物生产方式严格对齐Linux 车道不等待 Windows 或 macOS 的产物Windows 车道不等待 Linux 或 macOS 的产物macOS 车道不等待 Linux 或 Windows 的产物。这一拆分的依据可在 split-test-matrix-by-deps.ps1 中看到脚本先按requiresNugets过滤条目再按runs-on值调用Get-OsCategory归入 linux/windows/macos 三类产出tests_matrix_requires_nugets_{linux,windows,macos}三个矩阵。4.tests_requires_cli_archive只依赖 Linux CLI archive 车道当前的requires_cli_archive消费者运行在 Linux 上因此工作流只依赖build_cli_archive_linux而非全部 CLI archive 作业。它仍等待build_packages但在 CLI archive 作业中只需要 Linux 车道——见 tests.yml 的needs: [setup_for_tests, build_packages, build_cli_archive_linux, build_cli_e2e_image]。这是有意为之要求全部 CLI archive 构建只会增加无收益的等待时间。如果未来为 Windows 或 macOS 新增 archive 依赖测试应当重新审视这一依赖。5.tests_no_nugets尽早启动no_nugets桶不依赖任何包或归档的构建产物是最快获得广泛 CI 反馈的方式。让它立即启动可以减少开发者在单元测试等自包含车道中看到失败前的等待时间。在 tests.yml 中该作业的needs只有setup_for_tests。6.results保持集中即便执行更加并行工作流仍保留单一的results作业让 GitHub 对整个测试流水线报告一个最终、易懂的结果。当前 tests.yml 中results的needs列表覆盖了全部构建车道、测试车道、installer 制品准备与 TS SDK 车道并附带复杂的if:判定逻辑skipped只有在“该车道本应有工作却未执行”时才视为失败例如矩阵非空但作业被跳过从而兼容选择性 CI 下桶可能合法为空的场景。三项附加优化Linux 关键路径使用 8 核 runnerbuild_cli_archive_linux和build_packages都运行在8-core-ubuntu-latest上tests.yml、build-packages.yml。Linux CLI archive 处于tests_requires_cli_archive、polyglot_validation等 Linux 专属消费者的关键路径上而build_packages被每个需要包的测试车道共享。把额外构建容量花在 Linux 上回报最大共享包构建与 Linux archive 完成得越早下游验证车道启动得越早。build_packages跳过 RID 专属 bundle 依赖build_packages使用SkipBundleDepstrue而 CLI archive 作业使用BuildBundleDepsOnlytrue。两个设置互相配合共享包构建避免了本会重复的工作每个 CLI archive 作业负责其真正需要的 RID 专属依赖包构建与 archive 构建可以并行而不会为同一产物“抢跑”。VS Code 扩展在独立测试车道中构建扩展相关工作现在位于extension_tests_win而不再折叠进build_packagestests.yml。这使build_packages专注于共享包源并且由于extension_tests_win不依赖包或 archive 作业它可以独立运行而不是拉长关键路径。关键文件细节build-packages.ymlbuild_packages使用如下命令构建共享包源见 build-packages.yml./build.sh -restore -build -ci -pack -bl -p:InstallBrowsersForPlaywrightfalse -p:SkipTestProjectstrue -p:SkipPlaygroundProjectstrue -p:SkipBundleDepstrue其中SkipBundleDepstrue是关键——RID 专属的 bundle 依赖由按 OS 的 CLI archive 作业产出而不是由共享包构建产出。构建完成后作业清理artifacts/bin、artifacts/obj将artifacts/packages上传为built-nugets工件retention 15 天并无论成败都上传构建日志以便排障。build-cli-native-archives.yml每个 CLI archive 作业的执行序列是在本地构建 RID 专属 DCP 与 Dashboard 包-ci -restore -build -pack /p:BuildBundleDepsOnlytrue并注入/p:AspireCliChannelchannel渠道按触发事件计算PR 构建为pr-N、release 分支为staging、main 为local、其他为daily见 build-cli-native-archives.yml用 eng/Bundle.proj 构建 bundle 载荷归档/p:TargetRid{rid} /p:SkipNativeBuildtrue构建 CLI 包-pack -build/p:SkipManagedBuildtrue /p:TargetRids{rid}将 bundle 载荷路径传入通过verify-cli-tool-nupkg.ps1与verify-cli-npm-package.ps1对 nupkg / npm 包做结构校验上传built-nugets-for-{rid}包含Aspire.Hosting.Orchestration.{rid}、Aspire.Dashboard.Sdk.{rid}、Aspire.Cli.*nupkg 与microsoft-aspire-cli*.tgz与cli-native-archives-{rid}两类工件见 build-cli-native-archives.yml。这使 archive 作业对其所需的 RID 专属产物完全自给自足。关于原生 CLI 归档的签名、dotnet-tool 包结构以及为什么签名构建消费签名归档载荷参见 Native CLI Packaging。run-tests.ymlrequiresNugets 车道的消费流程当某测试车道设置requiresNugets: true时run-tests.yml 按如下顺序装配本地包源下载共享的built-nugets工件到artifacts/packages并把嵌套的built-nugets/Debug目录归位根据runner.os与runner.arch计算车道 RIDLinux-X64 → linux-x64、macOS-ARM64 → osx-arm64等映射见 run-tests.yml下载built-nugets-for-{rid}工件到arch-specific目录在运行测试前把这些 RID 专属包合并进本地包源artifacts/packages/Debug/Shipping。这正是依赖图必须保持“测试车道 ↔ 同 OS CLI archive 车道”关系的原因如果某个 OS 的车道没有声明对应 archive 作业的needs第 3 步下载到空目录第 4 步的合并会直接报错。矩阵拆分与 256 作业上限setup_for_tests中的拆分由 eng/scripts/split-test-matrix-by-deps.ps1 完成其行为要点读取 OS 展开后的all_tests矩阵按properties子对象中的requiresCliArchive、requiresNugets布尔标志分成三大类CLI archive 桶优先于 NuGet 桶判定requires_nugets类再按runs-on值归入 linux/windows/macos校验每个桶不超过约束脚本将$maxMatrixSize 256硬编码为 GitHub Actions 每个strategy.matrix的 256 作业上限split-test-matrix-by-deps.ps1、校验循环任何桶超限都会显式失败避免工作流静默丢失测试条目通过-OutputToGitHubEnv把五个桶tests_matrix_no_nugets、tests_matrix_requires_nugets_{linux,windows,macos}、tests_matrix_requires_cli_archive写入GITHUB_OUTPUT供后续作业消费。另外值得注意的是setup_for_tests中一个实现细节展开后的矩阵可能超过 128KB必须通过文件all_tests.json而非环境变量传递给拆分脚本——过长的单个环境变量会使 Linux 的execve因E2BIG失败见 tests.yml 注释。修改该区域时的验证清单按照 原文档 的约定改动 CI 结构时应验证产物生产与产物消费仍然匹配build_packages仍发布共享包源每个 CLI archive 车道仍发布正确的built-nugets-for-{rid}工件对照 run-tests.yml 的下载与合并逻辑。每个测试车道只等待它真正需要的工作除非某个消费者确实需要否则不要添加跨 OS 依赖。Linux 专属消费者保持在最短路径上尤其是tests_requires_cli_archive与polyglot_validation。矩阵桶大小保持在 GitHub 限制之内split-test-matrix-by-deps.ps1 强制执行 256 作业硬上限。文档保持同步依赖图变化时同步更新 docs/ci/ci-pipeline-optimizations.md 与 docs/ci/TestingOnCI.md后者是矩阵生成与测试枚举流水线的配套文档覆盖SplitTestsOnCI、RequiresNugets、RequiresCliArchive等 MSBuild 属性的完整注册表。小结Aspire 的 CI 优化本质上是把“产物生产”与“测试消费”之间的依赖关系做精细建模共享包源与按 OS 划分的原生 CLI archive 并行生产测试车道按requiresNugets/requiresCliArchive与所在 OS 对齐到最小等待集合再由集中式results作业收口。所有拆分决策都可以从 tests.yml 的needs声明和 split-test-matrix-by-deps.ps1 的桶校验逻辑中直接验证这也是后续维护者在改动流水线时应当遵循的验证方式。【免费下载链接】aspireAspire is the tool for code-first, extensible, observable dev and deploy.项目地址: https://gitcode.com/GitHub_Trending/as/aspire创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表