diff --git a/website/public/index.html b/website/public/index.html index d4b3f27551..c7b9d99ccf 100644 --- a/website/public/index.html +++ b/website/public/index.html @@ -82,7 +82,7 @@

The refactorable warehouse

└── revenue.sqlmodels └── finance └── daily_revenue.sql -sqb planMigrations (1)└── daily_revenue migrate prod.revenue -> prod.daily_revenue ├── compatibility compatible ├── transfer physical copy, promote by staged rename └── discovery automatic +sqb planMigrations (1)└── daily_revenue migrate prod.revenue -> prod.daily_revenue ├── compatibility compatible ├── transfer physical copy, promote by staged rename └── discovery automatic
@@ -202,14 +202,14 @@

Reorganise without breaking anything

│ └── datetime.py # timestamp_trunc └── daily_revenue.sql # uses payment_status and cents_to_dollars sqb scope model:daily_revenue --as-path models/intermediate/daily_revenue.sql -Move preview - Resource: model:daily_revenue - Destination: models/intermediate/daily_revenue.sql - Lost (3) - ├─ ● enum:payment_status models/marts/_sqlbuild/_enums/payment_status.sql:1:1 - ├─ ● macro:cents_to_dollars models/marts/_sqlbuild/_macros/currency.py:4:1 - └─ ○ macro:timestamp_trunc models/marts/_sqlbuild/_macros/datetime.py:4:1 - Invalidated usages (2) +Move preview + Resource: model:daily_revenue + Destination: models/intermediate/daily_revenue.sql + Lost (3) + ├─ ● enum:payment_status models/marts/_sqlbuild/_enums/payment_status.sql:1 + ├─ ● macro:cents_to_dollars models/marts/_sqlbuild/_macros/currency.py:4 + └─ ○ macro:timestamp_trunc models/marts/_sqlbuild/_macros/datetime.py:4 + Invalidated usages (2) - enum:payment_status - macro:cents_to_dollars @@ -326,11 +326,11 @@

Rename models without rebuilding history

sqb plan
-Migrations (1)
-└── daily_order_rollup  migrate  dev.daily_activity_rollup -> dev.daily_order_rollup
-    ├── compatibility  compatible
-    ├── transfer  physical copy, promote by staged rename
-    └── discovery  automatic
+Migrations (1) +└── daily_order_rollup migrate dev.daily_activity_rollup -> dev.daily_order_rollup + ├── compatibility compatible + ├── transfer physical copy, promote by staged rename + └── discovery automatic
diff --git a/website/recordings/.gitignore b/website/recordings/.gitignore new file mode 100644 index 0000000000..77f75d7e9a --- /dev/null +++ b/website/recordings/.gitignore @@ -0,0 +1,2 @@ +out/ +scratch/ diff --git a/website/recordings/README.md b/website/recordings/README.md new file mode 100644 index 0000000000..34f57ceada --- /dev/null +++ b/website/recordings/README.md @@ -0,0 +1,36 @@ +# CLI recordings + +Terminal recordings of `sqb` for the README and the website, rendered with +[VHS](https://github.com/charmbracelet/vhs) from the `.tape` scripts in `tapes/`. The tapes and +scripts are the source; the rendered GIF, MP4 and PNG files go to `out/`, which is not committed. + +| Demo | Shows | +|------|-------| +| `rename` | A model is moved and renamed, and `sqb plan` migrates the existing table. | +| `compile` | `sqb compile` catches an unknown column and a type mismatch. | +| `scope` | `sqb scope --as-path` previews what a move would lose. | +| `janitor` | `sqb janitor` archives a stale table before anything is deleted. | +| `quickstart` | The playground: `sqb playground`, `sqb build` and `sqb test`. | + +Each demo runs locally on DuckDB, using the projects in [`../examples`](../examples). + +## Requirements + +- `vhs`, `ttyd` and `ffmpeg` on `PATH`, plus a Chromium or Chrome that VHS can find (it downloads + one if none is on `PATH`). +- DejaVu Sans Mono, the font the tapes use. +- `sqb` on `PATH`, or `SQB_BIN` pointing at a directory that contains the `sqb` to record. + +## Record + +```bash +cd website/recordings +./record.sh rename # out/rename.gif, out/rename.mp4 and out/rename.png +``` + +`record.sh` runs `prepare.sh ` to build a clean project under `scratch//`, then renders +`tapes/.tape`. Shared terminal settings and the colour theme, which matches the website's +terminal blocks, are in `tapes/common.tape`. + +Look at every recording before publishing it: output such as timings, run IDs and dates changes +between runs. diff --git a/website/recordings/prepare.sh b/website/recordings/prepare.sh new file mode 100755 index 0000000000..c34af34b48 --- /dev/null +++ b/website/recordings/prepare.sh @@ -0,0 +1,62 @@ +#!/usr/bin/env bash +# Build a clean scratch project for one demo. Usage: prepare.sh +set -euo pipefail +demo="$1" +here="$(cd "$(dirname "$0")" && pwd)" +examples="$here/../examples" +dir="$here/scratch/$demo" +rm -rf "$dir" +mkdir -p "$here/scratch" +case "$demo" in + quickstart) + mkdir -p "$dir" ;; + rename) + # Build the model under its old name, so the tape can move and rename it. + cp -r "$examples/hero-shop" "$dir" + cd "$dir" + mkdir -p models/marts + mv models/finance/daily_revenue.sql models/marts/revenue.sql + rmdir models/finance + sqb build >/dev/null ;; + scope) + cp -r "$examples/waffle-shop" "$dir" + cd "$dir" + sqb compile >/dev/null || true ;; + janitor) + # Build a model, then remove it, so the janitor has a stale table to archive. + cp -r "$examples/tidy-shop" "$dir" + cd "$dir" + cat > models/weekly_revenue.sql <<'SQL' +MODEL ( + materialized table, +); + +SELECT DATE_TRUNC('week', revenue_date) AS revenue_week, SUM(total_revenue_cents) AS total_revenue_cents +FROM __ref("daily_revenue") +GROUP BY 1 +SQL + sqb build >/dev/null + rm models/weekly_revenue.sql ;; + compile) + # Introduce an unknown column and a type mismatch, checked against enforced source contracts. + cp -r "$examples/waffle-shop" "$dir" + cd "$dir" + python3 - <<'PY' +import re + +path = "sources/raw.yml" +text = open(path).read() +for name in ("raw__customers", "raw__orders"): + text = re.sub(rf"(\n(\s*)- name: {name}\n)", rf"\1\2 contract: enforced\n", text, count=1) +open(path, "w").write(text) + +path = "models/marts/fact_orders.sql" +text = open(path).read() +text = text.replace("o.quantity,", "o.qty,", 1).rstrip() + "\nWHERE o.ordered_at > 5\n" +open(path, "w").write(text) +PY + ;; + *) + echo "unknown demo: $demo" >&2 + exit 2 ;; +esac diff --git a/website/recordings/record.sh b/website/recordings/record.sh new file mode 100755 index 0000000000..69021d36cf --- /dev/null +++ b/website/recordings/record.sh @@ -0,0 +1,14 @@ +#!/usr/bin/env bash +# Record one demo to out/.gif and out/.mp4. Usage: record.sh +# Uses the sqb on PATH; set SQB_BIN to a directory containing another sqb to use that instead. +set -euo pipefail +demo="$1" +here="$(cd "$(dirname "$0")" && pwd)" +if [[ -n "${SQB_BIN:-}" ]]; then + export PATH="$SQB_BIN:$PATH" +fi +"$here/prepare.sh" "$demo" +mkdir -p "$here/out" +cd "$here" +# Headless Chromium's sandbox is unavailable in many containers and CI runners. +VHS_NO_SANDBOX="${VHS_NO_SANDBOX:-true}" vhs "tapes/$demo.tape" diff --git a/website/recordings/tapes/common.tape b/website/recordings/tapes/common.tape new file mode 100644 index 0000000000..8dade07714 --- /dev/null +++ b/website/recordings/tapes/common.tape @@ -0,0 +1,13 @@ +Set Shell bash +Set FontFamily "DejaVu Sans Mono" +Set FontSize 18 +Set LineHeight 1.0 +Set Width 1200 +Set Height 680 +Set Padding 28 +Set Margin 24 +Set MarginFill "#0d0f12" +Set BorderRadius 10 +Set WindowBar Colorful +Set TypingSpeed 45ms +Set Theme { "name": "SQLBuild", "black": "#626975", "red": "#f47089", "green": "#54cf8e", "yellow": "#f0c267", "blue": "#3788e8", "magenta": "#a78bfa", "cyan": "#4dd6c4", "white": "#c9cdd4", "brightBlack": "#9ba1ac", "brightRed": "#f47089", "brightGreen": "#54cf8e", "brightYellow": "#f0c267", "brightBlue": "#4f98ee", "brightMagenta": "#c79bf0", "brightCyan": "#4dd6c4", "brightWhite": "#e9ebef", "background": "#111418", "foreground": "#c9cdd4", "selection": "#2a2f37", "cursor": "#e9ebef" } diff --git a/website/recordings/tapes/compile.tape b/website/recordings/tapes/compile.tape new file mode 100644 index 0000000000..6dca3c1ee0 --- /dev/null +++ b/website/recordings/tapes/compile.tape @@ -0,0 +1,14 @@ +Source tapes/common.tape +Output out/compile.gif +Output out/compile.mp4 +Hide +Type "cd scratch/compile && export PS1='$ ' && clear" +Enter +Sleep 500ms +Show +Type "sqb compile" +Sleep 300ms +Enter +Sleep 6s +Screenshot out/compile.png +Sleep 3s diff --git a/website/recordings/tapes/janitor.tape b/website/recordings/tapes/janitor.tape new file mode 100644 index 0000000000..392a4e9d4c --- /dev/null +++ b/website/recordings/tapes/janitor.tape @@ -0,0 +1,18 @@ +Source tapes/common.tape +Output out/janitor.gif +Output out/janitor.mp4 +Hide +Type "cd scratch/janitor && export PS1='$ ' && clear" +Enter +Sleep 500ms +Show +Type "sqb janitor" +Sleep 300ms +Enter +Sleep 5s +Type "archive 1 and delete 1 items from prod" +Sleep 500ms +Enter +Sleep 4s +Screenshot out/janitor.png +Sleep 3s diff --git a/website/recordings/tapes/quickstart.tape b/website/recordings/tapes/quickstart.tape new file mode 100644 index 0000000000..70f9d9d2e0 --- /dev/null +++ b/website/recordings/tapes/quickstart.tape @@ -0,0 +1,25 @@ +Source tapes/common.tape +Output out/quickstart.gif +Output out/quickstart.mp4 +Hide +Type "cd scratch/quickstart && export PS1='$ ' && clear" +Enter +Sleep 500ms +Show +Type "sqb playground waffle-shop" +Sleep 300ms +Enter +Sleep 2s +Type "cd waffle-shop" +Enter +Sleep 500ms +Type "sqb build" +Sleep 300ms +Enter +Sleep 8s +Type "sqb test" +Sleep 300ms +Enter +Sleep 6s +Screenshot out/quickstart.png +Sleep 2s diff --git a/website/recordings/tapes/rename.tape b/website/recordings/tapes/rename.tape new file mode 100644 index 0000000000..9d2e1bbbd8 --- /dev/null +++ b/website/recordings/tapes/rename.tape @@ -0,0 +1,21 @@ +Source tapes/common.tape +Output out/rename.gif +Output out/rename.mp4 +Hide +Type "cd scratch/rename && export PS1='$ ' && clear" +Enter +Sleep 500ms +Show +Type "find models -name '*.sql'" +Enter +Sleep 1500ms +Type "mkdir models/finance && mv models/marts/revenue.sql models/finance/daily_revenue.sql" +Sleep 300ms +Enter +Sleep 800ms +Type "sqb plan" +Sleep 300ms +Enter +Sleep 5s +Screenshot out/rename.png +Sleep 3s diff --git a/website/recordings/tapes/scope.tape b/website/recordings/tapes/scope.tape new file mode 100644 index 0000000000..a208d29722 --- /dev/null +++ b/website/recordings/tapes/scope.tape @@ -0,0 +1,17 @@ +Source tapes/common.tape +Output out/scope.gif +Output out/scope.mp4 +Hide +Type "cd scratch/scope && export PS1='$ ' && clear" +Enter +Sleep 500ms +Show +Type "find models/marts -name '*.sql' -o -name '*.py'" +Enter +Sleep 1500ms +Type "sqb scope model:daily_revenue --as-path models/intermediate/daily_revenue.sql" +Sleep 300ms +Enter +Sleep 5s +Screenshot out/scope.png +Sleep 3s