-
Notifications
You must be signed in to change notification settings - Fork 0
324 lines (310 loc) · 14.4 KB
/
Copy pathci.yml
File metadata and controls
324 lines (310 loc) · 14.4 KB
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
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
name: CI
on:
pull_request:
push:
branches: [main]
schedule:
- cron: '0 3 * * *'
permissions:
contents: read
jobs:
test:
# Uses an explicit feature list rather than --all-features, deliberately
# excluding syntax-tests' `compile-fail` feature: it runs trybuild UI
# tests that assert on rustc's exact diagnostic text, which can drift
# between stable/beta/nightly. That feature gets its own `trybuild` job
# pinned to stable only, below.
#
# Matrix: every toolchain channel runs on ubuntu (cheap); stable
# additionally runs on windows/macos to catch platform-specific
# breakage (path separators, line endings, ...) without tripling the
# cost of the beta/nightly legs too. `macos-latest` is already Apple
# Silicon (arm64); `ubuntu-24.04-arm` adds the one other concretely
# available GitHub-hosted ARM runner (Linux), stable-only, same as the
# windows/macos legs — not a general cross-compilation matrix, just
# closing the one real remaining architecture gap.
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
include:
- os: ubuntu-latest
toolchain: stable
- os: ubuntu-latest
toolchain: beta
- os: ubuntu-latest
toolchain: nightly
- os: windows-latest
toolchain: stable
- os: macos-latest
toolchain: stable
- os: ubuntu-24.04-arm
toolchain: stable
steps:
- uses: actions/checkout@v7
- name: Install Rust
uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{ matrix.toolchain }}
components: rustfmt, clippy
- uses: Swatinem/rust-cache@v2
- name: fmt
run: cargo fmt --all --check
- name: clippy
run: cargo clippy --workspace --all-targets --features async,no_std,perf,fuzz,edge,snapshot -- -D warnings
- name: tests
run: cargo test --workspace --features async,no_std,perf,fuzz,edge,snapshot
nextest:
# Demonstrates cargo-nextest as an opt-in alternative test runner —
# cargo test remains the primary, dependency-free supported path (see
# CONTRIBUTING.md), this just proves the workspace actually works under
# nextest too, since it runs tests differently enough (process-per-test,
# no libtest harness) that "works under cargo test" doesn't guarantee
# "works under nextest". Note nextest doesn't run doc-tests — that's a
# real, known nextest limitation, not something to fix here.
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- name: Install Rust (stable)
uses: dtolnay/rust-toolchain@stable
- uses: taiki-e/install-action@nextest
- uses: Swatinem/rust-cache@v2
- name: nextest
run: cargo nextest run --workspace --features async,no_std,perf,fuzz,edge,snapshot
trybuild:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- name: Install Rust (stable)
uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- name: compile-fail UI tests
run: cargo test -p syntax-tests --features compile-fail
loom:
# Isolated from the main `test` matrix, same reasoning as `trybuild`
# above: exhaustive thread-interleaving search is slower than a normal
# test run and the result doesn't depend on toolchain channel or OS, so
# one stable-only run is enough — repeating it across all 5 `test`
# matrix legs would just multiply the cost for no extra signal.
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- name: Install Rust (stable)
uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- name: loom concurrency-permutation tests
run: cargo test -p semantic-tests --features loom
fuzz-build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- name: Install Rust (nightly)
uses: dtolnay/rust-toolchain@nightly
- uses: Swatinem/rust-cache@v2
with:
workspaces: fuzz -> target
- name: install cargo-fuzz
run: cargo install cargo-fuzz --locked
- name: build fuzz targets
working-directory: fuzz
run: cargo fuzz build
# Short timed smoke run per target, seeded from the committed
# fuzz/seed_corpus/ — catches "the target panics immediately" (a
# broken harness, not a real bug) without running a real fuzzing
# campaign in CI. -max_total_time is libFuzzer's own flag, passed
# through after `--`.
- name: smoke-run utf8_input
working-directory: fuzz
run: cargo fuzz run utf8_input seed_corpus/utf8_input -- -max_total_time=10
- name: smoke-run parse_u32_lenient
working-directory: fuzz
run: cargo fuzz run parse_u32_lenient seed_corpus/parse_u32_lenient -- -max_total_time=10
# Real (if still short) fuzzing campaign, only on the daily cron
# trigger — not on every push/PR, since a few minutes per target
# would slow down normal development for a check that's inherently
# about finding rare inputs, not about gating a specific change. See
# docs/fuzzing.md for running a longer campaign locally.
- name: extended-run utf8_input (scheduled only)
if: github.event_name == 'schedule'
working-directory: fuzz
run: cargo fuzz run utf8_input seed_corpus/utf8_input -- -max_total_time=240
- name: extended-run parse_u32_lenient (scheduled only)
if: github.event_name == 'schedule'
working-directory: fuzz
run: cargo fuzz run parse_u32_lenient seed_corpus/parse_u32_lenient -- -max_total_time=240
coverage:
# Informational only — reports coverage as a downloadable HTML artifact,
# doesn't gate merges on a threshold. A hard coverage floor tends to
# produce coverage-chasing busywork more than better tests; this is
# meant to make gaps visible; instead see the "Coverage, Reporting, and
# Debugging" section of README.md for the same thing locally.
#
# Nightly, not stable: `--doctests` (below) instruments doc-tests too —
# without it, every `///` example in the crates (there are several, e.g.
# `core-tests`'s `UserFixture`) is invisible to the coverage report, an
# easy-to-miss gap since nothing about a clean report tells you doctests
# were excluded. cargo-llvm-cov implements doc-test coverage via
# rustdoc's unstable `--persist-doctests`/`-Z unstable-options`, which
# only the nightly compiler accepts.
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- name: Install Rust (nightly)
uses: dtolnay/rust-toolchain@nightly
with:
components: llvm-tools-preview
- uses: taiki-e/install-action@cargo-llvm-cov
- uses: Swatinem/rust-cache@v2
- name: generate coverage report
run: cargo llvm-cov --workspace --all-features --doctests --html
- name: upload coverage report
uses: actions/upload-artifact@v7
with:
name: coverage-html
path: target/llvm-cov/html
# Optional coverage % badge: only runs once a maintainer has created a
# gist and configured `vars.COVERAGE_GIST_ID` + `secrets.COVERAGE_GIST_SECRET`
# (see the "Coverage badge setup" section in ci/README.md). Skipped
# entirely otherwise, so this template doesn't ship a CI job that fails
# by default for every adopter who copies it without that setup.
- name: coverage summary
if: vars.COVERAGE_GIST_ID != ''
id: coverage_summary
run: |
PCT=$(cargo llvm-cov --workspace --all-features --doctests --summary-only | tail -1 | awk '{print $NF}' | tr -d '%')
echo "percent=$PCT" >> "$GITHUB_OUTPUT"
- name: update coverage badge gist
if: vars.COVERAGE_GIST_ID != '' && github.event_name != 'pull_request' && github.ref == 'refs/heads/main'
uses: schneegans/dynamic-badges-action@v1.9.0
with:
auth: ${{ secrets.COVERAGE_GIST_SECRET }}
gistID: ${{ vars.COVERAGE_GIST_ID }}
filename: rustforge-coverage.json
label: coverage
message: ${{ steps.coverage_summary.outputs.percent }}%
color: blue
udeps:
# Informational only, like `coverage` above — reports unused
# dependencies without failing the build (`continue-on-error: true` on
# the one step that can actually fail). Feature-gated crates routinely
# produce false positives here (cargo-udeps analyzes one feature
# combination at a time, and a dependency only used behind a
# not-currently-selected feature can look unused), so this is a signal
# to review manually, not a gate — same reasoning as the `coverage`
# job's "avoid busywork" scope decision.
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- name: Install Rust (nightly)
uses: dtolnay/rust-toolchain@nightly
- uses: taiki-e/install-action@cargo-udeps
- uses: Swatinem/rust-cache@v2
- name: cargo udeps
run: cargo udeps --workspace --all-features
continue-on-error: true
msrv:
# Verifies the *default*-feature build actually compiles under the
# workspace's declared rust-version. The perf/fuzz features intentionally
# pull in ecosystem tooling with a newer MSRV of their own — see the
# "MSRV" section in README.md. The committed Cargo.lock is in lockfile
# format v4 (requires Cargo >= 1.78); Cargo reads whatever Cargo.lock is
# on disk regardless of --locked, so an MSRV 1.75 toolchain fails before
# it even gets a chance to re-resolve. Deleting the lockfile first makes
# 1.75's cargo generate its own compatible one — this only affects the
# ephemeral CI checkout, not the committed file.
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- name: Install Rust 1.75
uses: dtolnay/rust-toolchain@master
with:
toolchain: "1.75"
- uses: Swatinem/rust-cache@v2
- name: remove lockfile (format v4 needs Cargo >= 1.78)
run: rm -f Cargo.lock
- name: check (default features, whole workspace)
run: cargo check --workspace
# performance-tests' dev-dependency (criterion) can't be feature-gated
# (dev-deps never can be), so `cargo test` on it resolves criterion's
# whole transitive graph regardless of the `perf` feature. Individual
# pieces of that graph (clap, clap_lex, ...) have independently moved
# to requiring the `edition2024` Cargo feature, which breaks
# *resolution* itself under 1.75 — pinning each one as it comes up
# isn't sustainable, so this excludes performance-tests here. Its
# production code still compiles above; only its own dev/bench tests
# are skipped under this specific toolchain.
- name: test (default features, excluding performance-tests)
run: cargo test --workspace --exclude performance-tests
hack:
# Feature-interaction coverage the `test` job's single fixed feature
# list can't give you: with 6+ optional features spread across 7
# crates, a combination the `test` job never happens to select (e.g.
# `no_std` + `async` together, or `perf` alone without `fuzz`) can
# still be broken. cargo-hack builds every crate's own feature powerset
# independently rather than one workspace-wide `--all-features` blob,
# so a broken pairing is attributed to the crate that actually has it.
# `compile-fail` is excluded for the same reason it's excluded from the
# `test` job — trybuild's UI tests assert on rustc's exact diagnostic
# text, which isn't a feature-interaction concern and belongs to the
# dedicated stable-only `trybuild` job instead.
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- name: Install Rust (stable)
uses: dtolnay/rust-toolchain@stable
- uses: taiki-e/install-action@cargo-hack
- uses: Swatinem/rust-cache@v2
- name: cargo hack test --feature-powerset
run: cargo hack test --workspace --feature-powerset --exclude-features compile-fail
minimal-versions:
# `cargo test --workspace` resolves every dependency to its newest
# semver-compatible release, which can mask a `Cargo.toml` requirement
# that's looser than what the code actually needs (e.g. depending on
# `foo = "1"` while calling an API `foo` only added in 1.4) — a
# downstream adopter with an older lockfile hits a compile failure this
# repo's own CI never sees. `cargo minimal-versions` re-resolves every
# dependency down to the *lowest* version each `Cargo.toml` constraint
# allows (needs nightly for the `-Z minimal-versions` resolution step)
# and tests against that. Scoped to default features and excludes
# `performance-tests`, matching the `msrv` job below — Criterion's own
# transitive graph (`clap`/`plotters`/...) floors well above what this
# template's MSRV-sensitive pins are about, so it would fail here for
# reasons unrelated to this template's own minimum-version claims.
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- name: Install Rust (nightly)
uses: dtolnay/rust-toolchain@nightly
- uses: taiki-e/install-action@cargo-hack
- uses: taiki-e/install-action@cargo-minimal-versions
- uses: Swatinem/rust-cache@v2
- name: cargo minimal-versions test
run: cargo minimal-versions test --workspace --exclude performance-tests
deny:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- name: cargo-deny (main workspace)
uses: EmbarkStudios/cargo-deny-action@v2
with:
manifest-path: Cargo.toml
- name: cargo-deny (fuzz/)
uses: EmbarkStudios/cargo-deny-action@v2
with:
manifest-path: fuzz/Cargo.toml
docs:
# Catches broken intra-doc links and other rustdoc-only lints that
# clippy's own -D warnings doesn't cover (clippy and rustdoc are
# separate lint passes). Added after `[`slice::dedup`]` shipped as a
# broken link nothing in CI caught — `cargo doc` was never run here
# before this job.
runs-on: ubuntu-latest
env:
RUSTDOCFLAGS: -D warnings
steps:
- uses: actions/checkout@v7
- name: Install Rust (stable)
uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- name: cargo doc
run: cargo doc --workspace --all-features --no-deps