88 default : true
99
1010jobs :
11- ci :
11+ # 📋 Code Quality Checks
12+ code-quality :
13+ name : Code Quality
1214 runs-on : ubuntu-latest
1315 env :
14- CARGO_LOCKED : " true" # don't mutate Cargo.lock during CI
1516 CARGO_TERM_COLOR : always
1617 steps :
1718 - uses : actions/checkout@v5
1819 with :
1920 fetch-depth : 0
2021
21- # Read MSRV (rust-version) from Cargo.toml
22+ - name : Install nightly rustfmt
23+ uses : dtolnay/rust-toolchain@v1
24+ with :
25+ toolchain : nightly-2025-08-01
26+ components : rustfmt
27+
28+ - name : Check formatting
29+ run : cargo +nightly-2025-08-01 fmt --all -- --check
30+
31+ - name : REUSE Compliance
32+ uses : fsfe/reuse-action@v5
33+
34+ # 🔍 Linting
35+ clippy :
36+ name : Clippy (MSRV)
37+ runs-on : ubuntu-latest
38+ env :
39+ CARGO_LOCKED : " true"
40+ CARGO_TERM_COLOR : always
41+ steps :
42+ - uses : actions/checkout@v5
43+
2244 - name : Read MSRV from Cargo.toml
2345 id : msrv
2446 shell : bash
@@ -36,54 +58,79 @@ jobs:
3658 echo "msrv=${RV}" >> "$GITHUB_OUTPUT"
3759 echo "Using MSRV: $RV"
3860
39- # Install MSRV for clippy/tests/package
4061 - name : Install Rust (${{ steps.msrv.outputs.msrv }})
4162 uses : dtolnay/rust-toolchain@v1
4263 with :
4364 toolchain : ${{ steps.msrv.outputs.msrv }}
4465 components : clippy
4566
46- # Pin nightly for rustfmt because unstable_features = true in .rustfmt.toml
47- - name : Install nightly rustfmt
48- uses : dtolnay/rust-toolchain@v1
49- with :
50- toolchain : nightly-2025-08-01
51- components : rustfmt
52-
5367 - name : Cache cargo
5468 uses : Swatinem/rust-cache@v2
5569 with :
5670 save-if : ${{ github.ref == 'refs/heads/main' }}
5771
58- # Ensure Cargo.lock is present when CARGO_LOCKED=1
59- - name : Verify lockfile is committed
72+ - name : Run clippy
6073 shell : bash
6174 run : |
6275 set -euo pipefail
63- if [ ! -f Cargo.lock ]; then
64- echo "CARGO_LOCKED=1 but Cargo.lock is missing. Commit it or drop CARGO_LOCKED."
76+ if [ "${{ inputs.all-features }}" = "true" ]; then
77+ cargo +${{ steps.msrv.outputs.msrv }} clippy --workspace --all-targets --all-features -- -D warnings
78+ else
79+ cargo +${{ steps.msrv.outputs.msrv }} clippy --workspace --all-targets -- -D warnings
80+ fi
81+
82+ # 🧪 Tests
83+ test :
84+ name : Tests (MSRV)
85+ runs-on : ubuntu-latest
86+ env :
87+ CARGO_LOCKED : " true"
88+ CARGO_TERM_COLOR : always
89+ steps :
90+ - uses : actions/checkout@v5
91+
92+ - name : Read MSRV from Cargo.toml
93+ id : msrv
94+ shell : bash
95+ run : |
96+ set -euo pipefail
97+ if ! command -v jq >/dev/null 2>&1; then
98+ sudo apt-get update -y && sudo apt-get install -y jq
99+ fi
100+ RV=$(cargo metadata --no-deps --format-version=1 | jq -r '.packages[0].rust_version // empty')
101+ if [ -z "$RV" ]; then
102+ echo "rust-version is not set in Cargo.toml"
65103 exit 1
66104 fi
105+ [[ "$RV" =~ ^[0-9]+\.[0-9]+$ ]] && RV="${RV}.0"
106+ echo "msrv=${RV}" >> "$GITHUB_OUTPUT"
107+ echo "Using MSRV: $RV"
67108
68- - name : Check formatting (nightly rustfmt)
69- run : cargo +nightly-2025-08-01 fmt --all -- --check
109+ - name : Install Rust (${{ steps.msrv.outputs.msrv }})
110+ uses : dtolnay/rust-toolchain@v1
111+ with :
112+ toolchain : ${{ steps.msrv.outputs.msrv }}
70113
71- - name : Clippy (MSRV)
114+ - name : Cache cargo
115+ uses : Swatinem/rust-cache@v2
116+ with :
117+ save-if : ${{ github.ref == 'refs/heads/main' }}
118+
119+ - name : Verify lockfile is committed
72120 shell : bash
73121 run : |
74122 set -euo pipefail
75- if [ "${{ inputs.all-features }}" = "true" ]; then
76- cargo +${{ steps.msrv.outputs.msrv }} clippy --workspace --all-targets --all-features -- -D warnings
77- else
78- cargo +${{ steps.msrv.outputs.msrv }} clippy --workspace --all-targets -- -D warnings
123+ if [ ! -f Cargo.lock ]; then
124+ echo "CARGO_LOCKED=1 but Cargo.lock is missing. Commit it or drop CARGO_LOCKED."
125+ exit 1
79126 fi
80127
81128 - name : Install cargo-nextest
82129 uses : taiki-e/install-action@v2
83130 with :
84131 tool : cargo-nextest
85132
86- - name : Tests (MSRV)
133+ - name : Run tests
87134 shell : bash
88135 run : |
89136 set -euo pipefail
@@ -99,18 +146,53 @@ jobs:
99146 with :
100147 token : ${{ secrets.CODECOV_TOKEN }}
101148
102-
103- - name : Auto-commit changes (any branch)
149+ # 📦 Build & Package
150+ build :
151+ name : Build & Package
152+ runs-on : ubuntu-latest
153+ needs : [code-quality, clippy, test]
154+ env :
155+ CARGO_LOCKED : " true"
156+ CARGO_TERM_COLOR : always
157+ steps :
158+ - uses : actions/checkout@v5
159+
160+ - name : Read MSRV from Cargo.toml
161+ id : msrv
162+ shell : bash
163+ run : |
164+ set -euo pipefail
165+ if ! command -v jq >/dev/null 2>&1; then
166+ sudo apt-get update -y && sudo apt-get install -y jq
167+ fi
168+ RV=$(cargo metadata --no-deps --format-version=1 | jq -r '.packages[0].rust_version // empty')
169+ if [ -z "$RV" ]; then
170+ echo "rust-version is not set in Cargo.toml"
171+ exit 1
172+ fi
173+ [[ "$RV" =~ ^[0-9]+\.[0-9]+$ ]] && RV="${RV}.0"
174+ echo "msrv=${RV}" >> "$GITHUB_OUTPUT"
175+ echo "Using MSRV: $RV"
176+
177+ - name : Install Rust (${{ steps.msrv.outputs.msrv }})
178+ uses : dtolnay/rust-toolchain@v1
179+ with :
180+ toolchain : ${{ steps.msrv.outputs.msrv }}
181+
182+ - name : Cache cargo
183+ uses : Swatinem/rust-cache@v2
184+
185+ - name : Auto-commit changes
104186 if : always()
105187 run : |
106188 set -euo pipefail
107- git config user.name "github-actions[bot]"
108- git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
109- git config --global --add safe.directory "$GITHUB_WORKSPACE"
110- git add .
111- git commit -m "chore(readme): auto-refresh [skip ci]" || true
189+ git config user.name "github-actions[bot]"
190+ git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
191+ git config --global --add safe.directory "$GITHUB_WORKSPACE"
192+ git add .
193+ git commit -m "chore(readme): auto-refresh [skip ci]" || true
112194
113- - name : Ensure tree is clean before package
195+ - name : Ensure tree is clean
114196 shell : bash
115197 run : |
116198 set -euo pipefail
@@ -123,10 +205,9 @@ jobs:
123205 - name : Package (dry-run)
124206 run : cargo +${{ steps.msrv.outputs.msrv }} package --locked
125207
126- - name : REUSE Compliance
127- uses : fsfe/reuse-action@v5
128-
208+ # 📊 Coverage
129209 coverage :
210+ name : Coverage
130211 runs-on : ubuntu-latest
131212 steps :
132213 - uses : actions/checkout@v5
0 commit comments