持续集成

入门

一个基本的 CI 将构建并测试你的项目

GitHub Actions

要在 GitHub Actions 上测试你的包,这是一个示例 .github/workflows/ci.yml 文件

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@v4
      - 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 文件

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

这将在 stable 通道和 nightly 通道上进行测试,但 nightly 中的任何中断都不会导致你的整体构建失败。有关更多信息,请参阅GitLab CI 文档

builds.sr.ht

要在 sr.ht 上测试你的包,这是一个示例 .build.yml 文件。请务必将 <your repo><your project> 更改为要克隆的仓库和克隆目录。

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 ||:

这将在 stable 通道和 nightly 通道上测试并构建文档,但 nightly 中的任何中断都不会导致你的整体构建失败。有关更多信息,请参阅builds.sr.ht 文档

CircleCI

要在 CircleCI 上测试你的包,这是一个示例 .circleci/config.yml 文件

version: 2.1
jobs:
  build:
    docker:
      # check https://circleci.com/developer/images/image/cimg/rust#image-tags for latest
      - image: cimg/rust:1.77.2
    steps:
      - checkout
      - run: cargo test

要运行更复杂的流水线,包括不稳定测试检测、缓存和制品管理,请参阅CircleCI 配置参考

验证最新依赖项

Cargo.toml指定依赖项时,它们通常匹配一系列版本。详尽测试所有版本组合将变得笨拙。验证最新版本至少可以为运行 cargo addcargo install 的用户提供测试。

测试最新版本时的一些注意事项有

  • 最小化影响本地开发或 CI 的外部因素
  • 新依赖项发布的频率
  • 项目愿意接受的风险水平
  • CI 成本,包括间接成本,例如 CI 服务对并行运行器设置了最大值,导致达到最大值时新作业被串行化。

一些潜在的解决方案包括

  • 不将 Cargo.lock 检入
    • 取决于 PR 的速度,许多版本可能未经测试
    • 这会牺牲确定性
  • 设置一个 CI 作业来验证最新依赖项,但将其标记为“失败时继续”
    • 取决于 CI 服务,失败可能不明显
    • 取决于 PR 的速度,可能会使用比所需更多的资源
  • 设置一个计划的 CI 作业来验证最新依赖项
    • 托管的 CI 服务可能会禁用长时间未更改仓库的计划作业,影响被动维护的包
    • 取决于 CI 服务,通知可能无法路由到能够处理失败的人
    • 如果未与依赖项发布速率平衡,可能测试的版本不够多,或可能进行冗余测试
  • 通过 PR 定期更新依赖项,例如使用 DependabotRenovateBot
    • 可以将依赖项隔离到自己的 PR 中,或将它们合并到一个 PR 中
    • 仅使用必要的资源
    • 可以配置频率以平衡 CI 资源和依赖项版本的覆盖范围

使用 GitHub Actions 验证最新依赖项的示例 CI 作业

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@v4
      - 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 实现此目的的一种示例方法

jobs:
  msrv:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4
    - uses: taiki-e/install-action@cargo-hack
    - run: cargo hack check --rust-version --workspace --all-targets --ignore-private

这试图平衡彻底性和周转时间

  • 使用单个平台,因为大多数项目都是平台无关的,信任特定于平台的依赖项来验证其行为。
  • 使用 cargo check,因为贡献者遇到的大多数问题都是 API 可用性问题,而不是行为问题。
  • 跳过未发布的包,因为这假设只有通过注册表使用验证项目的消费者才会关心 rust-version