1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
# Reusable Rust quality gate for Distributed libraries and domain crates.
#
# Callers (this repo or any consumer):
# jobs:
# quality:
# permissions:
# contents: read
# pull-requests: write # required for coverage PR comments
# uses: hops-ops/distributed/.github/workflows/quality.yaml@main
# with:
# cargo_test_args: "--verbose --locked"
#
# Pipeline: rustfmt → clippy (-D warnings) → build → test (+ coverage)
# When cargo_coverage is true (default), tests run under cargo-llvm-cov; on
# pull_request a sticky comment shows TOTAL coverage % (not the compile log).
#
# Does not run broker/DB integrations or --all-features (see sibling workflows).
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@v4
with:
persist-credentials: false
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
with:
toolchain: ${{ inputs.toolchain }}
components: rustfmt, clippy, llvm-tools-preview
- 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 }}
# Run tests under llvm-cov and write lcov. Logs stay in the job log only —
# they must not be tee'd into the PR comment body.
- 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
# Quiet report only (no recompile / no test re-run noise in the file we post).
- name: Coverage summary for PR and job summary
if: inputs.cargo_test && inputs.cargo_coverage
id: coverage
shell: bash
env:
# Force plain text for the report file / PR comment
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@v4
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@v2
with:
header: distributed-rust-coverage
path: coverage-comment.md
recreate: true