ZDDC/build.sh
ZDDC 6e1777e9c2 feat(web): list zddc-server binaries + image tags on releases page
The releases index already enumerated HTML tools by channel and
version. Add a parallel section for zddc-server with two artifact
families:

- Standalone binaries: a channel × platform table linking to
  website/releases/zddc-server-{linux,darwin,windows}-{amd64,arm64}-<channel>
  (the files release-image.sh now mirrors there). Empty cells render
  as em-dashes; the table only renders when at least one binary
  exists locally so freshly-cloned repos don't show a ghost section.
- Container images: pull-snippet, channel chips linking to the
  codeberg package page, and a "Pin to version" row of historical
  tags (clean stables first, recent pre-releases listed separately
  with a "recent pre-releases:" label so the pre-release noise
  doesn't drown out the stable list).

Recent pre-releases capped at 10 entries to keep the list scannable
as alpha cuts proliferate over time.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 20:04:28 -05:00

331 lines
17 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 bootstrap stubs published under website/bootstrap/.
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/ ==="
# 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.
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"
# Cross-compiled zddc-server binaries — only relevant if you're shipping
# standalone Linux/macOS/Windows binaries to users. Skipped silently when
# podman isn't on PATH; the runtime container release path
# (release-image.sh) does its own internal build via Containerfile's
# multi-stage flow and doesn't need these host-side binaries.
echo ""
echo "=== Building zddc-server binaries ==="
if command -v podman >/dev/null 2>&1; then
podman build --target binaries -o "$SCRIPT_DIR/zddc/dist/" "$SCRIPT_DIR/zddc/" 2>&1 | grep -v "^-->"
else
echo "podman not found — skipping cross-compiled binary build."
echo " (Standalone-binary distribution only; the runtime container"
echo " release path builds its own copy via Containerfile.)"
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/<tool>.html — same-origin stubs for
# <project>/<tool>.html (4 tools;
# landing only lives at root)
# bootstrap/track-<channel>/<tool>.html — level-2 stubs that fetch the
# named channel from upstream
# (5 tools × 3 channels = 15)
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 <project>/<tool>.html fetches ../<tool>.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 <<EOF
archive|archive.html|Archive
transmittal|transmittal.html|Transmittal
classifier|classifier.html|Classifier
mdedit|mdedit.html|Markdown Editor
EOF
echo "Wrote $_stubs/level1/{archive,transmittal,classifier,mdedit}.html"
# Level-2 stubs, one set per channel. Each fetches its named channel
# from upstream on every page load.
for _channel in alpha beta stable; do
mkdir -p "$_stubs/track-$_channel"
while IFS='|' read -r _tool _file _title; do
render_stub "$BOOTSTRAP_DIR/level2.html.tmpl" "$_tool" "$_title" "$_channel" \
"$_stubs/track-$_channel/$_file"
done <<EOF
$TOOL_TABLE
EOF
echo "Wrote $_stubs/track-$_channel/ (5 stubs)"
done
}
# Regenerate website/releases/index.html — a static directory listing of
# all tool releases with channel rows + per-version archive links. Read
# from the filesystem so the page is always consistent with what's there.
build_releases_index() {
_out="$RELEASES_DIR/index.html"
{
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">
<div class="brand-logo">
<svg viewBox="0 0 24 24"><path d="M3 5h18v2H3V5zm0 6h12v2H3v-2zm0 6h6v2H3v-2z" /></svg>
</div>
<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
printf '%s\n' "$TOOL_TABLE" | while IFS='|' read -r _tool _file _title; do
_stable_target=""
if [ -L "$RELEASES_DIR/${_tool}_stable.html" ]; then
_stable_target=$(readlink "$RELEASES_DIR/${_tool}_stable.html")
fi
printf ' <section class="rel-tool">\n'
printf ' <h2>%s</h2>\n' "$_title"
printf ' <div class="rel-channels">\n'
[ -e "$RELEASES_DIR/${_tool}_stable.html" ] && printf ' <a class="stable" href="%s_stable.html">stable</a>\n' "$_tool"
[ -e "$RELEASES_DIR/${_tool}_beta.html" ] && printf ' <a class="beta" href="%s_beta.html">beta</a>\n' "$_tool"
[ -e "$RELEASES_DIR/${_tool}_alpha.html" ] && printf ' <a class="alpha" href="%s_alpha.html">alpha</a>\n' "$_tool"
printf ' </div>\n'
_versions=$(ls -1 "$RELEASES_DIR" 2>/dev/null | grep -E "^${_tool}_v[0-9]" | sort -V -r)
if [ -n "$_versions" ]; then
printf ' <div class="rel-versions"><strong>Pin to version:</strong>\n'
printf '%s\n' "$_versions" | while read -r _v; do
_ver=${_v#${_tool}_v}; _ver=${_ver%.html}
printf ' <a href="%s">v%s</a>\n' "$_v" "$_ver"
done
printf ' </div>\n'
fi
if [ -n "$_stable_target" ]; then
printf ' <div class="rel-meta">stable currently → %s</div>\n' "$_stable_target"
fi
printf ' </section>\n'
done
# zddc-server section — different artifact shape than the HTML tools.
# Two artifact families:
# 1. Downloadable binaries at website/releases/zddc-server-<os>-<arch>-<channel>
# (mutable channel pointers; release-image.sh writes them).
# 2. Container images at codeberg.org/varasys/zddc-server:<channel> and
# :<version> (the registry; we don't proxy them through the website,
# but we list the recent tags and a `podman pull` snippet for each).
printf ' <section class="rel-tool">\n'
printf ' <h2>zddc-server</h2>\n'
printf ' <p style="margin-top:0;color:var(--color-text-muted);font-size:0.95rem;">Go HTTP file server with ACL, .archive index, and a delegated-admin .zddc editor. Distributed as a container image (preferred) or a standalone binary.</p>\n'
# Binaries table.
_platforms="linux-amd64 darwin-amd64 darwin-arm64 windows-amd64"
_have_any_bin=0
for _ch in stable beta alpha; do
for _p in $_platforms; do
_ext=""; case "$_p" in windows-*) _ext=".exe" ;; esac
if [ -f "$RELEASES_DIR/zddc-server-${_p}-${_ch}${_ext}" ]; then
_have_any_bin=1; break 2
fi
done
done
if [ "$_have_any_bin" = "1" ]; then
printf ' <h3 style="font-size:1rem;margin:0.75rem 0 0.4rem;">Standalone binaries</h3>\n'
printf ' <table class="rel-bin-table"><thead><tr><th>Channel</th>'
for _p in $_platforms; do printf '<th>%s</th>' "$_p"; done
printf '</tr></thead><tbody>\n'
for _ch in stable beta alpha; do
printf ' <tr><td class="ch-%s">%s</td>' "$_ch" "$_ch"
for _p in $_platforms; do
_ext=""; case "$_p" in windows-*) _ext=".exe" ;; esac
_f="zddc-server-${_p}-${_ch}${_ext}"
if [ -f "$RELEASES_DIR/$_f" ]; then
printf '<td><a href="%s">download</a></td>' "$_f"
else
printf '<td class="empty">—</td>'
fi
done
printf '</tr>\n'
done
printf ' </tbody></table>\n'
fi
# Container image: pull-snippet box plus the recent git tag list.
printf ' <h3 style="font-size:1rem;margin:0.75rem 0 0.4rem;">Container image</h3>\n'
printf ' <p style="margin:0 0 0.4rem;font-size:0.9rem;">Pull from <a href="https://codeberg.org/VARASYS/-/packages/container/zddc-server">codeberg.org/varasys/zddc-server</a>:</p>\n'
printf ' <div class="rel-channels">\n'
printf ' <a class="stable" href="https://codeberg.org/VARASYS/-/packages/container/zddc-server/stable">:stable</a>\n'
printf ' <a class="beta" href="https://codeberg.org/VARASYS/-/packages/container/zddc-server/beta">:beta</a>\n'
printf ' <a class="alpha" href="https://codeberg.org/VARASYS/-/packages/container/zddc-server/alpha">:alpha</a>\n'
printf ' </div>\n'
printf ' <code class="rel-pull">podman pull codeberg.org/varasys/zddc-server:stable</code>\n'
# Recent zddc-server tags from git: clean stables first (top), then
# the most recent pre-releases. Dropping older pre-releases keeps the
# list readable since alpha/beta cuts proliferate.
_server_stables=$(git -C "$SCRIPT_DIR" tag --list 'zddc-server-v*' 2>/dev/null \
| grep -E '^zddc-server-v[0-9]+\.[0-9]+\.[0-9]+$' \
| sed 's|^zddc-server-v||' \
| sort -V -r)
_server_prereleases=$(git -C "$SCRIPT_DIR" tag --list 'zddc-server-v*' 2>/dev/null \
| grep -E '^zddc-server-v[0-9]+\.[0-9]+\.[0-9]+-' \
| sed 's|^zddc-server-v||' \
| sort -V -r \
| head -10)
if [ -n "$_server_stables" ] || [ -n "$_server_prereleases" ]; then
printf ' <div class="rel-versions" style="margin-top:0.6rem;"><strong>Pin to version:</strong>\n'
printf '%s\n' "$_server_stables" | while read -r _v; do
[ -n "$_v" ] || continue
printf ' <a href="https://codeberg.org/VARASYS/-/packages/container/zddc-server/%s">v%s</a>\n' "$_v" "$_v"
done
if [ -n "$_server_prereleases" ]; then
printf ' <span style="color:var(--color-text-muted);">recent pre-releases:</span>\n'
printf '%s\n' "$_server_prereleases" | while read -r _v; do
[ -n "$_v" ] || continue
printf ' <a href="https://codeberg.org/VARASYS/-/packages/container/zddc-server/%s">v%s</a>\n' "$_v" "$_v"
done
fi
printf ' </div>\n'
fi
printf ' </section>\n'
cat <<'TAIL'
<section style="margin-top: var(--spacing-2xl); color: var(--color-text-muted); font-size: 0.9rem;">
<p>Append <code>?v=alpha</code>, <code>?v=beta</code>, <code>?v=stable</code>, or <code>?v=0.0.1</code> to any deployment URL to switch versions for a single request — 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 bootstrap stubs and releases/index.html ==="
build_bootstrap_stubs
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 "Bootstrap stubs: website/bootstrap/"
echo " level1/<tool>.html — same-origin stubs for project subdirs"
echo " track-{alpha,beta,stable}/ — level-2 stubs for each channel"
echo ""
echo "The home page's 'Install on your server' section prints copy-pasteable"
echo "shell snippets that curl these files into the operator's deployment dir."