ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

SpacetimeDB 发布 CLI(cargo release)完全指南:自动化 crates/npm/NuGet/Docker 多生态发布

SpacetimeDB 发布 CLI(cargo release)完全指南:自动化 crates/npm/NuGet/Docker 多生态发布 SpacetimeDB 发布 CLIcargo release完全指南自动化 crates/npm/NuGet/Docker 多生态发布【免费下载链接】SpacetimeDBDevelopment at the speed of light项目地址: https://gitcode.com/GitHub_Trending/sp/SpacetimeDB导读SpacetimeDB 是一个多语言、多生态的实时数据库项目其产物横跨 Rust crates.io 包、TypeScript SDKnpm、C# SDKNuGet 与 Unity、C 绑定git subtree 镜像以及 Docker 容器单靠手工操作难以保证各渠道版本一致。仓库自带的发布 CLI位于 tools/release把上述所有发布动作统一封装为cargo release子命令支持细粒度选择发布目标、一键全量发布以及--dry-run预演。读完本文你将掌握该工具的设计目标、安装方式、每个发布目标的完整流程与前置条件、GitHub Actions 集成方式以及如何通过ReleaseTargettrait 扩展新的发布目标。工具定位与三大设计目标该工具被设计为「SpacetimeDB 版本发布与部署的一站式命令行工具」其核心设计目标在 tools/release/README.md 中明确为三条平台无关Platform Independence实现上尽可能少依赖 shell 脚本与平台特有命令保证在 Linux / macOS / Windows 上行为一致。从源码看所有子进程调用均通过 Rust 标准库std::process::Command或ductcrate 完成见 tools/release/src/targets/util.rs 中统一封装命令打印的print_command没有引入 bash 脚本。CI/CD 优先CI/CD Integration虽然可以本地运行但它主要面向 GitHub Actions workflow 设计从而免去本地安装工具链、配置密钥与权限的负担。官方推荐直接使用仓库已配置好权限与 token 的 release workflow任何拥有仓库权限的人都可以触发发布。可配置Configurability提供对「发布哪些组件」的细粒度控制可以精确选择发布某一部分也可以跳过指定目标。需要特别提醒该工具涉及的权限非常复杂。发布某个包需要成为对应组织clockworklabs的成员发布 crates.io 包还需要逐个包被添加为 owner。因此不建议在不了解全局的情况下本地随意执行。安装与验证该工具是仓库 workspace 的一部分以 cargo 子命令形式安装cd tools/release cargo install --path .从 tools/release/Cargo.toml 可以看到包名为spacetimedb-release但[[bin]]节将二进制命名为cargo-release。因此安装完成后二进制会落到~/.cargo/bin并可作为cargo release从任意目录调用cargo 会识别cargo-name前缀的可执行文件。验证安装cargo release --help依赖方面该工具使用clapderive 模式解析命令行参数用serde/serde_json解析cargo metadata与 GitHub Release 的 JSON 输出用toml解析Cargo.toml依赖用duct组装并执行命令错误统一由anyhow处理。CLI 命令总览从 tools/release/src/main.rs 的 clap 定义可以看出完整的命令面。CLI 顶层被伪装成cargobin_name cargo二级子命令为release三级子命令即各发布目标子命令参数功能crates version--dry-run发布 crates.io 包npm version--dry-run发布 TypeScript SDK 到 npmcsharp version--dry-run发布 C# SDKNuGet Unity SDKcpp version--dry-run发布 C 绑定git subtree 镜像 标签docker version--dry-run发布 Docker 容器到 DockerHubgithub-release version无在工件上传完成后发布 GitHub Release--all version--dry-run、--skip target...全量发布所有目标其中 version 参数通常形如v1.2.0带v前缀源码中有多处strip_prefix(v)处理。每个 target 均实现统一的ReleaseTargettrait// tools/release/src/targets/mod.rs pub trait ReleaseTarget { fn release(self) - Result(), String; fn name(self) - static str; }release()执行实际发布逻辑name()返回目标标识如crates、npm、docker供--skip匹配使用。发布 crates.io 包发布范围与命令该目标按依赖顺序发布以下包到 crates.iomemory-usageprimitivesmetricsbindings-macrobindings-sysbindingsdata-structuresclient-api-messagessatslibsdkcargo release crates v1.2.0预演dry-runcargo release crates v1.2.0 --dry-run注意从 tools/release/src/targets/crates.rs 看crates 目标的 dry-run 分支当前直接打印 “not supported” 并提前返回README 中也标注了这一点源码注释提及 workflow 文件中留有 TODO。也就是说crates 目标应视为「实际发布」操作验证请依赖 CI 流程。底层实现依赖顺序求解发布顺序并非硬编码而是由 tools/release/src/crates_resolver.rs 动态求解find_workspace_root()从当前目录向上逐级寻找包含Cargo.toml的目录作为 workspace 根get_crate_manifest_map()调用cargo metadata --format-version1 --no-deps解析出「包名 → manifest 路径」映射以根包spacetimedb对应 README 中的bindings和spacetimedb-sdk对应sdk为起点递归扫描各自Cargo.toml中所有spacetimedb-*前缀依赖find_spacetimedb_dependencies将整棵依赖树逆序并去重保证「每个 crate 都出现在依赖它的 crate 之前」。源码注释解释了正确性论证由于列表构造方式反转后每个 crate 一定先于使用者出现因此按「首次出现」去重不会破坏拓扑顺序。关键流程发布 → 等待索引可见 → 添加 owner对每个 crateCratesRelease::release()依次执行三步见 tools/release/src/targets/crates.rs发布在 crate 目录下执行cargo publish --allow-dirty。若 stderr 中出现 “already exists on crates.io index”视为成功并跳过幂等处理便于重跑。等待索引可见wait_for_crate_available()每隔 15 秒执行一次cargo info --registry crates-io nameversion最多轮询 15 分钟直到该版本在 crates.io 索引中可见才继续发布依赖它的下一个 crate。这是保证依赖链各版本能被顺序解析的关键。添加 owneradd_crate_owners()为 crate 依次执行cargo owner --add目标 owner 列表CRATE_OWNERS定义在源码中cloutiertyler、jdetter、bfops、rekhoff、spacetimedb-devops。若返回信息包含 “already”说明 owner 已存在跳过。版本号处理上发布到 crates.io 的版本会去掉v前缀并截断-之后的预发布段例如v1.2.0-rc1会以1.2.0查询索引。发布 npm 包TypeScript SDK命令与流程cargo release npm 1.2.0流程由 tools/release/src/targets/npm.rs 实现校验pnpm --version可执行在sdks/typescript目录执行pnpm install执行pnpm publish——这会自动触发prepublishOnly脚本。从 sdks/typescript/package.json 可见该脚本为pnpm run build pnpm run test pnpm run size即构建、跑测试并输出打包体积报告发布为clockworklabs/spacetimedb-sdkdist-tag 设为latest并核验。Dry-run 模式cargo release npm 1.2.0 --dry-rundry-run 下执行的是pnpm publish --dry-run --force --no-git-checks只验证构建与打包流程不会真正发布。源码细节--no-git-checks是必须的——CI 中 pnpm 处于 detached HEAD 状态默认的 git 分支/干净工作区检查会导致ERR_PNPM_GIT_UNKNOWN_BRANCH--force用于覆盖 pnpm 的「package already exists」校验dry-run 场景。前置条件Node.js 与 npm 已安装pnpm 已安装npm install -g pnpm已登录 npmnpm login对clockworklabs/spacetimedb-sdk包拥有发布权限。发布 C# SDKNuGet Unity为什么合并发布同一份 DLL 同时被 NuGet 包与 Unity SDK 使用一次性构建可确保两者版本完全一致、避免错位。这是该目标采用「统一发布」流程的根本原因。命令与流程cargo release csharp 1.2.0完整流程见 tools/release/src/targets/csharp.rs构建 DLL执行cargo regen csharp dllsrun_cargo_ci_dlls通过 tools/regen 工具链生成/编译 C# 互操作层发布 NuGetpush_nuget_packages()依次nuget push以下 4 个.nupkg到api.nuget.org/v3/index.jsonSpacetimeDB.BSATN.Runtime.versionSpacetimeDB.Runtime.versionSpacetimeDB.ClientSDK.versionSpacetimeDB.ClientSDK.Godot.version对应的 nupkg 产物路径分别为crates/bindings-csharp/BSATN.Runtime/bin/Release/、crates/bindings-csharp/Runtime/bin/Release/、sdks/csharp/bin~/Release/下的固定文件名。API key 从环境变量NUGET_API_KEY读取并带-SkipDuplicate参数做幂等处理。Hotfix 细节NuGet 包版本取自 csproj 的Version热修复时不会递增因此发布v2.7.0-hotfix2时实际产出的仍是2.7.0.nupkg。源码会剥离-hotfixN后缀来定位真实的包文件。更新 Unity 工程commit_csharp_dlls_for_unity()会强制git add由cargo regen生成的.meta文件、sdks/csharp/packages.meta以及 BSATN 运行时 DLL删除sdks/csharp/packages/.gitignoreUnity 6 会强制删除被 gitignore 列出的文件移除不需要的net8.0目标文件将sdks/csharp/LICENSE.txt的符号链接实体化读取链接目标内容后改写为普通文件打印git status并提交提交信息为Update Unity SDK to version vversion发布 Unity SDK 仓库配置 git 使用 SSH移除 checkout action 注入的 HTTPS 改写改为url.gitgithub.com:.insteadOf https://github.com/fetchrelease/mirror/csharp分支不存在则首次推送时创建git subtree split --prefixsdks/csharp --onto origin/release/mirror/csharp生成子树推送到clockworklabs/com.clockworklabs.spacetimedbsdk仓库以-f强制推送为release/latest分支并推送vversion标签。前置条件已安装 .NET SDK已安装 NuGet CLILinuxsudo apt-get install nuget mono-completemacOSbrew install nugetWindows从 nuget.org 下载已安装 git拥有对gitgithub.com:clockworklabs/com.clockworklabs.spacetimedbsdk.git的 SSH 访问权限配置 NuGet API key环境变量或 NuGet config。dry-run 模式cargo release csharp 1.2.0 --dry-run会构建 DLL 验证流程但不会推送 NuGet 与 Unity 仓库。发布 C 绑定README 对该目标着墨不多但源码 tools/release/src/targets/cpp.rs 给出了完整实现命令为cargo release cpp 1.2.0流程与 C# 的 Unity 部分高度类似目标仓库为clockworklabs/spacetimedb-bindings-cpp配置 git 使用 SSH与 csharp 目标相同的 URL 改写逻辑fetch 镜像分支release/mirror/bindings-cpp不存在则返回 false首次推送时创建对crates/bindings-cpp前缀执行git subtree split若镜像分支已存在会附带--onto origin/release/mirror/bindings-cpp加速依次推送release/MAJOR.MINOR分支从版本号前两段解析例如1.2.0→release/1.2、release/latest分支-f强制推送、vversion标签。发布 Docker 容器cargo release docker v1.2.0流程见 tools/release/src/targets/docker.rs校验 Docker 可用且已登录docker info使用docker buildx build --platform linux/amd64,linux/arm64构建多平台镜像推送版本化镜像clockworklabs/spacetime:v1.2.0通过docker buildx imagetools create -t ...:latest将版本镜像标记为:latest。dry-run 模式cargo release docker v1.2.0 --dry-run相当有意思它不会真的推送 DockerHub而是先在本地启动一个registry:2容器LocalRegistryGuard端口 5000容器名带当前进程 PID 以隔离多次运行把构建目标指向localhost:5000/clockworklabs/spacetime构建完成后自动销毁该本地 registry利用Droptrait。这样既能验证完整的 buildx 多平台构建链路又不产生任何对外影响。前置条件Docker 已安装并处于运行状态已登录 DockerHubdocker login拥有clockworklabs/spacetime仓库的推送权限。发布 GitHub Release在所有包与工件发布完成后执行cargo release github-release v1.2.0该目标tools/release/src/targets/github_release.rs依赖 GitHub CLIgh流程为gh release view tag --repo clockworklabs/SpacetimeDB --json isDraft,url校验标签对应的 release 存在且仍为 draft若已发布视为成功并直接退出不再重复上传工件gh workflow run attach-artifacts.yml --ref master -f release_tagtag派发上传客户端二进制的 workflow从返回 URL 中解析出 run idgh run watch run_id --exit-status阻塞等待该 workflow 成功结束gh release edit tag --draftfalse将 draft 正式发布。前置条件已安装 GitHub CLIghGH_TOKEN具有派发 workflow 与更新 release 的权限。一键全量发布与目标跳过执行全部目标的发布crates → npm → csharp → cpp → dockercargo release --all跳过指定目标cargo release --all --skip docker跳过多个目标注意目标名需要与ReleaseTarget::name()一致可参考上文表格cargo release --all --skip docker --skip nuget从 tools/release/src/main.rs 的release_all()实现看--all会构造全部 5 个目标crates、npm、csharp、cpp、docker注意github-release不在其中需单独执行先校验所有--skip值是否合法非法的目标名会直接报错退出再按顺序逐个执行、可跳过。--dry-run时打印DRY RUN: No changes will be published。GitHub Actions 集成与密钥配置该工具与.github/workflows/release.ymlworkflow 深度集成README 描述的机制手动触发通过 workflow_dispatch 可运行 dry-run 或真实发布两种模式Docker 发布 job自动从Cargo.toml提取版本号、配置 Docker Buildx 多平台构建、dry-run 下只构建不推送release 模式下构建并推送并打:latest标签。所需变量与密钥Docker 发布Variables / SecretsVariablesDOCKERHUB_USERNAMEDockerHub 用户名SecretsDOCKERHUB_TOKENDockerHub access token。crates.io 发布SecretsCARGO_REGISTRY_TOKENcrates.io API token。权限要求能发布 crate 并能添加 owner必须是所发布全部 crate 的 owner否则发布会报错。C# SDK 发布SecretsNUGET_API_KEYNuGet API key。建议只授权push权限并将 scope 限制到所需包可使用SpacetimeDB.*这样的通配符。npm 发布在 npm 包设置中为 workflow 配置 npm trusted publishing信任发布。手动触发步骤进入仓库的 Actions 标签页选择 Release workflow点击 Run workflow输入要发布的 tag例如v1.1.1选择是否 dry-run默认 true点击运行。扩展开发添加新的发布目标若需要支持新的发布渠道按ReleaseTargettrait 实现即可见 tools/release/src/targets/mod.rs在 tools/release/src/targets/ 下新建模块例如my_target.rs实现ReleaseTargetrelease(self) - Result(), String中编排子进程调用与发布逻辑name(self) - static str返回目标唯一标识供--skip使用在mod.rs中声明pub mod my_target;在 tools/release/src/main.rs 的Commands枚举中新增子命令并在main()与release_all()中接线。编写子命令时可直接复用 util.rs 的print_command()统一打印将要执行的命令便于 CI 日志审计。关键文件索引文件说明tools/release/README.md工具官方使用文档本文主体tools/release/Cargo.toml包定义与依赖清单tools/release/src/main.rsCLI 参数定义与命令分发tools/release/src/targets/mod.rsReleaseTargettraittools/release/src/targets/crates.rscrates.io 发布实现tools/release/src/crates_resolver.rs发布顺序依赖求解tools/release/src/targets/npm.rsnpm 发布实现tools/release/src/targets/csharp.rsNuGet Unity 发布实现tools/release/src/targets/cpp.rsC 绑定镜像发布实现tools/release/src/targets/docker.rsDocker 发布实现含 dry-run 本地 registrytools/release/src/targets/github_release.rsGitHub Release 发布实现sdks/typescript/package.jsonnpmprepublishOnly脚本定义build test size小结SpacetimeDB 的发布 CLI 通过「统一 trait 顺序编排 dry-run 预演 幂等重跑」的组合拳把跨语言、跨平台、跨仓库的发布复杂度收敛为一条条简单的cargo release命令。理解其设计——特别是 crates 目标的依赖顺序求解与索引轮询、C#/C 的 git subtree 镜像同步、Docker 目标的本地 registry 干跑策略——不仅有助于安全地执行发布也为设计其他多生态项目的自动化发布流水线提供了可借鉴的范本。实际发布时优先使用仓库已配置好权限的 GitHub Actions workflow并把 dry-run 作为默认演练手段是规避权限与密钥风险的最佳实践。【免费下载链接】SpacetimeDBDevelopment at the speed of light项目地址: https://gitcode.com/GitHub_Trending/sp/SpacetimeDB创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进