Skip to content

Commit a6e8da3

Browse files
committed
test: add script to run example livebooks against local checkout
scripts/test-livebooks.sh extracts the Elixir cells from each notebook in notebooks/, repoints the `{:emily, "~> x"}` Mix.install dependency at the working tree (a path dep, so the NIF is built from source and the notebook runs against local code), and runs each headless with `elixir`, reporting PASS/FAIL/SKIP plus per-notebook logs. Mirrors the standalone-Mix.install pattern in scripts/qwen3_conformance.exs. Notebooks are run, not interacted with — Kino form/input cells (e.g. the Whisper audio recorder) don't fire, but surrounding setup/inference does.
1 parent 781cb2b commit a6e8da3

1 file changed

Lines changed: 105 additions & 0 deletions

File tree

scripts/test-livebooks.sh

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
#!/usr/bin/env bash
2+
# Smoke-test the example livebooks against the LOCAL emily checkout.
3+
#
4+
# For each notebook in notebooks/, this extracts its Elixir cells,
5+
# repoints the `{:emily, "~> x"}` Mix.install dependency at this repo (as
6+
# a `path:` dep, so the notebook exercises the working tree — including a
7+
# from-source NIF build), and runs the result headlessly with `elixir`.
8+
# A notebook passes if it runs to completion with exit code 0.
9+
#
10+
# Notes:
11+
# * First run downloads model checkpoints via Bumblebee (cached under
12+
# ~/Library/Caches/bumblebee afterwards) and compiles emily's NIF, so
13+
# it needs network + disk and can take several minutes per notebook.
14+
# * Cells render Kino widgets; outside Livebook those just evaluate to
15+
# structs. Notebooks are *run*, not interacted with — anything gated
16+
# behind a Kino form/input (e.g. recording audio in the Whisper
17+
# notebook) won't fire, but the surrounding setup/inference still does.
18+
#
19+
# Usage:
20+
# scripts/test-livebooks.sh # all notebooks
21+
# scripts/test-livebooks.sh distilbert_qa nomic_embeddings # a subset
22+
#
23+
# Env:
24+
# LIVEBOOK_TIMEOUT per-notebook timeout, seconds (default 1200)
25+
# LIVEBOOK_SKIP space-separated notebook names to skip
26+
# EMILY_CACHE MLX/NIF cache dir (passed through to the build)
27+
28+
set -uo pipefail
29+
30+
REPO="$(cd "$(dirname "$0")/.." && pwd)"
31+
NB_DIR="$REPO/notebooks"
32+
TIMEOUT="${LIVEBOOK_TIMEOUT:-1200}"
33+
SKIP=" ${LIVEBOOK_SKIP:-} "
34+
35+
if ! command -v elixir >/dev/null 2>&1; then
36+
echo "error: elixir not on PATH" >&2
37+
exit 2
38+
fi
39+
40+
# Selection: explicit notebook basenames, or every *.livemd.
41+
if [[ $# -gt 0 ]]; then
42+
names=("$@")
43+
else
44+
names=()
45+
for f in "$NB_DIR"/*.livemd; do names+=("$(basename "$f" .livemd)"); done
46+
fi
47+
48+
# Print the contents of every ```elixir fenced block, blank-line separated.
49+
extract_cells() {
50+
awk '
51+
/^```elixir[[:space:]]*$/ { inblock=1; next }
52+
/^```[[:space:]]*$/ { if (inblock) { inblock=0; print "" }; next }
53+
inblock { print }
54+
' "$1"
55+
}
56+
57+
pass=()
58+
fail=()
59+
skip=()
60+
log_dir="$(mktemp -d "${TMPDIR:-/tmp}/emily-livebooks.XXXXXX")"
61+
echo "emily: $REPO (path dep)"
62+
echo "logs: $log_dir"
63+
echo
64+
65+
for name in "${names[@]}"; do
66+
nb="$NB_DIR/$name.livemd"
67+
if [[ ! -f "$nb" ]]; then
68+
echo ">> $name: NOT FOUND"
69+
fail+=("$name")
70+
continue
71+
fi
72+
if [[ "$SKIP" == *" $name "* ]]; then
73+
echo ">> $name: SKIP"
74+
skip+=("$name")
75+
continue
76+
fi
77+
78+
script="$log_dir/$name.exs"
79+
out="$log_dir/$name.out"
80+
# Extract the cells and repoint the emily dependency at this checkout.
81+
extract_cells "$nb" \
82+
| sed "s|{:emily,[^}]*}|{:emily, path: \"$REPO\"}|" \
83+
> "$script"
84+
85+
printf ">> %-28s running (timeout %ss) ... " "$name" "$TIMEOUT"
86+
start=$SECONDS
87+
if timeout "$TIMEOUT" elixir "$script" >"$out" 2>&1; then
88+
echo "PASS ($((SECONDS - start))s)"
89+
pass+=("$name")
90+
else
91+
code=$?
92+
echo "FAIL (exit $code, $((SECONDS - start))s)"
93+
tail -n 25 "$out" | sed 's/^/ | /'
94+
fail+=("$name")
95+
fi
96+
done
97+
98+
echo
99+
echo "==================== livebook results ===================="
100+
printf "PASS (%d): %s\n" "${#pass[@]}" "${pass[*]:-}"
101+
printf "FAIL (%d): %s\n" "${#fail[@]}" "${fail[*]:-}"
102+
printf "SKIP (%d): %s\n" "${#skip[@]}" "${skip[*]:-}"
103+
echo "logs in $log_dir"
104+
105+
[[ ${#fail[@]} -eq 0 ]]

0 commit comments

Comments
 (0)