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
# Inline CI per the T014 pragmatic-path decision (E003 reusable workflow does
# not yet exist in the umbrella repo). When E003 v1.0.0 ships, this file is
# replaced by a thin caller of `<umbrella>/.github/workflows/port-ci.yml@v1.0.0`.
#
# Mirrors the gates documented in `specs/00002-next-port-selection/plan.md`
# §Testing Strategy: Clippy strict, rustfmt, cargo audit, full DDR-003
# cross-compile matrix, snapshot suite, compat-matrix drift test, MSRV gate,
# public-api drift, completions drift, atomic-safety fault-injection.
name: CI
on:
push:
branches:
tags:
pull_request:
branches:
env:
CARGO_TERM_COLOR: always
RUST_BACKTRACE: 1
# Pinned locale for byte-equality fixture assertions (see
# tests/common/mod.rs::assert_pinned_env and fixtures/README.md). MUST
# be inherited by every job that runs `cargo test`.
LC_ALL: C.UTF-8
# Minimum permissions for the default GITHUB_TOKEN. `contents: read` is what
# `actions/checkout` needs to fetch the repo; declaring it explicitly avoids
# auth failures under restrictive org/repo workflow-permission defaults.
permissions:
contents: read
jobs:
fmt:
name: rustfmt
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
with:
components: rustfmt
- run: cargo fmt --all -- --check
clippy:
name: clippy (deny warnings)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
with:
components: clippy
- uses: Swatinem/rust-cache@v2
- run: cargo clippy --all-targets --all-features -- -D warnings
audit:
name: cargo audit
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
# Install a stable toolchain so any rustup-aware tool that runs outside
# the workspace gets a workable Rust. We do NOT cd into the repo before
# invoking cargo-audit so the repo's `rust-toolchain.toml` (1.85 pin)
# doesn't engage during the install step.
- uses: dtolnay/rust-toolchain@stable
# Prebuilt cargo-audit binary — avoids compiling from source, which
# would fail under 1.85 due to icu_*/home/time crates bumping MSRV
# to 1.86+.
- uses: taiki-e/install-action@v2
with:
tool: cargo-audit
# cargo audit reads `.cargo/audit.toml` automatically; documented
# ignores there (e.g., RUSTSEC-2026-0009 — transitive time-via-lopdf
# blocked by 1.85 MSRV) carry through to this step. The explicit
# `--ignore` flags belt-and-suspender that contract for runners that
# might not pick up the config file.
- run: cargo audit --ignore RUSTSEC-2026-0009
env:
# Force stable for this step in case `cargo` is wrapped by rustup
# and detects the workspace's rust-toolchain.toml.
RUSTUP_TOOLCHAIN: stable
msrv:
name: MSRV (1.85)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@1.85
- uses: Swatinem/rust-cache@v2
- run: cargo build --all-features
- run: cargo test --all-features
test:
name: test ${{ matrix.target }}
needs:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
include:
-
-
-
-
-
env:
LC_ALL: C.UTF-8
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.target }}
# The workspace pins to 1.85 via rust-toolchain.toml. dtolnay added the
# target to the stable channel, but cargo will switch to 1.85 when run
# from the workspace — and 1.85 doesn't have the cross-compile target
# installed. Add it explicitly here.
- name: Add cross-compile target to 1.85 toolchain
if: '!matrix.cross'
run: rustup target add ${{ matrix.target }} --toolchain 1.85
shell: bash
- uses: Swatinem/rust-cache@v2
with:
key: ${{ matrix.target }}
- name: Install cross
if: matrix.cross
run: cargo install cross --locked
- name: Build
run: |
if [ "${{ matrix.cross }}" = "true" ]; then
cross build --release --target ${{ matrix.target }} --all-features
else
cargo build --release --target ${{ matrix.target }} --all-features
fi
shell: bash
- name: Test
if: matrix.cross != true
run: cargo test --release --target ${{ matrix.target }} --all-features
- name: Library-without-binary build
if: matrix.target == 'x86_64-unknown-linux-gnu'
run: cargo build --no-default-features
library-no-default-features:
name: library-without-binary
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- run: cargo build --no-default-features
- run: cargo test --no-default-features --lib
publish-dry-run:
name: cargo publish --dry-run
needs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- run: cargo publish --dry-run --all-features