this repo has no description
at main 231 lines 9.1 kB view raw
1#!/bin/bash 2# Deploy interactive OCaml demo pages. 3# 4# This script builds 6 demo pages that showcase in-browser OCaml evaluation 5# using the odoc-interactive-extension and js_top_worker (jtw). 6# 7# ─── One-time setup ────────────────────────────────────────────────────── 8# 9# This script uses `jtw opam` to build universes from local opam switches. 10# In production, `day10 batch --with-jtw` does this at scale inside 11# containers (see docs/jtw-admin-guide.md). The manual switch setup 12# below is the local-dev path for running these demos. 13# 14# 1. Create the opam switches. The "default" switch is used for building 15# the monorepo and for the yojson 3.x universes. 16# 17# # default switch (should already exist) 18# opam switch create default ocaml-base-compiler.5.4.1 19# eval $(opam env --switch default --set-switch) 20# opam install yojson 21# 22# # yojson 2.x switch (for demo2_v2) 23# opam switch create demo-yojson-v2 ocaml-base-compiler.5.4.1 24# eval $(opam env --switch demo-yojson-v2 --set-switch) 25# opam install yojson.2.2.2 26# 27# # OxCaml switch (for demo3_oxcaml) 28# opam switch create 5.2.0+ox \ 29# --repos ox=git+https://github.com/oxcaml/opam-repository.git,default 30# 31# 2. Pin and install js_top_worker packages in every switch that needs a 32# universe. From the monorepo root: 33# 34# for sw in default demo-yojson-v2 5.2.0+ox; do 35# eval $(opam env --switch $sw --set-switch) 36# opam pin add js_top_worker . --no-action 37# opam pin add js_top_worker-web . --no-action 38# opam install js_top_worker js_top_worker-web 39# done 40# 41# 3. Build and install the monorepo tools (jtw, odoc, the extension) 42# into the default switch: 43# 44# eval $(opam env --switch default --set-switch) 45# dune build @install && dune install 46# 47# After this, `jtw opam --help` should work. 48# 49# ─── Production alternative (day10) ───────────────────────────────────── 50# 51# For building universes at scale (e.g. all of opam), use day10 instead 52# of manual switches. day10 runs builds in OCI containers with cached 53# overlay layers. See day10/docs/ADMIN_GUIDE.md for full details. 54# 55# dune exec -- day10 batch \ 56# --cache-dir /var/cache/day10 \ 57# --opam-repository /var/cache/opam-repository \ 58# --local-repo /path/to/js_top_worker \ 59# --with-jtw \ 60# --jtw-output /var/www/jtw \ 61# --html-output /var/www/docs \ 62# --with-doc \ 63# @packages.json 64# 65# --local-repo pins js_top_worker packages from a local checkout instead 66# of the default remote git repo. day10 discovers *.opam files in that 67# directory, bind-mounts it into the container, and uses it for pinning. 68# This is the easiest way to test local changes to js_top_worker. 69# 70# day10 handles switch creation, dependency solving, js_top_worker 71# installation, and per-package universe assembly automatically. 72# 73# ─── Usage ─────────────────────────────────────────────────────────────── 74# 75# ./deploy.sh # build everything and serve on port 8080 76# ./deploy.sh --no-serve # build only, don't start HTTP server 77 78set -euo pipefail 79 80MONO=$(cd "$(dirname "$0")/.." && pwd) 81DOC_HTML="$MONO/_build/default/_doc/_html/odoc-interactive-extension" 82ODOCL="$MONO/_build/default/_doc/_odocl/odoc-interactive-extension" 83OPAM_ODOC="$HOME/.opam/default/bin/odoc" 84UNIVERSES=$(mktemp -d) 85SERVE=true 86 87if [[ "${1:-}" == "--no-serve" ]]; then 88 SERVE=false 89fi 90 91echo "=== Step 1: Install odoc extension into opam switch ===" 92cd "$MONO" 93export OPAMSWITCH=default 94eval "$(opam env)" 95dune build @install 96dune install 2>&1 | tail -5 97 98echo "" 99echo "=== Step 2: Build odoc docs (generates .odocl + base HTML) ===" 100# @doc may exit non-zero due to warnings in other packages (e.g. odoc's own 101# cheatsheet referencing cmdliner). We tolerate that as long as the odocl 102# files we need were actually produced. 103dune build @doc 2>&1 | tail -5 || true 104if [ ! -f "$ODOCL/page-demo1.odocl" ]; then 105 echo "ERROR: odocl files not generated — dune build @doc failed." >&2 106 exit 1 107fi 108 109echo "" 110echo "=== Step 3: Regenerate demo HTML with opam odoc (has extension) ===" 111# dune's workspace-local odoc can't find dune-site plugins, so we use the 112# opam-installed one which has the extension registered. 113for page in demo1 demo2_v2 demo2_v3 demo3_oxcaml demo4_crossorigin demo5_multiverse; do 114 chmod u+w "$DOC_HTML/${page}.html" 2>/dev/null || true 115 "$OPAM_ODOC" html-generate "$ODOCL/page-${page}.odocl" \ 116 -o "$DOC_HTML/.." \ 117 --support-uri=_odoc_support 2>&1 118 echo " regenerated ${page}.html" 119done 120 121echo "" 122echo "=== Step 4: Build x-ocaml.js ===" 123dune build x-ocaml/src/x_ocaml.bc.js 124 125echo "" 126echo "=== Step 5: Build universes ===" 127 128# 5a. Default universe (yojson 3.0 — used by demo1) 129echo " building default universe (yojson, default switch)..." 130jtw opam --switch=default -o "$UNIVERSES/default" yojson 131 132# 5b. Yojson v2 universe 133echo " building yojson-v2 universe (demo-yojson-v2 switch)..." 134jtw opam --switch=demo-yojson-v2 -o "$UNIVERSES/v2" yojson 135 136# 5c. Yojson v3 universe (same as default, but separate dir for isolation) 137echo " building yojson-v3 universe (default switch)..." 138jtw opam --switch=default -o "$UNIVERSES/v3" yojson 139 140# 5d. OxCaml universe (stdlib only) 141echo " building oxcaml universe (5.2.0+ox switch)..." 142jtw opam --switch=5.2.0+ox -o "$UNIVERSES/oxcaml" 143 144echo "" 145echo "=== Step 6: Deploy assets into doc HTML output ===" 146 147# _x-ocaml runtime (shared by all pages) 148mkdir -p "$DOC_HTML/_x-ocaml" 149chmod -R u+w "$DOC_HTML/_x-ocaml" 2>/dev/null || true 150cp "$MONO/_build/default/x-ocaml/src/x_ocaml.bc.js" "$DOC_HTML/_x-ocaml/x-ocaml.js" 151cp "$UNIVERSES/default/worker.js" "$DOC_HTML/_x-ocaml/worker.js" 152echo " deployed _x-ocaml/" 153 154# Make deployed dirs writable so re-runs can overwrite them. 155chmod -R u+w "$DOC_HTML/universe" "$DOC_HTML/universe-v2" \ 156 "$DOC_HTML/universe-v3" "$DOC_HTML/universe-oxcaml" 2>/dev/null || true 157 158# demo1: ./universe 159rm -rf "$DOC_HTML/universe" 160cp -r "$UNIVERSES/default" "$DOC_HTML/universe" 161echo " deployed universe/ (demo1)" 162 163# demo2_v2: ./universe-v2 164rm -rf "$DOC_HTML/universe-v2" 165cp -r "$UNIVERSES/v2" "$DOC_HTML/universe-v2" 166echo " deployed universe-v2/ (demo2_v2)" 167 168# demo2_v3: ./universe-v3 169rm -rf "$DOC_HTML/universe-v3" 170cp -r "$UNIVERSES/v3" "$DOC_HTML/universe-v3" 171echo " deployed universe-v3/ (demo2_v3)" 172 173# demo3_oxcaml: ./universe-oxcaml 174rm -rf "$DOC_HTML/universe-oxcaml" 175cp -r "$UNIVERSES/oxcaml" "$DOC_HTML/universe-oxcaml" 176echo " deployed universe-oxcaml/ (demo3_oxcaml)" 177 178# Copy x-ocaml.js into each universe (for cross-origin blob: fallback) 179for d in universe universe-v2 universe-v3 universe-oxcaml; do 180 cp "$DOC_HTML/_x-ocaml/x-ocaml.js" "$DOC_HTML/$d/x-ocaml.js" 181done 182 183# Cross-origin universe (same content as default, served on port 9090) 184CROSSORIGIN_DIR="$DOC_HTML/../_crossorigin_universes" 185chmod -R u+w "$CROSSORIGIN_DIR" 2>/dev/null || true 186rm -rf "$CROSSORIGIN_DIR" 187mkdir -p "$CROSSORIGIN_DIR" 188cp -r "$DOC_HTML/universe" "$CROSSORIGIN_DIR/universe" 189echo " deployed _crossorigin_universes/ (for port 9090)" 190 191# Multiverse (per-package layout with universe linking) 192echo "" 193echo "=== Step 7: Build multiverse (per-package layout) ===" 194MULTIVERSE_DIR="$DOC_HTML/../_multiverse" 195chmod -R u+w "$MULTIVERSE_DIR" 2>/dev/null || true 196rm -rf "$MULTIVERSE_DIR" 197jtw opam-all --switch=default yojson -o "$MULTIVERSE_DIR" 198cp "$MONO/_build/default/x-ocaml/src/x_ocaml.bc.js" "$MULTIVERSE_DIR/x-ocaml.js" 199echo " deployed _multiverse/ (for port 9090)" 200 201echo "" 202echo "=== Done ===" 203echo "Demo pages at: $DOC_HTML/" 204echo "" 205echo " demo1.html — basic OCaml + yojson (default switch)" 206echo " demo2_v2.html — yojson 2.2.2 (demo-yojson-v2 switch)" 207echo " demo2_v3.html — yojson 3.0.0 (default switch)" 208echo " demo3_oxcaml.html — OxCaml extensions (5.2.0+ox switch)" 209echo " demo4_crossorigin.html — cross-origin loading (needs port 9090)" 210echo " demo5_multiverse.html — multiverse per-package layout (needs port 9090)" 211echo "" 212echo "Cross-origin demos (demo4, demo5) require a CORS-enabled server on port 9090." 213echo "They serve different directories, so you can only test one at a time:" 214echo "" 215echo " demo4 (cross-origin):" 216echo " python3 $MONO/odoc-interactive-extension/cors_server.py 9090 $DOC_HTML/../_crossorigin_universes" 217echo "" 218echo " demo5 (multiverse):" 219echo " python3 $MONO/odoc-interactive-extension/cors_server.py 9090 $DOC_HTML/../_multiverse" 220 221# Clean up 222rm -rf "$UNIVERSES" 223 224if $SERVE; then 225 echo "" 226 echo "Starting HTTP server on http://localhost:8080" 227 echo "Visit: http://localhost:8080/odoc-interactive-extension/demo1.html" 228 echo "" 229 cd "$DOC_HTML/.." 230 exec python3 -m http.server 8080 231fi