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
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
name: CI
on:
push:
branches:
pull_request:
env:
CARGO_TERM_COLOR: always
RUSTFLAGS: -D warnings
jobs:
fmt:
name: Format
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: dtolnay/rust-toolchain@stable
with:
components: rustfmt
- run: cargo fmt --all --check
clippy:
name: Clippy (${{ matrix.name }})
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
include:
# The shipped configuration.
- name: default
flags: ""
# The real hygiene floor. Code inside `#[cfg(feature = ...)]` is only
# linted when that feature is on, and a `#[cfg(not(feature = ...))]`
# block is only compiled when it is off -- so a single default-feature
# pass leaves half the crate unlinted. The consuming CMS learned this
# the expensive way; the lesson is imported rather than repeated.
- name: no-default-features
flags: "--no-default-features"
steps:
- uses: actions/checkout@v7
- uses: dtolnay/rust-toolchain@stable
with:
components: clippy
- uses: Swatinem/rust-cache@v2
# --all-targets, always: a bare `cargo clippy` lints only the lib and
# skips tests/ and benches/ entirely.
- run: cargo clippy --all-targets ${{ matrix.flags }} -- -D warnings
test:
name: Test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- run: cargo test --all-features
# The README's examples, actually executed. Compiling them proves they
# type-check; only running them proves the outputs the README quotes.
- run: cargo run --example readme --all-features
docs:
name: Docs
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- run: cargo doc --no-deps --all-features
env:
RUSTDOCFLAGS: -D warnings
# `rust-version` is a promise to consumers, and every other job runs on
# stable, so nothing else here tests it. `--lib` is what a consumer compiles;
# `check` is the question the field actually answers.
msrv:
name: MSRV
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: dtolnay/rust-toolchain@1.96
- uses: Swatinem/rust-cache@v2
- run: cargo check --lib
- run: cargo check --lib --no-default-features
standalone:
name: Standalone (Invariant 1)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- run: ./scripts/check-standalone.sh
# The binding crate, on the only target it is built for. Separate from the
# `Clippy` and `Test` jobs because those run `default-members`, which is the
# library alone: a member is never linted or tested by accident, only on
# purpose, and this is the purpose.
#
# The tests run in Node rather than on the host. A `js_sys::Object` has no
# meaning outside a JavaScript engine, so a host-side test of the same mapping
# would be a test of a different program. `wasm-bindgen-test-runner` has to
# match the `wasm-bindgen` the crate compiles against, which is why the
# version is pinned here and bumped with it.
wasm:
name: WebAssembly
runs-on: ubuntu-latest
env:
WASM_BINDGEN_VERSION: 0.2.128
steps:
- uses: actions/checkout@v7
- uses: dtolnay/rust-toolchain@stable
with:
targets: wasm32-unknown-unknown
components: clippy
- uses: Swatinem/rust-cache@v2
# `RUSTFLAGS: -D warnings` is set for the whole workflow and would other-
# wise apply to wasm-bindgen-cli's own dependency tree, failing the job on
# a warning in code this repository does not own.
- name: Install the test runner
env:
RUSTFLAGS: ""
run: cargo install wasm-bindgen-cli --version "$WASM_BINDGEN_VERSION" --locked
- run: cargo clippy -p accent-proust-wasm --all-targets --target wasm32-unknown-unknown -- -D warnings
- run: cargo build -p accent-proust-wasm --release --target wasm32-unknown-unknown
- name: Run the bindings in Node
env:
CARGO_TARGET_WASM32_UNKNOWN_UNKNOWN_RUNNER: wasm-bindgen-test-runner
run: cargo test -p accent-proust-wasm --target wasm32-unknown-unknown
# The npm package is the shipped artifact, so building it is a gate
# rather than a release-day surprise. `--pack` runs `npm pack --dry-run`,
# which is what catches a malformed `package.json`: nothing else here
# parses that file.
- name: Build the npm package
run: ./scripts/build-npm.sh --pack
# The vocabulary both hosts read. Not in `default-members` either, and the
# crate both hosts depend on, so its own gate rather than a ride on theirs:
# a lint that slipped here would surface as a failure in whichever host
# built first, pointing at the wrong crate.
schema-config:
name: Schema config
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: dtolnay/rust-toolchain@stable
with:
components: clippy
- uses: Swatinem/rust-cache@v2
- run: cargo clippy -p accent-proust-schema-config --all-targets -- -D warnings
- run: cargo test -p accent-proust-schema-config
# The command-line host. Not in `default-members`, so none of the jobs above
# reach it; this is its whole gate. The same shape as `Test` plus clippy over
# every target, because the integration tests drive the built binary and are
# the part most worth linting.
cli:
name: CLI
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: dtolnay/rust-toolchain@stable
with:
components: clippy
- uses: Swatinem/rust-cache@v2
- run: cargo clippy -p accent-proust-cli --all-targets -- -D warnings
- run: cargo test -p accent-proust-cli
# The corpus is redistribution, and `spec/UPSTREAM.md` says so in prose: "These
# files are never edited." Prose does not fail a build, and this one was broken
# within a month by a dependency bot that bumped a manifest no test reads --
# eight green checks on the pull request, because nothing here runs JavaScript.
# Ignoring `spec/**` in renovate.json aims at that one bot; this aims at the
# invariant, and catches a hand edit too. No toolchain and no cache: it is a
# blobless depth-1 fetch of two upstream paths and a diff.
vendored:
name: Vendored corpus
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- run: ./scripts/check-vendored.sh
# The conformance ratchet. Deliberately not an absolute 105/105 gate: that
# would leave every pull request failing a required check from the day the
# harness merged until the formatter lands, which destroys the red/green
# signal precisely while it matters most. Instead the harness compares the run
# against `conformance-baseline.txt` and fails on any drift -- a drop is a
# regression, a rise is a baseline that was not updated in the same commit.
conformance:
name: Conformance
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
# --nocapture because a passing test's output is swallowed, and the count
# is the point of the run. `shell: bash` for pipefail, so a failing test
# is not hidden by the successful `tee` after it.
- name: Run the corpus
shell: bash
run: cargo test --test conformance -- --nocapture | tee conformance.log
# The counter is the epic's shared progress signal, so it goes where it
# can be read without opening a log: the run summary, on success and on
# failure alike.
- name: Publish the count
if: always()
shell: bash
run: |
{
echo '```text'
# --nocapture prints the report inline with libtest's own line, so
# the count is matched anywhere on a line, not anchored to its start.
sed -n '/conformance: [0-9]/,$p' conformance.log || true
echo '```'
} >> "$GITHUB_STEP_SUMMARY"