Skip to content

Commit 4ea7c1c

Browse files
authored
Create ci.yml
1 parent d059871 commit 4ea7c1c

1 file changed

Lines changed: 316 additions & 0 deletions

File tree

.github/workflows/ci.yml

Lines changed: 316 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,316 @@
1+
# .github/workflows/ci.yml
2+
name: CI
3+
4+
on:
5+
push:
6+
branches: [main, master, develop]
7+
pull_request:
8+
branches: [main, master, develop]
9+
workflow_dispatch:
10+
11+
# Cancel in-progress runs for the same branch/PR
12+
concurrency:
13+
group: ${{ github.workflow }}-${{ github.ref }}
14+
cancel-in-progress: true
15+
16+
env:
17+
CARGO_TERM_COLOR: always
18+
CARGO_INCREMENTAL: 0
19+
CARGO_NET_RETRY: 10
20+
RUSTUP_MAX_RETRIES: 10
21+
RUST_BACKTRACE: short
22+
# Faster compilation via sccache
23+
SCCACHE_GHA_ENABLED: "true"
24+
RUSTC_WRAPPER: "sccache"
25+
26+
jobs:
27+
# ──────────────────────────────────────────────
28+
# 1. Code Quality (runs once, fast feedback)
29+
# ──────────────────────────────────────────────
30+
fmt:
31+
name: Rustfmt
32+
runs-on: ubuntu-latest
33+
steps:
34+
- uses: actions/checkout@v4
35+
- uses: dtolnay/rust-toolchain@nightly
36+
with:
37+
components: rustfmt
38+
- run: cargo fmt --all -- --check
39+
40+
clippy:
41+
name: Clippy
42+
runs-on: ubuntu-latest
43+
steps:
44+
- uses: actions/checkout@v4
45+
- uses: dtolnay/rust-toolchain@stable
46+
with:
47+
components: clippy
48+
- uses: mozilla-actions/sccache-action@v0.0.6
49+
- uses: taiki-e/install-action@cargo-hack
50+
- name: Clippy (all feature combinations)
51+
run: cargo hack clippy --feature-powerset --no-dev-deps -- -D warnings
52+
- name: Clippy (tests)
53+
run: cargo clippy --all-targets -- -D warnings
54+
55+
docs:
56+
name: Documentation
57+
runs-on: ubuntu-latest
58+
env:
59+
RUSTDOCFLAGS: -D warnings
60+
steps:
61+
- uses: actions/checkout@v4
62+
- uses: dtolnay/rust-toolchain@stable
63+
- uses: mozilla-actions/sccache-action@v0.0.6
64+
- run: cargo doc --no-deps --all-features
65+
66+
# ──────────────────────────────────────────────
67+
# 2. Security & Dependency Audit
68+
# ──────────────────────────────────────────────
69+
audit:
70+
name: Security Audit
71+
runs-on: ubuntu-latest
72+
steps:
73+
- uses: actions/checkout@v4
74+
- uses: taiki-e/install-action@cargo-deny
75+
- run: cargo deny check
76+
77+
# ──────────────────────────────────────────────
78+
# 3. Tests — Native (all target platforms)
79+
# ──────────────────────────────────────────────
80+
test:
81+
name: Test (${{ matrix.name }})
82+
needs: [fmt, clippy]
83+
strategy:
84+
fail-fast: false
85+
matrix:
86+
include:
87+
# ── Linux x86_64 ──
88+
- name: Linux x86_64
89+
os: ubuntu-latest
90+
target: x86_64-unknown-linux-gnu
91+
cross: false
92+
93+
# ── Linux ARM64 ──
94+
- name: Linux ARM64
95+
os: ubuntu-latest
96+
target: aarch64-unknown-linux-gnu
97+
cross: true
98+
99+
# ── macOS ARM64 (Apple Silicon) ──
100+
- name: macOS ARM64
101+
os: macos-14
102+
target: aarch64-apple-darwin
103+
cross: false
104+
105+
# ── macOS x86_64 ──
106+
- name: macOS x86_64
107+
os: macos-13
108+
target: x86_64-apple-darwin
109+
cross: false
110+
111+
# ── Windows x86_64 ──
112+
- name: Windows x86_64
113+
os: windows-latest
114+
target: x86_64-pc-windows-msvc
115+
cross: false
116+
117+
runs-on: ${{ matrix.os }}
118+
steps:
119+
- uses: actions/checkout@v4
120+
121+
- uses: dtolnay/rust-toolchain@stable
122+
with:
123+
targets: ${{ matrix.target }}
124+
125+
- uses: mozilla-actions/sccache-action@v0.0.6
126+
127+
- name: Install cross
128+
if: matrix.cross
129+
uses: taiki-e/install-action@cross
130+
131+
- name: Run tests (native)
132+
if: "!matrix.cross"
133+
run: cargo test --all-features --target ${{ matrix.target }}
134+
135+
- name: Run tests (cross)
136+
if: matrix.cross
137+
run: cross test --all-features --target ${{ matrix.target }}
138+
139+
# ──────────────────────────────────────────────
140+
# 4. Build Release Binaries (all platforms)
141+
# ──────────────────────────────────────────────
142+
build:
143+
name: Build (${{ matrix.name }})
144+
needs: [fmt, clippy]
145+
strategy:
146+
fail-fast: false
147+
matrix:
148+
include:
149+
- name: Linux x86_64
150+
os: ubuntu-latest
151+
target: x86_64-unknown-linux-gnu
152+
cross: false
153+
artifact: target/x86_64-unknown-linux-gnu/release
154+
155+
- name: Linux ARM64
156+
os: ubuntu-latest
157+
target: aarch64-unknown-linux-gnu
158+
cross: true
159+
artifact: target/aarch64-unknown-linux-gnu/release
160+
161+
- name: macOS ARM64
162+
os: macos-14
163+
target: aarch64-apple-darwin
164+
cross: false
165+
artifact: target/aarch64-apple-darwin/release
166+
167+
- name: macOS x86_64
168+
os: macos-13
169+
target: x86_64-apple-darwin
170+
cross: false
171+
artifact: target/x86_64-apple-darwin/release
172+
173+
- name: Windows x86_64
174+
os: windows-latest
175+
target: x86_64-pc-windows-msvc
176+
cross: false
177+
artifact: target/x86_64-pc-windows-msvc/release
178+
179+
runs-on: ${{ matrix.os }}
180+
steps:
181+
- uses: actions/checkout@v4
182+
183+
- uses: dtolnay/rust-toolchain@stable
184+
with:
185+
targets: ${{ matrix.target }}
186+
187+
- uses: mozilla-actions/sccache-action@v0.0.6
188+
189+
- name: Install cross
190+
if: matrix.cross
191+
uses: taiki-e/install-action@cross
192+
193+
- name: Build release (native)
194+
if: "!matrix.cross"
195+
run: cargo build --release --all-features --target ${{ matrix.target }}
196+
197+
- name: Build release (cross)
198+
if: matrix.cross
199+
run: cross build --release --all-features --target ${{ matrix.target }}
200+
201+
- name: Upload artifacts
202+
uses: actions/upload-artifact@v4
203+
with:
204+
name: build-${{ matrix.target }}
205+
path: |
206+
${{ matrix.artifact }}/*
207+
!${{ matrix.artifact }}/.fingerprint
208+
!${{ matrix.artifact }}/build
209+
!${{ matrix.artifact }}/deps
210+
!${{ matrix.artifact }}/examples
211+
!${{ matrix.artifact }}/incremental
212+
!${{ matrix.artifact }}/.cargo-lock
213+
if-no-files-found: error
214+
retention-days: 7
215+
216+
# ──────────────────────────────────────────────
217+
# 5. Code Coverage
218+
# ──────────────────────────────────────────────
219+
coverage:
220+
name: Code Coverage
221+
needs: [fmt, clippy]
222+
runs-on: ubuntu-latest
223+
steps:
224+
- uses: actions/checkout@v4
225+
- uses: dtolnay/rust-toolchain@stable
226+
- uses: mozilla-actions/sccache-action@v0.0.6
227+
- uses: taiki-e/install-action@cargo-llvm-cov
228+
229+
- name: Generate coverage
230+
run: cargo llvm-cov --all-features --workspace --lcov --output-path lcov.info
231+
232+
- name: Upload to Codecov
233+
uses: codecov/codecov-action@v4
234+
with:
235+
files: lcov.info
236+
fail_ci_if_error: false
237+
env:
238+
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
239+
240+
# ──────────────────────────────────────────────
241+
# 6. MSRV (Minimum Supported Rust Version)
242+
# ──────────────────────────────────────────────
243+
msrv:
244+
name: MSRV Check
245+
runs-on: ubuntu-latest
246+
steps:
247+
- uses: actions/checkout@v4
248+
- uses: taiki-e/install-action@cargo-hack
249+
- name: Check MSRV
250+
run: cargo hack check --rust-version --workspace --all-targets --ignore-private
251+
252+
# ──────────────────────────────────────────────
253+
# 7. Miri (Undefined Behavior Detection)
254+
# ──────────────────────────────────────────────
255+
miri:
256+
name: Miri
257+
runs-on: ubuntu-latest
258+
steps:
259+
- uses: actions/checkout@v4
260+
- uses: dtolnay/rust-toolchain@nightly
261+
with:
262+
components: miri
263+
- name: Run Miri
264+
run: cargo miri test --all-features
265+
env:
266+
MIRIFLAGS: -Zmiri-strict-provenance
267+
268+
# ──────────────────────────────────────────────
269+
# 8. Gate — all checks must pass
270+
# ──────────────────────────────────────────────
271+
ci-pass:
272+
name: CI Pass ✅
273+
if: always()
274+
needs: [fmt, clippy, docs, audit, test, build, coverage, msrv, miri]
275+
runs-on: ubuntu-latest
276+
steps:
277+
- name: Evaluate results
278+
run: |
279+
echo "Results:"
280+
echo " fmt: ${{ needs.fmt.result }}"
281+
echo " clippy: ${{ needs.clippy.result }}"
282+
echo " docs: ${{ needs.docs.result }}"
283+
echo " audit: ${{ needs.audit.result }}"
284+
echo " test: ${{ needs.test.result }}"
285+
echo " build: ${{ needs.build.result }}"
286+
echo " coverage: ${{ needs.coverage.result }}"
287+
echo " msrv: ${{ needs.msrv.result }}"
288+
echo " miri: ${{ needs.miri.result }}"
289+
290+
- name: All checks passed
291+
if: >-
292+
needs.fmt.result == 'success' &&
293+
needs.clippy.result == 'success' &&
294+
needs.docs.result == 'success' &&
295+
needs.audit.result == 'success' &&
296+
needs.test.result == 'success' &&
297+
needs.build.result == 'success' &&
298+
needs.coverage.result == 'success' &&
299+
needs.msrv.result == 'success' &&
300+
needs.miri.result == 'success'
301+
run: echo "🎉 All CI checks passed!"
302+
303+
- name: Some checks failed
304+
if: >-
305+
needs.fmt.result != 'success' ||
306+
needs.clippy.result != 'success' ||
307+
needs.docs.result != 'success' ||
308+
needs.audit.result != 'success' ||
309+
needs.test.result != 'success' ||
310+
needs.build.result != 'success' ||
311+
needs.coverage.result != 'success' ||
312+
needs.msrv.result != 'success' ||
313+
needs.miri.result != 'success'
314+
run: |
315+
echo "❌ Some CI checks failed!"
316+
exit 1

0 commit comments

Comments
 (0)