Repository navigation
835 lines (798 loc) · 32.2 KB
/
Copy pathpublish.yml
File metadata and controls
835 lines (798 loc) · 32.2 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
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
name: Publish Package to npm
on:
push:
branches:
- main
pull_request:
branches:
- main
# Pull requests and every job below run read-only. Only the `release` and
# `deploy-pages` jobs get write permissions, and they run on pushes to main
# alone, so no step a pull request controls can publish, tag, comment or deploy.
permissions:
contents: read
# CI always runs the latest releases: the `ubuntu-latest` runner, the newest
# major version of every action, and the latest stable Rust, Bun, Node.js,
# wasm-pack, cargo-binstall, cargo-tarpaulin and changepacks.
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: false
jobs:
benchmark:
runs-on: ubuntu-latest
timeout-minutes: 60
steps:
- name: Checkout
uses: actions/checkout@v7
- uses: actions-rust-lang/setup-rust-toolchain@v2
with:
toolchain: stable
components: clippy, rustfmt
- name: Cache cargo registry + target
uses: actions/cache@v6
with:
path: |
~/.cargo/registry/index/
~/.cargo/registry/cache/
~/.cargo/git/db/
target/
key: cargo-benchmark-${{ runner.os }}-${{ hashFiles('**/Cargo.lock') }}
- uses: oven-sh/setup-bun@v2
with:
bun-version: latest
name: Install bun
- name: Cache bun dependencies
uses: actions/cache@v6
with:
path: ~/.bun/install/cache
key: bun-benchmark-${{ runner.os }}-${{ hashFiles('**/bun.lock') }}
- &install-wasm-pack
name: Install and verify latest stable wasm-pack
shell: bash
env:
GH_TOKEN: ${{ github.token }}
run: |
set -euo pipefail
curl -L --proto '=https' --tlsv1.2 -sSf https://github.com/@raw/cargo-bins/cargo-binstall/main/install-from-binstall-release.sh | bash
export PATH="${CARGO_HOME:-$HOME/.cargo}/bin:$PATH"
cargo binstall wasm-pack --no-confirm --force
latest="$(curl -fsSL -A 'devup-ui CI (https://github.com/dev-five-git/devup-ui)' https://crates.io/api/v1/crates/wasm-pack | jq -er '.crate.max_stable_version | select(type == "string" and length > 0)')"
installed="$(wasm-pack --version)"
echo "Installed $installed; crates.io latest stable: $latest"
test "$installed" = "wasm-pack $latest"
- name: Install Node.js
uses: actions/setup-node@v7
with:
registry-url: "https://registry.npmjs.org"
# `latest` can select alphas from https://nodejs.org/dist/index.json;
# see https://github.com/actions/setup-node/issues/1657.
# The stable manifest can briefly trail nodejs.org after a stable release.
node-version: '*'
check-latest: true
- run: bun install
- run: bun run build
# Every row is the median of the same number of cold samples taken in
# rotating order (benchmark-manifest.json). The run goes to an artifact and
# the Devup UI rows are compared with the checked baseline at the end of the
# job, so the profile and the Rust measurement still run when it fails.
- name: Benchmark
run: bun run benchmark
- name: Profile Devup UI Turbopack
env:
DEVUP_UI_PROFILE: "1"
run: |
rm -rf benchmark/next-devup-ui-single-turbo/.next \
benchmark/next-devup-ui-single-turbo/df \
benchmark/next-devup-ui-single-turbo/tsconfig.tsbuildinfo
bun run --filter next-devup-ui-single-turbo-benchmark build
- name: Upload the measured run
uses: actions/upload-artifact@v7
if: ${{ !cancelled() }}
with:
name: benchmark-run
path: benchmark-run.json
if-no-files-found: ignore
retention-days: 30
- name: Measure the SemanticBuilder passes of the extractor
run: cargo bench -p extractor --bench semantic_pass_benchmark -- --quick
- name: Compare the Devup UI rows with the baseline
run: bun benchmark-check.js
wasm-size:
runs-on: ubuntu-latest
timeout-minutes: 60
permissions:
contents: read
env:
CARGO_BUILD_JOBS: "2"
RUSTUP_TOOLCHAIN: stable
steps:
- name: Checkout the tested source and both histories
uses: actions/checkout@v7
with:
fetch-depth: 0
persist-credentials: false
- uses: actions-rust-lang/setup-rust-toolchain@v2
with:
toolchain: stable
target: wasm32-unknown-unknown
cache: false
- uses: oven-sh/setup-bun@v2
with:
bun-version: latest
- uses: actions/setup-node@v7
with:
node-version: '*'
check-latest: true
- name: Resolve and report exact WASM comparison sources
run: node resolve-wasm-size-sources.js
- *install-wasm-pack
- name: Cache registry downloads only
uses: actions/cache@v6
with:
path: |
~/.cargo/registry/index/
~/.cargo/registry/cache/
~/.cargo/git/db/
key: cargo-wasm-size-${{ runner.os }}-${{ hashFiles('**/Cargo.lock') }}
- name: Install the latest shared optimizer once
env:
GH_TOKEN: ${{ github.token }}
run: |
set -euo pipefail
mkdir -p "$RUNNER_TEMP/wasm-size-tools/binaryen"
gh release download --repo WebAssembly/binaryen --pattern '*-x86_64-linux.tar.gz' --dir "$RUNNER_TEMP/wasm-size-tools"
tar -xzf "$RUNNER_TEMP"/wasm-size-tools/*.tar.gz --strip-components=1 -C "$RUNNER_TEMP/wasm-size-tools/binaryen"
echo "$RUNNER_TEMP/wasm-size-tools/binaryen/bin" >> "$GITHUB_PATH"
- name: Build exact sources with shared tools and lock-matched bindgen
env:
GH_TOKEN: ${{ github.token }}
run: |
set -euo pipefail
export SIZE_ROOT="$RUNNER_TEMP/wasm-size"
mkdir -p "$SIZE_ROOT"
stage=source
trap 'echo "## WASM size: FAIL - $stage build or provenance failed; no comparison was skipped or substituted." >> "$GITHUB_STEP_SUMMARY"' ERR
for side in base candidate; do
if [[ "$side" == base ]]; then sha="$BASE_SHA"; else sha="$CANDIDATE_SHA"; fi
git cat-file -e "$sha^{commit}"
mkdir -p "$SIZE_ROOT/$side"
git archive "$sha" | tar -x -C "$SIZE_ROOT/$side"
done
cat > "$SIZE_ROOT/provenance.mjs" <<'NODE'
import { execFileSync } from 'node:child_process'
import { createHash } from 'node:crypto'
import { readFileSync, writeFileSync } from 'node:fs'
import { join } from 'node:path'
const run = (command, args) => execFileSync(command, args, { encoding: 'utf8' }).trim()
const tools = Object.fromEntries([
['rustc', 'rustc', ['--version', '--verbose']],
['wasmPack', 'wasm-pack', ['--version']],
['wasmBindgen', 'wasm-bindgen', ['--version']],
['wasmOpt', 'wasm-opt', ['--version']],
['bun', 'bun', ['--version']],
['node', 'node', ['--version']],
].map(([key, command, args]) => {
const path = run('which', [command])
const hash = createHash('sha256').update(readFileSync(path)).digest('hex')
return [key, `${run(command, args)}\n${path}\nsha256:${hash}`]
}))
const side = process.argv[2]
const file = join(process.env.SIZE_ROOT, 'metadata.json')
const metadata = side === 'base' ? {
jobId: `${process.env.GITHUB_RUN_ID}/${process.env.GITHUB_RUN_ATTEMPT}/${process.env.GITHUB_JOB}`,
buildCommand: 'cargo metadata --locked --format-version 1 > /dev/null && wasm-pack build --mode no-install --release --target nodejs --out-dir ./pkg --out-name index --locked && node script.js',
} : JSON.parse(readFileSync(file, 'utf8'))
const sha = side === 'base' ? process.env.BASE_SHA : process.env.CANDIDATE_SHA
metadata[side] = {
commit: run('git', ['rev-parse', `${sha}^{commit}`]),
tree: run('git', ['rev-parse', `${sha}^{tree}`]),
wasmBindgenVersion: process.env.WASM_BINDGEN_VERSION,
packageDir: join(process.env.SIZE_ROOT, side, 'bindings/devup-ui-wasm/pkg'), tools,
}
writeFileSync(file, JSON.stringify(metadata, null, 2) + '\n')
NODE
shared_path="$PATH"
for side in base candidate; do
stage="$side"
(
WASM_BINDGEN_VERSION="$(bun resolve-wasm-bindgen.js "$SIZE_ROOT/$side/Cargo.lock")"
export WASM_BINDGEN_VERSION
bindgen_root="$SIZE_ROOT/abi-tools/$WASM_BINDGEN_VERSION"
if [[ ! -x "$bindgen_root/bin/wasm-bindgen" ]]; then
cargo binstall wasm-bindgen-cli --version "=$WASM_BINDGEN_VERSION" --root "$bindgen_root" --no-confirm --force
fi
export PATH="$bindgen_root/bin:$shared_path"
node "$SIZE_ROOT/provenance.mjs" "$side"
cd "$SIZE_ROOT/$side/bindings/devup-ui-wasm"
export CARGO_TARGET_DIR="$SIZE_ROOT/$side-target"
cargo metadata --locked --format-version 1 > /dev/null
wasm-pack build --mode no-install --release --target nodejs --out-dir ./pkg --out-name index --locked
node script.js
) 2>&1 | tee "$SIZE_ROOT/$side-build.log"
done
- name: Compare all four relative size metrics
run: |
node verify-wasm-size.js \
--base-pkg "$RUNNER_TEMP/wasm-size/base/bindings/devup-ui-wasm/pkg" \
--candidate-pkg "$RUNNER_TEMP/wasm-size/candidate/bindings/devup-ui-wasm/pkg" \
--metadata "$RUNNER_TEMP/wasm-size/metadata.json" \
--report "$RUNNER_TEMP/wasm-size/wasm-size.json"
- name: Upload size measurements and build evidence
uses: actions/upload-artifact@v7
if: ${{ !cancelled() }}
with:
name: wasm-size
path: |
${{ runner.temp }}/wasm-size/metadata.json
${{ runner.temp }}/wasm-size/wasm-size.json
${{ runner.temp }}/wasm-size/*-build.log
if-no-files-found: error
retention-days: 30
# The landing app is the only real-scale acceptance target in this repo, and
# `publish` runs it against the deployed vinext/@devup-ui/vite-plugin build.
# This job runs the SAME 128 assertions and the SAME screenshot baselines
# against a Next 16 + Turbopack build, so @devup-ui/next-plugin's production
# CSS path stays gated at 64 routes - the scale where extraction-wave races
# actually reproduce. It runs in parallel so it stays off the publish critical
# path, and its artifact is never deployed.
landing-next-e2e:
runs-on: ubuntu-latest
timeout-minutes: 60
steps:
- name: Checkout
uses: actions/checkout@v7
- uses: actions-rust-lang/setup-rust-toolchain@v2
with:
toolchain: stable
components: clippy, rustfmt
- name: Cache cargo registry + target
uses: actions/cache@v6
with:
path: |
~/.cargo/registry/index/
~/.cargo/registry/cache/
~/.cargo/git/db/
target/
key: cargo-landing-next-${{ runner.os }}-${{ hashFiles('**/Cargo.lock') }}
- uses: oven-sh/setup-bun@v2
with:
bun-version: latest
name: Install bun
- name: Cache bun dependencies
uses: actions/cache@v6
with:
path: ~/.bun/install/cache
key: bun-landing-next-${{ runner.os }}-${{ hashFiles('**/bun.lock') }}
- *install-wasm-pack
- name: Install Node.js
uses: actions/setup-node@v7
with:
node-version: '*'
check-latest: true
- run: bun install
- run: bun run build
- name: Build Landing (Next)
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
bun run --filter @devup-ui/components build-storybook
mv ./packages/components/storybook-static ./apps/landing/public/storybook
bun run --filter landing build:next
- name: Cache Playwright Browsers
uses: actions/cache@v6
with:
path: ~/.cache/ms-playwright
key: playwright-landing-next-${{ runner.os }}-${{ hashFiles('**/bun.lock') }}
- name: Install Playwright Browsers
run: bunx playwright install chromium --with-deps
- name: Run E2E Tests (Next)
run: bun run test:e2e:next
- name: Run Landing dev navigation tests (Next)
env:
LANDING_BUILD_MODE: next
run: bunx playwright test -c playwright.landing-dev.config.ts
- name: Build Landing (Next, singleCss)
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
rm -rf apps/landing/out apps/landing/.next apps/landing/df
DEVUP_SINGLE_CSS=1 bun run --filter landing build:next
- name: Run E2E Tests (Next, singleCss)
run: bun run test:e2e:next
- name: Upload Next Playwright Report
uses: actions/upload-artifact@v7
if: ${{ !cancelled() }}
with:
name: playwright-report-next
path: playwright-report/
retention-days: 1
# The packages take React ^18 || ^19 as a peer. This builds a React 18.3 app
# with the Vite plugin and the UI kit, then checks refs, context and events
# in Chromium, so React-19-only APIs cannot slip back in.
react-18:
runs-on: ubuntu-latest
timeout-minutes: 45
steps:
- name: Checkout
uses: actions/checkout@v7
- uses: actions-rust-lang/setup-rust-toolchain@v2
with:
toolchain: stable
components: clippy, rustfmt
- name: Cache cargo registry + target
uses: actions/cache@v6
with:
path: |
~/.cargo/registry/index/
~/.cargo/registry/cache/
~/.cargo/git/db/
target/
key: cargo-react-18-${{ runner.os }}-${{ hashFiles('**/Cargo.lock') }}
- uses: oven-sh/setup-bun@v2
with:
bun-version: latest
name: Install bun
- name: Cache bun dependencies
uses: actions/cache@v6
with:
path: ~/.bun/install/cache
key: bun-react-18-${{ runner.os }}-${{ hashFiles('**/bun.lock') }}
- *install-wasm-pack
- name: Install Node.js
uses: actions/setup-node@v7
with:
node-version: '*'
check-latest: true
- run: bun install
- run: bun run build
- name: Type-check and build the React 18 app
working-directory: apps/react-18
run: |
bun ../../node_modules/@typescript/native/bin/tsc
bun run build
- name: Cache Playwright Browsers
uses: actions/cache@v6
with:
path: ~/.cache/ms-playwright
key: playwright-react-18-${{ runner.os }}-${{ hashFiles('**/bun.lock') }}
- name: Install Playwright Browsers
run: bunx playwright install chromium --with-deps
- name: Run React 18 E2E Tests
working-directory: apps/react-18
run: bun run test:e2e
# @devup-ui/vite-plugin must keep the CSS every server page needs when the
# build is vinext/RSC. The fixture shares one Devup UI header between server
# list pages and a client page, and the tests read the styles the browser
# actually applies when each route is entered directly, so a dropped
# stylesheet dependency fails here whatever the CSS files are called.
vinext-rsc-css-e2e:
runs-on: ubuntu-latest
timeout-minutes: 30
permissions:
contents: read
steps:
- name: Checkout
uses: actions/checkout@v7
- uses: actions-rust-lang/setup-rust-toolchain@v2
with:
toolchain: stable
components: clippy, rustfmt
- name: Cache cargo registry + target
uses: actions/cache@v6
with:
path: |
~/.cargo/registry/index/
~/.cargo/registry/cache/
~/.cargo/git/db/
target/
key: cargo-vinext-rsc-css-${{ runner.os }}-${{ hashFiles('**/Cargo.lock') }}
- uses: oven-sh/setup-bun@v2
with:
bun-version: latest
name: Install bun
- name: Cache bun dependencies
uses: actions/cache@v6
with:
path: ~/.bun/install/cache
key: bun-vinext-rsc-css-${{ runner.os }}-${{ hashFiles('**/bun.lock') }}
- *install-wasm-pack
- name: Install Node.js
uses: actions/setup-node@v7
with:
node-version: '*'
check-latest: true
- run: bun install
- run: bun run build
- name: Cache Playwright Browsers
uses: actions/cache@v6
with:
path: ~/.cache/ms-playwright
key: playwright-vinext-rsc-css-${{ runner.os }}-${{ hashFiles('**/bun.lock') }}
- name: Install Playwright Browsers
run: bunx playwright install chromium --with-deps
- name: Build fixture (per-file CSS)
run: bun run --filter vinext-rsc-css-repro build
- name: Run E2E Tests (per-file CSS)
run: bun run test:e2e:rsc-css
- name: Build fixture (singleCss)
run: |
rm -rf apps/vinext-rsc-css-repro/dist apps/vinext-rsc-css-repro/.vinext apps/vinext-rsc-css-repro/df
DEVUP_SINGLE_CSS=1 bun run --filter vinext-rsc-css-repro build
- name: Run E2E Tests (singleCss)
run: bun run test:e2e:rsc-css
release-compat:
runs-on: ubuntu-latest
timeout-minutes: 30
env:
CARGO_BUILD_JOBS: "2"
steps:
- name: Checkout
uses: actions/checkout@v7
- uses: actions-rust-lang/setup-rust-toolchain@v2
with:
toolchain: stable
components: clippy, rustfmt
- name: Cache cargo registry + target
uses: actions/cache@v6
with:
path: |
~/.cargo/registry/index/
~/.cargo/registry/cache/
~/.cargo/git/db/
target/
key: cargo-release-compat-${{ runner.os }}-${{ hashFiles('**/Cargo.lock') }}
- uses: oven-sh/setup-bun@v2
with:
bun-version: latest
- name: Cache bun dependencies
uses: actions/cache@v6
with:
path: ~/.bun/install/cache
key: bun-release-compat-${{ runner.os }}-${{ hashFiles('**/bun.lock') }}
- *install-wasm-pack
- uses: actions/setup-node@v7
with:
node-version: '*'
check-latest: true
- run: bun install
- name: Test exited-process memory sampling
run: node --test e2e/release/process-memory.test.mjs
- name: Build packages under the memory watchdog
run: node e2e/release/build-packages.mjs
- name: Cache Playwright browsers
uses: actions/cache@v6
with:
path: ~/.cache/ms-playwright
key: playwright-release-compat-${{ runner.os }}-${{ hashFiles('**/bun.lock') }}
- name: Install Playwright browsers
run: bunx playwright install chromium firefox webkit --with-deps
- name: Build packed consumers and check production computed styles
run: bun run test:release
- name: Upload release compatibility evidence
if: ${{ !cancelled() }}
uses: actions/upload-artifact@v7
with:
name: release-compat-results
path: |
release-package-build.json
release-results.json
if-no-files-found: error
retention-days: 30
webpack-extends-theme:
runs-on: ubuntu-latest
timeout-minutes: 45
permissions:
contents: read
env:
CARGO_BUILD_JOBS: "2"
steps:
- name: Configure isolated paths
run: |
printf 'DEVUP_PLAYWRIGHT_ROOT=%s/webpack-extends-playwright\n' "$RUNNER_TEMP" >> "$GITHUB_ENV"
printf 'PLAYWRIGHT_BROWSERS_PATH=%s/webpack-extends-browsers\n' "$RUNNER_TEMP" >> "$GITHUB_ENV"
printf 'DEVUP_EXTENDS_RESULTS=%s/webpack-extends-results\n' "$RUNNER_TEMP" >> "$GITHUB_ENV"
- name: Checkout
uses: actions/checkout@v7
- uses: actions-rust-lang/setup-rust-toolchain@v2
with:
toolchain: stable
components: clippy, rustfmt
- name: Cache cargo registry + target
uses: actions/cache@v6
with:
path: |
~/.cargo/registry/index/
~/.cargo/registry/cache/
~/.cargo/git/db/
target/
key: cargo-webpack-extends-${{ runner.os }}-${{ hashFiles('**/Cargo.lock') }}
- uses: oven-sh/setup-bun@v2
with:
bun-version: latest
- name: Cache bun dependencies
uses: actions/cache@v6
with:
path: ~/.bun/install/cache
key: bun-webpack-extends-${{ runner.os }}-${{ hashFiles('**/bun.lock') }}
- *install-wasm-pack
- name: Install Node.js
uses: actions/setup-node@v7
with:
node-version: '*'
check-latest: true
- run: bun install
- name: Build fresh WASM
working-directory: bindings/devup-ui-wasm
run: bun run build
- run: bun run build
- name: Install latest private Playwright and Chromium
run: |
mkdir -p "$DEVUP_PLAYWRIGHT_ROOT" "$DEVUP_EXTENDS_RESULTS"
printf '{"private":true,"type":"module"}\n' > "$DEVUP_PLAYWRIGHT_ROOT/package.json"
bun add --cwd "$DEVUP_PLAYWRIGHT_ROOT" @playwright/test@latest
node "$DEVUP_PLAYWRIGHT_ROOT/node_modules/@playwright/test/cli.js" install chromium --with-deps
- name: Installed formats and production theme delivery regressions
run: |
set -euo pipefail
env -u CI node --test packages/webpack-plugin/src/__tests__/extends-theme/extends-theme-regression.mjs 2>&1 | tee "$DEVUP_EXTENDS_RESULTS/matrix.log"
- name: Upload packed-consumer matrix evidence
if: always()
uses: actions/upload-artifact@v7
with:
name: webpack-extends-theme-evidence
path: |
${{ runner.temp }}/webpack-extends-results/matrix.log
${{ runner.temp }}/webpack-extends-results/extends-theme-*/*.json
${{ runner.temp }}/webpack-extends-results/extends-theme-*/*/identity-*.json
${{ runner.temp }}/webpack-extends-results/extends-theme-*/*/bun.lock
${{ runner.temp }}/webpack-extends-results/extends-theme-*/packs/*/*.tgz
if-no-files-found: error
retention-days: 7
# Validation: runs on pull requests and on pushes to main, read-only. The job
# id stays `publish` because it is the status check the repository requires;
# the privileged release steps live in `release` and `deploy-pages` below.
publish:
runs-on: ubuntu-latest
timeout-minutes: 90
steps:
- name: Checkout
uses: actions/checkout@v7
with:
# changepacks diffs HEAD against the previous release commit. The
# default shallow fetch grafts away every parent, so that lookup dies
# with "Could not find a merge-base".
fetch-depth: 0
fetch-tags: true
- uses: actions-rust-lang/setup-rust-toolchain@v2
with:
toolchain: stable
components: clippy, rustfmt
- *install-wasm-pack
- name: Install cargo-tarpaulin
env:
GH_TOKEN: ${{ github.token }}
run: cargo binstall cargo-tarpaulin --no-confirm --force
- name: Cache cargo registry + target
uses: actions/cache@v6
with:
path: |
~/.cargo/registry/index/
~/.cargo/registry/cache/
~/.cargo/git/db/
target/
key: cargo-publish-${{ runner.os }}-${{ hashFiles('**/Cargo.lock') }}
- uses: oven-sh/setup-bun@v2
with:
bun-version: latest
name: Install bun
- name: Cache bun dependencies
uses: actions/cache@v6
with:
path: ~/.bun/install/cache
key: bun-publish-${{ runner.os }}-${{ hashFiles('**/bun.lock') }}
- name: Install Node.js
uses: actions/setup-node@v7
with:
registry-url: "https://registry.npmjs.org"
node-version: '*'
check-latest: true
- run: bun install
- run: bun run build
- name: Verify built package entry points
run: bun run verify:dist
- name: Verify the README benchmark tables
run: bun render-benchmark-readme.js --check
- name: Verify publish tarballs
shell: bash
run: |
set -euo pipefail
for manifest in bindings/*/package.json packages/*/package.json; do
package_dir="$(dirname "$manifest")"
pack_dir="$RUNNER_TEMP/publish-verify/${package_dir//\//-}"
mkdir -p "$pack_dir"
(cd "$package_dir" && bun pm pack --quiet --destination "$pack_dir")
tarballs=("$pack_dir"/*.tgz)
if [[ "${#tarballs[@]}" -ne 1 ]]; then
echo "Expected one tarball for $package_dir" >&2
exit 1
fi
packed_manifest="$(tar -xOf "${tarballs[0]}" package/package.json)"
if grep -q 'workspace:' <<< "$packed_manifest"; then
echo "Unresolved workspace dependency in $package_dir" >&2
exit 1
fi
done
- run: |
bun run lint
# rust coverage issue
echo 'max_width = 100000' > .rustfmt.toml
echo 'tab_spaces = 4' >> .rustfmt.toml
echo 'newline_style = "Unix"' >> .rustfmt.toml
echo 'fn_call_width = 100000' >> .rustfmt.toml
echo 'fn_params_layout = "Compressed"' >> .rustfmt.toml
echo 'chain_width = 100000' >> .rustfmt.toml
echo 'merge_derives = true' >> .rustfmt.toml
echo 'use_small_heuristics = "Default"' >> .rustfmt.toml
cargo fmt
- run: bun run test
- name: Regression test (bun-plugin preload race)
run: bun run --filter @devup-ui/bun-plugin test:regression
- name: Format Rollback
run: |
rm -rf .rustfmt.toml
# Formatting with the temporary coverage config and then with the
# default config is not a reversible round trip. Restore the exact
# checked-in sources so the checkout is clean again.
git restore --source=HEAD --staged --worktree -- .
cargo fmt --all -- --check
git diff --exit-code
- name: Check the changepacks of this change
if: github.event_name == 'pull_request'
run: |
# changepacks compares the change against a local main, which a pull request checkout does not have
git fetch --no-tags origin main:refs/heads/main
bunx @changepacks/cli@latest check --format json
- name: Build Landing
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
bun run --filter @devup-ui/components build-storybook
mv ./packages/components/storybook-static ./apps/landing/public/storybook
bun run --filter landing build
- name: Cache Playwright Browsers
id: playwright-cache
uses: actions/cache@v6
with:
path: ~/.cache/ms-playwright
key: playwright-publish-${{ runner.os }}-${{ hashFiles('**/bun.lock') }}
- name: Install Playwright Browsers
run: bunx playwright install chromium --with-deps
# A run only compares against the screenshots checked into the repository:
# it never creates or commits them. A new visual test needs its baselines
# generated by a maintainer (`bun run test:e2e:update`) and committed.
- name: Require the E2E baselines
run: |
SNAPSHOT_COUNT=$(find e2e -name '*-linux.png' -path '*-snapshots/*' 2>/dev/null | wc -l)
echo "Found $SNAPSHOT_COUNT linux baseline snapshot(s)"
if [ "$SNAPSHOT_COUNT" -eq 0 ]; then
echo "No checked-in baselines under e2e/**/*-snapshots; generate them with 'bun run test:e2e:update' and commit them." >&2
exit 1
fi
- name: Run E2E Tests
run: bun run test:e2e
- name: Run Landing dev navigation tests
run: bunx playwright test -c playwright.landing-dev.config.ts
- name: Build Landing (singleCss)
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
rm -rf apps/landing/dist apps/landing/.next apps/landing/.vinext apps/landing/df
DEVUP_SINGLE_CSS=1 bun run --filter landing build
- name: Run E2E Tests (singleCss)
run: bun run test:e2e
- name: Upload singleCss Playwright Report
uses: actions/upload-artifact@v7
if: ${{ !cancelled() }}
with:
name: playwright-report-singlecss
path: playwright-report/
retention-days: 1
- name: Upload the site for deployment
uses: actions/upload-pages-artifact@v5
with:
path: ./apps/landing/dist/client
retention-days: 1
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
- name: Upload to codecov.io
uses: codecov/codecov-action@v7
with:
token: ${{ secrets.CODECOV_TOKEN }}
fail_ci_if_error: true
files: ./coverage/root/lcov.info,./coverage/vite/lcov.info
# Pages deployment: the only job with `pages` and `id-token` write, and it
# only runs for a push to main whose validation passed.
deploy-pages:
needs: [publish]
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
timeout-minutes: 15
permissions:
contents: read
pages: write
id-token: write
steps:
- uses: actions/deploy-pages@v5
# Publishes through npm OIDC trusted publishing. The job's `id-token: write`
# permission lets npm exchange GitHub's short-lived OIDC token, and public
# packages receive provenance automatically.
#
# PREREQUISITE: every @devup-ui/* package must be registered as a Trusted
# Publisher on npmjs.com against repo dev-five-git/devup-ui and workflow
# file `publish.yml`. npm matches that filename exactly, so renaming or
# moving this file breaks publishing until the entries are updated.
#
# The publish command itself is selected in .changepacks/config.json.
# Bun packs each workspace so dependency ranges are materialized, then
# npm publishes that tarball with OIDC (Bun cannot do OIDC itself:
# oven-sh/bun#22423).
#
# It runs only for a push to main whose validation and end-to-end jobs
# passed, and is the only job that can write contents, open pull requests or
# mint an OIDC token for npm.
release:
needs: [publish, landing-next-e2e, react-18, release-compat]
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
timeout-minutes: 45
permissions:
contents: write
id-token: write
pull-requests: write
steps:
- name: Checkout
uses: actions/checkout@v7
with:
# changepacks diffs HEAD against the previous release commit. The
# default shallow fetch grafts away every parent, so that lookup dies
# with "Could not find a merge-base" and the release never publishes.
fetch-depth: 0
fetch-tags: true
- uses: actions-rust-lang/setup-rust-toolchain@v2
with:
toolchain: stable
components: clippy, rustfmt
- name: Cache cargo registry + target
uses: actions/cache@v6
with:
path: |
~/.cargo/registry/index/
~/.cargo/registry/cache/
~/.cargo/git/db/
target/
key: cargo-release-${{ runner.os }}-${{ hashFiles('**/Cargo.lock') }}
- uses: oven-sh/setup-bun@v2
with:
bun-version: latest
name: Install bun
- name: Cache bun dependencies
uses: actions/cache@v6
with:
path: ~/.bun/install/cache
key: bun-release-${{ runner.os }}-${{ hashFiles('**/bun.lock') }}
- *install-wasm-pack
- name: Install Node.js
uses: actions/setup-node@v7
with:
registry-url: "https://registry.npmjs.org"
node-version: '*'
check-latest: true
- run: bun install --frozen-lockfile
- run: bun run build
- name: Verify built package entry points
run: bun run verify:dist
- name: Verify clean publish checkout
run: git diff --exit-code
- uses: changepacks/action@main
id: changepacks
with:
publish: true