#semver #版本管理 #版本 #检查 #cargo #自动 #语义

nightly bin+lib semververfork

Rust 库 crate 中自动验证 SemVer 兼容性

19 个版本

0.1.64 2020年6月30日
0.1.63 2020年6月2日
0.1.62 2020年5月29日
0.1.57 2020年4月29日
0.1.52 2020年3月28日

#312Cargo 插件

每月 42 次下载

自定义许可

225KB
4.5K SLoC

rust-semverver

Travis Build Status AppVeyor Build status

rust-semverver 是一个用于检查 Rust 库 crate 中 semver 兼容性的工具。该工具的核心是在 2017 年 Google Summer of Code 期间作为学生项目开发的。

有关 2017 年 GSoC 期间完成的工作的详细信息,请参阅 此处

背景

采用的方法是编译 crate 的两个版本为 rlib,并将它们作为第三个空 dummy crate 的依赖项进行链接。然后,在该 dummy 上运行自定义的编译器驱动程序,并在该环境中执行所有必要的分析,其中提供了类型信息和其它资源。

有关工具内部工作原理的更多信息,请参阅 此处

安装

该工具实现为一个 cargo 插件。目前,可以从这个 git 仓库获取它,从源代码编译或从 crates.io 安装。请注意,任何给定时间只支持最新的 nightly 工具链版本。

如果您已经使用 Rust nightly 并且已成功安装了如 cargo addcargo clippy 这样的工具,只需

$ rustup update nightly
$ rustup component add rustc-dev --toolchain nightly
$ cargo +nightly install semverver

您还需要 cmake 来处理一些依赖项,以及一些常见的库(如果您因为缺少系统级依赖项而遇到构建错误,请打开一个问题,以便可以将它们添加到这里)。

您也可以从 git 安装工具的最新版本

$ rustup update nightly
$ rustup component add rustc-dev --toolchain nightly
$ cargo +nightly install --git https://github.com/rust-dev-tools/rust-semverver
手动安装和更多详细信息
# using rustup is recommended
$ rustup update nightly
$ rustup default nightly

$ git clone https://github.com/rust-dev-tools/rust-semverver
$ cd rust-semverver
$ cargo install

在此阶段,您可以在任何包含您项目的目录中使用 cargo semver 调用当前的开发版本。如果您不想将其安装到 ~/.cargo/bin,您可以在使用常规 cargo build 构建后按照如下方式调用它。

$ PATH=/path/to/repo/target/debug:$PATH cargo semver <args>

如果您使用 cargo build --release 进行构建,请将路径更改为指向 target 目录下的 release 子目录。

用法

默认情况下,在包含 Cargo 项目的目录中运行 cargo semver 将尝试比较本地版本与在 crates.io 上最后发布的版本,并对找到的所有更改显示警告或错误。

使用 cargo semver -h 获取最新的帮助信息,其中概述了如何使用 cargo 插件。

$ cargo semver -h
usage: cargo semver [options]

Options:
    -h, --help          print this message and exit
    -V, --version       print version information and exit
    -e, --explain       print detailed error explanations
    -q, --quiet         surpress regular cargo output, print only important
                        messages
        --show-public   print the public types in the current crate given by
                        -c or -C and exit
    -d, --debug         print command to debug and exit
    -a, --api-guidelines
                        report only changes that are breaking according to the
                        API-guidelines
        --features FEATURES
                        Space-separated list of features to activate
        --all-features  Activate all available features
        --no-default-features
                        Do not activate the `default` feature
        --compact       Only output the suggested version on stdout for
                        further processing
    -j, --json          Output a JSON-formatted description of all collected
                        data on stdout.
    -s, --stable-path PATH
                        use local path as stable/old crate
    -c, --current-path PATH
                        use local path as current/new crate
    -S, --stable-pkg NAME:VERSION
                        use a `name:version` string as stable/old crate
    -C, --current-pkg NAME:VERSION
                        use a `name:version` string as current/new crate
        --target <TRIPLE>
                        Build for the target triple

这意味着您可以将任何两个 crate 的指定版本进行比较,只要它们在 crates.io 上可用或在您的文件系统中存在。

CI 设置

假设您使用的是提供 cargo 访问权限的 CI 提供商,您可以使用以下片段来检查您的构建是否符合 semver 兼容性,并确保版本升级按您在 crates.io 上的 crate 当前版本正确执行。

# install a current version of rust-semverver
cargo install semverver
# fetch the version in the manifest of your crate (adapt this to your usecase if needed)
eval "current_version=$(grep -e '^version = .*$' Cargo.toml | cut -d ' ' -f 3)"
# run the semver checks and output them for convenience
cargo semver | tee semver_out
# fail the build if necessary
(head -n 1 semver_out | grep "\-> $current_version") || (echo "versioning mismatch" && return 1)

请确保您使用的是夜间构建工具链进行上述操作。有关如何执行此操作的说明,请参阅您的 CI 提供商的文档。

JSON 输出

通过传递 -j 标志,所有标准输出的输出都将格式化为机器可读的 JSON 块。这对于与其他工具的集成很有用,并且始终生成所有可能的输出(忽略其他输出相关标志)。输出格式定义如下

顶层对象包含 old_versionnew_versionchanges 键。前两个包含格式为 major.minor.patch 的版本号,后者是一个对象,描述了 crate 版本之间的更改,包含键 path_changeschanges 中的两个数组。

path_changes 数组包含描述项目添加和删除的对象,具有以下键

  • name:项目的名称。
  • def_span:一个对象,描述项目在某个 crate 中的位置。
  • additions:一个描述项目添加位置的 span 数组。
  • removals:一个描述项目删除位置的 span 数组。

一个示例对象可能如下所示

{
  "name": "NFT_META_CGROUP",
  "def_span": {
    "file": "/path/to/libc-0.2.48/src/unix/notbsd/linux/other/mod.rs",
    "line_lo": 776,
    "line_hi": 776,
    "col_lo": 0,
    "col_hi": 40
  },
  "additions": [
    {
      "file": "/path/to/libc-0.2.48/src/lib.rs",
      "line_lo": 195,
      "line_hi": 195,
      "col_lo": 16,
      "col_hi": 23
    }
  ],
  "removals": []
}

changes 数组包含描述所有其他更改的对象,具有以下键

  • name:项目的名称。
  • max_category:此项目的最严重更改类别,作为字符串。
    • 可能的值有 PatchNonBreakingTechnicallyBreakingBreaking
  • new_span:一个描述新 crate 中项目位置的对象(见示例)。
  • changes:包含错误信息和可选子跨度(如果没有,则为null)的2元素序列数组

一个示例对象可能如下所示

{
  "name": "<new::util::enumerate::Enumerate<T> as new::prelude::Stream>",
  "max_category": "TechnicallyBreaking",
  "new_span": {
    "file": "/path/to/tokio-0.1.17/src/util/enumerate.rs",
    "line_lo": 46,
    "line_hi": 63,
    "col_lo": 0,
    "col_hi": 1
  },
  "changes": [
    [
      "trait impl generalized or newly added",
      null
    ]
  ]
}

为了参考,所有描述跨度的对象都有相同的键

  • file:文件名。
  • line_lo:跨度开始的行。
  • line_hi:跨度结束的行。
  • col_lo:跨度开始的列。
  • col_hi:跨度结束的列。

功能

实现semver兼容性所使用的指南是API演变RFC,该指南将语义版本化的原则应用于Rust语言的语义。根据RFC,大多数更改已经正确识别,尽管在某些边缘情况下某些类型检查仍然表现不正确。长期目标是修复编译器中的这个问题。

撰写本文时,以下类型的更改已识别并正确分类

  • 项目从pub移动到非pub,反之亦然
  • 项目更改其类型,例如从struct更改为enum
  • 向项目声明添加或从项目声明中删除区域参数
  • 向项目声明添加或从项目声明中删除(可能是默认的)类型参数
  • 类型和区域参数的变体更改
  • 添加和删除枚举变体
  • 添加和删除枚举变体或结构体字段
  • 从元组结构体或变体更改为结构体变体,反之亦然
  • 函数或方法的const属性更改
  • 向方法添加或删除self参数
  • 添加或删除(可能已默认)特性项目
  • 正确处理“密封”特性
  • 特性的不安全性更改
  • 所有顶级项目的类型更改,以及固有实现和特性定义中的关联项目
  • 添加或删除固有实现或其中的方法
  • 添加或删除特性实现

然而,请注意,向用户呈现的结果仅是所需版本化策略的近似。

贡献

请参阅CONTRIBUTING.md

许可证

rust-semverver根据3条款BSD许可证分发。

有关详细信息,请参阅LICENSE。

依赖关系

~35–47MB
~1M SLoC