首页
/ OpenViking 发版实战:多产物 Tag 命名约定、Release 工作流与补发验证体系

OpenViking 发版实战:多产物 Tag 命名约定、Release 工作流与补发验证体系

2026-09-05 17:26:43作者:裘晴惠Vivianne

OpenViking 一次发版会同时产出 Python 主包、SDK、Docker 镜像、TOS 资产、Rust CLI/npm 包与多类插件,其发布体系围绕“一个主版本 tag + 多个独立 tag 命名空间”组织。本文基于仓库根目录的 RELEASE.md 以及 .github/workflows 下实际追踪的 GitHub Actions 工作流、pyproject.toml 包配置逐环节展开,帮助发版负责人和贡献者理解 OpenViking 的版本解析机制、各发布通道的触发条件,以及发布失败后的补发与验证方法。

发版目标:一次主版本发布,产出多个独立资产

OpenViking 不发布单一产物。一次正式主版本发版(以 vX.Y.Z 主 tag 为准)会围绕不同使用入口发布一组相互关联的资产:

  • openviking Python 主包:面向需要本地运行时、服务端、CLI 与完整功能的用户;
  • Python SDK openviking-sdk:面向只通过 HTTP 调用已有 OpenViking 服务的轻量客户端;
  • Docker 镜像:面向容器化部署,发布到 GHCR 和 Docker Hub;
  • TOS 发布资产:源码压缩包、安装脚本与稳定下载路径;
  • Rust CLI / npm 包:面向通过 npm 安装 ov CLI 的用户;
  • OpenClaw / ClawHub 插件:OpenClaw 插件分发渠道;
  • TypeScript SDK @openviking/sdk:TypeScript / JavaScript HTTP 客户端;
  • OpenCode 插件 @openviking/opencode-plugin:OpenCode 集成分发;
  • Controlplane MCP mcp-server-openviking-controlplane:控制面 MCP server 与 ov-cp CLI;
  • VikingBot:当前随 openviking[bot] 额外依赖与官方 Docker 镜像分发,历史独立发版入口单独说明以避免误用。

一条硬性约束是:正式主发版中,Python 主包、Docker 镜像与 TOS 资产必须使用同一个主版本 tag;SDK、CLI、ClawHub 插件则各自使用独立的 tag 或 version 命名空间。

从源码结构看,这一“多资产、单一主 tag”的设计在根 pyproject.toml 中有直接体现:

  • 主包名 openviking,版本 dynamic = ["version"],由 setuptools_scm 从 Git tag 解析,tag_regex 只匹配 v 开头的语义化版本(见 pyproject.toml#L203-L207),解析结果写入 openviking/_version.py
  • 主包 dependencies 中显式声明 openviking-sdk>=0.1.9,即主包依赖独立发布的 SDK,二者版本解耦(见 pyproject.toml#L32-L33);
  • [project.optional-dependencies] 中的 bot 额外依赖组承载 VikingBot 全功能(Telegram、Slack、钉钉、沙箱、Gradio 等),对应安装入口 pip install "openviking[bot]"(见 pyproject.toml#L140-L177);
  • 打包时 [tool.setuptools.packages.find].bot 两处收集 openviking*vikingbot* 包,package-data 还会把预编译的 ragfs Python 扩展、向量引擎 .so/.pydbin/ov 二进制打进 wheel(见 pyproject.toml#L209-L232),这就是“一个 wheel 包含运行时 + Rust CLI 二进制 + 服务端”的原因;
  • [project.scripts] 定义了 ovopenvikingopenviking-servervikingbot 四个可执行入口(见 pyproject.toml#L197-L201),其中 ov / openviking 是指向 Rust CLI 的极简包装器。

版本与 Tag 约定

各产物推荐使用如下 tag / 版本约定:

产物 推荐 tag / version 说明
openviking 主包 vX.Y.Z 主 release tag,例如 v0.3.26
openviking-sdk python-sdk@X.Y.Z SDK 专用 tag,例如 python-sdk@0.1.3
@openviking/sdk(TypeScript) typescript-sdk@X.Y.Z TypeScript SDK tag
Rust CLI / npm CLI cli@X.Y.Z CLI 专用 tag,例如 cli@0.2.0
ClawHub 插件 latest YYYY.M.DYYYY.M.D-N 由 workflow 自动生成或手动指定
ClawHub 插件 dev YYYY.M.D-dev.N dev channel 使用

主包版本通过 setuptools_scm 从 Git tag 解析,git_describe_command 明确限定 --match v[0-9]*(见 pyproject.toml#L203-L207);SDK 同样使用 setuptools_scm,但其工作目录限定在 sdk/python 且 tag 匹配 python-sdk@*,因此与主包 tag 互不干扰。这种“tag 前缀即命名空间”的约定,使得同一仓库里主包、SDK、CLI 可以在任意时刻独立发版而互不覆盖。

正式主包发版流程

主包正式发版走根仓库的 GitHub Release,完整链路如下:

  1. 确认待发布改动已合入目标分支,且 PR / main 分支检查通过;
  2. 创建主包 tag,例如 v0.3.26
  3. 在 GitHub 上基于该 tag 发布 Release;
  4. 03. Release 工作流在 Release published 事件触发;
  5. 工作流复用 _Build Distribution 构建 sdist 与多平台 wheel;
  6. 将构建产物发布到 PyPI;
  7. 构建并推送多架构 Docker 镜像;
  8. 20. Release TOS Upload 工作流上传源码压缩包与安装脚本到 TOS。

正式主发版的发布目标为:PyPI 上的 openviking;GHCR 上的 ghcr.io/<owner>/<repo>;Docker Hub 上的 <dockerhub-user>/openviking;TOS 上的版本化 release 路径与可选 latest 稳定路径。

.github/workflows/release.yml 的实现印证了这条链路:

  • 触发与门禁:工作流仅在 release.published 且 tag 以 v 开头时执行正式发布逻辑——if: github.event_name == 'workflow_dispatch' || startsWith(github.event.release.tag_name, 'v')(见 release.yml#L46-L54)。python-sdk@*cli@* 等组件 tag 的 Release 事件不会误触发主包发布,它们由各自专用工作流处理;
  • 构建build job 复用可调用工作流 _build.yml(即 _Build Distribution),默认构建 5 个平台的 wheel:ubuntu-24.04(x86_64)、ubuntu-24.04-arm(aarch64)、macos-14(arm64)、macos-15-intel(x86_64)、windows-latest(x86_64),Python 版本默认 3.10
  • 权限门禁:手动 dispatch 场景下,permission-check job 会调用 GitHub API 校验触发者具备 admin / maintain / write 权限,无写权限直接失败(见 release.yml#L56-L88);
  • 发布publish-testpypi / publish-pypi 两个 job 分别绑定 testpypi / pypi GitHub environment,使用 id-token: write 走 PyPI trusted publishing(OIDC),并设置 skip-existing: true,重复发布同版本时不会报错而是跳过;
  • 镜像校验verify-docker job 会轮询等待 tag 对应的 Docker 构建 run 完成,再用 docker buildx imagetools inspect 断言 GHCR 与 Docker Hub 上的版本 tag 与 latest 指向同一 manifest digest(见 release.yml#L159-L215)。这是“主包发版与镜像口径一致”的自动化保证。

主包手动构建、测试发布与补发

release.yml 同样支持 workflow_dispatch 手动触发,输入参数包括:

  • targetnone(只构建不发布)、testpypi(发布到 TestPyPI)、pypi(发布到 PyPI)、both(两者都发);
  • build_sdist / build_wheels:分别控制是否构建源码包与 wheel;
  • os_json:JSON 字符串形式的目标平台 runner 列表(ubuntu-24.04=x86_64、ubuntu-24.04-arm=aarch64、macos-14=arm64、macos-15-intel=x86_64、windows-latest=x86_64);
  • python_json:JSON 字符串形式的 Python 版本列表。

当“Python 包构建成功但发布失败”时,仓库提供 .github/workflows/_publish.yml(即 16. _Publish Distribution)作为恢复与补发通道:它支持 workflow_call 与手动 dispatch,手动时必须传入 build_run_id(从构建 run 的 URL 中获取),工作流会跨 run 下载该次构建产出的 python-package-distributions-* artifact 再执行发布(见 _publish.yml#L16-L31_publish.yml#L89-L97)。该路径定位为故障恢复,不应作为正常发版入口。

Docker 镜像发布与补发

正式主发版时,Docker 镜像由发布链路自动构建并推送到 GHCR 与 Docker Hub,正式 release 下写入版本 tag 与 latest tag。

仓库同时提供独立的 Build and Push Docker Image 工作流 .github/workflows/build-docker-image.yml,适用于三种场景:手动指定版本重建镜像、main 分支镜像构建、tag 触发后的镜像补发。从该工作流定义可以看到:

  • 触发条件为 main 分支 push、v*.*.* tag push 与 workflow_dispatch(需填 version 输入);
  • 镜像名由仓库名小写化生成;amd64 / arm64 双架构矩阵并行构建(linux/amd64ubuntu-24.04linux/arm64ubuntu-24.04-arm);
  • 版本解析优先级为:手动输入的 version > tag 名 > setuptools-scm 解析(main 分支走 build_support.versioning.resolve_openviking_version());解析出空值或 0.0.0 时直接失败退出。

需要注意的一点:独立 Docker 工作流当前也会在 v*.*.* tag push 时自动触发,而 tag push 与 release published 事件几乎同时发生。因此正式 GitHub Release 的发布口径仍以 03. Release 工作流为准,独立 Docker 工作流应视为“镜像专用构建或补发路径”。为避免重复发布,正式版本优先使用主发布工作流;仅当镜像需要补发或做特殊验证时才使用独立工作流。

TOS 发布资产

TOS 发布流程(20. Release TOS Upload,见 .github/workflows/release-tos.yml)会生成源码压缩包并上传以下资产:

  • releases/<tag>/openviking-<tag>-source.zip(由 git archive 生成);
  • Claude Code memory plugin 安装脚本;
  • Codex memory plugin 安装脚本;
  • 对应的 TOS install 脚本。

关键行为:

  • 触发条件与主发布一致:release.published 且 tag 以 v 开头,组件 tag(python-sdk@*cli@* 等)不会触发 TOS 上传;
  • 手动补发时可指定 tag 输入,并通过布尔量 update_latest 决定是否同时覆盖稳定 / latest 路径(默认覆盖);
  • 如果 TOS_ACCESS_KEYTOS_SECRET_KEYTOS_REGIONTOS_RELEASE_BUCKETTOS_ENDPOINT 任一 secret 未配置,工作流会跳过上传并在 step summary 中说明,而不会让整个发布流程失败——这使 TOS 通道对未配置该通道的镜像部署环境是可选的。

Python SDK 发版流程

Python SDK 位于 sdk/python,PyPI 包名为 openviking-sdk,使用独立 tag 命名空间 python-sdk@X.Y.Z。典型流程与 .github/workflows/python-sdk-release.yml 的实现一一对应:

  1. 合入 SDK 相关改动;
  2. 创建并推送 tag,例如 python-sdk@0.1.3
  3. Python SDK Release 工作流被 Release published 事件触发(其 if 条件限定 tag 以 python-sdk@ 开头);
  4. 工作流在 sdk/python 下执行 python -m setuptools_scm 解析 SDK 版本;
  5. 校验 tag 必须严格等于 python-sdk@<resolved-version>,不匹配即失败(见 python-sdk-release.yml#L70-L80);
  6. python -m build 构建 sdk/python 的 sdist/wheel,通过 trusted publishing 发布到 PyPI。

该工作流也支持手动 dispatch,可选 testpypipypiboth 目标,适合验证与补发;正式 SDK 发版仍建议使用 python-sdk@X.Y.Z tag。

Rust CLI / npm 发版流程

Rust CLI 的 tag 格式为 cli@X.Y.Z。推送 cli@* tag 后,Rust CLI Build 工作流(.github/workflows/rust-cli.yml)会为多平台构建 ov 二进制并发布 npm 包:

  • 平台包:@openviking/cli-linux-x64@openviking/cli-linux-arm64@openviking/cli-darwin-x64@openviking/cli-darwin-arm64@openviking/cli-win32-x64
  • wrapper 包:@openviking/cli(源码位于 npm/cli)。

从工作流实现可以看到几个工程细节:

  • Linux 侧通过 cargo-zigbuild 交叉编译 musl 目标(x86_64-unknown-linux-musl / aarch64-unknown-linux-musl),产物为完全静态的 musl 二进制,可运行在 glibc 较老的发行版上;
  • 版本注入:工作流用 sed 把 tag 中的版本写入 crates/ov_cli/Cargo.toml 中占位的 version = "0.0.0"(见 rust-cli.yml#L114-L122),npm 平台包与 wrapper 包的版本号同样来自 tag;非 tag 触发(如 crates/** 变更的 CI 构建)则以 0.0.0-dev 命名且不会进入 npm 发布 job;
  • 幂等保护:npm-publish job 逐个 npm view 检查,若某平台包或 wrapper 包同版本已存在于 npm,则打印“already published”并跳过,避免重复发布报错。

OpenClaw / ClawHub 插件发布

OpenClaw 插件通过 OpenViking OpenClaw plugin release 工作流手动发布(见 .github/workflows/clawhub-dev-release.yml)。输入参数包括:

  • version:可选;为空时由工作流按日期自动生成 YYYY.M.D / YYYY.M.D-N / YYYY.M.D-dev.N
  • channelautodevlatestauto 会根据仓库是否为配置的上游仓库决定发布到 latest 还是 dev 通道;
  • package_ref:指定要打包的 Git ref(默认 main),便于从其他分支工作流发布 main 上的插件代码;
  • changelog:本次插件发布说明;
  • publish_clawhub / publish_npm:分别控制是否发布 ClawHub 资产与 npm 上的 @openviking/openclaw-plugin

工作流先解析 channel 与 version(guard job),再打包 examples/openclaw-plugin,随后分别发布 ClawHub 兼容的 zip 资产与 npm packed tarball。工作流还设置了 concurrency 组(openclaw-plugin-release,不取消进行中的任务),避免连续两次合并自动触发的版本解析相互竞争。

推荐做法:正式渠道使用 latestauto;开发验证使用 dev;手动指定 version 时确保其符合所选 channel 的格式要求。

其他发布流程

VikingBot 发布说明

VikingBot 不再作为推荐的独立 PyPI 包发版路径维护,现行分发方式是随主包发布:

  • Python 安装入口:pip install "openviking[bot]"
  • 源码开发入口:uv pip install -e ".[bot]"
  • 官方 Docker 镜像默认已包含 VikingBot,可通过 --without-botOPENVIKING_WITH_BOT=0 关闭。

两条历史脉络需要注意:

  1. 根仓库原有的 First Release to PyPI 工作流已被删除。当前 bot/ 目录不包含独立的 pyproject.tomlsetup.pysetup.cfg,因此不能从本仓库作为独立 Python 包发布;它现在是根 pyproject.toml 打包范围的一部分(where = [".", "bot"]include = ["openviking*", "vikingbot*"],见 pyproject.toml#L209-L212)。
  2. bot/.github/workflows/release.yml 位于 bot 子目录下,应视为历史 bot 子项目或拆分仓库的发布参考,而不是根仓库当前可直接触发的 GitHub Actions 工作流。若要恢复独立 vikingbot 包,需要先补齐 bot/ 下的独立 Python 包元数据、版本策略与发布凭证策略。

发版前检查清单

发版前建议逐项确认:

  • 待发布改动已合入目标分支;
  • CI / PR 检查已通过;
  • 版本号未在 PyPI、npm 或 Docker registry 中发布过;
  • tag 命名符合对应产物约定(vX.Y.Z / python-sdk@X.Y.Z / typescript-sdk@X.Y.Z / cli@X.Y.Z / ClawHub 日期版本);
  • Python 依赖、构建配置与 README 已同步更新;
  • Docker Hub、PyPI/TestPyPI、TOS、npm、ClawHub 所需 secrets 或 trusted publishing 配置可用(PyPI 通道依赖 id-token OIDC,Docker Hub 依赖 DOCKERHUB_USERNAME 等 secrets,TOS 通道依赖五个 TOS_* secrets);
  • Release notes 已准备好,说明破坏性变更、迁移步骤与重要修复。

发版后验证清单

发版后建议验证:

  • PyPI / TestPyPI 上的包版本与 tag 一致;
  • pip install openviking==<version>pip install openviking-sdk==<version> 可成功安装;
  • Docker registry 中存在版本 tag 与预期的 latest / main tag;
  • 多架构 Docker manifest 可正常拉取(03. Releaseverify-docker job 已自动断言版本 tag 与 latest 指向同一 digest);
  • TOS 版本化路径与稳定路径可访问;
  • npm 上存在对应 CLI 平台包与 wrapper 包(@openviking/cli-linux-x64 等 + @openviking/cli);
  • ClawHub 插件 channel 与 version 符合预期。

故障处理与补发原则

  • PyPI 和 npm 版本一般不可覆盖:如果包内容有误,应发布新版本。两个工作流都通过 skip-existing 行为体现这一原则——重复发布只会跳过而不是覆盖;
  • Docker latestmain 与手动指定 tag 可通过镜像补发工作流重建,但应保持已发布版本 tag 的可追溯性;
  • TOS 版本化路径应视为不可变资产;稳定路径可通过手动工作流(update_latest)覆盖;
  • 构建成功但发布失败时,优先使用 _Publish Distribution 补发工作流或手动 dispatch(传入 build_run_id),而不是用不同内容重建同名 tag;
  • tag 命名错误时,只有在该 tag 尚未触发不可逆发布的前提下,才删除错误 tag 并重新创建正确 tag。

掌握以上约定后,发版人员可以按“选对 tag 命名空间 → 触发对应工作流 → 用发布后清单逐项验证”的固定路径完成 OpenViking 任意一条发布通道,并在失败时依据补发原则快速恢复,而不会造成版本覆盖或口径混乱。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.12 K
2.72 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
528
588
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
906
1.83 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
854
1.34 K
docsdocs
暂无描述
Markdown
891
5.78 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.53 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.34 K
1.45 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
987
506
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
540
384