08-持续集成
在 CI 中使用 Cargo 的常见做法
译文 · 基于 The Cargo Book
持续集成
原文链接: https://doc.rust-lang.org/cargo/guide/continuous-integration.html
入门
基本的 CI 会构建并测试你的项目:
GitHub Actions
要在 GitHub Actions 上测试你的包,下面是一个示例 .github/workflows/ci.yml 文件:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
| name: Cargo Build & Test
on:
push:
pull_request:
env:
CARGO_TERM_COLOR: always
jobs:
build_and_test:
name: Rust project - latest
runs-on: ubuntu-latest
strategy:
matrix:
toolchain:
- stable
- beta
- nightly
steps:
- uses: actions/checkout@v6
- run: rustup update ${{ matrix.toolchain }} && rustup default ${{ matrix.toolchain }}
- run: cargo build --verbose
- run: cargo test --verbose
|
这会在全部三个发行通道上测试(注意任一工具链版本失败都会导致整个作业失败)。你也可以在 GitHub UI 中点击 "Actions" > "new workflow" 并选择 Rust,将默认配置添加到仓库。更多信息参见 GitHub Actions 文档。
GitLab CI
要在 GitLab CI 上测试你的包,下面是一个示例 .gitlab-ci.yml 文件:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| stages:
- build
rust-latest:
stage: build
image: rust:latest
script:
- cargo build --verbose
- cargo test --verbose
rust-nightly:
stage: build
image: rustlang/rust:nightly
script:
- cargo build --verbose
- cargo test --verbose
allow_failure: true
|
这会在稳定通道与 nightly 通道上测试,但 nightly 上的任何破坏都不会导致整体构建失败。更多信息请参见 GitLab CI 文档。
builds.sr.ht
要在 sr.ht 上测试你的包,下面是一个示例 .build.yml 文件。请务必将 <your repo> 与 <your project> 改为要克隆的仓库以及克隆后的目录。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
| image: archlinux
packages:
- rustup
sources:
- <your repo>
tasks:
- setup: |
rustup toolchain install nightly stable
cd <your project>/
rustup run stable cargo fetch
- stable: |
rustup default stable
cd <your project>/
cargo build --verbose
cargo test --verbose
- nightly: |
rustup default nightly
cd <your project>/
cargo build --verbose ||:
cargo test --verbose ||:
- docs: |
cd <your project>/
rustup run stable cargo doc --no-deps
rustup run nightly cargo doc --no-deps ||:
|
这会在稳定通道与 nightly 通道上测试并构建文档,但 nightly 上的任何破坏都不会导致整体构建失败。更多信息请参见 builds.sr.ht 文档。
CircleCI
要在 CircleCI 上测试你的包,下面是一个示例 .circleci/config.yml 文件:
1
2
3
4
5
6
7
8
9
| version: 2.1
jobs:
build:
docker:
# 查看 https://circleci.com/developer/images/image/cimg/rust#image-tags 获取最新镜像
- image: cimg/rust:1.77.2
steps:
- checkout
- run: cargo test
|
要运行更复杂的流水线,包括不稳定测试检测、缓存与产物管理,请参见 CircleCI 配置参考。
验证最新依赖
在 Cargo.toml 中指定依赖时,它们通常匹配一个版本范围。穷尽测试所有版本组合不切实际。至少验证最新版本,可以对运行 cargo add 或 cargo install 的用户进行覆盖。
测试最新版本时需考虑:
- 尽量减少影响本地开发或 CI 的外部因素
- 新依赖发布的频率
- 项目愿意承担的风险水平
- CI 成本,包括间接成本,例如 CI 服务对并行运行器有上限,达到上限时新作业会被串行化
一些可能的方案包括:
- 不把
Cargo.lock 纳入版本控制- 取决于 PR 速度,许多版本可能未经测试
- 代价是失去确定性
- 用 CI 作业验证最新依赖,但将其标记为「失败时继续」
- 取决于 CI 服务,失败可能并不明显
- 取决于 PR 速度,可能比必要情况消耗更多资源
- 用定时 CI 作业验证最新依赖
- 托管 CI 服务可能对长时间未改动的仓库禁用定时作业,影响被动维护的包
- 取决于 CI 服务,通知可能无法送达能处理失败的人
- 若未与依赖发布频率平衡,可能测试的版本不够,或做了冗余测试
- 通过 PR 定期更新依赖,例如使用 Dependabot 或 RenovateBot
- 可将依赖隔离到各自的 PR,或汇总到单个 PR
- 只使用必要的资源
- 可配置频率,以平衡 CI 资源与依赖版本覆盖
用 GitHub Actions 验证最新依赖的示例 CI 作业:
1
2
3
4
5
6
7
8
9
10
11
12
13
| jobs:
latest_deps:
name: Latest Dependencies
runs-on: ubuntu-latest
continue-on-error: true
env:
CARGO_RESOLVER_INCOMPATIBLE_RUST_VERSIONS: allow
steps:
- uses: actions/checkout@v6
- run: rustup update stable && rustup default stable
- run: cargo update --verbose
- run: cargo build --verbose
- run: cargo test --verbose
|
说明:
对于按平台或按 Rust 版本失败风险较高的项目,可能需要测试更多组合。
验证 rust-version
发布指定了 rust-version 的包时,验证该字段的正确性很重要。
可提供帮助的一些第三方工具包括:
用 GitHub Actions 实现的一种方式示例:
1
2
3
4
5
6
7
| jobs:
msrv:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: taiki-e/install-action@cargo-hack
- run: cargo hack check --rust-version --workspace --all-targets --ignore-private
|
这试图在彻底性与周转时间之间取得平衡:
- 使用单一平台,因为大多数项目与平台无关,并信任平台相关依赖自行验证行为。
- 使用
cargo check,因为贡献者遇到的大多数问题是 API 可用性而非行为。 - 跳过未发布的包,因为假定只有通过注册表消费已验证项目的用户才会关心
rust-version。
检查警告
通常,项目希望在官方分支上「无警告」,同时对本地开发更宽松。可以使用 build.warnings = "deny" 在存在警告时让 CI 作业失败。
用 GitHub Actions 检查警告的示例 CI 作业:
1
2
3
4
5
6
7
8
9
10
| jobs:
warnings:
runs-on: ubuntu-latest
env:
CARGO_BUILD_WARNINGS: deny
steps:
- uses: actions/checkout@v6
- run: rustup update stable && rustup default stable
- run: rustup component add clippy
- run: cargo clippy --all-targets --all-features --keep-going
|
注意事项:
- CI 可能因新的工具链版本而失败,因为警告周围的兼容性保证有限。可考虑固定工具链版本,并用自动化作业在新版本发布时创建升级工具链的 PR。
- 在选择要检查的平台、特性与包/构建目标组合时,平衡穷尽性与周转时间
- 某些 CI 系统对报告 lint 有直接集成,例如在 GitHub 上使用
clippy-sarif