Files
huangxt a4ca734d0d 重构:RustCrypto 兼容接口
主要变更:
- 新增 sm2/、sm3/、sm4/ 独立 crate,实现 RustCrypto traits
  - sm2:实现 signature、elliptic-curve traits
  - sm3:实现 digest、crypto-common traits
  - sm4:实现 cipher、aead traits
- 新增 fuzz/ 模糊测试目标
- 新增 tests/sm2_proptest.rs 属性测试
- 重构 src/sm4/ 使用 RustCrypto AEAD traits
- 更新 CI 工作流支持多 crate 测试
- 更新 .gitignore 忽略 fuzz/target/
2026-03-11 18:32:21 +08:00

375 lines
13 KiB
YAML
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# =============================================================================
# libsmx CI/CD 工作流
# =============================================================================
# 触发条件:
# - main 分支的 push / PR → lint + test + coverage
# - v* tag 推送 → 上述全部 + 自动发布
# - PR → 额外运行 benchmark 并评论结果
# =============================================================================
name: CI
on:
push:
branches: [main]
tags: ["v*"]
pull_request:
branches: [main]
# 同一 PR 的新提交自动取消旧的运行,节省 CI 资源
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
env:
CARGO_TERM_COLOR: always
# 强制使用 sparse 协议,加速 crates.io 索引同步
CARGO_REGISTRIES_CRATES_IO_PROTOCOL: sparse
# =============================================================================
# Job 1: 代码质量检查(格式化 + Clippy + 依赖漏洞扫描)
# =============================================================================
jobs:
lint:
name: Lint & Audit
runs-on: ubuntu-latest
steps:
- name: 签出代码
uses: actions/checkout@v4
- name: 安装 Rust 工具链(stable + rustfmt + clippy
uses: dtolnay/rust-toolchain@stable
with:
components: rustfmt, clippy
- name: 缓存 Cargo 编译产物
uses: Swatinem/rust-cache@v2
- name: 检查代码格式
run: cargo fmt --check
- name: Clippy 检查(默认 features,所有警告视为错误)
run: cargo clippy --all-targets -- -D warnings
- name: Clippy 检查(no_std,无 alloc
# Reason: alloc-gated 函数在 no_std 模式下会产生 "unused" 假阳性,
# 因此只做编译检查,不启用 -D warnings
run: cargo check --no-default-features
- name: 安装 cargo-audit
run: cargo install cargo-audit --locked
- name: 依赖漏洞扫描(CVE 检查)
run: cargo audit
- name: 安全性扫描(panic/unwrap 检查)
run: bash .github/scripts/sanity_check.sh
shell: bash
# =============================================================================
# Job 2: 多平台测试矩阵
# =============================================================================
test-matrix:
name: Test (${{ matrix.os }})
needs: lint
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
runs-on: ${{ matrix.os }}
steps:
- name: 签出代码
uses: actions/checkout@v4
- name: 安装 Rust 工具链(stable
uses: dtolnay/rust-toolchain@stable
- name: 缓存 Cargo 编译产物
uses: Swatinem/rust-cache@v2
# Reason: 在所有平台上显式设置 bash 以统一 Windows/Linux/macOS 行为
- name: 运行测试(默认 features,全 workspace
run: cargo test --workspace --all-targets
shell: bash
- name: 运行测试(no_std,无 alloc
# Reason: 验证嵌入式 / WASM / 裸机兼容性
run: cargo test --workspace --no-default-features --lib
shell: bash
- name: 运行文档测试
run: cargo test --doc
shell: bash
- name: 构建文档(警告视为错误)
run: cargo doc --no-deps
env:
RUSTDOCFLAGS: "-D warnings"
shell: bash
# =============================================================================
# Job 3: MSRV 验证(最低支持版本)
# =============================================================================
msrv:
name: MSRV (1.83.0)
needs: lint
runs-on: ubuntu-latest
steps:
- name: 签出代码
uses: actions/checkout@v4
- name: 安装 MSRV 工具链
uses: dtolnay/rust-toolchain@master
with:
toolchain: "1.83.0"
- name: 缓存 Cargo 编译产物
uses: Swatinem/rust-cache@v2
# Reason: MSRV 只验证能编译,不运行测试(避免 dev-dependencies 兼容问题)
- name: 检查编译(默认 features
run: cargo check --workspace
- name: 检查编译(no_std
run: cargo check --workspace --no-default-features
# =============================================================================
# Job 4: no_std 跨目标编译验证
# =============================================================================
no-std:
name: no_std (${{ matrix.target }})
needs: lint
runs-on: ubuntu-latest
strategy:
matrix:
target:
- thumbv7em-none-eabi # ARM Cortex-M4,典型嵌入式目标
- wasm32-unknown-unknown # WebAssembly
steps:
- name: 签出代码
uses: actions/checkout@v4
- name: 安装 Rust 工具链(stable + 目标平台)
uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.target }}
- name: 缓存 Cargo 编译产物
uses: Swatinem/rust-cache@v2
# Reason: --no-default-features 禁用 alloc,验证裸机 no_std 兼容性
- name: 检查 sm3no_std,无 alloc
run: cargo check -p sm3 --target ${{ matrix.target }} --no-default-features
- name: 检查 sm4no_std,无 alloc
run: cargo check -p sm4 --target ${{ matrix.target }} --no-default-features
- name: 检查 sm2no_std,无 alloc
run: cargo check -p sm2 --target ${{ matrix.target }} --no-default-features
# =============================================================================
# Job 5: Feature Powerset(验证所有 feature 组合均可编译)
# =============================================================================
feature-powerset:
name: Feature Powerset
needs: lint
runs-on: ubuntu-latest
steps:
- name: 签出代码
uses: actions/checkout@v4
- name: 安装 Rust 工具链(stable
uses: dtolnay/rust-toolchain@stable
- name: 缓存 Cargo 编译产物
uses: Swatinem/rust-cache@v2
- name: 安装 cargo-hack
uses: taiki-e/install-action@cargo-hack
# Reason: 验证所有 feature 组合均能编译,防止 feature 互斥或遗漏依赖
- name: 检查 sm3 feature powerset
run: cargo hack check -p sm3 --feature-powerset --no-dev-deps
- name: 检查 sm4 feature powerset
run: cargo hack check -p sm4 --feature-powerset --no-dev-deps
- name: 检查 sm2 feature powerset
run: cargo hack check -p sm2 --feature-powerset --no-dev-deps
# =============================================================================
# Job 6: Miri 内存安全验证
# =============================================================================
miri:
name: Miri
needs: lint
runs-on: ubuntu-latest
steps:
- name: 签出代码
uses: actions/checkout@v4
- name: 安装 Rust nightly + Miri 组件
uses: dtolnay/rust-toolchain@nightly
with:
components: miri
- name: 缓存 Cargo 编译产物
uses: Swatinem/rust-cache@v2
# Reason: 只对纯算法 cratesm3/sm4/sm2)运行 Miri
# 避免对系统调用密集的代码产生误报。
# -Zmiri-strict-provenance 开启严格指针来源检查。
- name: Miri 检查 sm3
run: cargo miri test -p sm3
env:
MIRIFLAGS: "-Zmiri-strict-provenance"
- name: Miri 检查 sm4
run: cargo miri test -p sm4
env:
MIRIFLAGS: "-Zmiri-strict-provenance"
- name: Miri 检查 sm2(仅单元测试,跳过 alloc 密集测试)
run: cargo miri test -p sm2 --lib
env:
MIRIFLAGS: "-Zmiri-strict-provenance"
# =============================================================================
# Job 7: 测试覆盖率(仅 Linux,上传 Codecov
# =============================================================================
coverage:
name: Coverage
needs: lint
runs-on: ubuntu-latest
steps:
- name: 签出代码
uses: actions/checkout@v4
- name: 安装 Rust 工具链(stable
uses: dtolnay/rust-toolchain@stable
- name: 缓存 Cargo 编译产物
uses: Swatinem/rust-cache@v2
- name: 安装 cargo-tarpaulin
run: cargo install cargo-tarpaulin --locked
- name: 生成覆盖率报告
run: cargo tarpaulin --out xml --output-dir coverage/
- name: 上传覆盖率到 Codecov
uses: codecov/codecov-action@v4
with:
files: coverage/cobertura.xml
token: ${{ secrets.CODECOV_TOKEN }}
fail_ci_if_error: false
# Reason: fail_ci_if_error=false 避免 Codecov 暂时不可用时阻断 CI
# =============================================================================
# Job 8: 性能回归检测(仅 PR 触发)
# =============================================================================
benchmark:
name: Benchmark
if: github.event_name == 'pull_request'
needs: lint
runs-on: ubuntu-latest
permissions:
pull-requests: write
steps:
- name: 签出 PR 代码
uses: actions/checkout@v4
- name: 安装 Rust 工具链(stable
uses: dtolnay/rust-toolchain@stable
- name: 缓存 Cargo 编译产物
uses: Swatinem/rust-cache@v2
# Reason: 先运行当前 PR 分支的 benchmark 并保存结果
- name: 运行 Benchmark
run: cargo bench --bench sm3_bench --bench sm4_bench --bench sm2_bench -- --output-format bencher 2>&1 | tee bench_output.txt
shell: bash
# Reason: 将 benchmark 结果作为 PR 评论发布,方便审查性能变化
- name: 发布 Benchmark 结果到 PR
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
const benchOutput = fs.readFileSync('bench_output.txt', 'utf8');
const body = `## Benchmark Results\n\n<details>\n<summary>Click to expand</summary>\n\n\`\`\`\n${benchOutput}\n\`\`\`\n\n</details>\n\n> Benchmarks ran on \`ubuntu-latest\`. Results may vary across runs.`;
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: body
});
# =============================================================================
# Job 6: 自动发布到 crates.io(仅 v* Tag 触发)
# =============================================================================
release:
name: Release
if: startsWith(github.ref, 'refs/tags/v')
needs: [test-matrix, msrv]
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- name: 签出代码
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: 安装 Rust 工具链(stable
uses: dtolnay/rust-toolchain@stable
- name: 缓存 Cargo 编译产物
uses: Swatinem/rust-cache@v2
# Reason: 确保 Git Tag 版本号与 Cargo.toml 中的 version 字段完全一致
- name: 验证 Tag 与 Cargo.toml 版本匹配
run: |
TAG_VERSION="${GITHUB_REF_NAME#v}"
CARGO_VERSION=$(grep '^version' Cargo.toml | head -1 | sed 's/.*"\(.*\)".*/\1/')
if [ "$TAG_VERSION" != "$CARGO_VERSION" ]; then
echo "::error::Tag version ($TAG_VERSION) does not match Cargo.toml version ($CARGO_VERSION)"
exit 1
fi
echo "Version: $TAG_VERSION ✓"
shell: bash
# Reason: 发布前最后一轮完整测试,防止 tag 推送后才发现问题
- name: 发布前完整测试
run: cargo test --all-targets
- name: 发布到 crates.io
run: cargo publish
env:
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
# Reason: 从 CHANGELOG.md 中提取当前版本的发布说明
- name: 提取 Changelog 条目
id: changelog
run: |
TAG_VERSION="${GITHUB_REF_NAME#v}"
# 提取 ## [x.y.z] 到下一个 ## 之间的内容
NOTES=$(awk "/^## \\[${TAG_VERSION}\\]/{found=1; next} /^## \\[/{if(found) exit} found{print}" CHANGELOG.md)
if [ -z "$NOTES" ]; then
NOTES="Release v${TAG_VERSION}"
fi
# 写入多行输出
echo "notes<<EOF" >> $GITHUB_OUTPUT
echo "$NOTES" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
shell: bash
- name: 创建 GitHub Release
uses: softprops/action-gh-release@v2
with:
name: "v${{ github.ref_name }}"
body: ${{ steps.changelog.outputs.notes }}
draft: false
prerelease: ${{ contains(github.ref_name, '-') }}
# Reason: 如果 tag 包含 '-'(如 v0.4.0-rc1),标记为预发布