Skip to content

ci(rust): add cargo fmt formatting check to CI pipelines #234

@WilliamBerryiii

Description

@WilliamBerryiii

Summary

The repository has no cargo fmt enforcement in CI and no .rustfmt.toml configuration. PR #231 (issue #169) added clippy lint CI but formatting checks were out of scope. This issue adds cargo fmt --check to both GitHub Actions and Azure DevOps pipelines, mirroring the clippy CI structure established in PR #231.

Background

Current State:

  • No .rustfmt.toml or rustfmt.toml anywhere in the repository
  • No cargo fmt references in any CI pipeline
  • Formatting is entirely developer-discretion with no automated enforcement

Existing CI Structure (established by PR #231):

Pipeline Clippy Workflow Called From
GitHub Actions .github/workflows/rust-clippy.yml (reusable) pr-validation.yml (break_build: true), main.yml (break_build: false)
Azure DevOps .azdo/templates/rust-clippy-template.yml azure-pipelines.yml (Main/Scheduled + PR stages)

Both use the same crate discovery pattern: find src/ -name "Cargo.toml" -not -path "./Cargo.toml", detect WASM cdylib crates for --target wasm32-wasip2, and iterate over all 14 crates.

The cargo fmt check should follow this identical structure — parallel reusable workflows/templates alongside the clippy ones.

Acceptance Criteria

  • .rustfmt.toml created at repository root with project formatting conventions
  • GitHub Actions reusable workflow .github/workflows/rust-fmt.yml created
    • workflow_call with break_build boolean input (matching clippy pattern)
    • Iterates all 14 crates via find src/ -name "Cargo.toml"
    • Runs cargo fmt --check in each crate directory
    • WASM crates use standard cargo fmt --check (rustfmt is target-independent)
  • Azure DevOps template .azdo/templates/rust-fmt-template.yml created
    • Same crate discovery and iteration pattern
    • Runs cargo fmt --check in each crate
  • pr-validation.yml calls rust-fmt.yml with break_build: true
  • main.yml calls rust-fmt.yml with break_build: false
  • azure-pipelines.yml calls rust-fmt-template.yml in both Main/Scheduled and PR stages
  • All 14 crates pass cargo fmt --check

Implementation Guidance

.rustfmt.toml (Suggested Starting Point)

edition = "2021"

Keep minimal — Rust's default formatting is well-accepted. Add overrides only if the team has specific conventions. Common options to consider:

  • max_width = 100 (default is 100)
  • use_small_heuristics = "Default" (default)
  • imports_granularity = "Crate" (groups imports by crate — requires nightly or recent stable)

GitHub Workflow: .github/workflows/rust-fmt.yml

Mirror .github/workflows/rust-clippy.yml structure:

name: Rust Format Check
on:
  workflow_call:
    inputs:
      break_build:
        required: true
        type: boolean

Key difference from clippy: cargo fmt --check does NOT need --target wasm32-wasip2 — rustfmt operates on source text regardless of compilation target. This simplifies the WASM handling.

Caller Integration Points

pr-validation.yml — add alongside existing clippy call:

rust-fmt:
  needs: [mega-linter]
  uses: ./.github/workflows/rust-fmt.yml
  with:
    break_build: true

main.yml — add alongside existing clippy call:

rust-fmt:
  needs: [mega-linter-main]
  uses: ./.github/workflows/rust-fmt.yml
  with:
    break_build: false

azure-pipelines.yml — add template calls in both stages alongside clippy template calls.

Formatting Fix Command

Before this CI gate is added, run formatting across all crates:

for cargo_toml in $(find src/ -name "Cargo.toml" -not -path "./Cargo.toml"); do
  (cd "$(dirname "$cargo_toml")" && cargo fmt)
done

Related: #169, PR #231 (established the CI pattern), #232 (fix clippy violations)

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestrustPull requests that update rust code

    Type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions