-
Notifications
You must be signed in to change notification settings - Fork 1
342 lines (312 loc) · 12.8 KB
/
Copy pathci.yml
File metadata and controls
342 lines (312 loc) · 12.8 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
name: CI
on:
push:
branches: [main]
pull_request:
concurrency:
# PRs group by number so a newer push supersedes and cancels the stale
# run. Pushes to main group by commit SHA, giving every commit its own
# group: a constant branch-wide key would let a newer push evict the
# queued run of a commit still waiting behind an in-flight one, and
# that commit would never be validated. cancel-in-progress therefore
# only governs PR supersession.
group: ci-${{ github.event.pull_request.number || github.sha }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
jobs:
# The four jobs below were one serial `checks` job. Splitting them lets
# GitHub run them concurrently, so a PR's wall-clock is the slowest job
# rather than the sum of all of them, and a lint or structural failure
# reports in about a minute instead of waiting behind the build.
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/setup-workbench
- uses: actions/cache@v4
with:
path: |
.eslintcache
node_modules/.cache/prettier
key: lint-${{ runner.os }}-${{ hashFiles('bun.lock', 'eslint.config.ts', '.prettierrc.json', '.bun-version') }}
- run: bun run lint
typecheck:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: ./.github/actions/setup-workbench
- uses: actions/cache@v4
with:
# Restores each package's incremental tsbuildinfo (composite build
# and combined --noEmit check now write separate files, so caching
# both means the next run's `tsc` calls only recheck what actually
# changed since the cached commit, instead of every file every PR.
# Paths are the workspace roots spelled out rather than `**/dist`:
# a recursive glob walks node_modules and follows every workspace
# symlink in it, and the save step ran for over 40 minutes.
path: |
apps/*/dist
packages/*/dist
tools/*/dist
workflows/*/dist
vendor/intx/*/dist
apps/*/tsconfig.tsbuildinfo
packages/*/tsconfig.tsbuildinfo
tools/*/tsconfig.tsbuildinfo
workflows/*/tsconfig.tsbuildinfo
vendor/intx/*/tsconfig.tsbuildinfo
tsconfig.tsbuildinfo
test/tsconfig.tsbuildinfo
test/isolation/tsconfig.tsbuildinfo
key: typecheck-${{ runner.os }}-${{ hashFiles('bun.lock', '.bun-version', 'tsconfig.base.json', 'scripts/generate-tsconfig-references.ts') }}-${{ github.sha }}
restore-keys: |
typecheck-${{ runner.os }}-${{ hashFiles('bun.lock', '.bun-version', 'tsconfig.base.json', 'scripts/generate-tsconfig-references.ts') }}-
- run: bun run typecheck
# A hosted runner's 4 vCPUs cap how much a single job's package fan-out
# (scripts/run-all.ts's own concurrency) can cut wall-clock: the total
# CPU-seconds across every package's test script divided by 4 was still
# over 90s. Splitting the same total work across 3 runners, each with
# its own 4 vCPUs, is what actually buys more parallelism. --shard i/3
# (scripts/run-all.ts) round-robins the workspace's stably name-sorted
# package list across shards, so a run's set of packages-per-shard is
# reproducible and every package lands in exactly one shard.
build-test-shard:
strategy:
fail-fast: false
matrix:
shard: [1, 2, 3]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: ./.github/actions/setup-workbench
- run: bun run build
# The root-level scripts/*.test.ts suite (scripts/run-all.test.ts
# among them) isn't itself sharded — it only needs to run once, so
# it rides along on shard 1.
- if: matrix.shard == 1
run: bun test ./scripts/*.test.ts
- run: bun run scripts/run-all.ts test --shard ${{ matrix.shard }}/3
# The required check every branch protection rule and PR template
# names is "build-test" (predating the shard split above); this job
# keeps that name live by depending on every shard and failing if any
# of them did.
build-test:
needs: build-test-shard
if: always()
runs-on: ubuntu-latest
steps:
- if: contains(needs.build-test-shard.result, 'failure') || contains(needs.build-test-shard.result, 'cancelled')
run: |
echo "at least one build-test shard failed" >&2
exit 1
structural:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: ./.github/actions/setup-workbench
- run: bun run check:structural
e2e-plan:
runs-on: ubuntu-latest
outputs:
suites: ${{ steps.list-suites.outputs.suites }}
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/setup-workbench
- name: List e2e suites
id: list-suites
run: echo "suites=$(bun run scripts/e2e/list-suites.ts)" >> "$GITHUB_OUTPUT"
# One job per e2e suite so a PR's e2e wall-clock is the slowest suite
# rather than the sum of all of them, and a failing suite names itself
# instead of hiding behind "e2e failed". fail-fast is off so one flaky
# suite doesn't cancel every other suite's run.
e2e-suite:
needs: e2e-plan
runs-on: ubuntu-latest
timeout-minutes: 10
strategy:
fail-fast: false
matrix:
suite: ${{ fromJson(needs.e2e-plan.outputs.suites) }}
services:
postgres:
# pgvector-enabled Postgres 17, matching the local development
# database (brew postgresql@17 + pgvector).
image: pgvector/pgvector:pg17
env:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
ports:
- 5432:5432
options: >-
--health-cmd "pg_isready -U postgres -d postgres"
--health-interval 10s
--health-timeout 5s
--health-retries 5
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/setup-workbench
# The committed template ships a placeholder secret and a
# credential-less local DATABASE_URL; point the URL at the service
# container's superuser and mint a real session secret in place.
- name: Write env file
run: |
cp .env.example .env
secret=$(openssl rand -hex 32)
sed -i "s|^SESSION_SECRET=.*|SESSION_SECRET=${secret}|" .env
sed -i "s|^DATABASE_URL=.*|DATABASE_URL=postgres://postgres:postgres@localhost:5432/workbench|" .env
# The e2e suite skips itself when DATABASE_URL is absent, so a
# wiring mistake here could otherwise drop the whole suite while
# CI stays green. Fail loudly instead: the env file must exist
# with a usable DATABASE_URL and SESSION_SECRET, Postgres must be
# reachable, and git (the workflow-asset publication path) must be
# present. CI=true turns any remaining skip into a hard failure.
- name: Assert the e2e test env is wired
run: |
test -f .env
grep -q '^DATABASE_URL=postgres://postgres:postgres@localhost:5432/workbench$' .env
grep -Eq '^SESSION_SECRET=.{32,}$' .env
pg_isready -h localhost -p 5432
git --version
- name: Run the suite
run: |
if [ "${{ matrix.suite }}" = "unit" ]; then
bun test scripts/e2e/harness.test.ts scripts/e2e/db-gate.test.ts scripts/e2e/db-setup.test.ts scripts/e2e/list-suites.test.ts --max-concurrency=1
else
bun test "scripts/e2e/${{ matrix.suite }}.test.ts" --max-concurrency=1
fi
env:
DATABASE_URL: postgres://postgres:postgres@localhost:5432/workbench
E2E_LOG_DIR: e2e-logs
- name: Upload e2e logs
if: always()
uses: actions/upload-artifact@v4
with:
name: e2e-logs-${{ matrix.suite }}
path: e2e-logs
if-no-files-found: ignore
# Branch protection's required check is named "e2e"; this summary job
# keeps that name while the actual work runs as per-suite e2e-suite jobs.
e2e:
needs: e2e-suite
if: always()
runs-on: ubuntu-latest
steps:
- name: Check e2e-suite matrix result
run: |
if [ "${{ needs.e2e-suite.result }}" != "success" ]; then
echo "one or more e2e suites failed"
exit 1
fi
isolation:
runs-on: ubuntu-latest
timeout-minutes: 15
services:
postgres:
# pgvector-enabled Postgres 17, matching the local development
# database (brew postgresql@17 + pgvector).
image: pgvector/pgvector:pg17
env:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
ports:
- 5432:5432
options: >-
--health-cmd "pg_isready -U postgres -d postgres"
--health-interval 10s
--health-timeout 5s
--health-retries 5
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/setup-workbench
- name: Write env file
run: |
cp .env.example .env
secret=$(openssl rand -hex 32)
sed -i "s|^SESSION_SECRET=.*|SESSION_SECRET=${secret}|" .env
sed -i "s|^DATABASE_URL=.*|DATABASE_URL=postgres://postgres:postgres@localhost:5432/workbench|" .env
- name: Assert the e2e test env is wired
run: |
test -f .env
grep -q '^DATABASE_URL=postgres://postgres:postgres@localhost:5432/workbench$' .env
grep -Eq '^SESSION_SECRET=.{32,}$' .env
pg_isready -h localhost -p 5432
git --version
- name: Run the two-org isolation suite
run: bun test test/isolation
env:
DATABASE_URL: postgres://postgres:postgres@localhost:5432/workbench
db-suites:
runs-on: ubuntu-latest
timeout-minutes: 20
services:
postgres:
# pgvector-enabled Postgres 17, matching the local development
# database (brew postgresql@17 + pgvector).
image: pgvector/pgvector:pg17
env:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
ports:
- 5432:5432
options: >-
--health-cmd "pg_isready -U postgres -d postgres"
--health-interval 10s
--health-timeout 5s
--health-retries 5
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/setup-workbench
- name: Write env file
run: |
cp .env.example .env
secret=$(openssl rand -hex 32)
sed -i "s|^SESSION_SECRET=.*|SESSION_SECRET=${secret}|" .env
sed -i "s|^DATABASE_URL=.*|DATABASE_URL=postgres://postgres:postgres@localhost:5432/workbench|" .env
- name: Assert the e2e test env is wired
run: |
test -f .env
grep -q '^DATABASE_URL=postgres://postgres:postgres@localhost:5432/workbench$' .env
grep -Eq '^SESSION_SECRET=.{32,}$' .env
pg_isready -h localhost -p 5432
git --version
# apps/hub/test and most of the package suites below connect
# straight to DATABASE_URL (or its `_e2e`-suffixed sibling from
# `e2eDatabaseUrl()`) rather than booting through the harness, so
# — unlike e2e and isolation, which provision their own schema —
# this job must create and migrate both databases itself before
# those suites run.
- name: Set up the databases
run: |
DATABASE_URL=postgres://postgres:postgres@localhost:5432/workbench bun scripts/db-setup.ts
DATABASE_URL=postgres://postgres:postgres@localhost:5432/workbench_e2e bun scripts/db-setup.ts
# apps/hub's own DB-backed suites (e.g. the sign-up rate-limit
# proof) never run under the plain `checks` job, which has no
# Postgres. CI=true turns a would-be skip here into a hard
# failure, so a misconfigured invocation can't pass vacuously.
- name: Run the hub's database-backed suites
run: |
set -a
. ./.env
set +a
bun test apps/hub/test
env:
DATABASE_URL: postgres://postgres:postgres@localhost:5432/workbench
# Every DB-gated suite under packages/* and apps/hub/src gates on
# DATABASE_URL and describe.skip's without one, so build-test (no
# Postgres) never runs them. Find them by the same signal they
# gate on rather than hardcoding a file list, so a newly added
# suite gets picked up automatically. CI=true turns a would-be
# skip into a hard failure.
- name: Run the database-backed package suites
run: |
set -a
. ./.env
set +a
bun --env-file="${GITHUB_WORKSPACE}/.env" test $(grep -rl DATABASE_URL --include='*.test.ts' packages apps | grep -v apps/hub/test)
env:
DATABASE_URL: postgres://postgres:postgres@localhost:5432/workbench