#!/bin/sh # Capture the assembled site as a release artifact (improvise-oujb). # # `dist` runs this from the repo root as an `[[dist.extra-artifacts]]` build # command, inside release.yml's `build-global-artifacts` job, and then uploads # the file named here to the GitHub Release. Nothing about that job is edited # by hand: see the comment in dist-workspace.toml. # # WHAT THIS IS FOR, and it is narrower than it looks. GitHub Pages keeps # tracking `main` (user ruling, 2026-09-22: "I like Pages showing the latest # main for now"), so this tarball is NOT what a visitor to the published site # is running. It is a self-hostable copy of the site as of the tag, and a # rollback target. A reader who assumes it is the deployed site will be wrong. # # IT BUILDS NOTHING OF ITS OWN. web/build.sh and web/assemble.sh are the same # two scripts a developer runs and the same two ci.yml's `build` job runs; a # release that assembled the bundle its own way would reintroduce exactly the # drift that job's comment exists to prevent (improvise-vvl3). Everything # below the toolchain block is those two calls and a `tar`. # # Usage: scripts/build-web-release.sh [OUT_TARBALL] # # The cache-bust token is the tag (`GITHUB_REF_NAME`), where the Pages build # passes the commit SHA and a bare local run defaults to `dev`. A release is # the one case where a human-readable name is available and is what a bug # report will quote, and web/assemble.sh stamps it into the page's # #build-version element as well as into the two bundle URLs. set -eu root=$(cd "$(dirname "$0")/.." && pwd) out=${1:-"$root/improvise-web.tar.gz"} # A tag may legally contain `/` and a release.yml PR run puts `NN/merge` here, # so the token is reduced to what is safe in a URL query and a filename. raw=${IMPROVISE_WEB_TOKEN:-${GITHUB_REF_NAME:-dev}} token=$(printf '%s' "$raw" | sed 's|[^A-Za-z0-9._-]|-|g') # One home for the two pinned versions, read here and fed to $GITHUB_ENV by # ci.yml's `build` job. Pinning is what makes a local measurement evidence # about a CI run, and two copies of a pin is one of them going stale. . "$root/scripts/web-toolchain-versions.env" # The global build job carries a Rust toolchain and dist, and nothing else -- # `github-build-setup` injects only into build-local-artifacts, which is the # wrong job for a global artifact, so the provisioning has to live here. # Installs are Linux-only and on-demand: a developer running this on a Mac # gets told what is missing rather than handed a linux-x64 binary. os=$(uname -s) need_linux() { echo "build-web-release: $1 — install it, or run this on Linux/CI" >&2 exit 1 } if command -v rustup > /dev/null 2>&1; then rustup target add wasm32-unknown-unknown fi if ! wasm-pack --version 2>/dev/null | grep -qF "${WASM_PACK_VERSION#v}"; then [ "$os" = Linux ] || need_linux "wasm-pack ${WASM_PACK_VERSION} not on PATH" url="https://github.com/rustwasm/wasm-pack/releases/download/${WASM_PACK_VERSION}/wasm-pack-${WASM_PACK_VERSION}-x86_64-unknown-linux-musl.tar.gz" curl -sSfL "$url" | tar -xz --strip-components=1 -C /usr/local/bin \ "wasm-pack-${WASM_PACK_VERSION}-x86_64-unknown-linux-musl/wasm-pack" fi wasm-pack --version # `latest-v.x` is the same resolution actions/setup-node performs for a # bare major, so the pin means here what it means in ci.yml. SHASUMS256.txt is # read for the filename because the directory has no stable one. node_major=$(node --version 2>/dev/null | sed -n 's|^v\([0-9][0-9]*\).*|\1|p' || true) if [ "${node_major:-0}" != "$NODE_VERSION" ]; then [ "$os" = Linux ] || need_linux "node ${NODE_VERSION}.x not on PATH (found ${node_major:-none})" base="https://nodejs.org/dist/latest-v${NODE_VERSION}.x" file=$(curl -sSfL "$base/SHASUMS256.txt" \ | sed -n 's|.* \(node-v[0-9.]*-linux-x64\.tar\.xz\)$|\1|p') test -n "$file" || { echo "build-web-release: no linux-x64 node in $base" >&2; exit 1; } mkdir -p "$root/target/node" curl -sSfL "$base/$file" | tar -xJ --strip-components=1 -C "$root/target/node" PATH="$root/target/node/bin:$PATH" export PATH fi node --version sh "$root/web/build.sh" # The site is assembled into a directory named for what it is, so extracting # the tarball leaves one self-describing folder rather than loose files. stage="$root/target/web-release" rm -rf "$stage" mkdir -p "$stage" sh "$root/web/assemble.sh" "$stage/improvise-web" "$token" rm -f "$out" tar -czf "$out" -C "$stage" improvise-web echo "build-web-release: wrote $out (token $token)"