11name : CI
2+
23permissions :
34 contents : read
5+
46concurrency :
57 group : >
68 ci-${{ github.workflow }}-${{
1719 pull_request :
1820 branches :
1921 - main
22+ workflow_dispatch :
2023
2124env :
2225 CARGO_TERM_COLOR : always
2326 RUST_BACKTRACE : 1
24- ACTIONLINT_VERSION : " 1.7.10"
25- MARKDOWNLINT_VERSION : " 0.47.0"
26- SHFMT_VERSION : " 3.12.0"
27- TYPOS_VERSION : " 1.43.4"
28- UV_VERSION : " 0.9.28"
27+ CARGO_NEXTEST_VERSION : " 0.9.137"
28+ DPRINT_VERSION : " 0.54.0"
29+ JUST_VERSION : " 1.51.0"
30+ RUMDL_VERSION : " 0.2.4"
31+ TAPLO_VERSION : " 0.10.0"
32+ TYPOS_VERSION : " 1.47.0"
33+ UV_VERSION : " 0.11.16"
34+ ZIZMOR_VERSION : " 1.25.2"
2935
3036jobs :
3137 build :
3238 runs-on : ${{ matrix.os }}
3339 strategy :
34- fail-fast : false # Continue other jobs if one fails
40+ fail-fast : false
3541 matrix :
3642 os :
3743 - ubuntu-latest
@@ -46,190 +52,79 @@ jobs:
4652 target : x86_64-pc-windows-msvc
4753
4854 steps :
55+ - name : Disable Git autocrlf on Windows
56+ if : matrix.os == 'windows-latest'
57+ shell : pwsh
58+ run : |
59+ git config --global core.autocrlf false
60+ git config --global core.eol lf
61+
4962 - uses : actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
63+ with :
64+ persist-credentials : false
5065
5166 - name : Install Rust toolchain
5267 uses : actions-rust-lang/setup-rust-toolchain@46268bd060767258de96ed93c1251119784f2ab6 # v1.16.1
5368 with :
5469 target : ${{ matrix.target }}
55- cache : true # Built-in caching
70+ cache : true
5671 # toolchain, components, etc. are specified in rust-toolchain.toml
5772
58- - name : Install just
59- if : matrix.os != 'windows-latest'
60- uses : taiki-e/install-action@50b4a718b59c718df4ef27a3b445f86cd57b9f00 # v2.80.0
73+ - name : Set up Python
74+ uses : actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
6175 with :
62- tool : just
76+ python-version : " 3.12 "
6377
64- - name : Install uv (for Python scripts and pytest)
65- if : matrix.os != 'windows-latest'
78+ - name : Install uv
6679 uses : astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
6780 with :
6881 version : ${{ env.UV_VERSION }}
82+ enable-cache : true
83+
84+ - name : Sync Python tooling
85+ run : uv sync --locked --group dev
86+
87+ - name : Install just
88+ uses : taiki-e/cache-cargo-install-action@417450f3c33ee20393705369577571770643d4c7 # v3.0.7
89+ with :
90+ tool : just@${{ env.JUST_VERSION }}
6991
70- - name : Install Node.js (for markdownlint)
71- if : matrix.os != 'windows-latest'
72- uses : actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
92+ - name : Install dprint
93+ uses : taiki-e/cache-cargo-install-action@417450f3c33ee20393705369577571770643d4c7 # v3.0.7
7394 with :
74- node-version : " 20 "
95+ tool : dprint@${{ env.DPRINT_VERSION }}
7596
76- - name : Install Node.js packages
77- if : matrix.os != 'windows-latest'
78- run : |
79- npm install -g markdownlint-cli@${{ env.MARKDOWNLINT_VERSION }}
97+ - name : Install rumdl
98+ uses : taiki-e/cache-cargo-install-action@417450f3c33ee20393705369577571770643d4c7 # v3.0.7
99+ with :
100+ tool : rumdl@${{ env.RUMDL_VERSION }}
101+
102+ - name : Install taplo
103+ id : install-taplo
104+ continue-on-error : ${{ matrix.os == 'windows-latest' }}
105+ uses : taiki-e/cache-cargo-install-action@417450f3c33ee20393705369577571770643d4c7 # v3.0.7
106+ with :
107+ tool : taplo-cli@${{ env.TAPLO_VERSION }}
80108
81- - name : Install typos-cli
82- if : matrix.os != 'windows-latest'
83- uses : taiki-e/install-action@50b4a718b59c718df4ef27a3b445f86cd57b9f00 # v2.80.0
109+ - name : Install taplo on Windows after cached install failure
110+ if : matrix.os == 'windows-latest' && steps.install-taplo.outcome == 'failure'
111+ shell : pwsh
112+ run : cargo install --locked taplo-cli --version $env:TAPLO_VERSION
113+
114+ - name : Install typos
115+ uses : taiki-e/cache-cargo-install-action@417450f3c33ee20393705369577571770643d4c7 # v3.0.7
84116 with :
85117 tool : typos-cli@${{ env.TYPOS_VERSION }}
86118
87- - name : Install taplo (for TOML formatting and linting)
88- if : matrix.os != 'windows-latest'
89- uses : taiki-e/install-action@50b4a718b59c718df4ef27a3b445f86cd57b9f00 # v2.80.0
119+ - name : Install zizmor
120+ uses : taiki-e/cache-cargo-install-action@417450f3c33ee20393705369577571770643d4c7 # v3.0.7
90121 with :
91- tool : taplo-cli
122+ tool : zizmor@${{ env.ZIZMOR_VERSION }}
92123
93- - name : Install actionlint (Linux/macOS)
94- if : matrix.os != 'windows-latest'
95- run : |
96- set -euo pipefail
97-
98- # actionlint is published as prebuilt binaries (Go), not a Rust crate.
99- # Install directly from rhysd/actionlint releases to avoid cargo-binstall fallback failures.
100- # Verify SHA256 checksums from the upstream release for supply-chain hardening.
101- OS="$(uname -s)"
102- ARCH="$(uname -m)"
103-
104- case "$OS" in
105- Linux) ACTIONLINT_OS="linux" ;;
106- Darwin) ACTIONLINT_OS="darwin" ;;
107- *)
108- echo "Unsupported OS for actionlint: $OS" >&2
109- exit 1
110- ;;
111- esac
112-
113- case "$ARCH" in
114- x86_64|amd64) ACTIONLINT_ARCH="amd64" ;;
115- arm64|aarch64) ACTIONLINT_ARCH="arm64" ;;
116- *)
117- echo "Unsupported architecture for actionlint: $ARCH" >&2
118- exit 1
119- ;;
120- esac
121-
122- verify_sha256() {
123- local checksum_file="$1"
124- if command -v sha256sum >/dev/null 2>&1; then
125- sha256sum -c "$checksum_file"
126- else
127- shasum -a 256 -c "$checksum_file"
128- fi
129- }
130-
131- VERSION="${ACTIONLINT_VERSION}"
132- TARBALL="actionlint_${VERSION}_${ACTIONLINT_OS}_${ACTIONLINT_ARCH}.tar.gz"
133- CHECKSUMS_FILE="actionlint_${VERSION}_checksums.txt"
134- BASE_URL="https://github.com/rhysd/actionlint/releases/download/v${VERSION}"
135-
136- tmpdir="$(mktemp -d)"
137- trap 'rm -rf "$tmpdir"' EXIT
138-
139- curl -fsSL "${BASE_URL}/${TARBALL}" -o "$tmpdir/$TARBALL"
140- curl -fsSL "${BASE_URL}/${CHECKSUMS_FILE}" -o "$tmpdir/$CHECKSUMS_FILE"
141-
142- orig_dir="$PWD"
143- cd "$tmpdir"
144- awk -v f="$TARBALL" '$NF==f {print; found=1} END {exit found?0:1}' "$CHECKSUMS_FILE" > checksum.txt
145- verify_sha256 checksum.txt
146- cd "$orig_dir"
147-
148- tar -xzf "$tmpdir/$TARBALL" -C "$tmpdir"
149-
150- actionlint_path="$(find "$tmpdir" -type f -name actionlint | head -n 1)"
151- if [[ -z "$actionlint_path" ]]; then
152- echo "actionlint binary not found in $TARBALL" >&2
153- exit 1
154- fi
155-
156- sudo install -m 0755 "$actionlint_path" /usr/local/bin/actionlint
157-
158- - name : actionlint -version
159- if : matrix.os != 'windows-latest'
160- run : actionlint -version
161-
162- - name : Install additional tools (Linux)
163- if : matrix.os == 'ubuntu-latest'
164- run : |
165- # Install shellcheck, jq, and yamllint
166- sudo apt-get update
167- sudo apt-get install -y shellcheck jq yamllint
168-
169- # Install shfmt (pinned for CI consistency)
170- SHFMT_ASSET="shfmt_v${SHFMT_VERSION}_linux_amd64"
171- SHFMT_BASE_URL="https://github.com/mvdan/sh/releases/download/v${SHFMT_VERSION}"
172-
173- tmpdir="$(mktemp -d)"
174- trap 'rm -rf "$tmpdir"' EXIT
175-
176- curl -fsSL \
177- "${SHFMT_BASE_URL}/${SHFMT_ASSET}" \
178- -o "$tmpdir/${SHFMT_ASSET}"
179- curl -fsSL \
180- "${SHFMT_BASE_URL}/sha256sums.txt" \
181- -o "$tmpdir/sha256sums.txt"
182-
183- (
184- cd "$tmpdir"
185- awk -v f="${SHFMT_ASSET}" '$NF==f {print; found=1} END {exit found?0:1}' sha256sums.txt > checksum.txt
186- sha256sum -c checksum.txt
187- )
188-
189- sudo install -m 0755 "$tmpdir/${SHFMT_ASSET}" /usr/local/bin/shfmt
190-
191- - name : Install additional tools (macOS)
192- if : matrix.os == 'macos-latest'
193- run : |
194- # Install shellcheck, jq, and yamllint via Homebrew
195- brew install shellcheck jq yamllint
196-
197- # Install shfmt (pinned for CI consistency with Linux)
198- SHFMT_ARCH="amd64"
199- if [[ "$(uname -m)" == "arm64" ]]; then
200- SHFMT_ARCH="arm64"
201- fi
202-
203- SHFMT_ASSET="shfmt_v${SHFMT_VERSION}_darwin_${SHFMT_ARCH}"
204- SHFMT_BASE_URL="https://github.com/mvdan/sh/releases/download/v${SHFMT_VERSION}"
205-
206- tmpdir="$(mktemp -d)"
207- trap 'rm -rf "$tmpdir"' EXIT
208-
209- curl -fsSL \
210- "${SHFMT_BASE_URL}/${SHFMT_ASSET}" \
211- -o "$tmpdir/${SHFMT_ASSET}"
212- curl -fsSL \
213- "${SHFMT_BASE_URL}/sha256sums.txt" \
214- -o "$tmpdir/sha256sums.txt"
215-
216- (
217- cd "$tmpdir"
218- awk -v f="${SHFMT_ASSET}" '$NF==f {print; found=1} END {exit found?0:1}' sha256sums.txt > checksum.txt
219- shasum -a 256 -c checksum.txt
220- )
221-
222- sudo install -m 0755 "$tmpdir/${SHFMT_ASSET}" /usr/local/bin/shfmt
223-
224- - name : Run CI checks (Linux/macOS)
225- if : matrix.os != 'windows-latest'
226- run : just ci
124+ - name : Install cargo-nextest
125+ uses : taiki-e/cache-cargo-install-action@417450f3c33ee20393705369577571770643d4c7 # v3.0.7
126+ with :
127+ tool : cargo-nextest@${{ env.CARGO_NEXTEST_VERSION }}
227128
228- - name : Build and test (Windows)
229- if : matrix.os == 'windows-latest'
230- run : |
231- cargo build --verbose --all-targets
232- cargo test --lib --verbose
233- cargo test --doc --verbose
234- cargo test --tests --verbose
235- cargo test --features exact --verbose
129+ - name : Run CI checks
130+ run : just ci
0 commit comments