mcpField
R
rust-dependencies

rust-dependencies

github.com/full-stack-skills开发12111 次安装5 周前更新
代码仓库

关于 rust-dependencies

rust-dependencies 面向维护 Cargo 项目的 Rust 开发者,指导依赖治理,涵盖版本与来源选择、安全和策略检查、依赖分析及更新自动化。

主要功能

  1. 01选择 Cargo 版本要求
  2. 02评估依赖来源
  3. 03配置 cargo-deny 策略检查
  4. 04审计 RustSec 安全公告
  5. 05分析依赖树与重复版本
  6. 06管理并自动化依赖更新

适用场景

  1. 01为 Rust 项目制定依赖规则
  2. 02排查重复或循环依赖
  3. 03审查拟议的 Cargo.lock 更新
  4. 04检查依赖的安全公告与许可证策略

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/full-stack-skills/rust-skills --skill rust-dependencies

安装后在 Claude Code 中输入/rust-dependencies确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

agents/
openai.yaml
examples/
private-registry.md
examples/golden-deps/
Cargo.lock
Cargo.toml
examples/golden-deps/src/
lib.rs
references/
cargo-deny-cookbook.md
version-requirements.md

详细介绍

Rust 依赖管理与治理

权威参考:Cargo — 指定依赖项,Cargo — 依赖解析,Cargo — 源替换,Cargo — 凭据,cargo-deny,cargo-audit,RustSec。

本技能负责依赖治理:如何安全地声明依赖、它们会引入什么、哪些依赖可以纳入,以及出现问题时该如何处理。本技能不负责 Cargo.toml 字段参考(rust-cargo-build)、semver(rust-semver)或工作区拓扑结构(rust-workspace)。

能力边界

✅ 优势
  1. 选择合适的版本要求("1" 与 "1.2" 与 "=1.2.3")
  2. 评估依赖来源(crates.io / git / path / 私有注册表)
  3. 为供应商化或镜像注册表设置源替换
  4. 配置 cargo-deny(4 个表:advisories、licenses、bans、sources)
  5. 运行 cargo-audit 并响应 RustSec 安全公告
  6. 通过 cargo tree 诊断依赖循环和重复版本问题
  7. 设置支持 MSRV 的解析器行为
  8. 使用 Renovate / Dependabot 自动更新依赖
  9. 为组织制定供应链政策
⚠️ 前置要求
  1. Cargo 清单基础知识——参见 rust-cargo-build
  2. Semver 术语——参见 rust-semver
❌ 不在范围内
  1. Cargo.toml 字段逐项参考 → rust-cargo-build
  2. 工作区布局 → rust-workspace
  3. Clippy / lint 政策 → rust-style-clippy
  4. 测试依赖注入 → rust-testing

数据隐私

本技能不会收集、存储或传输用户数据。访问私有注册表和使用凭据均须由用户授权;切勿记录凭据或在构建产物中暴露令牌。


第 1 部分:版本要求语法

Cargo 默认使用 SemVer 版本要求(而不是精确版本)。

语法含义兼容性
"1" 或 "^1">=1.0.0, <2.0.0默认值——在主版本内自动更新
"1.2" 或 "^1.2">=1.2.0, <2.0.0至少为 1.2.x
"1.2.3" 或 "^1.2.3">=1.2.3, <2.0.0至少为 1.2.3,也可能引入 1.5.0
"=1.2.3"精确为 1.2.3锁定——用于确保可复现性
"~1.2">=1.2.0, <1.3.0仅限同一次版本
"~1.2.3">=1.2.3, <1.3.0仅限同一次版本
">=1.0, <2.0"范围显式边界
"*"任意版本crates.io 禁止——范围过宽
"0.1" 或 "^0.1">=0.1.0, <0.2.01.0 之前:次版本视为主版本
"0.0.1">=0.0.1, <0.0.20.1 之前:补丁版本视为主版本

默认值是插入符号(^)

[dependencies]
serde = "1"              # caret by default
serde = { version = "1" }   # same

通常这样就合适。你会自动获得错误修复和不破坏兼容性的功能。

何时使用其他写法

需求使用示例
锁定版本以确保可复现性="=1.2.3"
仅限制在次版本内~"~1.2"(不包括 1.3.x)
限定范围>=, <">=1.0, <1.5"
1.0 之前且次版本更新会破坏兼容性锁定次版本"0.7.3"(Cargo 将其视为 <0.8)
Git 最新提交git{ git = "..." }

1.0 之前的插入符号规则

# These are equivalent and both mean <0.2:
my-crate = "0.1"
my-crate = "^0.1"

# 0.0.x is even more restrictive:
my-crate = "0.0.3"      # means >=0.0.3, <0.0.4 — almost a pin

之所以存在 1.0 之前的规则,是因为 SemVer 规范将 0.x 视为“任何变更都可能发生”。Cargo 则采用了社区惯例:0.x 中的次版本递增意味着不兼容变更。


第 2 部分:依赖来源

crates.io(默认)

[dependencies]
serde = "1"

公开且不可变,并由 crates.io 审核。这是 99% 的依赖应使用的来源。

Git

[dependencies]
# Branch / tag / rev / default
my-crate = { git = "https://github.com/user/repo", branch = "dev" }
my-crate = { git = "https://github.com/user/repo", tag = "v1.0.0" }
my-crate = { git = "https://github.com/user/repo", rev = "abc1234" }
my-crate = { git = "https://github.com/user/repo" }

请谨慎使用:Git 依赖会降低 Cargo.lock 的可移植性、拖慢 CI;除非该 Git 依赖也已发布,否则无法发布到 crates.io。优先选择 crates.io、以其他名称发布的分叉版本,或 cargo vendor。

路径(本地 / 工作区)

[dependencies]
my-core = { path = "../core", version = "0.1" }

工作区内部依赖必需。发布时始终与 version 配对(否则 cargo publish 会失败)。

私有注册表

# .cargo/config.toml
[registries.my-registry]
index = "sparse+https://my-registry.example.com/index/"

[registry]
default = "my-registry"   # optional: make this the default
# Cargo.toml
[dependencies]
my-private-crate = { version = "1.0", registry = "my-registry" }

源替换(透明)

Cargo Source Replacement 可让你用镜像替换 crates.io,而无需编辑每个 Cargo.toml:

# .cargo/config.toml
[source.my-mirror]
registry = "sparse+https://mirrors.example.com/crates.io-index"

[source.crates-io]
replace-with = "my-mirror"

使用场景:企业代理、中国镜像(RsProxy、tuna)、离线构建时使用 vendored 依赖。

Vendored

cargo vendor vendor/   # downloads all deps to vendor/
# .cargo/config.toml
[source.crates-io]
replace-with = "vendored-sources"

[source.vendored-sources]
directory = "vendor"

适用于隔离网络 / 可复现构建。将 vendor/ 纳入 git(它体积较大,但稳定)。


第 3 部分:依赖树分析

cargo tree

cargo tree                        # full tree
cargo tree --depth 2              # limit
cargo tree --invert --package X   # what depends on X?
cargo tree -e features            # show feature unification
cargo tree -e no-dev              # exclude dev-deps
cargo tree -e no-build            # exclude build-deps

查找重复项

cargo tree --duplicates           # show crates with multiple versions

如果你同时看到版本为 1.0.180 和 1.0.195 的 serde,说明依赖树中存在两个版本。常见原因:

  • 某个旧的传递依赖要求旧版本
  • 某个 git 依赖拉取了特定版本
  • 你自己的版本要求过于严格

解决重复项

cargo update -p serde             # bump to latest matching req
cargo update -p serde --precise 1.0.200

如果某个传递依赖锁定了旧版本,你可以:

  1. 更新该传递依赖(cargo update -p that-crate)
  2. 接受重复版本(通常没有问题)
  3. 将该传递依赖替换为一个 fork

检测循环依赖

Cargo 禁止依赖图中存在循环。如果你看到:

error: cyclic package dependency: package `a` depends on `b`. package `b` depends on `a`.

这表明存在真正的设计缺陷——需要重构(通常是提取一个双方都依赖的共享 crate c)。


第 4 部分:依赖更新治理

关于当前 Cargo.lock 版本控制的指导,以及 --locked、--offline 和 --frozen 的确切行为,请使用 rust-cargo-build。当前 Cargo 指南建议:如有疑问,请提交 Cargo.lock;此处不要套用针对应用与库的禁止规则。

本技能负责规定如何提出、审查和批准已解析依赖的变更:

cargo update                      # bump all to latest within reqs
cargo update --precise 1.0.200 -p serde   # pin a specific version
cargo update --dry-run            # see what would change
  • 优先使用限定到特定软件包的更新,避免无关的依赖图变动。
  • 审查锁文件中源、校验和、版本、功能及重复版本的变更。
  • 对拟议的依赖图运行安全公告、许可证、禁用项和源策略检查。
  • 控制自动更新拉取请求的范围,并确保其变更可观察。
  • 如果库需要测试新解析的依赖版本范围,请使用单独的定期兼容性流程。
  • 绝不要仅为通过过时锁文件检查,就在必需的 CI 中无条件添加 cargo update。

第 5 部分:cargo-deny(供应链治理)

cargo-deny 是依赖策略事实上的标准工具。包含四项检查:

5.1 advisories — RustSec

# deny.toml
[advisories]
db-urls = ["https://github.com/rustsec/advisory-db"]
yanked = "deny"
ignore = [
    # "RUSTSEC-2024-0001",  # ignore specific advisory with justification
]
cargo deny check advisories

5.2 licenses — 策略

# deny.toml
[licenses]
allow = [
    "MIT",
    "Apache-2.0",
    "BSD-3-Clause",
    "ISC",
    "Unicode-DFS-2016",
]
confidence-threshold = 0.93

[[licenses.exceptions]]
allow = ["Zlib"]
name = "some-zlib-crate"
version = "1.0"
cargo deny check licenses

默认策略较宽松;请根据组织的策略收紧。

5.3 bans — 禁用的 crate

# deny.toml
[bans]
multiple-versions = "warn"
wildcards = "deny"        # don't allow "2.*" requirements

[[bans.deny]]
name = "openssl"          # prefer rustls
version = "*"

[[bans.deny]]
name = "chrono"
version = "<0.5"          # only old versions

[bans.workspace-dependencies]
duplicates = "deny"       # require [workspace.dependencies]
cargo deny check bans

5.4 sources — 依赖来源

# deny.toml
[sources]
unknown-registry = "deny"   # disallow non-crates.io registries
unknown-git = "deny"        # disallow non-allowlisted git sources
allow-registry = ["crates-io"]
allow-git = []
cargo deny check sources

一站式检查

cargo deny check               # runs all four

CI 集成:

- uses: EmbarkStudios/cargo-deny-action@v2
  with:
    command: check

第 6 部分:cargo-audit

cargo-audit 会根据 RustSec 安全公告数据库扫描 Cargo.lock。

cargo install cargo-audit --locked
cargo audit                           # scan
cargo audit --deny warnings           # fail CI on warnings
cargo audit --ignore RUSTSEC-XXXX     # ignore specific advisory

与 cargo-deny 的区别:

  • cargo-audit 仅检查安全公告(侧重安全)
  • cargo-deny 涵盖安全公告 + 许可证 + 禁用项 + 来源

大多数项目会使用功能更全面的 cargo-deny。有些项目会同时使用两者(纵深防御)。

响应安全公告

  1. 运行 cargo audit,找出存在漏洞的 crate 及其版本
  2. 在 RustSec 中查找已修复的版本
  3. 执行 cargo update -p vulnerable-crate --precise X.Y.Z
  4. 如果没有修复版本:切换到受维护的 fork、移除该依赖,或禁用受影响的功能
  5. 如果这是一个新漏洞,请向上游提交 issue

第 7 部分:自动化

Renovate

Renovate 会在依赖更新时自动创建 PR。它开箱即支持 Cargo:

// .renovaterc.json
{
  "extends": ["config:recommended", ":semanticCommits"],
  "schedule": ["before 6am on Monday"]
}

Dependabot

Dependabot 是 GitHub 原生工具:

# .github/dependabot.yml
version: 2
updates:
  - package-ecosystem: "cargo"
    directory: "/"
    schedule:
      interval: "weekly"

Cargo 自带的自动更新

Cargo 没有内置的“cargo update PR”工具,但你可以编写脚本:

cargo update
git diff Cargo.lock
# Commit + push to a branch

第 8 部分:精简功能

[dependencies]
serde = { version = "1", features = ["derive"] }     # only what you use
tokio = { version = "1", features = ["rt-multi-thread", "macros"] }

每启用一项功能,都会增加编译时间、二进制大小和攻击面。如果只需要部分功能,请禁用默认功能:

[dependencies]
tokio = { version = "1", default-features = false, features = ["rt", "net"] }

检查功能

cargo tree -e features              # which features are enabled, where
cargo tree -e features -p tokio     # just tokio's features

如果传递依赖中的 tokio 显示为 [full],说明你为用不到的功能付出了代价。

工作区依赖治理

# root Cargo.toml
[workspace.dependencies]
serde = { version = "1", features = ["derive"] }   # pin features once

# crates/abc/Cargo.toml
[dependencies]
serde.workspace = true    # inherits feature set

防止工作区成员之间的功能配置逐渐偏离。


工作流

  1. 盘点 — cargo tree -e features、cargo tree --duplicates
  2. 审计 — cargo audit(安全公告)+ cargo deny check(完整策略检查)
  3. 收紧版本 — 将 "*" 替换为 "1";仅在需要可复现时固定精确版本
  4. 精简功能 — 设置 default-features = false,并仅列出用到的功能
  5. 选择来源 — 优先使用 crates.io;仅在有正当理由时使用 git/path
  6. 配置 CI — cargo build --locked、cargo deny check,以及按计划运行的 cargo audit
  7. 自动更新 — 使用 Renovate 或 Dependabot,并采用语义化提交

决策速查

问题答案
固定版本还是使用插入符?默认使用插入符("1");仅为确保可复现时固定版本("=1.2.3")
使用 crates.io 还是 git?除非有具体理由,否则使用 crates.io
立即用最新版本还是等待?新主版本发布后等待 1-2 周;补丁版本自动更新
允许使用 "*" 版本要求吗?不允许 — crates.io 会拒绝,而且它们会掩盖升级
serde 应有多少个版本?一个。如果有重复项,通过 cargo tree --duplicates 追查
库项目要提交 Cargo.lock 吗?不要 — 下游项目负责管理锁文件
CI 用 --locked 还是 --frozen?常规 CI 使用 --locked;隔离网络环境使用 --frozen

资源

上游来源

评论

支持 Markdown