Rust 課程 – 專案管理與 Cargo
主題:發布到 crates.io
簡介
在 Rust 生態系統中,crates.io 是唯一官方的套件(crate)託管平台。把自己的程式庫發佈到 crates.io,不僅能讓其他開發者輕鬆取得、使用與回饋,還能提升個人或團隊的能見度與信譽。對於想要在開源社群留下足跡、或是希望未來的專案能透過 cargo add 快速整合的開發者而言,掌握正確的發布流程是必備技能。
本篇文章將從 Cargo 的基本設定說起,說明如何準備、測試、簽署與上傳 crate,並提供實作範例、常見陷阱與最佳實踐,協助你在 1500 左右的篇幅 內完成一次安全、可維護的發布。
核心概念
1. Cargo.toml 必備欄位
Cargo.toml 是 crate 的「身份證」與「說明書」。在發布前,必須確保以下欄位正確填寫:
| 欄位 | 說明 | 範例 |
|---|---|---|
name |
套件名稱(全小寫、只能使用 -、_) |
my-awesome-lib |
version |
依照 SemVer(MAJOR.MINOR.PATCH)規則更新 | 0.2.1 |
authors |
作者資訊(可多筆) | ["Alice <alice@example.com>"] |
description |
簡短說明,會顯示在 crates.io 搜尋結果 | "一個用於字串處理的輕量函式庫" |
license / license-file |
授權條款,必須明確指出 | "MIT OR Apache-2.0" |
repository |
原始碼倉庫 URL(GitHub、GitLab 等) | "https://github.com/alice/my-awesome-lib" |
homepage / documentation |
相關說明文件的連結(可選) | "https://docs.rs/my-awesome-lib" |
readme |
README 檔案路徑,建議使用 README.md |
"README.md" |
keywords、categories |
讓使用者更容易搜尋 | ["string", "utility"]、["text-processing"] |
重點:
license必須是 SPDX 識別碼,且 不能留空,否則 crates.io 會拒絕上傳。
程式碼範例 1:完整的 Cargo.toml
[package]
name = "my-awesome-lib"
version = "0.2.1"
authors = ["Alice <alice@example.com>"]
edition = "2021"
description = "一個用於字串處理的輕量函式庫"
license = "MIT OR Apache-2.0"
repository = "https://github.com/alice/my-awesome-lib"
homepage = "https://github.com/alice/my-awesome-lib#readme"
documentation = "https://docs.rs/my-awesome-lib"
readme = "README.md"
keywords = ["string", "utility"]
categories = ["text-processing"]
2. 產生與管理 API 金鑰
發布到 crates.io 必須使用 API token(金鑰)驗證身分。流程如下:
- 前往 https://crates.io/me,登入後點擊 "New Token"。
- 為金鑰命名(例如
ci-publish),並設定 只允許publish的權限。 - 複製金鑰,切勿在版本控制系統中暴露。
在本機端,使用 cargo login <TOKEN> 把金鑰寫入 ~/.cargo/credentials,之後的 cargo publish 會自動使用。
程式碼範例 2:CI/CD 中使用金鑰(GitHub Actions)
name: Publish to crates.io
on:
push:
tags:
- 'v*.*.*' # 只在標記版號時觸發
jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install Rust toolchain
uses: actions-rs/toolchain@v1
with:
toolchain: stable
override: true
- name: Publish crate
env:
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
run: cargo publish --token $CARGO_REGISTRY_TOKEN
小技巧:在 GitHub Secrets 中儲存金鑰,避免在日誌中洩漏。
3. 測試與檢查(cargo test、cargo clippy、cargo fmt)
在正式發布前,必須確保 crate 通過所有測試、Lint 與格式化。建議的 CI 步驟:
cargo fmt -- --check # 確認程式碼格式
cargo clippy -- -D warnings # 把所有警告視為錯誤
cargo test --all-features # 執行所有測試
如果有 示範範例(examples),也要在 CI 中編譯:
cargo build --examples
程式碼範例 3:簡易測試範例
// src/lib.rs
/// 反轉字串的函式,支援 Unicode
pub fn reverse(s: &str) -> String {
s.chars().rev().collect()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_reverse_ascii() {
assert_eq!(reverse("hello"), "olleh");
}
#[test]
fn test_reverse_unicode() {
assert_eq!(reverse("你好世界"), "界世好你");
}
}
4. cargo publish 的細節
| 參數 | 功能 | 範例 |
|---|---|---|
--dry-run |
模擬發布,檢查是否有遺漏檔案或錯誤 | cargo publish --dry-run |
--allow-dirty |
允許工作目錄有未提交變更(不建議在正式發布使用) | cargo publish --allow-dirty |
--no-verify |
跳過測試與 lint(僅在特殊情況下使用) | cargo publish --no-verify |
--registry <NAME> |
發布到自訂 registry(如私有) | cargo publish --registry my-registry |
最佳做法:先執行 cargo publish --dry-run,確定 Cargo.toml、README.md、LICENSE 等檔案皆在套件內,才正式執行 cargo publish。
程式碼範例 4:自動化發布腳本(Bash)
#!/usr/bin/env bash
set -euo pipefail
# 1. 確認工作目錄乾淨
if [[ -n $(git status --porcelain) ]]; then
echo "工作目錄有未提交的變更,請先 commit 或 stash。" >&2
exit 1
fi
# 2. 執行檢查
cargo fmt -- --check
cargo clippy -- -D warnings
cargo test --all-features
# 3. 模擬發布
cargo publish --dry-run
# 4. 正式發布
cargo publish
echo "✅ 已成功發布至 crates.io"
5. 發布後的版本管理
語意化版本(SemVer):
- MAJOR:破壞相容性變更
- MINOR:向下相容的新功能
- PATCH:向下相容的 bug 修正
YANK:若發現嚴重錯誤,可使用
cargo yank暫時隱藏特定版本,避免新專案依賴。
cargo yank --vers 0.2.1 # 隱藏 0.2.1 版
cargo yank --undo --vers 0.2.1 # 取消隱藏
- RETRACT:在
Cargo.toml中加入[package.metadata]讓舊版在cargo search時顯示「已撤回」訊息(Rust 1.71+ 支援)。
常見陷阱與最佳實踐
| 陷阱 | 為何會發生 | 解決方式 |
|---|---|---|
忘記更新 Cargo.lock(只在 binary crate) |
cargo publish 只會打包 src/,但 Cargo.lock 仍會被忽略,導致依賴版本不一致 |
不需要手動管理,只要在 library crate 中不放 Cargo.lock 即可 |
| License 欄位空白或不符合 SPDX | crates.io 會直接拒絕上傳 | 使用合法的 SPDX 識別碼,或提供 license-file |
| README 中的相對路徑失效 | crates.io 會把 README 渲染成 HTML,若使用相對路徑會找不到檔案 | 使用絕對 URL(GitHub raw)或把圖片放在 docs/ 並在 Cargo.toml 指定 readme = "README.md" |
| 發佈過於頻繁的 PATCH 版 | 版本號過於雜亂,使用者難以追蹤 | 遵循 SemVer,僅在必要時發布 PATCH |
| 金鑰洩漏 | 把 CARGO_REGISTRY_TOKEN 放在公開 repo 中 |
永遠使用 CI secret,且 .gitignore 排除 ~/.cargo/credentials |
最佳實踐總結
- CI/CD 完全自動化:測試 → Lint → Dry‑run → Publish。
- 使用
cargo-release套件:自動 bump 版本、產生 git tag、執行cargo publish。 - 在
README中加入安裝指令:cargo add my-awesome-lib,降低使用門檻。 - 維護 CHANGELOG:使用
keep-a-changelog標準,讓使用者快速了解變更。
實際應用場景
| 場景 | 需求 | 如何利用 crates.io |
|---|---|---|
| 內部工具庫 | 多個微服務共用相同的序列化/驗證函式 | 發佈為 私有 registry(或使用 cargo publish --registry) |
| 開源 CLI | 提供 cargo install my-cli 一鍵安裝 |
把二進位 [[bin]] 加入 Cargo.toml,發布後使用者即可 cargo install |
| WebAssembly (wasm) 套件 | 前端需要呼叫 Rust 編寫的演算法 | 發佈 wasm-bindgen 包,配合 npm 的 wasm-pack 發布流程 |
| 學術研究 | 公布實驗演算法與資料結構 | 在 Cargo.toml 中加入 documentation = "https://doi.org/...",讓引用更正式 |
案例:
serde、reqwest、tokio都是透過 crates.io 讓全球開發者即時取得、升級與回報問題的典範。
總結
將 Rust 程式庫發布到 crates.io 不僅是技術上的里程碑,更是與開源社群互動的橋樑。本文從 Cargo.toml 必備欄位、API 金鑰管理、測試與 Lint、發布指令、到 版本管理 與 常見陷阱,一步步說明了完整流程。只要遵循 SemVer、使用 CI/CD 自動化測試與發布,並妥善保護金鑰與授權資訊,你就能安全、快速地把自己的 crate 推向全球開發者。
祝你在 Rust 的開源旅程中,發佈順利、持續成長! 🚀