news 2026/9/18 18:57:45

Switchyard发布工作流揭秘:从git tag到PyPI/crates.io的完整流水线

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Switchyard发布工作流揭秘:从git tag到PyPI/crates.io的完整流水线

Switchyard发布工作流揭秘:从git tag到PyPI/crates.io的完整流水线

【免费下载链接】SwitchyardSwitchyard lets LLM applications route traffic across models and providers while preserving native OpenAI and Anthropic API compatibility - enabling flexible model selection, benchmarking, and cost/performance optimization.项目地址: https://gitcode.com/GitHub_Trending/switch/Switchyard

Switchyard 是一个让 LLM 应用跨多个模型与提供商路由流量的控制平面,同时保持 OpenAI 与 Anthropic 原生 API 兼容。那么这样一个 Rust 工作区 + Python 包双栈项目,是如何仅凭一条 git tag,就把 1 Python 包和 7 个 Rust crate 安全送达 PyPI 与 crates.io 的?本文揭秘其完整的发布工作流:零手动上传、版本号零失误、中途失败还能安全重跑。

🧭 发布流水线总览:一条 tag,两个注册表

Switchyard 的发布体系遵循「常规 CI 把关质量、tag 驱动正式出版、手动构建只产 artifact」的 OSS 标准路径,完整说明见 docs/internal/release_workflow.md:

触发方式做什么产物去向
PR / 推送 main 分支测试、lint、类型检查、Rust 检查、瘦身安装冒烟(.github/workflows/ci.yml)无,纯质量门禁
手动触发 dev 构建构建 1 个或全套.dev版本 wheelGitHub Actions artifact(仅 1 天保留期)
推送vMAJOR.MINOR.PATCHtag完整发布校验 + 构建矩阵 + 正式出版PyPI + crates.io + GitHub Release

这里藏着一个关键设计:PyPI 版本一旦上传事实上不可变更,所以正式发布只允许由根目录 tag 触发;而分支状态的手动构建绝不允许污染公共索引。版本号的唯一真相来源则是 pyproject.toml(Python 包)与 Cargo.toml(Rust 工作区),两者必须完全一致。

🔍 第一关:tag 与版本号三重绑定

推送 tag 后,publish工作流(.github/workflows/publish.yml)的第一个 job 就做一次「三重绑定」校验:

  1. 格式校验—— tag 必须严格形如v数字.数字.数字,任何v0.2.0-rc1之类的变体都会被拒绝;
  2. Python 绑定—— tag 必须与pyproject.tomlversion精确匹配(包版本0.2.0只能配v0.2.0);
  3. Rust 绑定—— Cargo 工作区版本必须与 Python 包版本相等。

三重校验保证了「tag 即版本」,从源头杜绝了 tag 与代码版本错位这种经典事故。

🧪 第二关:Python 与 Rust 双语言质量门禁

tag 通过后,两条独立的检查流水线并行展开(.github/workflows/publish.yml):

  • Python 矩阵:在 3.10 到 3.14 共5 个版本上逐一执行ruff check与完整测试套件;
  • Rust 工作区cargo fmt --check格式检查、cargo clippy-D warnings零容忍运行、cargo test --workspace全量测试。

任何一条失败都会让发布在出版之前终止——质量门禁全部位于「出版」上游,顺序不可逆。

📦 第三关:构建 7 件套发布物

校验通过后进入构建阶段,产出 1 个 sdist + 6 个平台 wheel:

源码包(sdist)用 maturin 构建 sdist 后,工作流还会解包检查LICENSENOTICE是否齐全,并在/tmp隔离目录做一次真实安装冒烟——确保用户pip install源码包时真的能装起来。

wheel 矩阵(6 平台)

平台构建方式
Linux x86_64 / aarch64manylinux2014 容器内构建,兼容主流 Linux 发行版
macOS x86_64 / arm64原生构建
Windows x86_64 / arm64原生构建

所有 wheel 均为abi3格式,一份 wheel 通吃多个 Python 版本。在可执行的平台上,工作流还会分别在Python 3.10 和 3.14两个端点做强制重装冒烟导入,验证switchyardswitchyard_rust及原生扩展均可正常加载(.github/workflows/publish.yml)。

🚀 第四关:零 Token 发布 PyPI(Trusted Publishing)

注意 PyPI 的包名是nemo-switchyard,而 Python 导入名与 CLI 仍叫switchyard。正式出版由publishjob 执行(.github/workflows/publish.yml):

uv publish --trusted-publishing always dist/*

它不依赖任何存储的 API 密钥,而是使用PyPI Trusted Publishing:GitHub 凭 tag 事件 + 匹配的待发布出版方(项目nemo-switchyard、工作流publish.yml、环境pypi)自动换取临时凭证。凭证不落库、不轮换、不泄露——这是目前最安全的 PyPI 发布姿势。发布成功后,工作流还会顺手创建 GitHub Release。

📚 第五关:7 个 Rust crate 按依赖顺序发布

同一个 tag 还会把 Rust 工作区的 7 个 crate 依序送上 crates.io,顺序严格遵循依赖方向(.github/workflows/publish.yml):

  1. switchyard-protocol(协议契约)
  2. switchyard-translation(格式转换)
  3. switchyard-libsy(可组合路由算法库)
  4. switchyard-llm-client(模型客户端)
  5. prefill-router(预填充路由)
  6. switchyard-runner(运行器)
  7. switchyard-server(独立服务端)

三个工程细节值得借鉴:

  • 版本再确认:发布前用cargo metadata核对 7 个 crate 的版本都与 tag 一致,防止漏改;
  • 等待索引同步:每发一个 crate 后轮询 crates.io 索引(最长 30 × 10 秒),确认它可见后才发布依赖它的下一个;
  • 幂等可重跑:若某 crate 已存在则直接跳过。因此中途失败时,只需在 GitHub 上点击Re-run failed jobs,已成功发布的 crate 不会被重复推送。

🛠️ 番外:不发 PyPI 的 dev 构建

想在正式切 tag 之前验证发布矩阵?publish.yml提供了两个手动开关(docs/internal/release_workflow.md):

开关效果
build_dev_artifact = true仅构建 1 个 Linux x86_64 dev wheel,artifact 保留 1 天,随后下载回来核对Name/Version元数据
build_dev_matrix = true构建完整 sdist + wheel 矩阵,仅作为 artifact 保存,绝不发布

dev 版本号遵循 PEP 440 的.dev规范(如0.0.1.dev0),由 scripts/release/set_dev_wheel_version.py 打戳到pyproject.toml,本地也能预览:

python scripts/release/set_dev_wheel_version.py 0.0.1.dev0 --print-version

(提示:除非发布流程明确要求,不要把打戳后的元数据提交回仓库。)

💡 核心要点速记

  • 3 处版本号强绑定:git tag ==pyproject.toml== Cargo 工作区版本,任何一处不符立即失败;
  • 2 种发布凭证策略:PyPI 用 Trusted Publishing(零密钥),crates.io 用CARGO_REGISTRY_TOKEN仓库 Secret;
  • 6 平台 wheel + 5 个 Python 版本测试,全部通过才允许出版;
  • 失败可恢复:crate 发布幂等设计 + GitHub「Re-run failed jobs」,成功步骤不重跑;
  • 版本记录:每个正式版的变更说明统一沉淀在 CHANGELOG.md,遵循 Keep a Changelog 与语义化版本规范。

整套流水线的精髓一句话:让「出版」成为整条链路中唯一不可逆的动作,它之前的每一步都是可重复、可验证、可失败的。对任何同时维护 Python 与 Rust 双栈的项目来说,这套从 tag 到 PyPI/crates.io 的完整发布工作流都值得直接抄作业。

【免费下载链接】SwitchyardSwitchyard lets LLM applications route traffic across models and providers while preserving native OpenAI and Anthropic API compatibility - enabling flexible model selection, benchmarking, and cost/performance optimization.项目地址: https://gitcode.com/GitHub_Trending/switch/Switchyard

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/18 18:57:06

华为云DevSecOps质量效能体系:QCP双轨制与三层指标实践

简介:本资源是华为云官方发布的《DevSecOps质量效能体系及数字化实践》白皮书,面向IT管理者、DevOps工程师、研发与运维人员、质量及效能优化从业者,系统解答企业如何在数字化转型中构建高质高效的价值交付能力。全文以“价值流”为主线&…

作者头像 李华
网站建设 2026/9/18 18:55:40

Java设计模式复习指南:从23种模式到期末试题实战

简介:《JAVA设计模式》期末试题归纳PDF文档,面向高校软件工程、计算机等相关专业学生,覆盖考前自测、知识点串联与应试答题框架梳理。卷面按选择题、填空题、名词解释、综合问答四大题型组织,开闭原则、依赖倒置、迪米特法则等设计…

作者头像 李华
网站建设 2026/9/18 18:46:32

RuoYi AI 多模型接入不想逐个填 Key?TaoToken 这样改模型 Base URL

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/18 18:44:47

区块链如何重塑工程监理:从联盟链存证到智能合约的可信闭环

简介:雄安集团区块链监理管理系统是一份面向工程建设监管数字化转型的解决方案,以区块链、大数据、云平台为底座,聚焦集团-公司-项目三级管理架构下的人员履约、质量验收、现场巡查、信用考核等核心业务,解决传统监理中责任落实难…

作者头像 李华