Files
mesh-lab/scripts/build-runtime-image.sh
jschoubben 5d1f7762c2 One archive per machine, not one per image
The images a bed stocks are almost entirely the same bytes: the base they share
is 227 MB and a module's own code is a few. Exported one at a time that base is
written, pushed and loaded once per image — for this bed, the same 227 MB crossed
thirty-odd times, and the whole set measured 9.7 GB.

Measured on eight of them: 2.24 GB as separate archives, 0.29 GB as one. 87 per
cent less, and it improves with the count.

This is the slowest thing a raise does, and the four-machine bed has been
exceeding its own ninety-minute limit while still copying — so it was failing on
the clock rather than on anything it was testing.

Also stops shipping a compiler in every module image. The image runs compiled
code and never compiles any; tsc runs on the workstation. Worth 26 MB an image,
which is small beside the above but was pure waste.
2026-09-14 19:58:01 +02:00

76 lines
3.5 KiB
Bash
Executable File

#!/usr/bin/env bash
# Build the runtime+audit-logger image the events test runs, and save it to a tar.
#
# The image is the tier-3 tool runtime (mesh-tools) carrying one tier-4 module (audit-logger) and
# the sdk it imports. It is what MESH_LAB_RUNTIME points at:
#
# scripts/build-runtime-image.sh /tmp/mesh-runtime-audit.tar
# MESH_LAB_RUNTIME=/tmp/mesh-runtime-audit.tar node --test test/integration/events.test.ts
#
# The sdk is vendored (dereferenced), not npm-installed: the sdk is not published, and the lab
# machine has no route out anyway — the image must be self-contained. Sibling repositories are
# assumed alongside this one; override with MESH_TOOLS / MESH_SDK / MESH_CATALOG.
set -euo pipefail
OUT="${1:?usage: build-runtime-image.sh <output.tar>}"
HERE="$(cd "$(dirname "$0")/.." && pwd)"
ROOT="$(cd "$HERE/.." && pwd)"
MESH_TOOLS="${MESH_TOOLS:-$ROOT/mesh-tools}"
MESH_SDK="${MESH_SDK:-$ROOT/mesh-sdk}"
MESH_CATALOG="${MESH_CATALOG:-$ROOT/mesh-catalog}"
AUDIT="$MESH_CATALOG/modules/audit-logger"
TAG="${RUNTIME_TAG:-mesh-runtime-audit:development}"
BASE="${RUNTIME_BASE:-node:22-bookworm-slim}"
echo "building $TAG from:"
echo " runtime $MESH_TOOLS"
echo " sdk $MESH_SDK"
echo " module $AUDIT"
# Compile the three, so the image carries current dist. The sdk first — the others import it.
( cd "$MESH_SDK" && npm run build >/dev/null )
( cd "$MESH_TOOLS" && npm run build >/dev/null )
( cd "$AUDIT" && npx tsc audit.ts index.ts --module NodeNext --moduleResolution NodeNext \
--target ES2022 --outDir dist >/dev/null )
STAGE="$(mktemp -d)"
trap 'rm -rf "$STAGE"' EXIT
cp -r "$MESH_TOOLS/dist" "$STAGE/dist"
cp -rL "$MESH_TOOLS/node_modules" "$STAGE/node_modules"
# And the sdk, from the sibling this script just built, whatever form the installed tree holds it
# in. It used to be relied on being a symlink into that sibling, which `-L` above materialised —
# true only on a workstation where somebody had linked them, and false the moment the runtime's
# dependencies are installed the ordinary way, which now fetches the sdk as sources with nothing
# compiled in it. The image built then looked fine and every entry point inside it pointed at
# nothing.
rm -rf "$STAGE/node_modules/@novox/mesh-sdk"
mkdir -p "$STAGE/node_modules/@novox"
cp -rL "$MESH_SDK" "$STAGE/node_modules/@novox/mesh-sdk"
rm -rf "$STAGE/node_modules/@novox/mesh-sdk/node_modules"
# **The image runs compiled code and never compiles any**, so it does not need a compiler. The
# tree copied above is the runtime's full install, development dependencies and all — and the
# compiler alone is 23 of its 28 MB. Every module image carried one, on every machine, for nothing:
# tsc runs on the workstation a few lines above, not in here.
#
# Removed by name rather than by `npm prune --omit=dev`, which would re-resolve dependencies — one
# of them a git URL with no registry behind it — and could drop something the image needs.
rm -rf "$STAGE/node_modules/typescript" "$STAGE/node_modules/@types" # -L materialises the @novox/mesh-sdk symlink
mkdir -p "$STAGE/modules/audit-logger"
cp -r "$AUDIT/dist" "$STAGE/modules/audit-logger/dist"
cp "$MESH_TOOLS/package.json" "$STAGE/package.json"
cat > "$STAGE/Dockerfile" <<DOCKER
FROM $BASE
WORKDIR /app
COPY package.json ./
COPY node_modules ./node_modules
COPY dist ./dist
COPY modules ./modules
ENV MESH_TOOL_MODULES=/app/modules/audit-logger/dist/index.js
ENTRYPOINT ["node", "dist/main.js"]
DOCKER
docker build -t "$TAG" "$STAGE"
docker save -o "$OUT" "$TAG"
echo "saved $TAG -> $OUT"