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
name: e2e-ui fixture (offline + browser)
# Nested Todos template under tests/e2e-ui — not the root workspace.
# Local parity:
# cd tests/e2e-ui && make check-client
# cd tests/e2e-ui && make test
# cd tests/e2e-ui && make ci-offline
# cd tests/e2e-ui && make up && make run # distributed dev; then make test-browser
on:
workflow_call:
env:
CARGO_TERM_COLOR: always
# Playwright / Auth.js over HTTP on localhost
CI: true
jobs:
offline:
name: e2e-ui offline (domain + suite + UI unit)
runs-on: ubuntu-latest
defaults:
run:
working-directory: tests/e2e-ui
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5
with:
persist-credentials: false
- uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8
with:
toolchain: stable
targets: wasm32-unknown-unknown
- uses: Swatinem/rust-cache@v2
with:
workspaces: |
. -> target
tests/e2e-ui -> target
shared-key: e2e-ui-offline
- name: Install wasm-pack
run: cargo install wasm-pack --locked || cargo install wasm-pack
- uses: actions/setup-node@v4
with:
node-version: "22"
cache: npm
cache-dependency-path: |
js/package-lock.json
tests/e2e-ui/ui/package-lock.json
- name: Build Distributed CLI
run: cargo build --manifest-path ../../Cargo.toml -p distributed_cli --bin distributed
# Production Rust + SvelteKit build enters through the same command users run.
- name: Distributed build + offline suites
run: make ci-offline DISTRIBUTED=../../target/debug/distributed
browser:
name: e2e-ui Playwright (live stack)
runs-on: ubuntu-latest
timeout-minutes: 45
defaults:
run:
working-directory: tests/e2e-ui
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5
with:
persist-credentials: false
- uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8
with:
toolchain: stable
targets: wasm32-unknown-unknown
- uses: Swatinem/rust-cache@v2
with:
workspaces: |
. -> target
tests/e2e-ui -> target
shared-key: e2e-ui-browser
- name: Install wasm-pack
run: cargo install wasm-pack --locked || cargo install wasm-pack
- uses: actions/setup-node@v4
with:
node-version: "22"
cache: npm
cache-dependency-path: |
js/package-lock.json
tests/e2e-ui/package-lock.json
tests/e2e-ui/ui/package-lock.json
- name: Install host tools
run: sudo apt-get update && sudo apt-get install -y jq openssl curl
- name: Docker stack + OIDC bootstrap (make up)
run: |
chmod +x scripts/up.sh
make up
- name: Build Distributed CLI
run: cargo build --manifest-path ../../Cargo.toml -p distributed_cli --bin distributed
# Build first so dev starts from the same coherent, warm generation that
# users get after `distributed build`, rather than racing a cold Cargo
# compile against the readiness deadline.
- name: Build application with Distributed
run: ../../target/debug/distributed build . --output json
- name: Start application with Distributed dev
run: |
set -euo pipefail
export AUTH_URL="${E2E_UI_ORIGIN:-http://localhost:5180}"
export AUTH_USE_SECURE_COOKIES=false
export AUTH_TRUST_HOST=true
../../target/debug/distributed dev . > .distributed-dev.log 2>&1 &
echo $! > .distributed-dev.pid
ok=0
for i in $(seq 1 240); do
if grep -Fq 'lifecycle dev: ready generation=' .distributed-dev.log; then
ok=1
break
fi
if ! kill -0 "$(cat .distributed-dev.pid)" 2>/dev/null; then
echo "distributed dev exited before readiness"
tail -200 .distributed-dev.log
exit 1
fi
sleep 0.5
done
if [ "$ok" != "1" ]; then
echo "distributed dev failed to become ready"
tail -200 .distributed-dev.log
exit 1
fi
grep -F 'lifecycle dev: process api ready http://127.0.0.1:8791' .distributed-dev.log
grep -F 'lifecycle dev: process ui ready http://localhost:5180' .distributed-dev.log
tail -40 .distributed-dev.log
- name: Install Playwright + Chromium
run: |
npm install
npx playwright install chromium --with-deps
- name: Run browser e2e
run: npm run test:browser
env:
E2E_UI_ORIGIN: http://localhost:5180
E2E_API_ORIGIN: http://127.0.0.1:8791
CI: true
- name: Upload Playwright report
if: failure()
uses: actions/upload-artifact@v4
with:
name: e2e-ui-playwright-report
path: |
tests/e2e-ui/playwright-report
tests/e2e-ui/test-results
if-no-files-found: ignore
retention-days: 7
- name: Dump logs on failure
if: failure()
run: |
echo '=== distributed dev ==='
tail -240 .distributed-dev.log || true
docker compose -f docker/docker-compose.yml ps -a || true
docker compose -f docker/docker-compose.yml logs --tail=100 || true
- name: Stop API/UI
if: always()
run: |
if [ -f .distributed-dev.pid ]; then
pid=$(cat .distributed-dev.pid)
kill -INT "$pid" 2>/dev/null || true
for _ in $(seq 1 40); do
kill -0 "$pid" 2>/dev/null || break
sleep 0.25
done
fi
lsof -ti:8791 2>/dev/null | xargs -r kill -9 2>/dev/null || true
lsof -ti:5180 2>/dev/null | xargs -r kill -9 2>/dev/null || true
- name: Tear down Docker
if: always()
run: docker compose -f docker/docker-compose.yml down -v || true