From 9b3b11fc2037e09fccd670112a41fd1cad78a8b4 Mon Sep 17 00:00:00 2001 From: ZDDC Date: Fri, 1 May 2026 15:24:52 -0500 Subject: [PATCH] refactor: drop install scripts; containerize zddc-server build Drops the install/distribution machinery in favor of two simpler paths: - Local: download a tool .html from website/releases/ and open it. - Server: run zddc-server, which embeds current-stable HTMLs at compile time via //go:embed (delivered in the next commit). Removed: - bootstrap/install.sh, bootstrap/README.md, bootstrap/level{1,2}.html.tmpl - website/bootstrap/{level1,track-stable,track-beta,track-alpha}/ - website/install.sh symlink - The bootstrap-stub generation in top-level build.sh Rewritten: - website/index.html "Install on your server" section: two cards (server / local) replacing the old four script-based snippets. - website/reference.html, website/css/style.css: updated to match. - website/releases/index.html: regenerated by build.sh from filesystem. Top-level build.sh: - All five tool HTMLs now copied into zddc/dist/web/ and into the new zddc/internal/apps/embedded/ for //go:embed. - Cross-compile is always containerized via podman or docker against docker.io/golang:1.24-alpine (the same image the helm prod chart uses), with named volumes for module + build cache. ZDDC_GO_BUILD_IMAGE overrides for air-gapped or pinned-mirror deployments. Co-Authored-By: Claude Opus 4.7 (1M context) --- bootstrap/README.md | 156 ----------- bootstrap/install.sh | 250 ------------------ bootstrap/level1.html.tmpl | 74 ------ bootstrap/level2.html.tmpl | 56 ---- build.sh | 190 ++++++------- website/bootstrap/level1/archive.html | 74 ------ website/bootstrap/level1/classifier.html | 74 ------ website/bootstrap/level1/mdedit.html | 74 ------ website/bootstrap/level1/transmittal.html | 74 ------ website/bootstrap/track-alpha/archive.html | 56 ---- website/bootstrap/track-alpha/classifier.html | 56 ---- website/bootstrap/track-alpha/index.html | 56 ---- website/bootstrap/track-alpha/mdedit.html | 56 ---- .../bootstrap/track-alpha/transmittal.html | 56 ---- website/bootstrap/track-beta/archive.html | 56 ---- website/bootstrap/track-beta/classifier.html | 56 ---- website/bootstrap/track-beta/index.html | 56 ---- website/bootstrap/track-beta/mdedit.html | 56 ---- website/bootstrap/track-beta/transmittal.html | 56 ---- website/bootstrap/track-stable/archive.html | 56 ---- .../bootstrap/track-stable/classifier.html | 56 ---- website/bootstrap/track-stable/index.html | 56 ---- website/bootstrap/track-stable/mdedit.html | 56 ---- .../bootstrap/track-stable/transmittal.html | 56 ---- website/css/style.css | 12 +- website/index.html | 67 ++--- website/install.sh | 1 - website/reference.html | 13 +- website/releases/index.html | 13 +- 29 files changed, 136 insertions(+), 1832 deletions(-) delete mode 100644 bootstrap/README.md delete mode 100755 bootstrap/install.sh delete mode 100644 bootstrap/level1.html.tmpl delete mode 100644 bootstrap/level2.html.tmpl delete mode 100644 website/bootstrap/level1/archive.html delete mode 100644 website/bootstrap/level1/classifier.html delete mode 100644 website/bootstrap/level1/mdedit.html delete mode 100644 website/bootstrap/level1/transmittal.html delete mode 100644 website/bootstrap/track-alpha/archive.html delete mode 100644 website/bootstrap/track-alpha/classifier.html delete mode 100644 website/bootstrap/track-alpha/index.html delete mode 100644 website/bootstrap/track-alpha/mdedit.html delete mode 100644 website/bootstrap/track-alpha/transmittal.html delete mode 100644 website/bootstrap/track-beta/archive.html delete mode 100644 website/bootstrap/track-beta/classifier.html delete mode 100644 website/bootstrap/track-beta/index.html delete mode 100644 website/bootstrap/track-beta/mdedit.html delete mode 100644 website/bootstrap/track-beta/transmittal.html delete mode 100644 website/bootstrap/track-stable/archive.html delete mode 100644 website/bootstrap/track-stable/classifier.html delete mode 100644 website/bootstrap/track-stable/index.html delete mode 100644 website/bootstrap/track-stable/mdedit.html delete mode 100644 website/bootstrap/track-stable/transmittal.html delete mode 120000 website/install.sh diff --git a/bootstrap/README.md b/bootstrap/README.md deleted file mode 100644 index 274a3f3..0000000 --- a/bootstrap/README.md +++ /dev/null @@ -1,156 +0,0 @@ -# Deployment bootstrap - -ZDDC tools (archive, transmittal, classifier, mdedit, landing) are single-file -HTML bundles. The bootstrap pattern lets you install once on a deployment and -update by editing a few lines, without re-uploading multi-megabyte HTML files. - -End users install via the unified [`install.sh`](install.sh) script, served at -`https://zddc.varasys.io/install.sh`. The script handles all three deployment -patterns (self-contained / channel-tracking / pin-to-version) plus both target -shapes (deployment root or project subdirectory) via a single command: - -```sh -sh -c "$(curl -fsSL https://zddc.varasys.io/install.sh)" -- [options] -``` - -The published stubs live under `https://zddc.varasys.io/bootstrap/`: - -- `bootstrap/level1/.html` — same-origin level-1 stubs (4 tools, no - landing — landing only lives at deployment root). -- `bootstrap/track-{stable,beta,alpha}/.html` — per-channel level-2 - stubs (5 tools each). - -Both directories are produced by the project's top-level `build.sh` from -`bootstrap/level{1,2}.html.tmpl`. `install.sh` orchestrates which stubs to -fetch and where to put them based on `--mode` / `--target` / `--channel`. - -## The two-level model - -A typical `zddc-server` deployment looks like this: - -``` -/ - index.html # landing tool (or bootstrap) - archive.html # archive tool (or bootstrap; site-wide channel switch lives here) - transmittal.html - classifier.html - mdedit.html - / - archive.html # level-1 bootstrap → fetches ../archive.html - transmittal.html - classifier.html - mdedit.html - - / - archive.html # level-1 bootstrap (or pinned to a specific version) - … -``` - -- **Level-1 stubs** at `/.html` always fetch the same-origin - `../.html`. They never touch `zddc.varasys.io`. Install them once; - they don't need to change. -- **At deployment root** (`/.html`), put either: - - the actual built tool HTML — fully self-contained install, no external - dependencies; or - - a level-2 bootstrap — fetches `/releases/_.html` - directly (that path is a checked-in symlink on the upstream that resolves - to the current channel mirror). No manifest lookup, no version arithmetic, - no Codeberg proxy magic — every URL is a real static file or a static - symlink chain. - -The site administrator switches the whole site to a channel by re-running -`install.sh --mode track --channel ` — that overwrites the root -`.html` files with the matching level-2 stubs. A single project can -override one tool by editing just `/.html` (replace the -relative `upstream` URL with an absolute zddc.varasys.io URL pointing at -the desired version, channel mirror, or partial-version pin). - -## Why two levels - -The level-1 stubs let projects share a single source of truth for "which -build of the archive tool runs here." Switching channels is one file change -at the root; pinning a single project is one file change in that directory. - -`document.write()` chains across both levels: level-1 fetches and writes, -the new document's level-2 script runs and writes again, the third write -is the actual tool. Origin stays at the deployment domain throughout, so -File System Access API, `crypto.subtle`, and `localStorage` all work and -preferences stay scoped to the deployment. - -## Pinning options - -There are two ways to choose a version: edit the stub for a permanent -pin, or pass a `?v=` URL parameter for a per-request override. - -### 1. Permanent pin (point the stub at a fixed URL) - -The default level-2 stub fetches `/releases/_.html` — -which is itself a symlink on the upstream that resolves to the current -channel mirror. To pin permanently, change the URL inside the stub: - -| Target stability | URL the stub should fetch | -|----------------------------------|------------------------------------------------------------------------| -| Exact stable version | `https://zddc.varasys.io/releases/_vX.Y.Z.html` | -| Latest patch within `.*` | `https://zddc.varasys.io/releases/_v.html` (symlink) | -| Latest within `.*.*` | `https://zddc.varasys.io/releases/_v.html` (symlink) | -| Track stable channel (default) | `https://zddc.varasys.io/releases/_stable.html` (symlink) | -| Track beta / alpha channel | `https://zddc.varasys.io/releases/_.html` | - -### 2. Per-request `?v=` parameter - -Both stub levels honor a `?v=` URL parameter. The parameter survives the -`document.write()` chain, so it flows through level-1 → level-2 → -upstream automatically. - -| URL parameter | Resolves to | -|--------------------------------|-------------------------------------------------------| -| `?v=0.0.4` (or `?v=v0.0.4`) | `_v0.0.4.html` (exact) | -| `?v=0.0` (or `?v=v0.0`) | `_v0.0.html` (latest 0.0.x patch — symlink) | -| `?v=0` (or `?v=v0`) | `_v0.html` (latest 0.x — symlink) | -| `?v=stable` | `_stable.html` | -| `?v=beta` | `_beta.html` | -| `?v=alpha` | `_alpha.html` | -| (omitted) | the default channel baked into the stub at install time | - -When level-1 has `?v=…`, it tries `../_.html` first (useful -when the admin has staged specific versions locally — the upstream's -symlink layout works the same locally) and falls back to `../.html` -if 404 — which then forwards the parameter via level-2 if one is installed. - -Stable per-version files are immutable. The `_stable.html`, -`_beta.html`, and `_alpha.html` symlinks (or real bytes when a -channel has active dev) get updated whenever the relevant channel -advances upstream — expect them to change. The build label rendered on -the tool page tells you exactly which build you're seeing -(`v-{alpha,beta} · · ` for channel mirrors, -`v` for pinned stables). - -## Auditing what's installed - -Every stub contains a `fallback` (level-1) or `upstream` (level-2) -constant. To see what each tool / project on the deployment points at: - -```sh -grep -rn "fallback\|upstream" -``` - -## CORS prerequisite (level-2 only) - -A level-2 fetch is cross-origin (deployment → `zddc.varasys.io`). The -upstream must serve `Access-Control-Allow-Origin: *` (or a list including -your deployment origin) on each released asset. Verify with: - -```sh -curl -I https://zddc.varasys.io/releases/archive_stable.html | grep -i access-control -curl -I https://zddc.varasys.io/releases/archive_v0.0.2.html | grep -i access-control -``` - -Level-1 fetches are same-origin so no CORS is involved. - -## Templates - -`level1.html.tmpl` and `level2.html.tmpl` are the source of truth. The -project's top-level `build.sh` substitutes `{{TOOL}}`, `{{TOOL_TITLE}}`, -`{{CHANNEL}}`, and `{{FAVICON}}` to produce the per-tool stubs published -under `website/bootstrap/level1/` and `website/bootstrap/track-/`, -which the install snippets curl from `https://zddc.varasys.io/bootstrap/`. diff --git a/bootstrap/install.sh b/bootstrap/install.sh deleted file mode 100755 index cc85d9f..0000000 --- a/bootstrap/install.sh +++ /dev/null @@ -1,250 +0,0 @@ -#!/bin/sh -# install.sh — Bootstrap a ZDDC deployment from zddc.varasys.io -# (or any compatible upstream) into the current directory. -# -# This script replaces the four hand-rolled install snippets that used -# to live inline on the home page. It handles all three deployment -# patterns (self-contained / channel-tracking / pinned-version) plus -# both target shapes (ZDDC root or project subdirectory). -# -# Usage: -# sh -c "$(curl -fsSL https://zddc.varasys.io/install.sh)" -# sh -c "$(curl -fsSL https://zddc.varasys.io/install.sh)" -- [options] -# -# Options: -# --channel -# Channel or pinned-version selector (default: stable). -# stable / beta / alpha — channel mirrors (auto-update -# on the upstream). X.Y.Z — exact version. X.Y — latest -# patch within X.Y.* (symlink-resolved on upstream). -# X — latest within X.*.* (symlink-resolved upstream). -# Optional leading 'v' is accepted and stripped. -# -# --source Upstream base URL (default: https://zddc.varasys.io). -# Use this to point at your own dev server during -# active alpha development, or at a mirror. -# -# --mode copy: fetch the actual HTML and save locally — -# site does not depend on the upstream after -# install. Use for pinned-version installs -# and air-gapped deployments. (default) -# track: install tiny level-2 stubs that fetch the -# chosen channel from the upstream on every -# page load. Auto-updates within the channel. -# Only valid with channel names (stable / beta -# / alpha), not with pinned versions. -# -# --target -# root: install at the deployment root — five tool -# HTMLs (incl. landing as index.html) plus -# a _template/ directory of level-1 stubs -# to copy into project subdirs. -# project: install in a project subdirectory — four -# level-1 stubs that fetch ../.html -# (same-origin) at load time. Use this in -# each / subdir under your root. -# auto: detect from CWD (default). 'project' if -# CWD's parent has a ZDDC-looking index.html; -# 'root' otherwise. -# -# --tools Comma-separated subset of tools to install -# (default: archive,transmittal,classifier,mdedit). -# Landing is always included in --target root copy -# installs as index.html. -# -# --dry-run Print what would happen; don't write any files. -# -h | --help Show this help. -# -# Examples: -# -# Self-contained install of current stable at the deployment root: -# cd /srv/archive -# sh -c "$(curl -fsSL https://zddc.varasys.io/install.sh)" -# -# Track beta from upstream: -# cd /srv/archive -# sh -c "$(curl -fsSL https://zddc.varasys.io/install.sh)" -- \ -# --mode track --channel beta -# -# Pin to a specific version (immutable): -# cd /srv/archive -# sh -c "$(curl -fsSL https://zddc.varasys.io/install.sh)" -- \ -# --channel 0.0.2 -# -# Track alpha from your own dev server (level-2 stubs point at it): -# cd /srv/archive -# sh -c "$(curl -fsSL https://zddc.varasys.io/install.sh)" -- \ -# --mode track --channel alpha --source https://my-dev.local -# -# Install level-1 stubs in a project subdirectory (auto-detected): -# cd /srv/archive/Project-A -# sh -c "$(curl -fsSL https://zddc.varasys.io/install.sh)" - -set -eu - -CHANNEL="stable" -SOURCE="https://zddc.varasys.io" -MODE="copy" -TARGET="auto" -TOOLS="archive,transmittal,classifier,mdedit" -DRY_RUN=0 - -usage() { - awk '/^# Usage:/,/^$/' "$0" | sed 's/^# \{0,1\}//' >&2 - exit "${1:-1}" -} - -# --- Parse args ------------------------------------------------------------ -while [ $# -gt 0 ]; do - case "$1" in - --channel) CHANNEL="${2:-}"; shift 2 ;; - --source) SOURCE="${2:-}"; shift 2 ;; - --mode) MODE="${2:-}"; shift 2 ;; - --target) TARGET="${2:-}"; shift 2 ;; - --tools) TOOLS="${2:-}"; shift 2 ;; - --dry-run) DRY_RUN=1; shift ;; - -h|--help) usage 0 ;; - *) echo "install.sh: unknown argument '$1'" >&2; usage ;; - esac -done - -# Strip a trailing slash from SOURCE so URL composition is consistent. -SOURCE="${SOURCE%/}" - -# --- Validate --mode and --target ------------------------------------------ -case "$MODE" in - copy|track) ;; - *) echo "install.sh: --mode must be 'copy' or 'track' (got '$MODE')" >&2; exit 1 ;; -esac -case "$TARGET" in - root|project|auto) ;; - *) echo "install.sh: --target must be 'root', 'project', or 'auto' (got '$TARGET')" >&2; exit 1 ;; -esac - -# --- Resolve --channel into a filename suffix ------------------------------ -# stable / beta / alpha → _stable / _beta / _alpha -# 0.0.4 / v0.0.4 → _v0.0.4 -# 0.0 / v0.0 → _v0.0 -# 0 / v0 → _v0 -_chan_arg="$CHANNEL" -case "$_chan_arg" in - stable|beta|alpha) SUFFIX="_${_chan_arg}" ;; - v*) SUFFIX="_${_chan_arg}" ;; - [0-9]*) SUFFIX="_v${_chan_arg}" ;; - *) echo "install.sh: --channel must be stable, beta, alpha, or a semver (got '$_chan_arg')" >&2; exit 1 ;; -esac - -# --mode track is only meaningful for the three named channels — pinned -# version stubs aren't pre-built (they'd need a different stub per version, -# and an immutable pin doesn't really benefit from runtime indirection). -if [ "$MODE" = "track" ]; then - case "$_chan_arg" in - stable|beta|alpha) ;; - *) echo "install.sh: --mode track only supports channel names (stable, beta, alpha); for pinned versions use --mode copy" >&2; exit 1 ;; - esac -fi - -# --- Auto-detect --target -------------------------------------------------- -if [ "$TARGET" = "auto" ]; then - # Heuristic: parent dir has an index.html with the ZDDC brand string — - # we're inside a project subdirectory of an existing ZDDC deployment. - if [ -f "../index.html" ] && grep -q 'ZDDC' "../index.html" 2>/dev/null; then - TARGET="project" - else - TARGET="root" - fi - echo "install.sh: auto-detected --target=$TARGET (use --target to override)" -fi - -# --- Plan summary ---------------------------------------------------------- -echo "install.sh: $MODE $_chan_arg into $(pwd) (target=$TARGET, source=$SOURCE)" -[ "$DRY_RUN" = "1" ] && echo " [DRY RUN — no files will be written]" - -TOOL_LIST=$(echo "$TOOLS" | tr ',' ' ') - -# --- Helpers --------------------------------------------------------------- -fetch_to() { - _url="$1"; _dest="$2" - if [ "$DRY_RUN" = "1" ]; then - echo " [dry-run] $_url -> $_dest" - return 0 - fi - echo " $_dest" - curl -fsSL "$_url" -o "$_dest" -} - -# Fetch a track-channel stub and rewrite the upstream URL inside it if -# --source is non-default. The stub embeds 'https://zddc.varasys.io/releases/' -# as a constant; sed swaps it for the chosen base when the operator's -# pointed at a different host. POSIX sed handles this fine (no escaping -# concerns since SOURCE doesn't contain ampersand or slash inside the host). -fetch_stub_with_source() { - _url="$1"; _dest="$2" - if [ "$DRY_RUN" = "1" ]; then - echo " [dry-run] $_url -> $_dest (rewrite source if needed)" - return 0 - fi - echo " $_dest" - if [ "$SOURCE" = "https://zddc.varasys.io" ]; then - curl -fsSL "$_url" -o "$_dest" - else - # POSIX sed; pipe through stdin to avoid editing in place. - curl -fsSL "$_url" \ - | sed "s|https://zddc.varasys.io/releases/|${SOURCE}/releases/|g" \ - > "$_dest" - fi -} - -# --- Install --------------------------------------------------------------- -case "$MODE:$TARGET" in - copy:root) - # Five tool HTMLs at the root + level-1 _template/ for project subdirs. - for _t in $TOOL_LIST; do - fetch_to "$SOURCE/releases/${_t}${SUFFIX}.html" "${_t}.html" - done - # Landing always becomes index.html in the root install. - fetch_to "$SOURCE/releases/landing${SUFFIX}.html" "index.html" - if [ "$DRY_RUN" = "1" ]; then - echo " [dry-run] mkdir -p _template" - else - mkdir -p _template - fi - for _t in $TOOL_LIST; do - fetch_to "$SOURCE/bootstrap/level1/${_t}.html" "_template/${_t}.html" - done - ;; - - copy:project) - # Four level-1 stubs only — they fetch ../.html at load time. - for _t in $TOOL_LIST; do - fetch_to "$SOURCE/bootstrap/level1/${_t}.html" "${_t}.html" - done - ;; - - track:root) - # Five level-2 stubs (incl. landing as index.html) + _template/. - # Each stub fetches the channel from $SOURCE on every load. - for _t in $TOOL_LIST; do - fetch_stub_with_source "$SOURCE/bootstrap/track-$_chan_arg/${_t}.html" "${_t}.html" - done - fetch_stub_with_source "$SOURCE/bootstrap/track-$_chan_arg/index.html" "index.html" - if [ "$DRY_RUN" = "1" ]; then - echo " [dry-run] mkdir -p _template" - else - mkdir -p _template - fi - for _t in $TOOL_LIST; do - fetch_to "$SOURCE/bootstrap/level1/${_t}.html" "_template/${_t}.html" - done - ;; - - track:project) - # Same as copy:project — level-1 stubs are channel-agnostic - # (they fetch ../.html, which is whatever the root has). - for _t in $TOOL_LIST; do - fetch_to "$SOURCE/bootstrap/level1/${_t}.html" "${_t}.html" - done - ;; -esac - -echo "install.sh: done." diff --git a/bootstrap/level1.html.tmpl b/bootstrap/level1.html.tmpl deleted file mode 100644 index c24bf06..0000000 --- a/bootstrap/level1.html.tmpl +++ /dev/null @@ -1,74 +0,0 @@ - - - - - - Loading {{TOOL_TITLE}}… - - - - - Loading… - - - diff --git a/bootstrap/level2.html.tmpl b/bootstrap/level2.html.tmpl deleted file mode 100644 index 0fccfa7..0000000 --- a/bootstrap/level2.html.tmpl +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - Loading {{TOOL_TITLE}}… - - - - - Loading… - - - diff --git a/build.sh b/build.sh index adf500f..213c072 100755 --- a/build.sh +++ b/build.sh @@ -2,7 +2,7 @@ set -eu # Top-level build script — builds all ZDDC HTML tools, the zddc-server -# binaries, and the bootstrap stubs published under website/bootstrap/. +# binaries, and the website/releases/index.html versions index. SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd) @@ -16,114 +16,87 @@ sh "$SCRIPT_DIR/landing/build.sh" "${1:-}" "${2:-}" echo "" echo "=== Assembling zddc/dist/web/ ===" -# Only landing and archive ship inside the server bundle: they call the -# server's JSON API (GET / for the project list, directory listings for the -# archive) and are useless without it. transmittal, classifier, and mdedit -# are pure client-side tools that work from file:// or any static host; -# they are released to website/ for download but not bundled with the server. +# All five tool HTMLs ship inside the server bundle. landing and archive call +# server APIs (GET / for the project list, directory listings for archive) and +# are useless without zddc-server. transmittal, classifier, and mdedit are +# pure client-side tools but are still bundled — the server uses these copies +# as the embedded fallback (//go:embed in internal/apps/embedded/) when both +# the cache is empty AND the upstream is unreachable. mkdir -p "$SCRIPT_DIR/zddc/dist/web" -cp "$SCRIPT_DIR/landing/dist/index.html" "$SCRIPT_DIR/zddc/dist/web/index.html" -cp "$SCRIPT_DIR/archive/dist/archive.html" "$SCRIPT_DIR/zddc/dist/web/archive.html" -echo "Wrote zddc/dist/web/index.html" -echo "Wrote zddc/dist/web/archive.html" +cp "$SCRIPT_DIR/landing/dist/index.html" "$SCRIPT_DIR/zddc/dist/web/index.html" +cp "$SCRIPT_DIR/archive/dist/archive.html" "$SCRIPT_DIR/zddc/dist/web/archive.html" +cp "$SCRIPT_DIR/transmittal/dist/transmittal.html" "$SCRIPT_DIR/zddc/dist/web/transmittal.html" +cp "$SCRIPT_DIR/classifier/dist/classifier.html" "$SCRIPT_DIR/zddc/dist/web/classifier.html" +cp "$SCRIPT_DIR/mdedit/dist/mdedit.html" "$SCRIPT_DIR/zddc/dist/web/mdedit.html" +echo "Wrote zddc/dist/web/{index,archive,transmittal,classifier,mdedit}.html" -# Cross-compiled zddc-server binaries — only relevant if you're shipping -# standalone Linux/macOS/Windows binaries to users. Skipped silently when -# Go isn't on PATH. (zddc/release.sh handles the publish flow that -# uploads these to Codeberg release assets.) +# Mirror the same five HTMLs into the Go embed source dir so the next +# `go build` of zddc-server picks them up via //go:embed. Files are checked +# into git as empty placeholders; the build always overwrites them with the +# fresh dist/ output. +EMBED_DIR="$SCRIPT_DIR/zddc/internal/apps/embedded" +mkdir -p "$EMBED_DIR" +cp "$SCRIPT_DIR/landing/dist/index.html" "$EMBED_DIR/index.html" +cp "$SCRIPT_DIR/archive/dist/archive.html" "$EMBED_DIR/archive.html" +cp "$SCRIPT_DIR/transmittal/dist/transmittal.html" "$EMBED_DIR/transmittal.html" +cp "$SCRIPT_DIR/classifier/dist/classifier.html" "$EMBED_DIR/classifier.html" +cp "$SCRIPT_DIR/mdedit/dist/mdedit.html" "$EMBED_DIR/mdedit.html" +echo "Populated $EMBED_DIR/ for //go:embed" + +# Cross-compiled zddc-server binaries for Linux/macOS/Windows. Always built +# inside docker.io/golang:1.24-alpine via podman (or docker), matching the +# helm/zddc-server-prod chart's `buildImage` so dev binaries are byte-for-byte +# what production gets. The build container is downloaded on first run. echo "" -echo "=== Building zddc-server binaries ===" -if command -v go >/dev/null 2>&1; then - cd "$SCRIPT_DIR/zddc" - mkdir -p dist - for target in linux/amd64 darwin/amd64 darwin/arm64 windows/amd64; do - os="${target%/*}"; arch="${target#*/}" - out="zddc-server-${os}-${arch}" - case "$os" in windows) out="${out}.exe" ;; esac - echo " building $out" - CGO_ENABLED=0 GOOS="$os" GOARCH="$arch" \ - go build -trimpath -ldflags="-s -w" -o "dist/$out" ./cmd/zddc-server - done - cd "$SCRIPT_DIR" +echo "=== Building zddc-server binaries (containerized) ===" +mkdir -p "$SCRIPT_DIR/zddc/dist" + +# Pick a container runtime. Both work; podman is preferred (rootless default). +GO_RUNNER="" +if command -v podman >/dev/null 2>&1; then + GO_RUNNER=podman +elif command -v docker >/dev/null 2>&1; then + GO_RUNNER=docker else - echo "go not found — skipping cross-compiled binary build." - echo " (Install Go 1.24+ to build standalone binaries.)" + echo "error: neither podman nor docker is available — cannot build zddc-server binaries." >&2 + echo " Install podman (preferred) or docker. zddc-server build is containerized as policy." >&2 + exit 1 fi -# ─── Bootstrap stubs ───────────────────────────────────────────────────────── -# Generated from bootstrap/level{1,2}.html.tmpl on every build and published -# as standalone files under website/bootstrap/. The website's "Install on -# your server" section prints copy-pasteable shell snippets that curl these -# files into the operator's deployment directory. -# -# bootstrap/level1/.html — same-origin stubs for -# /.html (4 tools; -# landing only lives at root) -# bootstrap/track-/.html — level-2 stubs that fetch the -# named channel from upstream -# (5 tools × 3 channels = 15) +GO_BUILD_IMAGE="${ZDDC_GO_BUILD_IMAGE:-docker.io/golang:1.24-alpine}" + +# Cache the Go module + build cache across runs via named volumes that +# persist between container invocations. Second build is fast. +GO_MOD_VOL="${ZDDC_GO_MOD_VOL:-zddc-go-mod}" +GO_BUILD_VOL="${ZDDC_GO_BUILD_VOL:-zddc-go-cache}" + +# Single container invocation, multiple cross-compile targets inside a +# `for` loop — avoids paying image-startup overhead 4×. +"$GO_RUNNER" run --rm \ + -v "$SCRIPT_DIR:/src:Z" \ + -v "${GO_MOD_VOL}:/go/pkg/mod" \ + -v "${GO_BUILD_VOL}:/root/.cache/go-build" \ + -w /src/zddc \ + -e GOFLAGS=-mod=mod \ + -e CGO_ENABLED=0 \ + "$GO_BUILD_IMAGE" \ + sh -c ' + set -e + for target in linux/amd64 darwin/amd64 darwin/arm64 windows/amd64; do + os="${target%/*}"; arch="${target#*/}" + out="zddc-server-${os}-${arch}" + case "$os" in windows) out="${out}.exe" ;; esac + echo " building $out" + GOOS="$os" GOARCH="$arch" \ + go build -trimpath -ldflags="-s -w" -o "dist/$out" ./cmd/zddc-server + done + ' WEBSITE_DIR="$SCRIPT_DIR/website" RELEASES_DIR="$WEBSITE_DIR/releases" -BOOTSTRAP_DIR="$SCRIPT_DIR/bootstrap" mkdir -p "$WEBSITE_DIR" -# tool|filename|title -TOOL_TABLE='archive|archive.html|Archive -transmittal|transmittal.html|Transmittal -classifier|classifier.html|Classifier -mdedit|mdedit.html|Markdown Editor -landing|index.html|ZDDC' - -# Substitute {{TOOL}}, {{TOOL_TITLE}}, {{CHANNEL}}, {{FAVICON}} in a template. -# The favicon is a base64-encoded data URI built once from shared/favicon.svg. -_favicon_data_uri="" -if [ -f "$SCRIPT_DIR/shared/favicon.svg" ]; then - _favicon_data_uri="data:image/svg+xml;base64,$(base64 -w 0 "$SCRIPT_DIR/shared/favicon.svg")" -fi -render_stub() { - sed \ - -e "s|{{TOOL_TITLE}}|$3|g" \ - -e "s|{{TOOL}}|$2|g" \ - -e "s|{{CHANNEL}}|${4:-}|g" \ - -e "s|{{FAVICON}}|$_favicon_data_uri|g" \ - "$1" > "$5" -} - -build_bootstrap_stubs() { - _stubs="$WEBSITE_DIR/bootstrap" - rm -rf "$_stubs" - mkdir -p "$_stubs/level1" - - # Level-1 stubs (same-origin, channel-agnostic). Drop into a project - # subdirectory so /.html fetches ../.html. - # Landing has no level-1 stub — landing only lives at deployment root. - while IFS='|' read -r _tool _file _title; do - render_stub "$BOOTSTRAP_DIR/level1.html.tmpl" "$_tool" "$_title" "" \ - "$_stubs/level1/$_file" - done <
- + ZDDC