Repository navigation
255 lines (238 loc) · 11.3 KB
/
Copy pathmulti-runtime.yml
File metadata and controls
255 lines (238 loc) · 11.3 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
name: multi-runtime
# Verifies actor-ts boots and the core actor + cluster paths work
# identically across Bun, Node.js, and Deno. The smoke harness at
# tests/smoke/run-cases.mjs discovers cases under
# tests/smoke/cases/*.mjs and runs every one on each runtime —
# adding a new case is dropping a new file, no CI edits required.
# Job matrix keeps the runs parallel so the wall clock is bounded
# by the slowest runtime (Deno, ~30s including the build step).
# Bun runs twice: once on `latest` and once pinned to the `engines`
# floor (1.3.0), so the floor we claim is actually exercised.
#
# Bun additionally runs the full `bun test` suite — the unit /
# multi-node suite uses bun:test's APIs and isn't portable to
# Node/Deno. Those two runtimes are exercised only via the smoke
# script + the build output (`dist/`), which is the surface
# end-users would consume.
#
# Triggers identical to test.yml — any change that could plausibly
# affect a test outcome.
on:
push:
# `main` as well as `develop`: `main` moves only via the release merge, and
# that merge commit is the one that gets tagged and published. The
# documented release flow merges `--no-ff` directly rather than through a
# PR, so the `pull_request` leg below never covers it — without `main` here
# the exact commit users install had no Node/Deno signal at all.
branches: [develop, main]
paths:
- 'src/**'
- 'tests/**'
- 'package.json'
- '.bun-version'
- 'bun.lock'
- 'tsconfig.json'
- 'tsconfig.dev.json'
- '.github/workflows/multi-runtime.yml'
pull_request:
branches: [main, develop]
paths:
- 'src/**'
- 'tests/**'
- 'package.json'
- '.bun-version'
- 'bun.lock'
- 'tsconfig.json'
- 'tsconfig.dev.json'
- '.github/workflows/multi-runtime.yml'
workflow_dispatch:
# Least privilege, stated rather than inherited: the repository default is
# read-only today, but a settings flip would otherwise hand a write token to
# a job that installs and runs the whole dependency tree. #621
permissions:
contents: read
jobs:
smoke:
runs-on: ubuntu-latest
timeout-minutes: 20
strategy:
# fail-fast: false so a Deno-only regression doesn't mask a
# Node-only one. Each runtime gets its own red mark.
fail-fast: false
matrix:
runtime: [bun, bun-floor, node, deno]
name: smoke (${{ matrix.runtime }})
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
# Every job needs Bun even for the Node/Deno runs because the
# build step (`bun run build`) emits `dist/` which Node/Deno
# consume. Bun's `setup-bun@v2` is fast (~3s cached) so the
# overhead is acceptable. Two steps rather than one matrix
# expression because the version comes from different places:
# `bun-floor` pins the `engines` floor literally, every other leg
# reads the repo-wide `.bun-version` pin — and setup-bun has no
# input that mixes an inline version with a version file.
- name: Setup Bun (engines floor)
if: matrix.runtime == 'bun-floor'
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
with:
bun-version: '1.3.0'
- name: Setup Bun
if: matrix.runtime != 'bun-floor'
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
with:
bun-version-file: .bun-version
# Install in a Bun-only environment (no Node on PATH), exactly like
# publish.yml: better-sqlite3's postinstall then resolves a prebuilt
# binary for Bun's ABI instead of falling back to a node-gyp source
# build. No smoke case touches better-sqlite3, so the Bun-ABI
# binary is inert for the Node/Deno runs. Frozen, like every other
# install in CI: an unfrozen resolve can green-light a dependency set
# no lockfile records, so the check passes against something nobody
# can reproduce. #622
- name: Install
run: bun install --frozen-lockfile
# Node/Deno are set up AFTER the install (see above). Node stays on
# 24 deliberately — it is the `engines` floor we claim to support.
- name: Setup Node.js
if: matrix.runtime == 'node'
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: '24'
- name: Setup Deno
if: matrix.runtime == 'deno'
uses: denoland/setup-deno@22d081ff2d3a40755e97629de92e3bcbfa7cf2ed # v2.0.5
with:
deno-version: v2.x
# Bun + Deno can load TS directly. The Node job runs the compiled
# output in `dist/` — deliberately, since that is the surface
# end-users consume. Build only for runtimes that need it;
# saves ~20s on the Bun smoke jobs.
- name: Build (tsc → dist/)
if: ${{ !startsWith(matrix.runtime, 'bun') }}
run: bun run build:lib
- name: Smoke (Bun)
if: startsWith(matrix.runtime, 'bun')
run: bun run smoke:bun
- name: Smoke (Node)
if: matrix.runtime == 'node'
run: bun run smoke:node
- name: Smoke (Deno)
if: matrix.runtime == 'deno'
run: bun run smoke:deno
# The full bun:test unit suite runs only under Bun (Bun.serve,
# better-sqlite3 native compile, fastify autoload — these are
# Bun-specific or Bun-tested-only). This job mirrors the
# `test.yml` Bun job but without the README-badge-update side
# effect — that stays in test.yml as the canonical updater.
unit-bun:
runs-on: ubuntu-latest
timeout-minutes: 30
name: bun unit suite
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
with:
bun-version-file: .bun-version
# Frozen, like every other install in CI: an unfrozen resolve can
# green-light a dependency set no lockfile records, so the check
# passes against something nobody can reproduce. #622
- run: bun install --frozen-lockfile
# The root typecheck reaches the DevTools UI through
# scripts/ui-toolchain.mjs, which skips locally and fails hard under CI
# (#483) — so CI is where the nested Angular install has to exist.
# Frozen for the reason above, and written out rather than
# `bun run ui:install`: that script is the developer's unfrozen
# regenerate command, and through it this was the one CI install the
# frozen-install guard could not see (#1622).
- run: bun install --frozen-lockfile --cwd devtools-ui
- run: bun run typecheck
# Every suite, including the three that were quarantined behind
# `ACTOR_TS_SKIP_FLAKY_MNS` until #538's criterion was met and #839
# removed the reason the third one was in there at all.
#
# In shuffled order (#1422), with the seed drawn here and printed rather
# than left to bun: bun reports its own seed in the trailing summary
# block, which it stops printing under GitHub Actions. A seed nobody can
# read is not a reproduction.
#
# **`--parallel` here and deliberately not in `test.yml`** (#1332). It is
# measured, not assumed: on a 32-core machine the suite goes from 293 s to
# 28 s — 10.5x — with 11 962 tests green, and 5 of 5 green when repeated
# under different shuffles. Nothing depends on cross-file state that the
# implied `--isolate` breaks.
#
# The coverage run in `test.yml` stays single-process because the same
# measurement showed why it must: identical execution, but a 19 % larger
# instrumented-line denominator. See the comment on that step.
#
# Running the two gates under *different* schedulings is a small bonus
# rather than a redundancy — one shuffle across one process, one across
# thirty-two, is more of the ordering space than either alone.
- name: Tests, in randomized order
run: |
SEED=$(( (RANDOM << 15) + RANDOM ))
echo "test order seed: --seed=$SEED"
printf 'Test order seed: `--seed=%s`\n' "$SEED" >> "$GITHUB_STEP_SUMMARY"
bun test --parallel --seed="$SEED"
# **The only non-Linux job in the repository** (#816). Every other job across
# all ten workflows runs `ubuntu-latest`, while development happens on
# Windows — and that gap has already shipped a bug: #521, the DevTools UI
# freshness gate that could never pass from a Windows checkout, existed
# precisely because nothing here ran Windows.
#
# The specific thing it buys is not "the same tests again". `bun test`
# enumerates files in a different order on Windows, so a green Linux run
# proves nothing about ordering effects and vice versa — and bun's *runtime*
# semantics differ too, not just its file order: `server.maxConnections` is
# enforced on Windows and not on the Linux runner, which is a whole class of
# defect a Linux-only matrix cannot see.
#
# Deliberately narrower than `unit-bun` above. No `typecheck` and no
# DevTools UI install: the compiler's output does not depend on the OS, and
# the Angular toolchain is a slow install whose staleness gate lives in the
# `build` workflow. What is left is what is actually platform-sensitive —
# the suite, and the cross-runtime smoke cases that open real sockets and
# spawn real processes.
#
# The proposal in #816 also asked for `ACTOR_TS_SKIP_FLAKY_MNS=1` here, to
# match the Linux job. That is not carried over and cannot be: the
# quarantine is gone, all three suites run everywhere, and
# `tests/unit/ci/NoEnvironmentGatedSkips.test.ts` refuses a test an
# environment variable can remove. A Windows-only failure is a finding to
# triage, which is the whole reason for adding the leg.
unit-windows:
runs-on: windows-latest
timeout-minutes: 40
name: bun unit suite (windows)
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
with:
bun-version-file: .bun-version
- run: bun install --frozen-lockfile
# Same shape as the Linux leg: shuffled, with the seed drawn here and
# printed, because bun stops printing its own under GitHub Actions.
# `--parallel` was measured at 10.5x on 32 cores; a hosted runner has
# far fewer, and the floor is 1x.
- name: Tests, in randomized order
shell: bash
run: |
SEED=$(( (RANDOM << 15) + RANDOM ))
echo "test order seed: --seed=$SEED"
printf 'Windows test order seed: `--seed=%s`\n' "$SEED" >> "$GITHUB_STEP_SUMMARY"
bun test --parallel --seed="$SEED"
# The smoke cases are where a platform difference shows up as a hang
# rather than a failure — a socket left open keeps the loop alive — so
# they are worth running on the OS the runtime abstractions were written
# against second.
- name: Smoke (Bun)
run: bun run smoke:bun
- name: Setup Node.js
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: '24'
- name: Build (tsc -> dist/)
run: bun run build:lib
- name: Smoke (Node)
run: bun run smoke:node