name: Distributed Rust Quality
on:
workflow_call:
inputs:
runs_on:
description: GitHub-hosted runner label
type: string
required: false
default: ubuntu-latest
toolchain:
description: Rust toolchain channel or version
type: string
required: false
default: stable
cargo_fmt:
description: Run cargo fmt --check
type: boolean
required: false
default: true
cargo_clippy:
description: Run cargo clippy with -D warnings
type: boolean
required: false
default: true
cargo_build:
description: Run cargo build before tests
type: boolean
required: false
default: true
cargo_test:
description: Run cargo test (or llvm-cov when cargo_coverage is true)
type: boolean
required: false
default: true
cargo_coverage:
description: Collect coverage with cargo-llvm-cov and comment on PRs
type: boolean
required: false
default: true
cargo_build_args:
description: Extra args for cargo build
type: string
required: false
default: "--verbose"
cargo_test_args:
description: Extra args for cargo test / cargo llvm-cov
type: string
required: false
default: "--verbose"
cargo_clippy_args:
description: Args after `cargo clippy` (include `--` flags for rustc/clippy)
type: string
required: false
default: "--all-targets -- -D warnings"
cargo_llvm_cov_args:
description: Extra args for cargo llvm-cov (e.g. --workspace)
type: string
required: false
default: ""
rust_cache:
description: Enable Swatinem/rust-cache
type: boolean
required: false
default: true
jobs:
quality:
name: fmt · clippy · build · test · coverage
runs-on: ${{ inputs.runs_on }}
permissions:
contents: read
pull-requests: write
env:
CARGO_TERM_COLOR: always
RUST_BACKTRACE: "1"
steps:
- name: Checkout
uses: actions/checkout@v7
with:
persist-credentials: false
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
with:
toolchain: ${{ inputs.toolchain }}
components: rustfmt, clippy, llvm-tools-preview, rust-src
- name: Rust cache
if: inputs.rust_cache
uses: Swatinem/rust-cache@v2
- name: Install cargo-llvm-cov
if: inputs.cargo_test && inputs.cargo_coverage
uses: taiki-e/install-action@cargo-llvm-cov
- name: cargo fmt --check
if: inputs.cargo_fmt
run: cargo fmt --check
- name: cargo clippy
if: inputs.cargo_clippy
run: cargo clippy ${{ inputs.cargo_clippy_args }}
- name: cargo build
if: inputs.cargo_build
run: cargo build ${{ inputs.cargo_build_args }}
- name: cargo llvm-cov (test + lcov)
if: inputs.cargo_test && inputs.cargo_coverage
shell: bash
run: |
set -euo pipefail
cargo llvm-cov clean --workspace
cargo llvm-cov \
${{ inputs.cargo_llvm_cov_args }} \
${{ inputs.cargo_test_args }} \
--lcov \
--output-path lcov.info
- name: Coverage summary for PR and job summary
if: inputs.cargo_test && inputs.cargo_coverage
id: coverage
shell: bash
env:
CARGO_TERM_COLOR: never
TERM: dumb
run: |
set -euo pipefail
cargo llvm-cov report \
${{ inputs.cargo_llvm_cov_args }} \
--summary-only \
--color never \
| tee coverage-summary.txt
# llvm-cov TOTAL line usually ends with a percentage field, e.g.:
# TOTAL 1234 56 95.46% ...
TOTAL_LINE="$(grep -E '^TOTAL' coverage-summary.txt | tail -n1 || true)"
PCT="$(echo "$TOTAL_LINE" | grep -oE '[0-9]+([.][0-9]+)?%' | tail -n1 || true)"
if [ -z "${PCT}" ]; then
PCT="n/a"
fi
echo "total_pct=${PCT}" >> "$GITHUB_OUTPUT"
echo "Coverage TOTAL: ${PCT}"
RUN_URL="${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"
{
echo "## Code coverage"
echo ""
echo "**TOTAL: \`${PCT}\`**"
echo ""
echo "<details>"
echo "<summary>Full summary table</summary>"
echo ""
echo '```'
cat coverage-summary.txt
echo '```'
echo ""
echo "</details>"
echo ""
echo "- LCOV artifact: download **\`lcov\`** from this workflow run"
echo "- [Open workflow run](${RUN_URL})"
echo ""
echo "_Generated by \`hops-ops/distributed\` quality workflow (cargo-llvm-cov)._"
} > coverage-comment.md
cat coverage-comment.md >> "$GITHUB_STEP_SUMMARY"
- name: Upload lcov artifact
if: inputs.cargo_test && inputs.cargo_coverage
uses: actions/upload-artifact@v7
with:
name: lcov
path: lcov.info
if-no-files-found: warn
- name: cargo test
if: inputs.cargo_test && !inputs.cargo_coverage
run: cargo test ${{ inputs.cargo_test_args }}
- name: Comment coverage on PR
if: >
inputs.cargo_test &&
inputs.cargo_coverage &&
github.event_name == 'pull_request'
uses: marocchino/sticky-pull-request-comment@v3.0.5
with:
header: distributed-rust-coverage
path: coverage-comment.md
recreate: true