#!/bin/sh # Assemble the whole website into build/www: # # / web/ the front page (this directory) # /docs/ contrib/gen-docs the rendered documentation # /demo/ web/demo/ the in-browser machine, on its own page # # web/build-site everything (or: make www) # NO_DEMO=1 web/build-site skip the demo (it cross-compiles a # guest and needs zig + e2fsprogs) # NO_BOOT_CHECK=1 web/build-site # build the demo but do not boot it # # The output is only static files. Serve it with anything that serves a # directory; the one condition is .wasm as application/wasm, which # `web/demo/serve --dir build/www` handles locally. set -eu here="$(cd "$(dirname "$0")" && pwd)" root="$(dirname "$here")" www="$root/build/www" # Assemble into a staging directory and swap at the end: a build that fails # halfway (set -eu) must not have already deleted the site that worked. out="$root/build/.www-staging" rm -rf "$out" mkdir -p "$out" publish() { rm -rf "$www" mv "$out" "$www" } # The front page. Its recordings are below; there is no video. The released # version is stamped in from ./VERSION: the file the release invariant keeps # equal to the newest tag, so the page cannot claim a version that was never # cut, and a snapshot without git still knows the answer. sed "s/@VERSION@/v$(cat "$root/VERSION")/g" "$here/index.html" > "$out/index.html" cp "$here/site.css" "$out/" # The social-embed card (og:image / twitter:image). Rendered by hand with # web/gen-card when logo.txt or the palette changes, committed, and only # copied here -- regenerating would make Pillow a build dependency. cp "$here/card.png" "$out/" # The docs, rendered by the same generator `make docs` uses. python3 "$root/contrib/gen-docs" "$out/docs" # The recordings: scripted feature playbacks (see recordings/PLAN.md), # re-rendered from their driver scripts so they can never be stale. make -C "$here/recordings" mkdir -p "$out/recordings" cp "$here/recordings/build/"*.json \ "$here/recordings/player.js" "$here/recordings/player.css" \ "$out/recordings/" # The demo, assembled by its own Makefile, on its own page. if [ "${NO_DEMO:-0}" = 1 ]; then echo "build-site: skipping demo (NO_DEMO=1)" else make -C "$here/demo" site # Boot it before shipping it. The demo is the one artifact here whose # build succeeding says nothing about it working: it is a cross-compiled # riscv64 guest, so everything the rest of this script would notice -- # compiler errors, a missing file -- is not where its failures live. A # guest that segfaults on startup links and packages perfectly, and the # page then loads, draws a terminal, and sits there dead. # # That is not hypothetical: v0.1.7 shipped a demo whose every calloc() # returned NULL (vendor/patches/0002), and the site was live and broken # because nothing between `make` and rsync ever ran the binary. boot-check # boots this exact image in a native emulator in about twenty seconds and # fails if init does not reach a composed screen. if [ "${NO_BOOT_CHECK:-0}" = 1 ]; then echo "build-site: skipping demo boot-check (NO_BOOT_CHECK=1)" else make -C "$here/demo" check fi mkdir -p "$out/demo" cp -R "$here/demo/build/site/." "$out/demo/" fi publish echo "build-site: $www" echo "build-site: serve with: web/demo/serve --dir build/www"