-
Notifications
You must be signed in to change notification settings - Fork 2
348 lines (335 loc) Β· 15.6 KB
/
Copy pathci.yml
File metadata and controls
348 lines (335 loc) Β· 15.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
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
name: CI
on:
push:
branches: [main]
pull_request:
# Every job here reads the repository and writes nothing back, so the token is
# narrowed once at the top rather than per job. The repository default is
# already `read`, which makes this a guard against that setting being widened
# later rather than a change in what the jobs can do today.
permissions:
contents: read
# Clean adoption resolves a fresh dependency graph outside the checkout. Keep
# its installer independent of whichever npm release ships with the Node runner.
env:
CLEAN_ADOPTION_NPM_VERSION: 11.6.4
jobs:
check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
with:
persist-credentials: false
- uses: pnpm/action-setup@0977fd99725f1db4007ccb2928dbb4e90d06cc86 # v6
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7
with:
node-version: 22
cache: pnpm
- run: pnpm install --frozen-lockfile
- name: Build the documentation site and check its Markdown integrations
run: pnpm docs:check
- name: Check the drawing-game source snippets
run: pnpm example:drawing-game:snippets:check
- run: pnpm typecheck
- run: pnpm lint
- run: pnpm format:check
test:
name: test (${{ matrix.os }}, node ${{ matrix.node }})
runs-on: ${{ matrix.os }}
strategy:
# One version failing should not hide the others.
fail-fast: false
matrix:
# The versions still in maintenance. Node 20 left it in April 2026, which
# is why it is not here; that pnpm 11 cannot install on it either is a
# consequence, not the reason, so raising pnpm does not raise this list.
# What the published package supports is a separate question, answered by
# `engines.node` and guarded by the `node-floor` job below.
os: [ubuntu-latest]
node: [22, 24]
# Every Node version on Linux, and one job each for the other two systems
# rather than a full cross product, which would be six jobs to answer a
# question two can. smocket ships as a devDependency and runs on
# contributors' machines rather than on a server, so an operating system
# the dual run has never been executed on is a gap in the central claim,
# not a convenience. `lts/*` tracks the current LTS so this does not need
# editing every October; it is a toolchain choice and deliberately not
# tied to `engines.node`, which a consumer's own runner honors instead.
include:
- os: windows-latest
node: lts/*
- os: macOS-latest
node: lts/*
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
with:
persist-credentials: false
- uses: pnpm/action-setup@0977fd99725f1db4007ccb2928dbb4e90d06cc86 # v6
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7
with:
node-version: ${{ matrix.node }}
cache: pnpm
- run: pnpm install --frozen-lockfile
- name: Run the suite against real socket.io
run: pnpm test:real
# The mock suite hard-gates like any other check: a mock regression fails
# it, and with it the badge.
- name: Run the suite against smocket
run: pnpm test:mock
# The example is documentation that executes, so it rots the moment nothing
# runs it. This builds `dist/` and runs the program, which fails the job if
# the example stops working against the package it demonstrates.
- name: Run the chat room example
run: pnpm example:chat-room
- name: Compare the drawing game against both Node targets
run: pnpm example:drawing-game:test
browser:
name: browser (chromium)
needs: package
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
with:
persist-credentials: false
- uses: pnpm/action-setup@0977fd99725f1db4007ccb2928dbb4e90d06cc86 # v6
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7
with:
node-version: 22
cache: pnpm
- run: pnpm install --frozen-lockfile
- name: Install the clean-adoption npm runner
run: npm install --global "npm@$CLEAN_ADOPTION_NPM_VERSION"
- name: Download the verified release candidate
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
with:
name: release-candidate-${{ github.event.pull_request.head.sha || github.sha }}
path: .release-candidate
- name: Install Chromium for Playwright
run: pnpm exec playwright install --with-deps chromium
# Only the mock target has a counterpart in a page, so this asks a narrower
# question than the dual run. Does the mock behave in a browser the way it
# behaves in Node. #139 is what happens without it.
- name: Run the mock target in a browser
run: pnpm test:browser
- name: Prove one SharedWorker lobby across three Chromium tabs
run: pnpm test:shared-worker
- name: Verify production SharedWorker tab lifecycle
run: xvfb-run --auto-servernum pnpm test:shared-worker:lifecycle
- name: Reject unexpected SharedWorker page errors
run: xvfb-run --auto-servernum pnpm test:shared-worker:errors
- name: Compare SharedWorker with a real Socket.IO sidecar
run: pnpm test:shared-worker:parity
- name: Run the documented SharedWorker lobby
run: pnpm example:shared-worker
- name: Run the drawing game across three pages and both targets
run: pnpm example:drawing-game:verify
- name: Run candidate packages in Chromium
run: pnpm consumer:client:candidate -- --manifest .release-candidate/release-candidate.json --browser
node-floor:
name: declared node floor
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
with:
persist-credentials: false
- uses: pnpm/action-setup@0977fd99725f1db4007ccb2928dbb4e90d06cc86 # v6
# Install and build on a version the toolchain runs on. pnpm 11 needs
# 22.13, so this half cannot move down and does not need to: what it
# produces is `dist/`, and `dist/` is what the two steps below run.
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7
with:
node-version: 22
cache: pnpm
- run: pnpm install --frozen-lockfile
- name: Install the Node 20 compatibility runner
run: pnpm --dir compat/node20 install --frozen-lockfile
- run: pnpm build
- run: pnpm --filter smocket-client build
# Lower tier: the exact floor `engines.node` declares. Nothing installed
# is invoked here, not even pnpm, because pnpm 11 would not start on this
# version either. `scripts/smoke.mjs` imports `node:assert` and `dist/`
# and nothing else, so whatever Node can run the package can run it. It
# drives one room broadcast rather than only importing the module, so a
# `>=20` that delivers nothing fails here instead of shipping.
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7
with:
node-version: 20.0.0
- run: node scripts/smoke.mjs
- run: node --test packages/smocket-client/test/runtime.test.mjs packages/smocket-client/test/runtime.test.cjs
# Upper tier: the whole mock suite against `dist/` on Node 20.13.0. The
# exact 20.0.0 floor can collect this suite, but its fake timer cleanup
# does not complete. The smoke checks above cover that exact runtime,
# while this tier keeps the broader package behavior on Node 20.
#
# The root suite uses Vitest 5, which requires Node 22.12 or newer. This
# tier invokes Vitest 4 from `compat/node20` instead, which keeps the
# runner in a dedicated lockfile without executing unsupported Vitest 5
# code.
# The `node_modules` installed above is reused as is. Node 20 resolves
# pnpm's links without a reinstall or a separate artifact.
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7
with:
node-version: 20.13.0
- name: Reject a missing SharedWorker artifact with the Node 20 runner
run: node scripts/check-shared-worker-dist-gate.mjs
env:
SMOCKET_DIST_VITEST: compat/node20/node_modules/vitest/vitest.mjs
- run: node compat/node20/node_modules/vitest/vitest.mjs run --config vitest.dist.config.ts
compat:
name: real target (socket.io ${{ matrix.socketio }})
runs-on: ubuntu-latest
strategy:
matrix:
# Exercise the oracle across its supported range, not one pinned version.
socketio: ['4.7', '4.8']
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
with:
persist-credentials: false
- uses: pnpm/action-setup@0977fd99725f1db4007ccb2928dbb4e90d06cc86 # v6
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7
with:
node-version: 22
cache: pnpm
- run: pnpm install --frozen-lockfile
- name: Pin socket.io ${{ matrix.socketio }}
run: pnpm add --workspace-root -D socket.io@${{ matrix.socketio }} socket.io-client@${{ matrix.socketio }}
- name: Typecheck against socket.io ${{ matrix.socketio }}
run: pnpm typecheck
- name: Run the suite against real socket.io ${{ matrix.socketio }}
run: pnpm test:real
conformance:
name: conformance report
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
with:
persist-credentials: false
- uses: pnpm/action-setup@0977fd99725f1db4007ccb2928dbb4e90d06cc86 # v6
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7
with:
node-version: 22
cache: pnpm
- run: pnpm install --frozen-lockfile
# docs/conformance.md is generated from a dual run, so it is only true as
# long as it matches the suite. This runs the same generation and fails if
# the committed file has drifted, which is what keeps the report evidence
# rather than a claim someone forgot to update. It runs both targets again
# rather than reusing the `test` job, because the report needs the two
# results side by side and that job reports them separately per platform.
- name: Check the conformance report is current
run: pnpm check:conformance
public-surface:
name: public surface ledger
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
with:
persist-credentials: false
- uses: pnpm/action-setup@0977fd99725f1db4007ccb2928dbb4e90d06cc86 # v6
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7
with:
node-version: 22
cache: pnpm
- run: pnpm install --frozen-lockfile
# This owns upstream declaration and classification drift only. The packed
# manifest, dependency policy, and import scanner remain in `package`.
- name: Check the reviewed upstream public surface
run: pnpm check:public-surface
- name: Reject classifications that reference closed issues
run: pnpm check:public-surface-issues
env:
GITHUB_TOKEN: ${{ github.token }}
published-type-version:
name: published type version
if: github.event_name == 'pull_request'
needs: package
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
with:
fetch-depth: 0
persist-credentials: false
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7
with:
node-version: 22
- name: Detect synchronized package version changes
id: versions
env:
BASE_SHA: ${{ github.event.pull_request.base.sha }}
run: node scripts/check-published-types.mjs detect --base "$BASE_SHA" >> "$GITHUB_OUTPUT"
- if: steps.versions.outputs.changed == 'true'
uses: pnpm/action-setup@0977fd99725f1db4007ccb2928dbb4e90d06cc86 # v6
- if: steps.versions.outputs.changed == 'true'
run: pnpm install --frozen-lockfile
- if: steps.versions.outputs.changed == 'true'
name: Download the synchronized release candidate
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
with:
name: release-candidate-${{ github.event.pull_request.head.sha || github.sha }}
path: .release-candidate
- if: steps.versions.outputs.changed == 'true'
name: Enforce the published public-type version boundary
env:
BASE_SHA: ${{ github.event.pull_request.base.sha }}
run: |
pnpm check:published-types check \
--base "$BASE_SHA" \
--manifest .release-candidate/release-candidate.json
coverage:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
with:
persist-credentials: false
- uses: pnpm/action-setup@0977fd99725f1db4007ccb2928dbb4e90d06cc86 # v6
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7
with:
node-version: 22
cache: pnpm
- run: pnpm install --frozen-lockfile
# Coverage of smocket's own code, which only the mock target exercises; it
# gates on the thresholds in vitest.config.ts.
- name: Coverage against smocket
run: pnpm coverage
# The gate above is the check that matters. This upload only feeds the
# Codecov report, and it needs the CODECOV_TOKEN secret even on a public
# repository, since a tokenless upload is rejected. It never fails the job,
# so a Codecov outage or a missing token costs the report and not the run.
- name: Upload coverage to Codecov
uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7
with:
files: ./coverage/lcov.info
token: ${{ secrets.CODECOV_TOKEN }}
fail_ci_if_error: false
package:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
with:
persist-credentials: false
- uses: pnpm/action-setup@0977fd99725f1db4007ccb2928dbb4e90d06cc86 # v6
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7
with:
node-version: 22
cache: pnpm
- run: pnpm install --frozen-lockfile
- name: Install the clean-adoption npm runner
run: npm install --global "npm@$CLEAN_ADOPTION_NPM_VERSION"
- name: Build one immutable two-package release candidate
run: pnpm release:candidate
- name: Reject external imports in the built root package
run: pnpm assert:no-imports
# Package policy, Publint, Are The Types Wrong, and both independent
# consumers receive the exact tarballs named by this digest manifest.
- name: Verify every package and candidate consumer against one artifact set
run: pnpm check:release-candidate
- name: Preserve the verified candidate for later read-only jobs
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
with:
name: release-candidate-${{ github.event.pull_request.head.sha || github.sha }}
path: .release-candidate
if-no-files-found: error
include-hidden-files: true
retention-days: 7