rust-dependencies について
rust-dependencies は、Cargo プロジェクトを保守する Rust 開発者向けの依存関係管理スキルです。バージョンや取得元の選定から、監査、ポリシー確認、更新自動化まで扱います。
主な機能
- 01Cargo のバージョン要件選定
- 02依存関係の取得元評価
- 03cargo-deny のポリシー設定
- 04RustSec アドバイザリの監査
- 05依存ツリーと重複の分析
- 06依存更新の管理と自動化
活用シーン
- 01Rust プロジェクトの依存ポリシー策定
- 02重複・循環依存の調査
- 03Cargo.lock の更新案のレビュー
- 04アドバイザリとライセンスポリシーの確認
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ full-stack-skills/ rust-skills --skill rust-dependenciesインストール後、Claude Code で/rust-dependenciesを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
agents/openai.yamlexamples/private-registry.mdexamples/golden-deps/Cargo.lockCargo.tomlexamples/golden-deps/src/lib.rsreferences/cargo-deny-cookbook.mdversion-requirements.md詳細
Rust の依存関係管理とガバナンス
権威ある情報源:Cargo — 依存関係の指定、Cargo — 依存関係の解決、Cargo — ソースの置換、Cargo — 認証情報、cargo-deny、cargo-audit、RustSec。
このスキルは依存関係のガバナンスを担当します。安全な依存関係の宣言方法、依存関係が取り込むもの、許可する対象、問題が起きたときの対処方法を扱います。Cargo.toml のフィールドリファレンス(rust-cargo-build)、semver(rust-semver)、ワークスペースの構成(rust-workspace)は対象外です。
対応範囲
✅ 得意分野
- 適切なバージョン要件の選択(
"1"と"1.2"と"=1.2.3") - 依存関係のソースの評価(crates.io / git / path / プライベートレジストリ)
- ベンダー化またはミラーリングされたレジストリのためのソース置換の設定
cargo-denyの設定(4 つのテーブル:advisories、licenses、bans、sources)cargo-auditの実行と RustSec アドバイザリへの対応cargo treeを使った依存関係の循環と重複バージョンの問題の診断- MSRV を考慮したリゾルバーの動作の設定
- Renovate / Dependabot による依存関係の更新の自動化
- 組織のサプライチェーンポリシーの策定
⚠️ 前提条件
- Cargo マニフェストの基本 —
rust-cargo-buildを参照 - SemVer の用語 —
rust-semverを参照
❌ 対象外
- Cargo.toml のフィールドごとのリファレンス →
rust-cargo-build - ワークスペースのレイアウト →
rust-workspace - Clippy / lint ポリシー →
rust-style-clippy - テストでの依存性注入 →
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.0 | 1.0.0 より前:マイナーバージョンをメジャーバージョンとして扱う |
"0.0.1" | >=0.0.1, <0.0.2 | 0.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 より前で、マイナー更新が破壊的変更を含む場合 | マイナーバージョンを固定 | "0.7.3"(Cargo は <0.8 として扱います) |
| Git の最新コミット | git | { git = "..." } |
1.0.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.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 を優先してください。
Path(ローカル/ワークスペース)
[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 を使うと、各 Cargo.toml を編集せずに crates.io をミラーに置き換えられます。
# .cargo/config.toml
[source.my-mirror]
registry = "sparse+https://mirrors.example.com/crates.io-index"
[source.crates-io]
replace-with = "my-mirror"
用途:エンタープライズプロキシ、中国のミラー(RsProxy、tuna)、ベンダー化されたオフラインビルド。
ベンダー化
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
serde が 1.0.180 と 1.0.195 の両方で表示される場合、ツリー内に 2 つのバージョンがあります。よくある原因は次のとおりです。
- 古い推移的依存関係が古いバージョンを要求している
- Git 依存関係が特定のバージョンを取り込んでいる
- 独自のバージョン要件が厳しすぎる
重複の解消
cargo update -p serde # bump to latest matching req
cargo update -p serde --precise 1.0.200
推移的依存関係が古いバージョンに固定されている場合、次のいずれかを選べます。
- 推移的依存関係を更新する(
cargo update -p that-crate) - 重複を許容する(通常は問題ありません)
- 推移的依存関係をフォークに置き換える
循環の検出
Cargo は依存関係グラフ内の循環を禁止しています。次のように表示された場合:
error: cyclic package dependency: package `a` depends on `b`. package `b` depends on `a`.
設計上の問題があります。構造を見直してください(多くの場合、両方が依存する共有クレート c を抽出します)。
パート 4:依存関係更新のガバナンス
rust-cargo-build を使用して、Cargo.lock のバージョン管理に関する最新のガイダンスと、--locked、--offline、--frozen の正確な動作を確認してください。現行の Cargo Guide では、判断に迷う場合は 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 は、依存関係ポリシーを扱う事実上の標準ツールです。チェック項目は 4 つあります。
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 — 禁止クレート
# 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 を使用します。多層防御のために両方を使うプロジェクトもあります。
アドバイザリへの対応
cargo auditを実行して、脆弱性のあるクレートとバージョンを特定します。- RustSec で修正版のバージョンを確認します。
cargo update -p vulnerable-crate --precise X.Y.Z- 修正がない場合は、メンテナンスされているフォークに切り替えるか、依存関係を削除するか、該当する機能を無効にします。
- 新たな脆弱性の場合は、アップストリームに課題を報告します。
パート 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 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
メンバー間で機能がずれていくのを防ぎます。
ワークフロー
- 一覧化 —
cargo tree -e features、cargo tree --duplicates - 監査 —
cargo audit(アドバイザリ)+cargo deny check(包括的なポリシー) - バージョンを絞り込む —
"*"を"1"に置き換えます。再現性が必要な場合に限り、正確なバージョンを固定します - 機能を最小化する —
default-features = falseを指定し、使用する機能だけを列挙します - ソースを決める — crates.io を優先し、正当な理由がある場合に限り git/path を使用します
- CI を設定する —
cargo build --locked、cargo deny check、スケジュール実行のcargo audit - 更新を自動化する — Renovate または Dependabot を、セマンティックコミットと併用します
判断の早見表
| 質問 | 回答 |
|---|---|
| バージョン固定とキャレット指定のどちらにするか? | デフォルトではキャレット("1")を使います。再現性が必要な場合に限り、バージョンを固定します("=1.2.3") |
| crates.io と git のどちらを使うか? | 特別な理由がない限り crates.io を使います |
| 最新版を使うか、待つか? | 新しいメジャーバージョンは 1〜2 週間待ち、パッチは自動適用します |
"*" の指定を許可するか? | いいえ。crates.io では拒否され、アップグレードが見えにくくなります |
serde のバージョンはいくつ使うか? | 1 つです。重複している場合は、cargo tree --duplicates で追跡します |
ライブラリの Cargo.lock をコミットするか? | いいえ。ロックファイルは下流の利用者が管理します |
CI では --locked と --frozen のどちらを使うか? | 通常の CI では --locked、ネットワークから隔離された環境では --frozen を使います |
リソース
- Cargo — 依存関係の指定 — 構文の完全なリファレンス
- cargo-deny 設定クックブック — 4 つのテーブルによるポリシー
- プライベートレジストリの設定 — 認証情報、ソースの置き換え
examples/golden-deps/— 依存関係を最小限に絞り、監査した小規模なクレート