-
Notifications
You must be signed in to change notification settings - Fork 19
239 lines (231 loc) · 10.6 KB
/
ci.yml
File metadata and controls
239 lines (231 loc) · 10.6 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
name: CI
on:
push:
branches: [main]
pull_request:
# Default-deny: CI only needs to read the repo. Narrower than the
# implicit permissions so a compromised action in any job gets the
# minimum required surface.
permissions:
contents: read
env:
CARGO_TERM_COLOR: always
jobs:
rust:
name: Rust (${{ matrix.toolchain }})
runs-on: ubuntu-latest
# Nightly clippy adds new lints constantly; treat it as informational.
continue-on-error: ${{ matrix.toolchain == 'nightly' }}
strategy:
fail-fast: false
matrix:
toolchain: [stable, nightly]
steps:
- uses: actions/checkout@v6
- name: Clone sibling repos
run: |
git clone --depth 1 https://github.com/ecto/tang.git ../tang
git clone --depth 1 https://github.com/ecto/phyz.git ../phyz
git clone --depth 1 https://github.com/ecto/loon.git ../loon
- uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{ matrix.toolchain }}
components: rustfmt, clippy
- uses: Swatinem/rust-cache@v2
# `cargo fmt --all` would traverse into the path-dep workspaces
# (tang/phyz/loon, cloned above). Format only vcad workspace members
# explicitly so external repos don't gate our CI.
- name: Format check (vcad members only)
run: |
cargo metadata --no-deps --format-version 1 \
| python3 -c "import json,sys; d=json.load(sys.stdin); print('\n'.join(p['name'] for p in d['packages']))" \
| xargs -n 1 -I{} cargo fmt -p {} --check
- run: cargo clippy --workspace --exclude vcad-desktop --features vcad-kernel-text/no-builtin-font -- -D warnings
- run: cargo test --workspace --exclude vcad-desktop --features vcad-kernel-text/no-builtin-font
- run: cargo build --workspace --exclude vcad-desktop --examples --features vcad-kernel-text/no-builtin-font
- run: cargo doc --workspace --exclude vcad-desktop --no-deps --features vcad-kernel-text/no-builtin-font
# wasm-pack dominates the TS critical path (~3m23s of a 7m job), so it
# runs as its own job. The TS job starts in parallel and downloads the
# built pkg/ via artifact — no Rust toolchain needed there.
wasm:
name: WASM build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Clone sibling repos
run: |
git clone --depth 1 https://github.com/ecto/tang.git ../tang
git clone --depth 1 https://github.com/ecto/phyz.git ../phyz
git clone --depth 1 https://github.com/ecto/loon.git ../loon
# Include sibling repo commits in the cache key so updates to
# tang/phyz/loon invalidate prebuilt wasm.
- name: Record sibling SHAs
run: |
mkdir -p .sibling-sha
git -C ../tang rev-parse HEAD > .sibling-sha/tang
git -C ../phyz rev-parse HEAD > .sibling-sha/phyz
git -C ../loon rev-parse HEAD > .sibling-sha/loon
# Cache the produced pkg/ directly, keyed on every source input that
# could change the wasm bytes. A hit skips the whole Rust build.
- name: Restore wasm pkg cache
id: wasm-cache
uses: actions/cache@v5
with:
path: |
packages/kernel-wasm/pkg
packages/kernel-wasm/vcad_kernel_wasm.js
packages/kernel-wasm/vcad_kernel_wasm.d.ts
packages/kernel-wasm/vcad_kernel_wasm_bg.wasm
packages/kernel-wasm/vcad_kernel_wasm_bg.wasm.d.ts
# v2 in the key prefix forces eviction of --dev-profile entries
# from before we switched to --profiling.
key: wasm-pkg-v2-${{ runner.os }}-${{ hashFiles('crates/**/src/**', 'crates/**/Cargo.toml', 'Cargo.lock', 'Cargo.toml', '.sibling-sha/*') }}
restore-keys: |
wasm-pkg-v2-${{ runner.os }}-
- uses: dtolnay/rust-toolchain@master
if: steps.wasm-cache.outputs.cache-hit != 'true'
with:
toolchain: stable
targets: wasm32-unknown-unknown
- uses: Swatinem/rust-cache@v2
if: steps.wasm-cache.outputs.cache-hit != 'true'
with:
cache-workspace-crates: true
- name: Install wasm-pack
if: steps.wasm-cache.outputs.cache-hit != 'true'
# Install via cargo so the binary comes through the same trust
# chain as the rest of our Rust toolchain instead of a
# curl-pipe-to-shell from the rustwasm GitHub Pages site.
run: cargo install wasm-pack --locked --version 0.13.1
# --profiling uses cargo release + light `-O` wasm-opt (configured
# in vcad-kernel-wasm/Cargo.toml). Saves ~2m vs default release
# (which runs full wasm-opt). We can't use --dev because the PWA
# plugin in @vcad/app caps precachable assets at 10 MB and
# dev-profile wasm is ~29 MB.
#
# `no-builtin-font` drops the include_bytes!() of
# node_modules/next/.../noto-sans.ttf, which doesn't exist here
# (this job doesn't run `npm ci`). Matches the Rust CI job.
- name: Build wasm (profiling)
if: steps.wasm-cache.outputs.cache-hit != 'true'
run: |
wasm-pack build crates/vcad-kernel-wasm --profiling --target web \
--out-dir ../../packages/kernel-wasm/pkg \
--features no-builtin-font
cp packages/kernel-wasm/pkg/vcad_kernel_wasm* packages/kernel-wasm/
# Freshness of the committed kernel-wasm bindings is NOT verified
# here. The previous `git diff`-against-fresh-build check turned out
# to be platform-dependent: wasm-bindgen 0.2.x emits a handful of
# formatting / doc-comment differences when the host toolchain
# isn't byte-identical (macOS vs Linux runners, LLVM micro-version
# drift, etc.), so the check would fire on every PR authored from a
# non-Linux dev box even when the bindings were logically correct.
#
# The protections that are left standing:
# * Vercel preview builds run `tsc` against the source, so a
# stale .d.ts with a missing export surfaces there.
# * The downstream TypeScript job downloads *this job's* fresh
# wasm-pkg artifact (see upload-artifact below) — consumers
# never read the committed .js/.d.ts via npm/vite at that
# point, so the commit can drift without masking a real break.
#
# To update locally (still good hygiene, still recommended before
# merge):
# cargo install wasm-pack --locked --version 0.13.1
# wasm-pack build crates/vcad-kernel-wasm --profiling --target web \
# --out-dir ../../packages/kernel-wasm/pkg --features no-builtin-font
# cp packages/kernel-wasm/pkg/vcad_kernel_wasm* packages/kernel-wasm/
# git add packages/kernel-wasm/vcad_kernel_wasm* && git commit
- uses: actions/upload-artifact@v7
with:
name: wasm-pkg
path: |
packages/kernel-wasm/pkg
packages/kernel-wasm/vcad_kernel_wasm.js
packages/kernel-wasm/vcad_kernel_wasm.d.ts
packages/kernel-wasm/vcad_kernel_wasm_bg.wasm
packages/kernel-wasm/vcad_kernel_wasm_bg.wasm.d.ts
retention-days: 1
if-no-files-found: error
typescript:
name: TypeScript
runs-on: ubuntu-latest
needs: wasm
steps:
- uses: actions/checkout@v6
- uses: actions/setup-node@v6
with:
node-version: 22
cache: npm
# Pull the wasm pkg built by the `wasm` job. Unpacks into
# packages/kernel-wasm/ (both pkg/ and the root-level copies).
- uses: actions/download-artifact@v8
with:
name: wasm-pkg
path: packages/kernel-wasm
# Turbo local cache. Primary key is the commit SHA (always unique,
# so we always save); restore-keys fall back to the most recent
# entry for the branch/OS. Turbo's own per-task hash determines
# what's reused vs rebuilt — no need to encode inputs in the key.
- name: Restore turbo cache
uses: actions/cache@v5
with:
path: node_modules/.cache/turbo
key: turbo-${{ runner.os }}-${{ github.sha }}
restore-keys: |
turbo-${{ runner.os }}-
# --ignore-scripts skips the canvas native build (hf-space only).
# hf-space has no `build` or `test` task so CI never touches canvas
# at runtime, which lets us drop libcairo/libpango/librsvg apt deps
# (~23s) and the native compile step.
- run: npm ci --prefer-offline --no-audit --no-fund --ignore-scripts
- run: npm run version:check
# VCAD_WASM_SKIP short-circuits vcad-kernel-wasm's build script
# (the `wasm` job already produced pkg/ via the artifact above).
# turbo's task graph still includes vcad-kernel-wasm#build as a
# dep of @vcad/engine#build, so we can't just filter it out —
# the script itself has to become a noop.
#
# @vcad/docs is excluded: it's a Next.js static-site build (~44s,
# 303 pages) that deploys via its own Vercel project, not via CI
# artifacts. Building it in the PR job adds latency without
# exercising anything other code paths don't already cover.
- run: npm run build -- --filter=!@vcad/docs
env:
VCAD_WASM_SKIP: '1'
- run: npm test --workspaces --if-present
# Dependency CVE gate. Informational for now so an unpatched upstream
# advisory doesn't block feature work; flip to blocking (drop the `|| true`
# suffixes) once the team agrees to require a clean audit.
cargo-audit:
name: cargo audit
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Clone sibling repos
run: |
git clone --depth 1 https://github.com/ecto/tang.git ../tang
git clone --depth 1 https://github.com/ecto/phyz.git ../phyz
git clone --depth 1 https://github.com/ecto/loon.git ../loon
- uses: dtolnay/rust-toolchain@master
with:
toolchain: stable
- name: Install cargo-audit
run: cargo install cargo-audit --locked
- name: cargo audit (advisory)
# `|| true` keeps the check green while surfacing findings in the
# log. Drop it to turn this into a merge gate.
run: cargo audit --deny warnings || true
npm-audit:
name: npm audit
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/setup-node@v6
with:
node-version: 22
- name: npm audit (advisory)
# moderate+ is a pragmatic gate — low-severity advisories on dev
# tooling churn too often to block on. See cargo-audit above for
# how to flip this into a blocking check.
run: npm audit --audit-level=moderate || true