ZDDC/build.sh
ZDDC 9b3b11fc20 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) <noreply@anthropic.com>
2026-05-01 15:24:52 -05:00

268 lines
12 KiB
Bash
Executable file
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/bin/sh
set -eu
# Top-level build script — builds all ZDDC HTML tools, the zddc-server
# binaries, and the website/releases/index.html versions index.
SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
echo "=== Building ZDDC tools ==="
sh "$SCRIPT_DIR/transmittal/build.sh" "${1:-}" "${2:-}"
sh "$SCRIPT_DIR/archive/build.sh" "${1:-}" "${2:-}"
sh "$SCRIPT_DIR/classifier/build.sh" "${1:-}" "${2:-}"
sh "$SCRIPT_DIR/mdedit/build.sh" "${1:-}" "${2:-}"
sh "$SCRIPT_DIR/landing/build.sh" "${1:-}" "${2:-}"
echo ""
echo "=== Assembling zddc/dist/web/ ==="
# 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"
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"
# 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 (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 "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
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"
mkdir -p "$WEBSITE_DIR"
# Regenerate website/releases/index.html from a filesystem scan of
# website/releases/. Lists per-version files (real .html files, immutable
# archives) plus channel mirrors and partial-version pins (symlinks).
#
# All URLs in the page resolve directly under <upstream>/releases/<file>
# — no Codeberg API call, no manifest, no proxy magic. Page is static
# and current as of the last `sh build.sh` run.
#
# zddc-server's section links to its Codeberg release pages directly
# (different distribution model — per-platform binaries).
build_releases_index() {
_out="$RELEASES_DIR/index.html"
mkdir -p "$RELEASES_DIR"
{
cat <<'HEAD'
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Releases — ZDDC</title>
<meta name="description" content="All released versions and channel builds of every ZDDC tool.">
<meta name="theme-color" content="#2a5a8a">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap" rel="stylesheet">
<link rel="stylesheet" href="../css/style.css">
<style>
.rel-tool { margin-top: var(--spacing-xl); padding: var(--spacing-md); border: 1px solid var(--color-border); border-radius: 8px; }
.rel-tool h2 { margin-top: 0; }
.rel-channels { display: flex; flex-wrap: wrap; gap: 0.5rem; margin: 0.75rem 0 1.25rem 0; }
.rel-channels a { padding: 0.25rem 0.625rem; border-radius: 999px; text-decoration: none; border: 1px solid var(--color-border); color: var(--color-text); font-size: 0.9rem; }
.rel-channels a.stable { border-color: var(--color-primary); color: var(--color-primary); font-weight: 600; }
.rel-channels a.beta, .rel-channels a.alpha { color: var(--color-text-muted); }
.rel-channels a:hover { background: var(--color-bg-subtle); }
.rel-versions { font-size: 0.875rem; color: var(--color-text-muted); }
.rel-versions a { margin-right: 0.5rem; color: var(--color-text); text-decoration: none; padding: 0.1rem 0.4rem; border-radius: 4px; }
.rel-versions a:hover { background: var(--color-bg-subtle); text-decoration: underline; }
.rel-meta { font-size: 0.85rem; color: var(--color-text-muted); margin-top: 0.5rem; }
.rel-bin-table { width: 100%; border-collapse: collapse; margin: 0.5rem 0 1rem; font-size: 0.9rem; }
.rel-bin-table th, .rel-bin-table td { text-align: left; padding: 0.4rem 0.6rem; border-bottom: 1px solid var(--color-border); }
.rel-bin-table th { font-weight: 600; color: var(--color-text-muted); }
.rel-bin-table td.ch-stable { color: var(--color-primary); font-weight: 600; }
.rel-bin-table td.ch-beta, .rel-bin-table td.ch-alpha { color: var(--color-text-muted); }
.rel-bin-table a { color: var(--color-text); text-decoration: none; padding: 0.1rem 0.35rem; border-radius: 4px; }
.rel-bin-table a:hover { background: var(--color-bg-subtle); text-decoration: underline; }
.rel-bin-table td.empty { color: var(--color-text-muted); font-style: italic; }
.rel-pull { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 0.85rem; background: var(--color-bg-subtle); padding: 0.25rem 0.5rem; border-radius: 4px; display: inline-block; margin: 0.2rem 0; }
</style>
</head>
<body>
<header class="site-header">
<div class="container header-content">
<a href="/" class="brand">
<svg class="brand-logo" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" aria-hidden="true">
<rect width="64" height="64" rx="12" fill="#1e3a5f"/>
<g fill="#fff">
<rect x="14" y="18" width="36" height="7"/>
<polygon points="43,25 50,25 21,43 14,43"/>
<rect x="14" y="43" width="36" height="7"/>
</g>
</svg>
<span class="brand-name">ZDDC</span>
</a>
<nav class="header-nav">
<a href="/" class="nav-link">Home</a>
<a href="../reference.html" class="nav-link">Docs</a>
<a href="index.html" class="nav-link active">Releases</a>
</nav>
</div>
</header>
<section class="hero">
<div class="container">
<h1>Releases</h1>
<p class="hero-subtitle">All published versions and channel builds of every ZDDC tool. Stable releases are immutable; alpha and beta channels are rebuilt without notice.</p>
</div>
</section>
<main class="container" style="margin-bottom: var(--spacing-2xl);">
HEAD
# Render one section per HTML tool, scanning website/releases/ for
# <tool>_v*.html real files (per-version archives) and resolving the
# current channel symlinks.
for _tool_entry in 'archive|Archive' \
'transmittal|Transmittal' \
'classifier|Classifier' \
'mdedit|Markdown Editor' \
'landing|Landing (project picker)'; do
_tool="${_tool_entry%%|*}"
_title="${_tool_entry#*|}"
# All per-version real files for this tool, semver-descending.
# Use find to filter out symlinks; grep + sort -Vr for ordering.
_versioned=$(find "$RELEASES_DIR" -maxdepth 1 -type f -name "${_tool}_v*.html" 2>/dev/null \
| sed "s|^${RELEASES_DIR}/||" \
| sort -Vr)
if [ -z "$_versioned" ]; then
continue
fi
printf ' <section class="rel-tool">\n'
printf ' <h2>%s</h2>\n' "$_title"
# Channel chips — only render if the symlink exists.
printf ' <div class="rel-channels">\n'
for _ch in stable beta alpha; do
_link="${_tool}_${_ch}.html"
if [ -e "$RELEASES_DIR/$_link" ]; then
printf ' <a class="%s" href="%s">%s</a>\n' "$_ch" "$_link" "$_ch"
fi
done
printf ' </div>\n'
# Pin-to-version row: every per-version real file, descending.
printf ' <div class="rel-versions"><strong>Pin to version:</strong>\n'
printf '%s\n' "$_versioned" | while read -r _f; do
[ -n "$_f" ] || continue
# Display as v<X.Y.Z> stripped of <tool>_v prefix and .html suffix.
_v="${_f#${_tool}_v}"
_v="${_v%.html}"
printf ' <a href="%s">v%s</a>\n' "$_f" "$_v"
done
printf ' </div>\n'
printf ' </section>\n'
done
# zddc-server section — links to Codeberg release pages directly,
# since binaries don't live under website/releases/.
printf ' <section class="rel-tool">\n'
printf ' <h2>zddc-server (Go file server)</h2>\n'
printf ' <p>Binaries are published as Codeberg release assets. Pick a platform from the release page; or build from source via the helm charts under <code>helm/</code>.</p>\n'
printf ' <p><a href="https://codeberg.org/VARASYS/ZDDC/releases">Browse zddc-server releases on Codeberg →</a></p>\n'
printf ' </section>\n'
cat <<'TAIL'
<section style="margin-top: var(--spacing-2xl); color: var(--color-text-muted); font-size: 0.9rem;">
<p>Each link above is a real static file (or a checked-in symlink resolving to one). Channel chips track the current build of that channel and may change at any time; per-version files are immutable. To install or pin in your own deployment, see <a href="../">the home page</a>.</p>
</section>
</main>
<footer class="site-footer">
<div class="container footer-content">
<span>ZDDC is open source — <a href="https://codeberg.org/VARASYS/ZDDC">codeberg.org/VARASYS/ZDDC</a></span>
</div>
</footer>
</body>
</html>
TAIL
} > "$_out"
echo "Wrote $_out"
}
echo ""
echo "=== Building releases/index.html ==="
build_releases_index
echo ""
echo "=== All tools built successfully ==="
echo ""
echo "Server deployment package: zddc/dist/"
echo " Binaries: zddc-server-{linux,darwin,windows}-*"
echo " Web files: web/ (copy contents to ZDDC_ROOT)"
echo ""
echo "Operator install: see website/index.html 'Install on your server'."