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
name: CI
on:
push:
branches:
pull_request:
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
env:
CARGO_TERM_COLOR: always
RUST_BACKTRACE: 1
jobs:
check:
name: check (${{ matrix.os }})
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os:
steps:
- uses: actions/checkout@v7.0.1
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2.9.2
with:
# Skip cache save on PR runs — the Post step's tar.exe is
# flaky on windows-latest (file locks under target/ make
# the save fail and mark the otherwise-green job FAILURE,
# blocking renovate auto-merge for downstream consumers).
# Main keeps saving so every PR rebuild gets a warm cache.
save-if: ${{ github.ref == 'refs/heads/main' }}
# The GH Actions cache backend transient-flakes the restore
# step on windows-latest just often enough to gate release
# pipelines (verified on yukimemi/kanade@v0.6.2 — the cache
# restore died mid-tar, killed the Windows build matrix, and
# blocked the publish). Fall through to a cold cargo build
# when the restore errors out: ~3–5 min slower on a single
# job, but self-healing instead of release-blocking.
continue-on-error: true
- run: cargo check --all-targets
test:
name: test (${{ matrix.os }})
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os:
steps:
- uses: actions/checkout@v7.0.1
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2.9.2
with:
save-if: ${{ github.ref == 'refs/heads/main' }}
# See the check job above for why continue-on-error is set
# on every rust-cache restore (transient GH Actions cache
# backend flake on windows-latest).
continue-on-error: true
# `cargo test --all-targets` covers lib / bins / tests / benches
# / examples but EXCLUDES doc tests, so run --doc separately.
# Doc-test step is gated on `src/lib.rs` presence: `cargo test
# --doc` errors with `no library targets found` on bin-only
# crates (yukimemi/todoke#50, yukimemi/rvpm#176 track the
# consumer-side refactor). Drop this `if:` once both land.
- run: cargo test --all-targets
- if: ${{ hashFiles('src/lib.rs') != '' }}
run: cargo test --doc
fmt:
name: rustfmt
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7.0.1
- uses: dtolnay/rust-toolchain@stable
with:
components: rustfmt
- run: cargo fmt --all -- --check
editorconfig:
# Enforces the repo's `.editorconfig` (LF, trimmed trailing
# whitespace, per-filetype indent width) across every tracked file,
# not just Rust sources. `cargo make check`'s `editorconfig-check`
# task runs the same tool locally but skips gracefully when the
# `editorconfig-checker` binary isn't on PATH (it isn't a Rust
# crate, so `cargo install` can't fetch it) — this job is the
# actual enforcement gate.
name: editorconfig
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7.0.1
- uses: editorconfig-checker/action-editorconfig-checker@v3.0.0
- run: editorconfig-checker
clippy:
# Matrix across all three OSes so OS-specific dead code (e.g. helpers
# gated under `cfg(target_os = "windows")`) is caught everywhere, not
# just on the maintainer's machine. Without this, a Windows-only
# helper looks fine on a Windows pre-push hook but blows up the Linux
# clippy run.
name: clippy (${{ matrix.os }})
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os:
steps:
- uses: actions/checkout@v7.0.1
- uses: dtolnay/rust-toolchain@stable
with:
components: clippy
- uses: Swatinem/rust-cache@v2.9.2
with:
save-if: ${{ github.ref == 'refs/heads/main' }}
# See the check job above for why continue-on-error is set
# on every rust-cache restore (transient GH Actions cache
# backend flake on windows-latest).
continue-on-error: true
- run: cargo clippy --all-targets -- -D warnings
lockfile:
# Catches stale Cargo.lock (e.g. version bumped in Cargo.toml but lock
# still points at the old version) before it reaches the publish job,
# which uses --locked and would otherwise fail there.
name: cargo lockfile in sync
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7.0.1
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2.9.2
with:
save-if: ${{ github.ref == 'refs/heads/main' }}
# See the check job above for why continue-on-error is set
# on every rust-cache restore (transient GH Actions cache
# backend flake on windows-latest).
continue-on-error: true
- run: cargo check --locked --all-targets
coverage:
# llvm-cov on Linux + Codecov upload. taiki-e/install-action grabs the
# cargo-llvm-cov binary. codecov-action@v5 nominally accepts tokenless
# uploads from public repos, but in practice Codecov rejects them with
# 'Token required - not valid tokenless upload', so plumb CODECOV_TOKEN
# through as a repo secret. `fail_ci_if_error: false` still keeps a
# flaky upload from gating merges.
name: coverage
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7.0.1
- uses: dtolnay/rust-toolchain@stable
with:
components: llvm-tools-preview
- uses: Swatinem/rust-cache@v2.9.2
with:
save-if: ${{ github.ref == 'refs/heads/main' }}
# See the check job above for why continue-on-error is set
# on every rust-cache restore (transient GH Actions cache
# backend flake on windows-latest).
continue-on-error: true
- uses: taiki-e/install-action@v2
with:
tool: cargo-llvm-cov
- run: cargo llvm-cov --workspace --lcov --output-path lcov.info
- uses: codecov/codecov-action@v5
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: lcov.info
fail_ci_if_error: false