Skip to content

Commit f2eaafb

Browse files
committed
Merge remote-tracking branch 'origin/staging' into improvement/landing
# Conflicts: # apps/sim/app/(landing)/demo/components/demo-scheduler/demo-scheduler.tsx # apps/sim/content/library/6-best-ai-observability-tools-for-production-agents-in-2026/index.mdx # apps/sim/lib/analytics/google.ts # apps/sim/lib/consent/scripts.ts # apps/sim/lib/content/index-list.ts
2 parents be65723 + db30e1a commit f2eaafb

133 files changed

Lines changed: 41150 additions & 2036 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.github/scripts/stop-session.sh‎

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
#!/usr/bin/env bash
2+
# Stops every process in a session started with `setsid`, and returns only once none is left.
3+
#
4+
# Usage: stop-session.sh <session-leader-pid>
5+
#
6+
# `next dev` runs its server and workers as child processes. Waiting on `next dev` alone returns
7+
# while those can still be running, and the next app in the job reuses the same .next directory.
8+
# Every member of the session is signalled, including one that moved to its own process group.
9+
# The leader stays a zombie until the shell that started it waits on it, so zombies don't count.
10+
set -u
11+
12+
leader=$1
13+
grace_seconds=10
14+
15+
session_pids() {
16+
ps -s "$leader" -o pid=,stat= 2>/dev/null | awk '$2 !~ /^Z/ { print $1 }'
17+
}
18+
19+
signal_session() {
20+
local pids
21+
pids=$(session_pids)
22+
[ -z "$pids" ] || kill "-$1" $pids 2>/dev/null || true
23+
}
24+
25+
running() {
26+
[ -n "$(session_pids)" ]
27+
}
28+
29+
leader_running() {
30+
ps -p "$leader" -o stat= 2>/dev/null | grep -qv '^Z'
31+
}
32+
33+
now_us() {
34+
echo "${EPOCHREALTIME/./}"
35+
}
36+
37+
# Waits while the given check holds, until the shared deadline. Succeeds once it stops holding.
38+
wait_while() {
39+
while (($(now_us) < deadline)); do
40+
"$@" || return 0
41+
sleep 0.1
42+
done
43+
! "$@"
44+
}
45+
46+
deadline=$(($(now_us) + grace_seconds * 1000000))
47+
signal_session TERM
48+
wait_while leader_running
49+
if ! leader_running && running; then
50+
echo "Processes from session $leader outlived its leader:"
51+
ps -s "$leader" -o pid,stat,etimes,args 2>/dev/null | cut -c1-200 || true
52+
fi
53+
wait_while running && exit 0
54+
55+
echo "::warning::Processes from session $leader were still running ${grace_seconds}s after SIGTERM:"
56+
ps -s "$leader" -o pid,stat,etimes,args 2>/dev/null | cut -c1-200 || true
57+
deadline=$(($(now_us) + grace_seconds * 1000000))
58+
signal_session KILL
59+
wait_while running && exit 0
60+
61+
echo "::error::Processes from session $leader survived SIGKILL for ${grace_seconds}s."
62+
exit 1

‎.github/workflows/desktop-e2e.yml‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,8 @@ jobs:
8484
- name: Run Playwright _electron smoke suite
8585
working-directory: apps/desktop
8686
run: bunx playwright test
87+
env:
88+
BACKGROUND_EXECUTOR_REPORT_PATH: test-results/background-executor-report.json
8789

8890
- name: Upload test results
8991
if: failure()

‎.github/workflows/test-build.yml‎

Lines changed: 79 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,13 @@ jobs:
217217
# immediately, and either way the server log tail lands in the job log. No
218218
# step timeout: the job's bound covers a hang without cutting a slow but
219219
# healthy suite short of writing its report.
220+
#
221+
# Every `next dev` app in this job shares apps/sim/.next, so each one follows the
222+
# same lifecycle. It starts from an empty Turbopack dev cache: a cache written under
223+
# other NEXT_PUBLIC_* values, by a server that `next dev` SIGKILLs 100ms after
224+
# SIGTERM, can panic Turbopack or wedge a route compile on restore. It runs in its
225+
# own session, and stop-session.sh returns only once all of it has exited, so no app
226+
# starts beside one still writing .next/dev.
220227
- name: Verify SCIM, administration and workflow comparisons over real HTTP
221228
working-directory: apps/sim
222229
env:
@@ -243,17 +250,22 @@ jobs:
243250
report_dir="$RUNNER_TEMP/e2e"
244251
server_log="$report_dir/scim-next.log"
245252
mkdir -p "$report_dir"
246-
node ../../node_modules/next/dist/bin/next dev --hostname 127.0.0.1 --port 3017 > "$server_log" 2>&1 &
253+
rm -rf .next/dev
254+
setsid node ../../node_modules/next/dist/bin/next dev --hostname 127.0.0.1 --port 3017 > "$server_log" 2>&1 &
247255
server_pid=$!
248256
finish() {
249-
kill "$server_pid" 2>/dev/null || true
257+
status=$?
258+
bash ../../.github/scripts/stop-session.sh "$server_pid" || status=1
250259
wait "$server_pid" 2>/dev/null || true
251260
awk '/^ (GET|POST|PUT|PATCH|DELETE|HEAD) \/api\// { print }' "$server_log" > "$report_dir/scim-http-status.log"
261+
if [ "$status" -ne 0 ]; then
262+
tail -n 200 "$server_log"
263+
exit "$status"
264+
fi
252265
}
253266
trap finish EXIT
254267
fail_startup() {
255268
echo "::error::$1"
256-
tail -n 200 "$server_log"
257269
exit 1
258270
}
259271
started=$SECONDS
@@ -275,6 +287,54 @@ jobs:
275287
VERSION_COMPARE_E2E_REPORT_PATH="$report_dir/version-compare-http-report.json" \
276288
bun run test:workflow-version-compare:e2e
277289
290+
# Self-hosted without billing: hosted billing admits runs through Redis, which
291+
# this job does not provision.
292+
- name: Verify embedded CLI workflow runs and log reads over real HTTP
293+
working-directory: apps/sim
294+
env:
295+
NEXT_PUBLIC_APP_URL: http://127.0.0.1:3018
296+
BETTER_AUTH_URL: http://127.0.0.1:3018
297+
NEXT_PUBLIC_FORCE_HOSTED: 'false'
298+
INTERNAL_API_SECRET: cli-http-ci-local-secret-at-least-32-characters
299+
DISABLE_TELEMETRY: 'true'
300+
NEXT_TELEMETRY_DISABLED: '1'
301+
READY_TIMEOUT_SECONDS: 300
302+
run: |
303+
report_dir="$RUNNER_TEMP/e2e"
304+
server_log="$report_dir/cli-next.log"
305+
mkdir -p "$report_dir"
306+
rm -rf .next/dev
307+
setsid node ../../node_modules/next/dist/bin/next dev --hostname 127.0.0.1 --port 3018 > "$server_log" 2>&1 &
308+
server_pid=$!
309+
finish() {
310+
status=$?
311+
bash ../../.github/scripts/stop-session.sh "$server_pid" || status=1
312+
wait "$server_pid" 2>/dev/null || true
313+
if [ "$status" -ne 0 ]; then
314+
tail -n 200 "$server_log"
315+
exit "$status"
316+
fi
317+
}
318+
trap finish EXIT
319+
fail_startup() {
320+
echo "::error::$1"
321+
exit 1
322+
}
323+
started=$SECONDS
324+
until curl --fail --silent --max-time 10 http://127.0.0.1:3018/api/health > /dev/null; do
325+
kill -0 "$server_pid" 2>/dev/null || fail_startup 'Local CLI app exited during startup.'
326+
[ $((SECONDS - started)) -lt "$READY_TIMEOUT_SECONDS" ] ||
327+
fail_startup "Local CLI app did not become ready within $READY_TIMEOUT_SECONDS seconds."
328+
sleep 2
329+
done
330+
echo "Local CLI app ready after $((SECONDS - started))s"
331+
CLI_LATENCY_E2E_BASE_URL="$NEXT_PUBLIC_APP_URL" \
332+
CLI_LATENCY_E2E_DATABASE_URL="$DATABASE_URL" \
333+
CLI_LATENCY_E2E_RUNS=3 \
334+
CLI_LATENCY_E2E_WARMUP=1 \
335+
CLI_LATENCY_E2E_REPORT_PATH="$report_dir/cli-run-latency-report.json" \
336+
bun run test:cli-run-latency:e2e
337+
278338
# A self-hosted app: hosted billing admits a run only through a Redis usage
279339
# reservation, and the SCIM suite above asserts PostgreSQL rate-limit storage,
280340
# so workflow execution gets its own app rather than adding Redis to that one.
@@ -294,17 +354,22 @@ jobs:
294354
report_dir="$RUNNER_TEMP/e2e"
295355
server_log="$report_dir/stop-after-next.log"
296356
mkdir -p "$report_dir"
297-
node ../../node_modules/next/dist/bin/next dev --hostname 127.0.0.1 --port 3018 > "$server_log" 2>&1 &
357+
rm -rf .next/dev
358+
setsid node ../../node_modules/next/dist/bin/next dev --hostname 127.0.0.1 --port 3018 > "$server_log" 2>&1 &
298359
server_pid=$!
299360
finish() {
300-
kill "$server_pid" 2>/dev/null || true
361+
status=$?
362+
bash ../../.github/scripts/stop-session.sh "$server_pid" || status=1
301363
wait "$server_pid" 2>/dev/null || true
302364
awk '/^ (GET|POST|PUT|PATCH|DELETE|HEAD) \/api\// { print }' "$server_log" > "$report_dir/stop-after-http-status.log"
365+
if [ "$status" -ne 0 ]; then
366+
tail -n 200 "$server_log"
367+
exit "$status"
368+
fi
303369
}
304370
trap finish EXIT
305371
fail_startup() {
306372
echo "::error::$1"
307-
tail -n 200 "$server_log"
308373
exit 1
309374
}
310375
started=$SECONDS
@@ -340,17 +405,22 @@ jobs:
340405
report_dir="$RUNNER_TEMP/e2e"
341406
server_log="$report_dir/desktop-inbox-next.log"
342407
mkdir -p "$report_dir"
343-
node ../../node_modules/next/dist/bin/next dev --hostname 127.0.0.1 --port 3019 > "$server_log" 2>&1 &
408+
rm -rf .next/dev
409+
setsid node ../../node_modules/next/dist/bin/next dev --hostname 127.0.0.1 --port 3019 > "$server_log" 2>&1 &
344410
server_pid=$!
345411
finish() {
346-
kill "$server_pid" 2>/dev/null || true
412+
status=$?
413+
bash ../../.github/scripts/stop-session.sh "$server_pid" || status=1
347414
wait "$server_pid" 2>/dev/null || true
348415
awk '/^ (GET|POST|PUT|PATCH|DELETE|HEAD) \/api\// { print }' "$server_log" > "$report_dir/desktop-inbox-http-status.log"
416+
if [ "$status" -ne 0 ]; then
417+
tail -n 200 "$server_log"
418+
exit "$status"
419+
fi
349420
}
350421
trap finish EXIT
351422
fail_startup() {
352423
echo "::error::$1"
353-
tail -n 200 "$server_log"
354424
exit 1
355425
}
356426
started=$SECONDS

0 commit comments

Comments
 (0)