-
Notifications
You must be signed in to change notification settings - Fork 2
167 lines (156 loc) · 7.01 KB
/
Copy pathexamples.yml
File metadata and controls
167 lines (156 loc) · 7.01 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
name: examples
# Two jobs over `examples/`, answering two different questions.
#
# frontend — do the eight bundled example frontends still install and
# build? (#903)
# snippets — do the standalone examples still *run*? (#545)
#
# Installs and builds the eight bundled example frontends (#903).
#
# The two React legs were added by #540. `tsconfig.dev.json` excludes
# every `examples/*/frontend-*` directory — their dependencies come from
# the per-directory `npm ci` below and are unresolvable from the root
# install — and React was the only pair this matrix did not already
# cover, so without them those two directories would have had no check
# of any kind.
#
# These directories had no CI coverage at all until now: no workflow
# carried `examples/**` in a path filter, so a PR touching only the
# examples produced *zero* checks. #890 (a six-directory dependency
# change) is the worked example — it reported an empty check rollup.
#
# What that cost: `ts-pattern` was declared in all six example
# `package.json` files and missing from all six `package-lock.json`
# files, so `npm ci` failed in every example frontend on `develop` and
# nothing noticed, because nothing installs them. Both failure modes
# this job checks are ones that actually happened:
#
# - `npm ci` — manifest/lockfile desync (the defect above).
# Deliberately `ci`, not `install`: only `ci`
# treats a desynced lockfile as an error rather
# than quietly rewriting it.
# - `npm run build` — a dependency bump that breaks the build.
#
# What this job deliberately does NOT do is rebuild the committed
# bundles under `examples/*/static/**` and diff the bytes. That is not
# a judgement call — for four of the original six legs it is impossible.
# Two builds from an identical tree were compared:
#
# - Next — a fresh build id every run (`Kb3j7R17-emTNVLO8IAvl` ->
# `BcT-Fi9UF2LGQStSayjG0`), which renames the build-id
# directory and rewrites every RSC payload and HTML entry.
# - Svelte — `_app/version.json` is a build timestamp, and
# `index.html` embeds it.
# - Angular — byte-identical, the only deterministic one.
#
# So a rebuild-and-diff gate would be permanently red on four legs
# regardless of staleness, which is the same conclusion `check:ui`
# reached for `UiAssets.ts` by a different route. A content-independent
# freshness gate (a source hash over the inputs, the way `UiAssets.ts`
# has one) is the open question in #903.
# `src/**` is in the filter because of the `snippets` job, and it is the
# whole point of it: the failure this gate exists to catch is a framework
# change that breaks an example, and an `examples/**`-only filter — which
# is all `frontend` ever needed — would produce zero checks for exactly
# that case. The `frontend` job pays for the wider trigger by running on
# `src/**` pushes that cannot affect it; eight cached `npm ci` legs are
# cheaper than the alternative of two workflows that drift apart.
on:
push:
branches: ['**']
paths:
- 'src/**'
- 'examples/**'
- 'tests/examples/**'
- 'package.json'
- 'bun.lock'
- '.github/workflows/examples.yml'
pull_request:
branches: [main, develop]
paths:
- 'src/**'
- 'examples/**'
- 'tests/examples/**'
- 'package.json'
- 'bun.lock'
- '.github/workflows/examples.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:
frontend:
runs-on: ubuntu-latest
strategy:
# fail-fast: false so an Angular-only regression doesn't mask a
# Next-only one. Each frontend gets its own red mark — the same
# reasoning as the runtime matrix in multi-runtime.yml.
fail-fast: false
matrix:
# Listed explicitly rather than globbed: a new example frontend
# should be a deliberate line in this file, not a directory that
# silently joins (or silently doesn't) the matrix.
directory:
- examples/chat/frontend-angular
- examples/chat/frontend-next
- examples/chat/frontend-react
- examples/chat/frontend-svelte
- examples/voice/frontend-angular
- examples/voice/frontend-next
- examples/voice/frontend-react
- examples/voice/frontend-svelte
name: ${{ matrix.directory }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
# 24 for the same reason multi-runtime.yml pins its Node leg there:
# it is the `engines` floor the package claims to support, so the
# examples are exercised on the oldest runtime a user might have.
#
# Note the major alone is load-bearing here: `@angular/cli` 22
# declares `^22.22.3 || ^24.15.0 || >=26.0.0`, so the Angular legs
# need 24.15 or newer. `node-version: '24'` resolves to the latest
# 24.x and satisfies that; pinning a narrower 24.x would not.
- name: Setup Node.js
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: '24'
cache: npm
cache-dependency-path: ${{ matrix.directory }}/package-lock.json
- name: Install (npm ci — fails on a desynced lockfile)
working-directory: ${{ matrix.directory }}
run: npm ci
- name: Build
working-directory: ${{ matrix.directory }}
run: npm run build
# #545 — until this job existed, nothing in CI ever executed an example.
# A framework change could break every snippet in the tree and the only
# signal would be a user running one.
#
# `tests/examples/examples.manifest.json` classifies all 78 standalone
# scripts as runnable-with-an-assertion or skipped-with-a-reason, and the
# runner fails when the manifest and the tree disagree in either
# direction — so a new example cannot silently opt out of the gate.
#
# Bun only. The cross-runtime question is `bun run smoke`'s, over cases
# written to be runtime-neutral; the examples are written for Bun (they
# reach for `Bun.sleep`, and they import `.ts` directly), so running them
# on Node and Deno would test the examples' portability rather than the
# framework's.
snippets:
runs-on: ubuntu-latest
# ~90 s of actual work; the ceiling is here so a snippet that learns to
# hang takes the job down with a red mark instead of burning the
# runner's default six hours.
timeout-minutes: 15
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Setup Bun
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
with:
bun-version: latest
- name: Install
run: bun install --frozen-lockfile
- name: Run the examples
run: bun run test:examples