Rust 实践教程-开发工具及简单配置(002)

生产环境中会用到的工具及简单配置

上一篇简单说明了 rust 的基本安装 , 这一篇是常用开发工具的简单配置及自动化方案的分享

依赖检查

Cargo Deny 是 Rust 的一个工具,旨在帮助开发者管理和控制项目依赖项,特别是帮助防止引入不安全的、过时的或不符合项目要求的 crate。它通过检查 Cargo.tomlCargo.lock 文件中的依赖关系,并与设定的规则进行对比,从而提高项目的安全性和合规性。

安装

首先,确保你已经安装了 Rust(可以参考专栏中之前的教程)。然后,你可以通过 cargo 来安装 cargo deny

shell 复制代码
$ cargo install cargo-deny

此命令会安装 cargo deny 工具,并将其添加到你的 PATH 中。安装完成后,你可以通过以下命令验证安装是否成功:

shell 复制代码
$ cargo deny --version

配置文件

在成功安装了 deny 之后可以通过 init 初始化配置文件

shell 复制代码
$ cargo deny init

上面的指令会在项目目录下创建一个 deny.toml 文件 , 里面包含缺省配置 , 通常来讲我们只需要修改 allow 字段的内容就可以了 , 打开deny.toml 文件并找到 allow 字段 , 按需修改其中的内容 , 例如:

toml 复制代码
[licenses]
allow = [
  "MIT",
  "Apache-2.0",
  "Unicode-DFS-2016",
  "MPL-2.0",
  "BSD-2-Clause",
  "BSD-3-Clause",
  "ISC",
  "CC0-1.0",
  "Unicode-3.0"
]

现在就可以使用 cargo deny 进行检查了

shell 复制代码
$ cargo deny check

当 allow 中的许可没有没遇到的时候会出现类似下面这样的 wraning

shell 复制代码
warning[license-not-encountered]: license was not encountered
   ┌─ /Users/wuzexian/codes/rust_project/rust_demo/deny.toml:95:4
   │
95 │   "Unicode-DFS-2016",
   │    ━━━━━━━━━━━━━━━━ unmatched license allowance

可以通过 unused-allowed-license 设置未使用的 license 不再 "wran" 而是 "allow"

toml 复制代码
[licenses]
unused-allowed-license = "allow" # defult wran
allow = [..]

拼写检查

安装

首先,确保你已经安装了 Rust 环境。如果尚未安装 Rust,请访问 Rust 官网 进行安装。

然后,使用以下命令通过 cargo 安装 cargo typos 工具:

bash 复制代码
$ cargo install typos-cli

安装完成后,您可以通过以下命令验证是否成功安装:

bash 复制代码
$ typos --version

如果安装成功,命令会输出 cargo-typos 的版本号。


使用

一旦安装完成,你就可以使用 cargo typos 来检查项目中的拼写错误了。在项目根目录下运行以下命令:

bash 复制代码
$ typos

这会扫描项目中的源代码(包括 .rs 文件),并报告任何拼写错误。输出内容会列出拼写错误的单词和位置,例如:

go 复制代码
error: possible typo in documentation: "recieve" should be "receive"
   --> src/lib.rs:10:5
    |
10  |     // This function will recieve the value
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: `cargo typos` suggests replacing with "receive"

在此输出中,cargo typos 会列出错误的单词(如 "recieve"),并且还会给出一个建议的更正(如 "receive")。

忽略

有的时候我们代码中会有 "故意错误" 的单词 , 或者不想进行拼写检查的文件 , 可以同意typos.toml进行配置

toml 复制代码
[default.extend-words]
teh = "teh" # 不纠正 teh

[files]
# 不纠正某些文件
extend-exclude = ["README.md", "LICENSECHANGELOG.md", "notebooks/*"]

NEXTEST

nextest 是 rust 下一代的 "test runner" , 界面干净简介 , 最重要的是比 cargo test 快 3 倍

安装

首先,确保你已经安装了 Rust 环境。如果尚未安装 Rust,请访问 Rust 官网 进行安装。

然后,使用以下命令通过 cargo 安装 nextest

shell 复制代码
$ cargo install cargo-nextest

在需要测试的时候使用 nextest 代替 test即可

shell 复制代码
$ cargo nextest run

日志文件生成

git-cliff 可以通过使用传统的提交以及regex驱动的自定义解析器从Git历史记录中生成更新日志文件。用于自动生成 CHANGELOG 文件

安装

首先,确保你已经安装了 Rust 环境。如果尚未安装 Rust,请访问 Rust 官网 进行安装。

然后,使用以下命令通过 cargo 安装 git-cliff

shell 复制代码
$ cargo install git-cliff

配置

git-ciff 的配置需要在根目录下有 cliff.toml 文件 , rust 项目中可以通过 metadata tablecargo.toml 中直接配置

toml 复制代码
[package]
name = "..."

[dependencies]
# ...

# 配置 git-cliff 的 Changelog 生成器
[package.metadata.git-cliff.changelog]
# 定义 Changelog 文件的头部内容
header = """
# 更新日志\n
所有显著的变化将记录在此文件中。请参阅 [常规提交](https://www.conventionalcommits.org/) 规范以了解提交指南。\n
"""
# 定义 Changelog 正文的模板,使用 Tera 模板语言
body = """
---
{% if version %}\
    {% if previous.version %}\
        ## [{{ version | trim_start_matches(pat="v") }}]($REPO/compare/{{ previous.version }}..{{ version }}) - {{ timestamp | date(format="%Y-%m-%d") }}
    {% else %}\
        ## [{{ version | trim_start_matches(pat="v") }}] - {{ timestamp | date(format="%Y-%m-%d") }}
    {% endif %}\
{% else %}\
    ## [未发布]
{% endif %}\
{% for group, commits in commits | group_by(attribute="group") %}
    ### {{ group | striptags | trim | upper_first }}
    {% for commit in commits
    | filter(attribute="scope")
    | sort(attribute="scope") %}
        - **({{commit.scope}})**{% if commit.breaking %} [**破坏性更改**]{% endif %} \
            {{ commit.message|trim }} - ([{{ commit.id | truncate(length=7, end="") }}]($REPO/commit/{{ commit.id }})) - {{ commit.author.name }}
    {%- endfor -%}
    {% raw %}\n{% endraw %}\
    {%- for commit in commits %}
        {%- if commit.scope -%}
        {% else -%}
            - {% if commit.breaking %} [**破坏性更改**]{% endif %}\
                {{ commit.message|trim }} - ([{{ commit.id | truncate(length=7, end="") }}]($REPO/commit/{{ commit.id }})) - {{ commit.author.name }}
        {% endif -%}
    {% endfor -%}
{% endfor %}\n
"""
# 定义 Changelog 文件的尾部内容
footer = """
<!-- 由 git-cliff 生成 -->
"""
# 移除模板字符串首尾的空白字符
trim = true
# 定义 postprocessors,用于替换模板中的变量或模式
postprocessors = [
    # 替换 $REPO 为实际的仓库地址
    { pattern = '\$REPO', replace = "" }, # 替换仓库 URL
]

[package.metadata.git-cliff.git]
# 是否解析遵循 conventional commits 规范的提交
conventional_commits = true
# 是否过滤掉非 conventional commits 规范的提交
filter_unconventional = false
# 是否将每个提交的每个正文行作为单独的提交处理
split_commits = false
# 提交消息的预处理正则表达式列表
commit_preprocessors = [
    # 替换 Issue 编号为链接形式
    # { pattern = '\((\w+\s)?#([0-9]+)\)', replace = "([#${2}](https://github.com/orhun/git-cliff/issues/${2}))" },
]
# 解析和分组提交的正则表达式列表
commit_parsers = [
    # 跳过
    { message = "\\[skip", skip = true },
    # 包含任何中文跳过
    # { message = "\\p{Han}", skip = true },
    # feat 开头放入特性分类
    { message = "^feat", group = "feat" },
    # fix 开头放入 bug 修复分类
    { message = "^fix", group = "fix bug" },
    # doc 开头放入文档分类
    { message = "^doc", group = "document" },
    # perf 开头放入性能分类
    { message = "^perf", group = "perf" },
    # refactor 放入重构分类
    { message = "^refactor", group = "refactor" },
    # style 开头放入样式分类
    { message = "^style", group = "style" },
    # revert 放入还原复原分类
    { message = "^revert", group = "revert" },
    # test 放入测试分类
    { message = "^test", group = "tests" },
    # 以 chore: 开头,跳过这条提交
    { message = "^chore:", skip = true },
    # 包含 security 安全修复
    { body = ".*security", group = "security" },
    # 不匹配的其他内容归入 Other 
    { message = ".*", group = "others" },
]
# 是否保护破坏性更改不被跳过
protect_breaking_commits = false
# 是否过滤掉不符合 commit parsers 的提交
filter_commits = false
# 匹配 git 标签的正则表达式
tag_pattern = "v[0-9].*"
# 跳过匹配的标签
skip_tags = "v0.1.0-beta.1"
# 忽略匹配的标签
ignore_tags = ""
# 是否按照拓扑排序排序标签
topo_order = false
# 小节内提交的排序方式,"oldest" 或 "newest"
sort_commits = "oldest"
# 限制在 Changelog 中包含的提交数量
# limit_commits = 42

此时使用 git cliff -o CHANGELOG.md 即可自动根据git 的提交历史生成CHANGELOG.md 文件 ,例如进行了两次提交 , 第一次commit 的是"first commit: init" ,第二次是"fix : fix unused warning" , 并打了个0.1.1的 tag , 最终生成如下:

markdown 复制代码
# 更新日志 Change log

所有显著的变化将记录在此文件中。请参阅 [常规提交](https://www.conventionalcommits.org/) 规范以了解提交指南。

All notable changes to this project will be documented in this file. See [conventional commits](https://www.conventionalcommits.org/) for commit guidelines.

---
## [0.1.1] - 2025-01-03

### Fix bug

- fix : fix unused warning - ([9560718](https://github.com/WITstudio86//commit/956071822239ee41896a95199bce8187f99a5995)) - WITstudio

### others

- first commit: init - ([7c97ec1](https://github.com/WITstudio86//commit/7c97ec1228e0ce282a9bbc3c5547070272a67c36)) - WITstudio

<!-- 由 git-cliff 生成 -->

自动化

自动化执行流程,在每次 Git 提交之前执行 cargo fmtcargo denynextesttyposgit-cliff,可以使用 Git 钩子来实现。Git 钩子(git hooks)是 Git 提供的一种机制,可以在特定的 Git 操作(如提交、推送、合并等)之前或之后执行自定义脚本。

使用pre-commit

我们可以使用 pre-commit 钩子来在每次提交之前自动执行这些任务。如果它们都通过了,提交才会继续进行。以下是如何配置和实现这一流程:

安装

先通过pip 安装 pre-commit , 这需要电脑中存在 pip 工具 , 需要安装 python

shell 复制代码
$ pip install pre-commit

和之前其他工具一样 ,安装之后可以通过--version 检查安装是否成功

配置

.pre-commit-config.yaml 文件中,配置你要执行的所有工具。

toml 复制代码
# 如果检测到任何钩子失败,pre-commit 将不会继续执行剩余的钩子。
fail_fast: false

# repos 是一个钩子仓库的列表,每个仓库可以包含多个钩子。
repos:
  # 每个仓库通过 URL 指定,并且可以指定特定的版本(rev)。
  - repo: https://github.com/pre-commit/pre-commit-hooks 
    rev: v4.3.0
    hooks:
      # 这是从上述仓库中定义的钩子列表。
      - id: check-byte-order-marker   # 检查文件是否包含字节顺序标记(BOM)。
      - id: check-case-conflict       # 检查文件名在不同操作系统的大小写冲突。
      - id: check-merge-conflict     # 检查文件中是否有合并冲突。
      - id: check-symlinks           # 检查文件是否是符号链接。
      - id: check-yaml                # 检查 YAML 文件的格式。
      - id: end-of-file-fixer         # 确保文件以单个换行符结束。
      - id: mixed-line-ending        # 检查文件的行结束符是否一致。
      - id: trailing-whitespace      # 检查并修复行尾的空格。

  # local 部分定义了本地钩子。
  - repo: local
    hooks:
      # 每个钩子有以下属性:
      # id: 钩子的唯一标识符。
      # name: 钩子的名称。
      # description: 钩子的描述。
      # entry: 要执行的命令。
      # language: 钩子运行的语言环境。
      # files: 钩子应该运行的文件模式。
      # args: 传递给钩子的参数列表。
      # pass_filenames: 如果设置为 false,pre-commit 将不会传递文件名给钩子脚本。
      - id: cargo-fmt
        name: cargo fmt
        description: Format files with rustfmt.
        entry: bash -c 'cargo fmt -- --check'
        language: rust
        files: \.rs$  # 钩子仅对 Rust 源文件生效。
        args: []  # 不传递额外的参数。
	  - .......
	  - ......

cargo make

pre-commit 本身是按照顺序执行某些特定的指令 , fail_fast 配置在出错的时候是否继续执行 , cargo make 可以实现定义多个子指令 , 并将他们组合,配置依赖 , 轻松的组合成为很多不同的自动化脚本

安装

首先,确保你已经安装了 Rust 环境。如果尚未安装 Rust,请访问 Rust 官网 进行安装。

然后,使用以下命令通过 cargo 安装 cargo make

shell 复制代码
$ cargo install --force cargo-make
使用

我们需要使用一个Makefile.toml 文件对cargo make 进行配置 , 配置很简单,

  • [tasks.<name>] 配置不同任务的别名
  • command 设置要执行的指令
  • args 设置传递的参数
  • dependencies 用于设置依赖 , 说明当前任务需要依赖于哪个任务的成功
  • install_crate 可以帮助下载需要的 crate

下面是一个实例:

toml 复制代码
[tasks.format]
install_crate="rustfmt"
command = "cargo"
args = ["fmt", "--", "--emit=files"]

[tasks.clean]
command = "cargo"
args = ["clean"]

[tasks.build]
command = "cargo"
args = ["build"]
dependencies = ["clean"]

[tasks.test]
command = "cargo"
args = ["test"]
dependencies = ["clean"]

[tasks.my-flow]# 下面指令执行时的my-flow是在这里定义的别名
dependencies = [
    "format",
    "build",
    "test"
]

在使用的时候只需要执行下面的指令即可:

shell 复制代码
$ cargo make my-flow

下面是对于本篇所说到的所有工具的自动化执行配置:

toml 复制代码
[tasks.format]
command = "cargo"
args = ["fmt", "--", "--emit=files"]

[tasks.deny]
install_crate="cargo-deny"
command = "cargo"
args = ["deny" , "check"]

[tasks.typos]
install_crate="typos-cli"
command = "typos"
dependencies = ["deny"]

[tasks.check]
command = "cargo"
args = ["check" , "--all"]
dependencies = ["typos"]

[tasks.clippy]# 一种代码风格检查工具
command = "cargo"
args = ["clippy" , "--all-features" , "--tests" , "--benches" , "--", "-D" , "warnings"]
dependencies = ["check"]

[tasks.test]
install_crate="cargo-nextest"
command = "cargo"
args = ["nextest" , "run"]
dependencies = ["clippy"]

[tasks.commit]
command = "git"
args = ["commit" , "-a"]
dependencies = ["test"]

[tasks.cliff]
install_crate="git-cliff"
command = "git"
args = ["cliff" , "-o" , "CHANGELOG.md"]
dependencies = ["commit"]


[tasks.doit]
dependencies = [
    "format",
    "deny",
    "typos",
    "check",
    "clippy",
    "test",
    "commit",
    "cliff"
]

从模板新建

经过刚才的配置 , 现在的项目目录看起来应该像是下面这样:

css 复制代码
.
├── CHANGELOG.md
├── Cargo.toml
├── Makefile.toml
├── deny.toml
├── README.md
├── src
│   └── main.rs
└── typos.toml

generate 让我们可以将这个项目目录作为模本使用 , 首先将这个项目 push到 github , 然后下载 generate 并通过它创建一个新的项目

shell 复制代码
$ cargo install cargo-generate
$ cargo generate --git 模板的github地址

视频版: 小破站

相关推荐
世事如云有卷舒4 小时前
《Rust权威指南》学习笔记(二)
笔记·学习·rust
SomeB1oody4 小时前
【Rust自学】10.6. 生命周期 Pt.2:生命周期的语法与例子
开发语言·后端·rust
记得多喝水o4 小时前
Rust编程语言
rust·信息与通信
世事如云有卷舒10 小时前
《Rust权威指南》学习笔记(三)
笔记·学习·rust
世事如云有卷舒10 小时前
《Rust权威指南》学习笔记(四)
笔记·学习·rust
AH_HH19 小时前
node-sass安装报错,换成sass
前端·rust·sass·node-sass
懒人Ethan20 小时前
SASS 简化代码开发的基本方法
前端·rust·sass
从善若水1 天前
【Rust 学习笔记】Rust 基础数据类型介绍——指针、元组和布尔类型
笔记·学习·rust
Grovvy_Deng1 天前
使用rust加速python的tgz解压
开发语言·python·rust
bluebonnet272 天前
【Rust练习】26.Package and Crate
开发语言·后端·rust