十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

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

Rust 仓库 CI 工具 citool 完全解析:任务矩阵计算、try-job 调度与本地复现

Rust 仓库 CI 工具 citool 完全解析:任务矩阵计算、try-job 调度与本地复现 Rust 仓库 CI 工具 citool 完全解析任务矩阵计算、try-job 调度与本地复现【免费下载链接】rustEmpowering everyone to build reliable and efficient software.项目地址: https://gitcode.com/GitHub_Trending/ru/rust导读citool是 Rust 官方仓库rust-lang/rust中用于驱动 GitHub Actions CI 的核心 Rust 工具它以极简的方式解决了两个关键问题根据当前场景Pull Request、bors try试运行、bors r合并尝试、main 分支推送动态计算应该执行哪些 CI 任务以及把部分CI 任务在本地完整复现。本文以 src/ci/citool/README.md 为切入点深入其源码覆盖运行类型判定、jobs.yml配置格式、try-job 提交信息语法、任务矩阵输出、数据库校验、本地执行与指标分析等全部环节读完即可理解 rust-lang/rust 的 CI 是如何做动态裁剪的并掌握在本地复现任意 Linux CI 任务的方法。citool 是什么README 定义的两大职责官方 README 用两句话定义了它的全部职责原文:This is a simple Rust script that determines which jobs should be executed on CI based on the situation (pull request, try job, merge attempt). It also provides a simple way of executing (some) CI jobs locally.翻译过来即CI 任务矩阵计算根据触发场景PR 推送、try job、merge attempt决定本次 CI 应该执行哪些任务本地任务执行提供在本地运行部分CI 任务的简单途径。simple 只是谦虚的说法——从源码看它承担了 CI 定义jobs.yml的解析、校验、展开、环境变量合并、GitHub API 查询、指标下载与 Datadog 上报等大量工作。它被设计为一个独立的 Cargo 工作区见 Cargo.toml 中的[workspace]注释citool 独立于仓库其他 crate避免被误并入根工作区使用edition 2024依赖clapCLI 解析、serde_yaml配置解析、askamaHTML 模板、ureqHTTP 客户端等。源码结构一览citool 的全部代码位于 src/ci/citool/src 目录模块职责main.rsCLI 入口与子命令分发、GitHub 上下文加载、本地执行流程jobs.rsjobs.yml数据模型、加载/校验、任务矩阵计算核心analysis.rs构建步骤耗时、测试套件结果、测试差异的报告输出metrics.rs从 CI 制品站点下载 / 缓存metrics-*.jsongithub.rs查询 GitHub Actions 工作流任务信息耗时、摘要链接test_dashboard.rs生成测试结果 HTML 仪表盘配合 templates 下的 askama 模板cpu_usage.rs解析collect-cpu-stats.sh生成的 CPU 使用 CSVdatadog.rs向 Datadog 上报 CI 自定义指标utils.rs环境变量读取、子模块初始化等工具函数场景判定RunType 与 GitHub 上下文的映射任务矩阵计算的第一个步骤是判定当前 CI 属于哪种运行类型。GitHubContextmain.rs从环境变量GITHUB_EVENT_NAME、GITHUB_REF和仅 push 事件COMMIT_MESSAGE中读取上下文get_run_type()main.rs按如下规则映射事件分支引用GITHUB_REF运行类型含义pull_request任意PullRequestPR 推送触发的常规 CIpushrefs/heads/automation/bors/tryTryJobbors try触发的试运行可携带自定义任务模式pushrefs/heads/automation/bors/try-perfTryJob无自定义模式、不设限性能测试专用试运行pushrefs/heads/automation/bors/autoAutoJobbors r后的合并尝试pushrefs/heads/mainMainJobmain 分支推送返回空矩阵仅用于共享 GitHub Actions 缓存其他其他None无法判定直接报错退出其中RunType枚举定义在 jobs.rs。值得注意MainJob的设计它故意不执行任何任务但会在 CI 上触发一次工作流从而预热缓存供后续任务共享。TryJob变体携带两个可选字段job_patterns自定义任务 glob 模式列表与nolimit是否跳过最多 20 个自定义任务的限制二者均从提交信息中解析而来。从提交信息解析 try-job 模式与 nolimitget_try_job_metadata()main.rs逐行扫描提交信息支持两种语法1. 自定义任务模式—— 形如try-job: job-pattern或为了避免 GitHub 把 glob 当作 Markdown 渲染可以用反引号包裹try-job: job-pattern反引号会在解析时被trim_matches() 剥离。2. 取消任务数量限制—— 提交信息中出现try-nolimit行即可。例如取自 tests/jobs.rs 的测试用例This is a test PR try-job: test-aarch64-gnu try-job: dist-i686-msvcjobs.ymlCI 任务的单一数据源所有任务的声明集中在 src/ci/github-actions/jobs.yml约 889 行citool 在 CI 中动态读取它。顶层结构包含三个部分runners定义可复用的 YAML 锚点base-job、job-linux-4c、job-macos-15、job-windows等声明 runner 的os如ubuntu-24.04、macos-15、windows-2025、AWS EC2 实例等与free_disk等公共属性envs按运行类型pr/try/auto声明共享环境变量例如pr注入PR_CI_JOB: 1production锚点注入DEPLOY_BUCKET、AWS 密钥 ID 与TOOLSTATE_PUBLISHjobs声明dist-*发布构建任务随后是pr:、try:、auto:、optional:四个任务列表。Job 数据模型每个任务对应 Job 结构体serde(deny_unknown_fields)严格反序列化字段类型说明nameString任务名如test-pr-check-1、dist-x86_64-linuxosString执行任务的 runner 标签envBTreeMapString, Value任务级环境变量值支持字符串/布尔/数字only_on_channelOptionString仅在指定 channel 执行如beta否则被skip_jobs过滤continue_on_errorOptionbool失败时不取消整个工作流free_diskOptionbool是否先释放磁盘空间doc_urlOptionString排障文档链接codebuildOptionbool是否在 AWS CodeBuild 上执行JobDatabasejobs.rs聚合pr_jobs、try_jobs、auto_jobs、optional_jobs四个列表以及按运行类型共享的envs。加载时有两个值得注意的细节YAML merge key 展开load_job_db()jobs.rs先对serde_yaml::Value连续两次调用apply_merge()因为 serde_yaml 无法直接处理合并键两次调用可展开最多嵌套两层的合并默认镜像名Job::image()jobs.rs中Docker 镜像名默认等于任务名但可被env.IMAGE覆盖。任务矩阵计算流程calculate_jobs()jobs.rs按运行类型选择任务来源与共享环境然后依次执行四步变换选择任务集PullRequest→pr_jobs前缀PR注入pr_envTryJob→ 有自定义模式则按 glob 展开auto_jobsoptional_jobs否则用try_jobsAutoJob→auto_jobs注入auto_env替换 GitHub 上下文变量substitute_github_vars()jobs.rs把os中的$github.run_id、$github.run_attempt替换为真实环境变量值——这正是jobs.yml中 AWS EC2 实例名如ec2-x86_64ami-m8a.2xlarge-x64-linux-$github.run_id-$github.run_attempt得以唯一化的原因channel 过滤skip_jobs()jobs.rs剔除only_on_channel与当前 channel 不匹配的任务合并环境变量并输出共享环境与任务环境合并任务级优先生成带full_name如auto - dist-x86_64-linux即{run_type} - {job_name}的GithubActionsJob。此外还有一个隐藏的优化默认bors try无自定义模式时会给任务注入DIST_TRY_BUILD1jobs.rs。该变量告诉opt-dist跳过某些构建步骤和测试让 try 构建更快完成——jobs.yml顶部注释也说明了这一点。try-job 模式的 glob 展开与数量限制当提交信息指定了自定义模式时jobs.rs用glob_match::glob_match如dist-*匹配所有dist-前缀任务在auto_jobsoptional_jobs中展开结果去重未匹配到任何任务的模式会直接报错Patternsxxxdid not match any auto jobs展开后的任务数超过MAX_TRY_JOBS_COUNT 20jobs.rs且未指定nolimit时报错并提示使用bors try jobs... nolimit。矩阵输出calculate_job_matrix()jobs.rs把结果按任务名排序后以jobsJSON与run_typepr|try|auto|main两行输出到 stdout供 GitHub Actions 的后续步骤消费同时向 stderr 打印jobs与run_type便于排障。空矩阵非MainJob会触发错误Computed job list is empty。数据完整性校验防止 PR 红灯被合并进 maincitool 在加载数据库后执行两轮校验这是它最体现工程严谨性的部分。1. PR 任务自动注册为 Auto 任务——register_pr_jobs_as_auto_jobs()jobs.rs为保证PR 任务必须是 Auto 任务的子集所有未在auto列表出现的 PR 任务会被自动克隆进auto_jobs并将continue_on_error强制覆写为falsefail-fast避免浪费 Auto CI 资源。jobs.yml中pr:段落注释也明确说明自动注册时以continue_on_errorfalse复制显式覆盖时则逐字段校验等价性。2. 数据库校验——validate_job_database()jobs.rs包含四类约束四个任务列表中都不允许出现重名任务PR 任务与同名 Auto 任务必须等价除continue_on_error和env外的所有字段一致例如test-x86_64-gnu-tools在 Auto 环境下会多出DEPLOY_TOOLSTATES_JSON环境变量这属于允许的 carve-outAuto 任务若continue_on_error: true则名字必须以optional-开头否则报错所有 Auto 任务名必须以test-或dist-开头允许optional-前缀保证命名约定统一。这些约束从机制上杜绝了PR 只跑部分任务、红灯却合入 main导致后续所有 PR 全红的隐患见 jobs.rs 的注释。本地执行 CI 任务run-local 子命令这是 README 提到的第二大能力。run-localmain.rs接收任务名和可选的--typeauto或pr默认auto在本地复现 CI 任务cargo run --manifest-path src/ci/citool/Cargo.toml run-local x86_64-gnu-llvm-21-1其实现run_workflow_locally()main.rs的关键步骤从auto_jobs或pr_jobs中按名字查找任务find_linux_job只允许 Linux 任务否则报错并列出可用任务清单复刻setup-environment.sh的行为任务名以dist-开头时注入DEPLOY1以-alt结尾则注入DEPLOY_ALT1把任务env中布尔/数字/字符串类型的环境变量注入子进程若src/llvm-project/子模块为空目录则自动执行git submodule update --initinit_submodule_if_neededutils.rs最终调用src/ci/docker/run.sh image启动对应的 Docker 镜像执行任务。与 Docker 执行器的配合src/ci/docker/README.md 补充了本地执行的关键细节镜像与任务名的关系一个 Docker 镜像可被多个任务复用任务名才是关键镜像名取自env.IMAGE或默认等于任务名输出目录本地执行时构建产物输出到仓库根目录的obj/image-name/CI 中则直接输出到obj/这是为了避免多个 Docker 镜像交替使用时产生奇怪的链接器错误需要 DOCKER_SCRIPT 的复杂工作流对于x86_64-gnu-llvm-21-N这类任务需要从 jobs.yml 中查得该任务执行的脚本再手动传入例如DOCKER_SCRIPTx86_64-gnu-llvm3.sh ./src/ci/docker/run.sh x86_64-gnu-llvm-21辅助子命令指标、仪表盘与可观测性除矩阵计算与本地执行外citool 还提供四个面向 CI 指标分析的子命令CLI 定义见 main.rs子命令作用postprocess-metrics metrics_path [--parent sha --job-name name]处理 bootstrap 生成的metrics.json输出构建步骤耗时表与测试结果汇总若提供--parent与--job-name还会下载父提交的指标做 diff见 analysis.rs 的format_build_step_diffs与report_test_diffs含 Markdown 表格形式的步骤耗时变化、最多 100 条测试差异、按 job 分组索引、按 stage 分组等upload-build-metrics cpu_usage_csv解析collect-cpu-stats.sh生成的 CSV每行两列第二列为 idle 值换算为100 - idle得到 CPU 使用率计算平均值后上传 Datadog 指标avg-cpu-usage见 cpu_usage.rs 与 datadog.rspost-merge-report parent current对比父/当前提交输出测试差异、任务耗时 Top10 变化output_largest_job_duration_changes并提示生成测试仪表盘的命令test-dashboard current --output-dir dir下载该提交所有 auto 任务的指标生成包含全部 compiletest 测试结果的 HTML 仪表盘test_dashboard.rs 借助 askama 模板按目录层级递归组织测试分组并为每个测试标注在哪些任务上通过的 jobset 编号其中指标下载metrics.rs从https://ci-artifacts.rust-lang.org/rustc-builds/{sha}/metrics-{job_name}.json拉取-alt任务走-alt制品桶并在.citool-cache/{sha}/{job_name}.json建立本地缓存以加速重复执行github.rs 则通过 GitHub API 查询工作流任务的started_at/completed_at以计算耗时并对 workflow run id 做内存缓存以减少 API 调用。post-merge-report的注释明确提示该报告主要面向 t-infra 成员用于排查 CI 变慢因为任务耗时会受 runner 实例、系统噪声、缓存失效等因素干扰。测试保障快照测试锁定矩阵行为citool 的矩阵计算行为由 tests/jobs.rs 中的 insta 快照测试锁定。测试通过cargo run -q calculate-job-matrix --jobs-file src/ci/citool/tests/test-jobs.yml并注入GITHUB_EVENT_NAME、COMMIT_MESSAGE、GITHUB_REF等环境变量env_clear()清空其余环境分别验证autopush 到automation/bors/autoPR 任务被自动注册进 auto 列表且continue_on_errorfalsetest-tidy等任务带doc_urltrypush 到automation/bors/try默认 try 任务被注入DIST_TRY_BUILD1自定义 try-job两条try-job:模式精确展开为对应任务prpull_request事件仅执行 PR 任务注入PR_CI_JOB1main输出空矩阵。这些快照同时验证了环境变量合并、full_name前缀auto -/try -/PR -、free_disk、continue_on_error等字段的序列化结果是理解矩阵输出的最佳活文档。总结citool 虽然 README 只有两句话但它实际是 rust-lang/rust CI 体系的大脑以 jobs.yml 为单一数据源通过运行类型判定PR / try / auto / main、glob 模式展开、环境变量分层合并与严格的数据库校验动态生成每次 CI 的任务矩阵同时又以run-local把 Docker 化的 CI 任务平移到本地配合指标分析、测试仪表盘与 Datadog 上报构成一套完整、可观测、可本地复现的 CI 工作流。对任何想理解大型开源项目 CI 工程化实践的开发者而言src/ci/citool 是一个值得通读的范本。【免费下载链接】rustEmpowering everyone to build reliable and efficient software.项目地址: https://gitcode.com/GitHub_Trending/ru/rust创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表