Repository navigation
678 lines (592 loc) · 24.2 KB
/
Copy pathci.yaml
File metadata and controls
678 lines (592 loc) · 24.2 KB
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
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
---
name: CI
"on":
push:
branches:
- main
pull_request:
branches:
- main
# Every cargo cache below is keyed on Cargo.lock AND the workspace Cargo.toml.
# actions/cache only saves on a primary-key miss, so a key that ignored
# Cargo.toml froze the cache across a profile change (the cache kept serving
# artifacts of the old profile, and every run recompiled the new one from
# scratch until the next Cargo.lock bump); the restore-keys prefix still
# warms a rotated key from the previous cache.
env:
CARGO_TERM_COLOR: always
CARGO_INCREMENTAL: 0
# Hosted runners occasionally lose DNS for crates.io mid-build; cargo's default of three
# retries with short backoff has not been enough on the Windows smoke job.
CARGO_NET_RETRY: 8
jobs:
build:
name: Build
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-24.04, macos-latest]
env:
RUSTFLAGS: -D warnings
RUST_BACKTRACE: 1
steps:
- name: Checkout repository
uses: actions/checkout@v7
# simlin-mcp's pysimlin_version_matches_latest_tag reads the
# pysimlin-v* tags (setuptools-scm makes the tag the version's
# source of truth) and skips when it sees none. The checkout is
# one commit deep and `fetch-tags: true` adds no tag refspec to
# that fetch (the step's own log line is `git fetch --depth=1
# origin +<sha>:refs/remotes/origin/main`), so the tags are
# fetched by name here; the step fails if there are none, which
# is what keeps the guard from skipping on every run.
- name: Fetch the pysimlin release tags
shell: bash
run: |
git fetch --depth=1 origin 'refs/tags/pysimlin-v*:refs/tags/pysimlin-v*'
test -n "$(git tag --list 'pysimlin-v*')"
- name: Install Rust toolchain
run: rustup show
- name: Cache cargo registry and target
uses: actions/cache@v6
with:
path: |
~/.cargo/registry/index/
~/.cargo/registry/cache/
~/.cargo/git/db/
target/
key: cargo-build-${{ matrix.os }}-${{ hashFiles('**/Cargo.lock', 'Cargo.toml') }}
restore-keys: |
cargo-build-${{ matrix.os }}-
- name: Compile
run: cargo build --workspace --verbose
- name: Compile tests
run: cargo test --workspace --no-run
# 3-minute wall-clock cap on `cargo test` (post-compile). On a
# 4-core runner the step takes 56 to 127 s for the same suite
# (the spread is the runner, not the commit), so the cap is
# 1.4x the slow end: a rail
# against the kind of regression that made PR #461's job
# hit GitHub's 60-minute per-job cap (one test binary there
# took 44 minutes), with little room for the suite to grow.
# Uses the step-level `timeout-minutes`
# field rather than coreutils `timeout(1)` so we do not need
# to special-case macos-latest (which has no `timeout` on
# PATH). Raise in lockstep with scripts/pre-commit if the
# suite legitimately grows past it. See docs/dev/rust.md
# for per-test budget guidance.
- name: Test
timeout-minutes: 3
run: cargo test --workspace
rust:
name: Lint and format Rust
runs-on: ubuntu-24.04
env:
RUSTFLAGS: -D warnings
RUST_BACKTRACE: 1
steps:
- name: Checkout repository
uses: actions/checkout@v7
- name: Install Rust toolchain
run: rustup show
- name: Cache cargo registry and target
uses: actions/cache@v6
with:
path: |
~/.cargo/registry/index/
~/.cargo/registry/cache/
~/.cargo/git/db/
target/
key: cargo-lint-${{ hashFiles('**/Cargo.lock', 'Cargo.toml') }}
restore-keys: |
cargo-lint-
- name: Check formatting
run: cargo fmt -- --check --color=auto
# The same invocation scripts/pre-commit runs. Without `--all-targets`
# no test, example or bench is linted, and without `--all-features` no
# code behind `ext_data` or `ltm_bench` is even compiled, so
# a change that never went through the hook would be held to less here
# than a local commit is.
- name: Lint with Clippy
run: cargo clippy --workspace --all-targets --all-features -- -D warnings
- name: Install cargo-deny
uses: taiki-e/install-action@v2
with:
tool: cargo-deny
# The checks that are a function of this tree alone. `advisories` is
# not: a RUSTSEC entry published tomorrow fails the same commit that
# passed today, so it runs in .github/workflows/advisories.yml (daily,
# and on every change to Cargo.lock or deny.toml), which opens an issue
# rather than turning an unrelated pull request red.
- name: Run cargo-deny (bans, licenses, sources)
run: cargo deny check bans licenses sources
# The gates: every test the Build job cannot run. A test is `#[ignore]`d
# when a debug build takes too long over it (a sweep of the model corpus,
# C-LEARN or World3 compiled and run), so `cargo test` and the pre-commit
# hook skip it and this job is the only thing that holds what it pins. An
# ignored test nothing runs goes stale silently: a pin a later change moved
# is found by whoever next runs it by hand, long after the change.
#
# So `#[ignore]` means exactly "needs an optimized build", and every ignored
# test has to pass here. A test that records a known defect is not ignored:
# it asserts the defect and runs in the Build job, so it fails when the
# defect is fixed.
#
# scripts/gates.sh is the one statement of what runs (the packages, the
# features, the `gates` cargo profile: optimized, with debug assertions and
# overflow checks) and is what a developer runs too. It runs the ignored
# tests only (the Build job runs the rest), plus the tests of `ext_data`,
# the Excel data provider, which no other run compiles.
#
# The run is a few minutes on a four-core runner; the
# caps leave room for several times that, since corpus sweeps are added
# here rather than to the capped debug suite.
gates:
name: Gates (ignored tests, optimized)
runs-on: ubuntu-24.04
timeout-minutes: 60
env:
RUSTFLAGS: -D warnings
RUST_BACKTRACE: 1
steps:
- name: Checkout repository
uses: actions/checkout@v7
- name: Install Rust toolchain
run: rustup show
- name: Cache cargo registry and target
uses: actions/cache@v6
with:
path: |
~/.cargo/registry/index/
~/.cargo/registry/cache/
~/.cargo/git/db/
target/
key: cargo-gates-${{ hashFiles('**/Cargo.lock', 'Cargo.toml') }}
restore-keys: |
cargo-gates-
- name: Compile the gates
run: scripts/gates.sh --no-run
- name: Run the gates
timeout-minutes: 25
run: scripts/gates.sh
coverage:
name: Code Coverage
runs-on: ubuntu-24.04
env:
RUSTFLAGS: -D warnings
RUST_BACKTRACE: 1
steps:
- name: Checkout repository
uses: actions/checkout@v7
- name: Install Rust toolchain
run: rustup show
- name: Cache cargo registry and target
uses: actions/cache@v6
with:
path: |
~/.cargo/registry/index/
~/.cargo/registry/cache/
~/.cargo/git/db/
target/
key: cargo-llvm-cov-${{ hashFiles('**/Cargo.lock', 'Cargo.toml') }}
restore-keys: |
cargo-llvm-cov-
# The suite's pysimlin_version_matches_latest_tag needs the release
# tags, as in the Build job.
- name: Fetch the pysimlin release tags
run: |
git fetch --depth=1 origin 'refs/tags/pysimlin-v*:refs/tags/pysimlin-v*'
test -n "$(git tag --list 'pysimlin-v*')"
- name: Install cargo-llvm-cov
uses: taiki-e/install-action@v2
with:
tool: cargo-llvm-cov
# cargo-llvm-cov needs the llvm-tools component for the pinned
# toolchain. It is deliberately NOT in rust-toolchain.toml: every
# other job (and every developer `rustup show`) would pay the
# download for a component only this job uses.
- name: Install llvm-tools
run: rustup component add llvm-tools
# Source-based LLVM coverage replaced cargo-tarpaulin's default
# ptrace engine (GH #622, #726): ptrace instrumentation ran the
# suite 5-50x slower than native, first blowing a 90-minute cap
# and later violating timing assumptions in libsimlin's
# concurrency tests. llvm-cov instrumentation runs tests at
# near-native speed (native `cargo test --workspace` is one to
# two minutes post-compile), so this cap is a generous backstop dominated by
# the instrumented build: a warm-cache run fits comfortably in
# 30 minutes, and the headroom above that absorbs the cold-cache
# case (first run after a Cargo.lock change or cache eviction
# rebuilds the whole instrumented workspace from scratch). Note
# that unlike tarpaulin, llvm-cov has no per-test 60s
# self-policing -- a runaway test eats the whole cap, and the
# Build job's 3-minute test cap is the primary guard against
# that.
- name: Run cargo-llvm-cov
timeout-minutes: 45
run: cargo llvm-cov --workspace --lcov --output-path lcov.info
- name: Upload Coverage
uses: codecov/codecov-action@v7
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: lcov.info
frontend:
runs-on: ubuntu-24.04
steps:
- name: Checkout
uses: actions/checkout@v7
- name: Install pnpm
uses: pnpm/action-setup@v6
- name: Install node
uses: actions/setup-node@v7
with:
node-version: '22'
cache: 'pnpm'
- name: Install Rust toolchain
run: rustup show
- name: Cache cargo registry and target
uses: actions/cache@v6
with:
path: |
~/.cargo/registry/index/
~/.cargo/registry/cache/
~/.cargo/git/db/
target/
key: cargo-wasm-${{ hashFiles('**/Cargo.lock', 'Cargo.toml') }}
restore-keys: |
cargo-wasm-
- name: Install Python
uses: actions/setup-python@v7
with:
python-version: '3.12'
- name: Install Python dependencies
run: python -m pip install jupyterlab
- name: Install pnpm dependencies
run: pnpm install
# eslint only disables prettier-conflicting rules via
# eslint-config-prettier; this is the step that actually
# enforces prettier formatting (mirrors scripts/pre-commit).
- name: Check TypeScript formatting
run: pnpm js-needs-format
- name: Build the Typescript project
run: DISABLE_WASM_OPT=1 pnpm build
- name: Run TypeScript tests
run: pnpm test
# The production deploy is a local command with no CI gate, so
# without this step a regression in the deploy assembly (build
# outputs landing at the wrong path, hashed bundle not
# referenced from index.html, web component bundle missing,
# etc.) only surfaces during the actual `gcloud app deploy`.
# This re-runs the deploy:assemble step against the existing
# build, asserts the expected artifacts, and runs deploy:clean
# so the workspace is restored before any subsequent steps.
- name: Verify deploy build artifacts
run: |
pnpm --filter @simlin/app run deploy:assemble
bash scripts/verify-deploy-build.sh
pnpm --filter @simlin/app run deploy:clean
# After deploy:clean the working tree should be clean. A
# non-empty `git status` here means deploy:clean is missing
# a path the build wrote into public/.
status=$(git status --porcelain)
if [ -n "$status" ]; then
echo "ERROR: deploy:clean left the working tree dirty:" >&2
echo "$status" >&2
exit 1
fi
pysimlin:
name: pysimlin type check and tests
runs-on: ubuntu-24.04
env:
RUST_BACKTRACE: 1
steps:
- name: Checkout
uses: actions/checkout@v7
- name: Install Rust toolchain
run: rustup show
- name: Cache cargo registry and target
uses: actions/cache@v6
with:
path: |
~/.cargo/registry/index/
~/.cargo/registry/cache/
~/.cargo/git/db/
target/
key: cargo-pysimlin-${{ hashFiles('**/Cargo.lock', 'Cargo.toml') }}
restore-keys: |
cargo-pysimlin-
- name: Install uv
uses: astral-sh/setup-uv@v10.2.0
with:
enable-cache: true
- name: Build libsimlin
run: cargo build --release --manifest-path src/libsimlin/Cargo.toml
- name: Install pysimlin with dev dependencies
working-directory: src/pysimlin
run: |
uv sync --extra dev
uv pip install setuptools
uv run python setup.py build_ext --inplace 2>/dev/null || true
# ruff format --check enforces formatting (ruff check, run by the
# pre-commit pysimlin script, is the linter only and does not).
- name: Check formatting and lint with ruff
working-directory: src/pysimlin
run: |
uv run ruff format --check .
uv run ruff check .
- name: Type check with mypy
working-directory: src/pysimlin
run: uv run mypy simlin/
- name: Run tests
working-directory: src/pysimlin
run: uv run pytest -q --no-cov tests/
pysimlin-e2e:
name: pysimlin notebook editor journey (JupyterLab)
runs-on: ubuntu-24.04
# Dominated by builds (libsimlin release, the wasm32 engine, the diagram
# and widget bundles); the journey itself runs in well under a minute.
# A warm cargo cache brings the whole job to a few minutes; the headroom
# is for a cold cache, which builds two engines from scratch.
timeout-minutes: 45
env:
RUST_BACKTRACE: 1
steps:
- name: Checkout
uses: actions/checkout@v7
- name: Install Rust toolchain
run: rustup show
- name: Install pnpm
uses: pnpm/action-setup@v6
- name: Install node
uses: actions/setup-node@v7
with:
node-version: '22'
cache: 'pnpm'
- name: Cache cargo registry and target
uses: actions/cache@v6
with:
path: |
~/.cargo/registry/index/
~/.cargo/registry/cache/
~/.cargo/git/db/
target/
key: cargo-pysimlin-e2e-${{ hashFiles('**/Cargo.lock', 'Cargo.toml') }}
restore-keys: |
cargo-pysimlin-e2e-
- name: Install uv
uses: astral-sh/setup-uv@v10.2.0
with:
enable-cache: true
- name: Install pnpm dependencies
run: pnpm install --frozen-lockfile
- name: Build libsimlin
run: cargo build --release --manifest-path src/libsimlin/Cargo.toml
# The widget bundle and its workspace deps (@simlin/engine builds the
# wasm32 engine, @simlin/core, @simlin/diagram) in topological order;
# the widget's build ends by staging widget.js and the wasm into
# src/pysimlin/simlin/_widget/ (scripts/stage_widget_assets.py).
# DISABLE_WASM_OPT=1 marks a gate build: no multi-minute wasm-opt pass,
# and the `wasm-gate` cargo profile (no LTO, parallel codegen) for the
# engine. The journey exercises the widget's behaviour, not the
# shipped blob's size or speed.
- name: Build the notebook widget and stage its assets into pysimlin
env:
DISABLE_WASM_OPT: "1"
run: pnpm --filter "@simlin/notebook-widget..." run build
- name: Install pysimlin with the dev and e2e extras
working-directory: src/pysimlin
run: |
uv sync --extra dev --extra e2e
uv pip install setuptools
uv run python setup.py build_ext --inplace
# The version pinned by the root package.json's @playwright/test.
- name: Install Playwright chromium
run: pnpm exec playwright install --with-deps chromium
- name: Run the JupyterLab journey
run: make -C src/pysimlin e2e
# The example notebook, executed headless in a real kernel (nbconvert
# comes with jupyterlab), then exported to HTML twice: with the stored
# widget state (the widget view + embedded state) and without it (the
# SVG fallback static renderers show). The script-style run in
# tests/test_examples.py cannot see the display path; this can.
- name: Execute and export the example notebook headless
run: make -C src/pysimlin export-check
# Screenshots, the trace, and the jupyter server log are what a failed
# journey needs to be understood. They live in a dot-directory, and
# upload-artifact skips hidden files unless told otherwise (it then
# finds nothing at all). Nothing to upload is a warning, not an error:
# this step also runs when an earlier build step failed, before the
# journey wrote anything.
- name: Upload journey output
if: failure()
uses: actions/upload-artifact@v7
with:
name: pysimlin-e2e-output
path: src/pysimlin/e2e/.output/
include-hidden-files: true
if-no-files-found: warn
policy:
name: Policy checks
runs-on: ubuntu-24.04
steps:
- name: Checkout
uses: actions/checkout@v7
- name: Install ripgrep
run: sudo apt-get install -y ripgrep
- name: Install Python
uses: actions/setup-python@v7
with:
python-version: '3.12'
- name: Check dependency policy
run: python3 scripts/check-deps.py
- name: Check documentation links
run: python3 scripts/check-docs.py
- name: Run project lint rules
run: bash scripts/lint-project.sh
# The embedded SPA is built ONCE, on ubuntu, and handed to the smoke legs
# as an artifact. web/dist/ is platform-independent (wasm, JS, CSS), and
# building it per leg cost every leg two wasm engine builds, which on the
# 4-core macOS and Windows runners was 8 to 16 minutes by itself and pushed
# the Windows leg past its cap (GH #1054).
serve-web:
name: simlin-serve embedded SPA
runs-on: ubuntu-24.04
timeout-minutes: 20
steps:
- name: Checkout
uses: actions/checkout@v7
- name: Install Rust toolchain
run: rustup show
- name: Install pnpm
uses: pnpm/action-setup@v6
- name: Install node
uses: actions/setup-node@v7
with:
node-version: '24'
cache: 'pnpm'
# Same key family as the frontend job: both build the same gate-profile
# wasm engine into the same target directories, so they share one cache.
- name: Cache cargo registry and target
uses: actions/cache@v6
with:
path: |
~/.cargo/registry/index/
~/.cargo/registry/cache/
~/.cargo/git/db/
target/
key: cargo-wasm-${{ hashFiles('**/Cargo.lock', 'Cargo.toml') }}
restore-keys: |
cargo-wasm-
- name: Install workspace dependencies
run: pnpm install --frozen-lockfile
# `rsbuild build` only builds the @simlin/serve-web package; it
# does NOT build its workspace dependencies. The pnpm `...` filter
# selects serve-web AND its transitive deps (@simlin/core,
# @simlin/engine, @simlin/diagram) in topological order so each
# one's `lib/`/`lib.browser/`/`dist/` output exists before rsbuild
# tries to resolve them. DISABLE_WASM_OPT=1 marks a gate build of
# the engine package: no wasm-opt pass, and the `wasm-gate` cargo
# profile (no LTO, parallel codegen; see the workspace Cargo.toml)
# -- release-quality WASM is irrelevant for a smoke test of the
# serve binary.
- name: Build embedded SPA (with workspace deps)
env:
DISABLE_WASM_OPT: "1"
run: pnpm --filter "@simlin/serve-web..." run build
- name: Upload the SPA for the smoke legs
uses: actions/upload-artifact@v7
with:
name: serve-web-dist
path: src/simlin-serve/web/dist
if-no-files-found: error
retention-days: 1
serve-smoke:
name: simlin-serve smoke (${{ matrix.os }})
needs: serve-web
runs-on: ${{ matrix.os }}
# One release compile of simlin-engine, simlin-mcp-core and simlin-serve
# (fat LTO, the profile that ships) and then the smoke test itself, which
# runs in well under a second. Warm-cache runs are 5 to 9 minutes; the
# headroom is for a cold cache, which rebuilds the whole dependency
# closure under LTO on a 4-core runner.
timeout-minutes: 30
strategy:
fail-fast: false
matrix:
# The platforms whose runtime behaviour the smoke test can exercise.
# Windows is covered by serve-windows-check below: the smoke module
# is compiled out there (tech-debt #38), so a Windows leg here would
# spend a release LTO build on running zero tests. The @simlin/serve
# npm matrix (serve-release.yml) additionally ships linux-arm64 and
# win32-x64, both cross-compiled; neither is a GitHub-hosted runner
# option, and linux-x64 covers the Linux runtime path.
os: [ubuntu-24.04, macos-latest]
env:
RUST_BACKTRACE: 1
steps:
- name: Checkout
uses: actions/checkout@v7
- name: Install Rust toolchain
run: rustup show
- name: Cache cargo registry and target
uses: actions/cache@v6
with:
path: |
~/.cargo/registry/index/
~/.cargo/registry/cache/
~/.cargo/git/db/
target/
key: cargo-serve-smoke-${{ matrix.os }}-${{ hashFiles('**/Cargo.lock', 'Cargo.toml') }}
restore-keys: |
cargo-serve-smoke-${{ matrix.os }}-
# Restored to the path build.rs and rust-embed read, so the binary the
# test spawns embeds this SPA. The smoke test asserts the entry point is
# actually served, which is what catches a missing or empty embed.
- name: Download the embedded SPA
uses: actions/download-artifact@v8
with:
name: serve-web-dist
path: src/simlin-serve/web/dist
# The smoke test lives in the consolidated `integration` harness;
# `smoke::` filters to just its tests (all `#[ignore]`d, hence
# `--ignored`). Cargo builds the `simlin-serve` binary the test spawns
# (`CARGO_BIN_EXE_simlin-serve`) as part of this invocation, so there
# is no separate build step. The run command is quoted because a plain
# YAML scalar ending in `:` parses as a mapping key, which made the
# whole workflow file invalid (every CI run since failed at startup
# with zero jobs).
- name: Run smoke test
run: 'cargo test -p simlin-serve --release --test integration -- --ignored --nocapture smoke::'
# simlin-serve's Windows-only code (the path resolution and watcher
# branches under cfg(windows)) compiles nowhere else, and the smoke test is
# compiled out on Windows (tech-debt #38), so this is a type-check of every
# target rather than a release build that would run nothing. The shipped
# win32-x64 binary is cross-compiled for the GNU target by
# serve-release.yml; this job is what tells a PR that the crate no longer
# builds on Windows at all.
serve-windows-check:
name: simlin-serve check (windows-latest)
runs-on: windows-latest
timeout-minutes: 20
env:
RUSTFLAGS: -D warnings
RUST_BACKTRACE: 1
steps:
- name: Checkout
uses: actions/checkout@v7
- name: Install Rust toolchain
run: rustup show
- name: Cache cargo registry and target
uses: actions/cache@v6
with:
path: |
~/.cargo/registry/index/
~/.cargo/registry/cache/
~/.cargo/git/db/
target/
key: cargo-serve-check-windows-latest-${{ hashFiles('**/Cargo.lock', 'Cargo.toml') }}
restore-keys: |
cargo-serve-check-windows-latest-
- name: Type-check every simlin-serve target
run: cargo check -p simlin-serve --all-targets