第11章 在 crates.io 上发布
当你拥有一个想要分享给全世界的库时,是时候将其发布到 crates.io 了!发布 crate 是指将特定版本上传至 crates.io 进行托管。
发布 crate 需谨慎,因为发布行为通常具有永久性。版本无法被覆盖,代码也不能被删除。不过,可发布的版本数量没有限制。
首次发布前
首先,你需要在 crates.io 注册一个账户以获取 API token。方法是访问主页并通过 GitHub 账号登录(目前这是必须的)。此外,你还需要在账户设置页面提供并验证你的电子邮件地址。完成后,创建一个 API token并确保复制它。一旦离开该页面,你将无法再次看到它。
然后运行 cargo login 命令。
$ cargo login
接下来在提示符处输入指定的 token。
please paste the API Token found on https://crates.io/me below
abcdefghijklmnopqrstuvwxyz012345
此命令会告知 Cargo 你的 API token,并将其存储在本地 ~/.cargo/credentials.toml 中。请注意,此 token 属于机密信息,切勿与他人分享。如果因任何原因泄露,应立即吊销它。
注意:可以使用
cargo logout命令从credentials.toml中移除 token。如果你不再需要在本机保存该 token,这会很有用。
发布新 crate 前
请记住,crates.io 上的 crate 名称遵循先到先得原则。一旦某个 crate 名称被占用,它就不能再用于其他 crate。
建议先看看 Cargo.toml 中可以指定的元数据,让你的 crate 更容易被发现!发布前,请确保填写了以下字段:
另外,最好再加上一些 keywords 和 categories,虽然这不是必需的。
如果你要发布的是一个库,还可以参考一下 Rust API Guidelines。
打包 crate
下一步是把你的 crate 打包并上传到 crates.io,这需要用到 cargo publish 子命令。该命令会执行以下步骤:
- 对包执行一些验证检查。
- 把源代码压缩成
.crate文件。 - 把
.crate文件解压到临时目录,并验证它能编译。 - 把
.crate文件上传到 crates.io。 - registry 在添加上传的包之前会做一些额外的检查。
建议在正式发布前先运行 cargo publish --dry-run(或等效的 cargo package),确保没有任何警告或错误。它会执行上面列出的前三步。
$ cargo publish --dry-run
你可以在 target/package 目录下检查生成的 .crate 文件。crates.io 目前对 .crate 文件大小限制为 10MB。建议检查一下 .crate 文件的大小,确保没有误打包那些构建时非必需的大文件,例如测试数据、网站文档或代码生成文件。你可以用以下命令查看包含哪些文件:
$ cargo package --list
打包时 Cargo 会自动忽略版本控制系统中指定的忽略文件,但如果想指定额外的忽略文件集合,可以使用 manifest 中的 exclude 键:
[package]
# ...
exclude = [
"public/assets/*",
"videos/*",
]
如果更倾向于明确列出要包含的文件,Cargo 也支持 include 键,设置后会覆盖 exclude 键:
[package]
# ...
include = [
"**/*.rs",
]
上传 crate
准备好发布时,使用 cargo publish 命令将 crate 上传至 crates.io:
$ cargo publish
就这样,你的第一个 crate 已经发布成功!
发布现有 crate 的新版本
要发布新版本,请修改 Cargo.toml manifest 中指定的 version 值。请注意 SemVer 规则,它规定了哪些变更是兼容的。然后按上述说明运行 cargo publish 上传新版本。
建议: 考虑完整的发布流程,并尽可能实现自动化。
每个版本应包含:
以下是一些代表不同工作流的第三方工具示例(按字母顺序排列):
更多工具请参阅 crates.io。
管理基于 crates.io 的 crate
crate 的管理主要通过命令行 cargo 工具进行,而非使用 crates.io 的 Web 界面。为此,Cargo 提供了一些用于管理 crate 的子命令。
cargo yank
有时,你可能会发布一个因某种原因(如语法错误、忘记包含文件等)而实际存在缺陷的 crate 版本。在这种情况下,Cargo 支持对该 crate 版本进行“撤回”(yank)。
$ cargo yank --version 1.0.1
$ cargo yank --version 1.0.1 --undo
撤回操作不会删除任何代码。此功能并非用于删除意外上传的敏感信息(例如密钥)。如果发生这种情况,你必须立即重置这些敏感信息。
已撤回版本的语义是:不能基于该版本创建新的依赖项,但所有现有的依赖项仍可继续工作。 crates.io 的主要目标之一是作为 crate 的永久归档库,且内容不随时间改变,允许删除版本将违背这一目标。实质上,撤回意味着所有包含 Cargo.lock 文件的包不会因此损坏,而未来生成的 Cargo.lock 文件将不再列出已撤回的版本。
cargo owner
一个 crate 通常由多人开发,或者主要维护者可能会随时间改变!crate 的所有者是唯一有权发布该 crate 新版本的人,但所有者可以指定其他所有者。
$ cargo owner --add github-handle
$ cargo owner --remove github-handle
$ cargo owner --add github:rust-lang:owners
$ cargo owner --remove github:rust-lang:owners
这些命令中的 owner ID 必须是 GitHub 用户名或 GitHub 团队。
如果给 --add 传入的是用户名,该用户会以“具名”所有者的身份受邀,拥有该 crate 的全部权限。除了可以发布或撤销(yank)crate 的版本之外,他们还能添加或移除其他所有者,包括把他们设为所有者的那个人。不用说,不要把你不完全信任的人设为具名所有者。要成为具名所有者,该用户必须曾登录过 crates.io。
如果给 --add 传入的是团队名,该团队会以“团队”所有者的身份受邀,权限受到限制。他们可以发布或撤销 crate 的版本,但不能添加或移除所有者。团队不仅便于批量管理所有者,还能在一定程度上降低所有者作恶的风险。
团队名目前的语法是 github:org:team(见上面的示例)。要邀请某个团队作为所有者,你必须自己是该团队的成员。移除团队所有者则没有这个限制。
GitHub 权限
GitHub 并没有为团队身份提供简单的公开访问方式,你在使用时很可能会遇到如下提示:
看起来你没有权限从 GitHub 查询完成此请求所需的属性。你可能需要在 crates.io 上重新认证,以授予读取 GitHub 组织成员身份的权限。
这基本上是“你尝试查询某个团队,但在五层成员权限控制的某一层被拒绝了”的兜底提示。这并非夸张,GitHub 对团队权限控制的支持堪称企业级水准。
出现这种情况最常见的原因,通常是因为该功能添加前你就已登录过。最初,我们在用户认证时并未向 GitHub 请求任何权限,因为我们实际只用用户的 token 来登录,而没有将其用于其他用途。但为了代你查询团队成员关系,现在我们需要read:org 权限。
你可以拒绝授予此权限,在引入团队功能之前可用的所有操作将继续保持正常。但你永远无法将团队添加为负责人,也无法以团队负责人的身份发布 crate。如果你尝试这样做,就会看到上述错误。此外,如果你试图发布一个你并不拥有、但碰巧属于某个团队的 crate,也可能会看到此错误。
如果你改变主意,或者不确定 crates.io 是否拥有足够的权限,你可以随时访问 https://crates.io/ 重新认证。如果 crates.io 缺少所需的权限,系统会提示你授权。
查询 GitHub 的另一个障碍是,该组织可能正在主动拒绝第三方访问。你可以前往以下页面进行确认:
https://github.com/organizations/:org/settings/oauth_application_policy
其中 :org 代表组织名称(例如 rust-lang)。你可能会看到类似以下内容:

在这里,你可以选择将 crates.io 从组织的黑名单中显式移除,或者直接点击“Remove Restrictions”按钮,允许所有第三方应用程序访问这些数据。
或者,当 crates.io 请求 read:org 权限时,你可以点击其名称旁边的“Grant Access”按钮,显式将 crates.io 加入白名单,允许其查询相关组织:

排查 GitHub 团队访问错误
在尝试将 GitHub 团队添加为 crate 负责人时,你可能会看到如下错误:
error: failed to invite owners to crate <crate_name>: api errors (status 200 OK): could not find the github team org/repo
出现这种情况时,请前往GitHub 应用设置页面,检查 Authorized OAuth Apps 选项卡中是否列有 crates.io。如果没有,请前往https://crates.io/进行授权。然后返回 GitHub 的应用设置页面,点击列表中的 crates.io 应用,确认你或你的组织出现在“Organization access”列表中,并带有绿色对勾标记。如果看到标有 Grant 或 Request 的按钮,请授予访问权限,或请求组织管理员执行该操作。