Skip to content

build(build): add clippy lint configuration and CI integration#231

Open
WilliamBerryiii wants to merge 2 commits intomainfrom
ci/add-rust-clippy-lints
Open

build(build): add clippy lint configuration and CI integration#231
WilliamBerryiii wants to merge 2 commits intomainfrom
ci/add-rust-clippy-lints

Conversation

@WilliamBerryiii
Copy link
Member

@WilliamBerryiii WilliamBerryiii commented Mar 8, 2026

Description

Added per-crate [lints.clippy] configuration to all 13 Rust crates and created dedicated CI pipeline templates for both Azure DevOps and GitHub Actions to enforce clippy lints on pull requests, fulfilling the OSSF Silver warnings_strict criterion.

CI Templates

Two reusable CI templates were created with matching behavior — each iterates all Rust crates under src/, auto-detects WASM crates via cdylib crate-type, and applies --target wasm32-wasip2 for those crates.

  • Created .azdo/templates/rust-clippy-template.yml as an Azure DevOps reusable job template with configurable dependsOn, displayName, condition, and agentPool parameters
    • Handles aio-sdks private registry authentication via CARGO_REGISTRIES_AIO_SDKS_TOKEN environment variable
  • Created .github/workflows/rust-clippy.yml as a GitHub Actions reusable workflow with a break_build parameter controlling fail vs. warn behavior
    • Uses dtolnay/rust-toolchain@stable action and pinned actions/checkout commit hash

Pipeline Integration

Integrated the clippy templates into all CI stages across both platforms.

  • Added rust-clippy job to .github/workflows/pr-validation.yml with break_build: true (blocking on PRs), running after mega-linter
  • Added rust-clippy-main job to .github/workflows/main.yml with break_build: false (warning-only on main), running after mega-linter
  • Integrated rust-clippy-template.yml into both Main and PR stages of azure-pipelines.yml

Cargo.toml Lint Configuration

Applied consistent [lints.clippy] sections to all 13 Rust crate Cargo.toml files with five category-level rules.

  • Configured correctness as deny and suspicious, complexity, style, perf as warn across all crates
  • Added missing_safety_doc = "allow" for the three WASM cdylib crates (custom-provider, map, avro-to-json) where FFI boundaries make safety docs impractical
  • Placed [lints.clippy] sections consistently before [profile.release] or [workspace] following Cargo.toml conventions

Related Issue

Closes #169

Type of Change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Blueprint modification or addition
  • Component modification or addition
  • Documentation update
  • CI/CD pipeline change
  • Other (please describe):

Implementation Details

The approach uses Cargo's native [lints.clippy] table (stabilized in Rust 1.74) rather than workspace-level [workspace.lints] inheritance, since the 13 crates are independent (separate [workspace] declarations, no shared workspace root). Each crate's Cargo.toml declares lint severity per category group with priority = -1 to ensure category-level rules apply before individual lint overrides.

WASM crates targeting wasm32-wasip2 received an additional missing_safety_doc = "allow" because their FFI boundary code uses unsafe blocks where safety documentation is not applicable.

Both CI templates share identical crate-iteration logic: find src/ -name "Cargo.toml", then grep for cdylib crate-type to determine whether --target wasm32-wasip2 is needed. The GitHub Actions variant adds break_build conditional logic for fail vs. warn behavior.

Testing Performed

  • Manual validation
  • Other:

Local Rust toolchain was unavailable in this environment. CI validation will run on first push. YAML structure and Cargo.toml syntax were validated by review.

Validation Steps

  1. Verify the PR triggers the Rust Clippy Lint Check job in GitHub Actions
  2. Confirm all 13 crates pass clippy or report expected warnings
  3. Check that WASM crates (custom-provider, map, avro-to-json) run with --target wasm32-wasip2
  4. Verify the AzDO pipeline shows the clippy template in both Main and PR stages

Checklist

  • I have updated the documentation accordingly
  • I have added tests to cover my changes
  • All new and existing tests passed
  • I have run terraform fmt on all Terraform code
  • I have run terraform validate on all Terraform code
  • I have run az bicep format on all Bicep code
  • I have run az bicep build to validate all Bicep code
  • I have checked for any sensitive data/tokens that should not be committed
  • I have run MegaLinter on my code (mega-linter-runner)

Additional Notes

  • This PR intentionally does not add RUST_CLIPPY to MegaLinter due to incompatibility with the multi-crate, multi-target structure of the repository
  • No .rs source files were modified — this is purely configuration and CI infrastructure
  • The 901-video-tools crate under src/900-tools-utilities/ was included despite being outside the 500-application/ matrix detection scope, ensuring full crate coverage
  • Clippy violations discovered during CI runs should be addressed in follow-up PRs

- add [lints.clippy] to all 13 Rust crate Cargo.toml files
- create AzDO and GitHub Actions reusable clippy CI templates
- integrate clippy into PR and Main pipeline stages
- handle WASM crates with --target wasm32-wasip2

🔧 - Generated by Copilot
@WilliamBerryiii WilliamBerryiii requested a review from a team as a code owner March 8, 2026 21:12
Copilot AI review requested due to automatic review settings March 8, 2026 21:12
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds Rust clippy lint enforcement to all 13 Rust crates in the repository and integrates clippy checks into both GitHub Actions and Azure DevOps CI pipelines. It fulfills the OSSF Silver warnings_strict criterion (issue #169) by configuring per-crate [lints.clippy] sections in each Cargo.toml and creating reusable CI templates that auto-detect WASM vs. native crates.

Changes:

  • Added consistent [lints.clippy] configuration to all 13 Rust crate Cargo.toml files (correctness = deny, suspicious/complexity/style/perf = warn), with missing_safety_doc = "allow" for the three WASM cdylib crates
  • Created reusable CI templates for both GitHub Actions (.github/workflows/rust-clippy.yml) and Azure DevOps (.azdo/templates/rust-clippy-template.yml) that iterate all crates and auto-detect WASM targets
  • Integrated the clippy checks into pr-validation.yml (blocking), main.yml (warning-only), and azure-pipelines.yml (both Main and PR stages)

Reviewed changes

Copilot reviewed 18 out of 18 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
.github/workflows/rust-clippy.yml New reusable GitHub Actions workflow for running clippy across all Rust crates
.github/workflows/pr-validation.yml Adds rust-clippy job (blocking) after mega-linter
.github/workflows/main.yml Adds rust-clippy-main job (warning-only) after mega-linter
.azdo/templates/rust-clippy-template.yml New AzDO reusable job template for clippy with private registry auth
azure-pipelines.yml Integrates clippy template into both Main and PR pipeline stages
src/500-application/501-rust-telemetry/services/sender/Cargo.toml Adds [lints.clippy] section (5 category rules)
src/500-application/501-rust-telemetry/services/receiver/Cargo.toml Adds [lints.clippy] section (5 category rules)
src/500-application/502-rust-http-connector/services/broker/Cargo.toml Adds [lints.clippy] section (5 category rules)
src/500-application/502-rust-http-connector/services/subscriber/Cargo.toml Adds [lints.clippy] section (5 category rules)
src/500-application/503-media-capture-service/services/media-capture-service/Cargo.toml Adds [lints.clippy] section (5 category rules)
src/500-application/504-mqtt-otel-trace-exporter/services/mqtt-otel-trace-exporter/Cargo.toml Adds [lints.clippy] section (5 category rules)
src/500-application/507-ai-inference/services/ai-edge-inference/Cargo.toml Adds [lints.clippy] section (5 category rules)
src/500-application/507-ai-inference/services/ai-edge-inference-crate/Cargo.toml Adds [lints.clippy] section (5 category rules)
src/500-application/507-ai-inference/services/ai-edge-inference-crate/tests/no-features-test/Cargo.toml Adds [lints.clippy] section (5 category rules)
src/500-application/511-rust-embedded-wasm-provider/operators/custom-provider/Cargo.toml Adds [lints.clippy] section with missing_safety_doc = "allow" for WASM crate
src/500-application/511-rust-embedded-wasm-provider/operators/map/Cargo.toml Adds [lints.clippy] section with missing_safety_doc = "allow" for WASM crate
src/500-application/512-avro-to-json/operators/avro-to-json/Cargo.toml Adds [lints.clippy] section with missing_safety_doc = "allow" for WASM crate
src/900-tools-utilities/901-video-tools/cli/video-to-gif/Cargo.toml Adds [lints.clippy] section (5 category rules)

Comment on lines +58 to +61
if [ -n "$(System.PullRequest.SourceBranch)" ]; then
git checkout "$(System.PullRequest.SourceBranch)"
fi
condition: and(succeeded(), ne(variables['System.PullRequest.SourceBranch'], ''))
Copy link

Copilot AI Mar 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PR source branch checkout pattern deviates from the established convention used by all other AzDO templates in this repository. Every other template (e.g., checkov-template.yml:54-63, aio-version-checker-template.yml:83-92, megalinter-template.yml:115, etc.) uses:

condition: eq(variables['Build.Reason'], 'PullRequest')

with the script pattern:

BRANCH_NAME=$(echo "$(System.PullRequest.SourceBranch)" | sed 's|^refs/heads/||')
echo "Switching to PR source branch HEAD: $BRANCH_NAME"
git checkout "$BRANCH_NAME"
git log -1 --oneline

This template should follow the same pattern for consistency: use eq(variables['Build.Reason'], 'PullRequest') as the condition, strip the refs/heads/ prefix from the branch name, and include the informational log messages.

Suggested change
if [ -n "$(System.PullRequest.SourceBranch)" ]; then
git checkout "$(System.PullRequest.SourceBranch)"
fi
condition: and(succeeded(), ne(variables['System.PullRequest.SourceBranch'], ''))
BRANCH_NAME=$(echo "$(System.PullRequest.SourceBranch)" | sed 's|^refs/heads/||')
echo "Switching to PR source branch HEAD: $BRANCH_NAME"
git checkout "$BRANCH_NAME"
git log -1 --oneline
condition: eq(variables['Build.Reason'], 'PullRequest')

Copilot uses AI. Check for mistakes.
targetType: inline
script: |
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain stable -c clippy
echo "##vso[task.prependpath]$HOME/.cargo/bin"
Copy link

Copilot AI Mar 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The ##vso[task.prependpath] command on line 69 only updates PATH for subsequent Azure DevOps tasks, not the currently running script. Since rustup.rs installs to $HOME/.cargo/bin and a Bash@3 task runs in a non-interactive non-login shell (so ~/.bashrc/~/.profile are not sourced), the rustup binary will not be in PATH when line 70 executes.

To fix this, source the cargo environment before calling rustup, for example by adding source "$HOME/.cargo/env" between lines 69 and 70, or by using the full path "$HOME/.cargo/bin/rustup" target add wasm32-wasip2.

Suggested change
echo "##vso[task.prependpath]$HOME/.cargo/bin"
echo "##vso[task.prependpath]$HOME/.cargo/bin"
source "$HOME/.cargo/env"

Copilot uses AI. Check for mistakes.
Comment on lines +53 to +68
- name: Run Clippy on all Rust crates
shell: bash
env:
BREAK_BUILD: ${{ inputs.break_build }}
run: |
set -euo pipefail
FAILED=0
for cargo_toml in $(find src/ -name "Cargo.toml" -not -path "./Cargo.toml"); do
crate_dir=$(dirname "$cargo_toml")
echo "::group::Clippy: $crate_dir"
if grep -q 'crate-type.*=.*\["cdylib"\]' "$cargo_toml"; then
echo "WASM crate detected — using --target wasm32-wasip2"
(cd "$crate_dir" && cargo clippy --target wasm32-wasip2 -- -D warnings) || FAILED=1
else
(cd "$crate_dir" && cargo clippy -- -D warnings) || FAILED=1
fi
Copy link

Copilot AI Mar 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The GitHub Actions workflow doesn't configure CARGO_REGISTRIES_AIO_SDKS_TOKEN for the clippy step, but multiple crates (including custom-provider, map, avro-to-json, broker, subscriber, sender, receiver, media-capture-service, mqtt-otel-trace-exporter, and ai-edge-inference) depend on the aio-sdks private registry. The AzDO template correctly sets this via env: CARGO_REGISTRIES_AIO_SDKS_TOKEN (line 95 of rust-clippy-template.yml), but the GitHub Actions workflow is missing this configuration.

Without this token, cargo clippy will fail when resolving dependencies from the aio-sdks registry. You should add CARGO_REGISTRIES_AIO_SDKS_TOKEN as an environment variable to the "Run Clippy" step, sourced from a secret, and also declare it in the workflow_call secrets section (or rely on secrets: inherit and reference the secret directly).

Copilot uses AI. Check for mistakes.
fetch-depth: 0

- name: Install Rust toolchain and clippy
uses: dtolnay/rust-toolchain@stable

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we use a commit SHA here instead of mutable floating tag stable? The latest stable commit appears to be 631a55b12751854ce901bb631d5902ceb48146f7

- add CARGO_REGISTRIES_AIO_SDKS_TOKEN to GitHub Actions workflow env
- fix PATH for rustup in AzDO template install task
- pin dtolnay/rust-toolchain to commit SHA

🔧 - Generated by Copilot
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ci(lint): add per-crate Rust clippy lints and CI integration

4 participants