ZDDC/release-image.sh
ZDDC 566070ca80 release: zddc-server v0.0.8-alpha.2 + binary publish step
Adds binary mirroring to release-image.sh: cross-compiled binaries from
zddc/dist/ are now copied to website/releases/zddc-server-<os>-<arch>-<channel>
for every channel in the cascade, so https://zddc.varasys.io/releases/
serves binaries alongside the HTML tools. Channel pointers are mutable;
no immutable per-version files are written (the container registry
provides per-version pinning via image tags).

Plain `sh build.sh` does NOT mirror binaries — only `release-image.sh`
does, deliberately, to avoid 40MB git churn per dev iteration.

This commit also picks up the routine alpha-mirror refresh from the
v0.0.8-alpha.2 image cut.
2026-04-29 18:07:36 -05:00

214 lines
7.9 KiB
Bash
Executable file

#!/bin/sh
# release-image.sh — build the zddc-server runtime image locally and push it
# to codeberg.org/varasys/zddc-server with cascading channel tags.
#
# Usage:
# sh release-image.sh # alpha cut, version auto-derived
# sh release-image.sh alpha # same
# sh release-image.sh beta # beta cut, version auto-derived
# sh release-image.sh stable # stable cut, patch++ from latest stable
# sh release-image.sh stable 0.1.0 # stable cut, explicit version
#
# Channel cascade rules (unchanged from earlier):
# alpha → :<version> :alpha
# beta → :<version> :beta :alpha
# stable → :<version> :stable :beta :alpha
#
# Versioning: pre-release semver. Stable releases own clean vX.Y.Z; alpha
# and beta carry vX.Y.Z-alpha.N / vX.Y.Z-beta.N suffixes, where X.Y.Z is
# the next patch of the latest clean stable tag and N is a per-channel
# counter that resets when stable advances.
#
# The script does ONE thing the old version did not: it `git tag`s the
# release before pushing the image, since auto-derivation means the
# operator can no longer predict the version up-front. The tag is pushed
# to origin only if the operator runs `git push --tags` afterwards
# (intentional — the script never pushes git history on its own).
#
# Prerequisites:
# - podman (or docker — commands are identical)
# - logged in to codeberg.org: `podman login codeberg.org`
# (Codeberg username + a token with `package:write` scope, generated at
# https://codeberg.org/user/settings/applications)
#
# What it does:
# 1. Compute the version (auto for alpha/beta, auto-or-explicit for stable).
# 2. Refresh dist/web by running sh build.sh — the Containerfile's
# server stage COPYs those files in.
# 3. Tag the current commit zddc-server-v<version>.
# 4. Build zddc/Containerfile's `server` stage as a single local image.
# 5. Tag and push each cascade tag.
set -eu
usage() {
cat >&2 <<'EOF'
usage: release-image.sh [alpha|beta|stable] [<version>]
alpha (default) cut alpha, version auto-derived from the latest
clean stable tag (vX.Y.Z + patch++ + -alpha.N).
beta cut beta, version auto-derived (vX.Y.Z + -beta.N).
stable cut stable. Without <version>, patch-bump from the
latest clean stable tag. With <version>, use it
verbatim (must be a clean X.Y.Z).
EOF
exit 1
}
CHANNEL="${1:-alpha}"
case "$CHANNEL" in
alpha | beta | stable) ;;
-h | --help) usage ;;
*) echo "error: unknown channel '$CHANNEL'" >&2; usage ;;
esac
EXPLICIT_VERSION="${2:-}"
if [ -n "$EXPLICIT_VERSION" ] && [ "$CHANNEL" != "stable" ]; then
echo "error: an explicit <version> is only valid with the 'stable' channel" >&2
echo " alpha and beta versions are auto-derived." >&2
exit 1
fi
REPO="codeberg.org/varasys/zddc-server"
SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
TAG_PREFIX="zddc-server-v"
# Source build-lib.sh so we can call next_prerelease for alpha/beta and
# share the validation helpers used by the HTML tools.
root_dir="$SCRIPT_DIR"
. "$SCRIPT_DIR/shared/build-lib.sh"
# --- Determine the version --------------------------------------------------
case "$CHANNEL" in
alpha | beta)
VERSION=$(next_prerelease "$CHANNEL" "$TAG_PREFIX")
;;
stable)
if [ -n "$EXPLICIT_VERSION" ]; then
_validate_semver "$EXPLICIT_VERSION"
VERSION="$EXPLICIT_VERSION"
else
# Auto-bump patch from the latest clean stable tag.
_latest=$(git -C "$SCRIPT_DIR" tag --list "${TAG_PREFIX}*" 2>/dev/null \
| grep -E "^${TAG_PREFIX}[0-9]+\.[0-9]+\.[0-9]+\$" \
| sed "s|^${TAG_PREFIX}||" \
| sort -V \
| tail -1)
[ -n "$_latest" ] || _latest="0.0.0"
_major="${_latest%%.*}"
_rest="${_latest#*.}"
_minor="${_rest%%.*}"
_patch="${_rest#*.}"
VERSION="${_major}.${_minor}.$((_patch + 1))"
fi
;;
esac
case "$CHANNEL" in
alpha) TAGS="$VERSION alpha" ;;
beta) TAGS="$VERSION beta alpha" ;;
stable) TAGS="$VERSION stable beta alpha" ;;
esac
# Pick podman or docker, whichever is on PATH.
if command -v podman >/dev/null 2>&1; then
OCI=podman
elif command -v docker >/dev/null 2>&1; then
OCI=docker
else
echo "error: neither podman nor docker found on PATH" >&2
exit 1
fi
GIT_TAG="${TAG_PREFIX}${VERSION}"
echo "=== Building $REPO ==="
echo "Channel: $CHANNEL"
echo "Version: $VERSION"
echo "Git tag: $GIT_TAG"
echo "Image tags: $TAGS"
echo "OCI CLI: $OCI"
echo
# --- Refresh HTML dist (Containerfile COPYs from dist/web) ------------------
sh "$SCRIPT_DIR/build.sh"
# --- Mirror cross-compiled binaries to website/releases/ -------------------
# Channel pointers, mutable: cascade rules mirror this image's binaries to
# every channel in the cascade so a `zddc-use :stable` curl pulls bytes that
# match the just-published stable image. Per-version pinning is provided by
# the container registry's :vX.Y.Z-alpha.N tag, not by an immutable file
# here — keeps the repo from growing 40MB per release. Plain `sh build.sh`
# does NOT mirror binaries, deliberately: it would dirty 40MB of files on
# every dev iteration. Use release-image.sh as the publish trigger.
publish_binary() {
_src="$1" # path under zddc/dist/, e.g. zddc-server-linux-amd64
_basename=$(basename "$_src")
if [ ! -f "$SCRIPT_DIR/zddc/dist/$_src" ]; then
echo "warn: $_src not found in zddc/dist/; skipping mirror" >&2
return 0
fi
# The version-style tag (e.g. 0.0.8-alpha.1) is in $TAGS too — skip it;
# only iterate the channel-name tags.
for _tag in $TAGS; do
case "$_tag" in
alpha | beta | stable)
_dest="$SCRIPT_DIR/website/releases/${_basename%.exe}-${_tag}"
case "$_basename" in *.exe) _dest="${_dest}.exe" ;; esac
cp -f "$SCRIPT_DIR/zddc/dist/$_src" "$_dest"
echo "mirrored $_src → website/releases/$(basename "$_dest")"
;;
esac
done
}
publish_binary zddc-server-linux-amd64
publish_binary zddc-server-darwin-amd64
publish_binary zddc-server-darwin-arm64
publish_binary zddc-server-windows-amd64.exe
# --- Tag the commit (idempotent: skip if the tag already points here) -------
if git -C "$SCRIPT_DIR" rev-parse -q --verify "refs/tags/$GIT_TAG" >/dev/null; then
_existing=$(git -C "$SCRIPT_DIR" rev-list -n 1 "$GIT_TAG")
_head=$(git -C "$SCRIPT_DIR" rev-parse HEAD)
if [ "$_existing" != "$_head" ]; then
echo "error: tag $GIT_TAG already exists at $_existing, but HEAD is $_head" >&2
echo " refusing to overwrite. Resolve manually." >&2
exit 1
fi
echo "(tag $GIT_TAG already at HEAD)"
else
git -C "$SCRIPT_DIR" tag "$GIT_TAG"
echo "tagged $GIT_TAG (run 'git push --tags' to publish)"
fi
# --- Build + push -----------------------------------------------------------
"$OCI" build --target server -t zddc-server:build "$SCRIPT_DIR/zddc/"
echo
echo "=== Pushing tags ==="
for tag in $TAGS; do
"$OCI" tag zddc-server:build "$REPO:$tag"
"$OCI" push "$REPO:$tag"
echo "pushed $REPO:$tag"
done
echo
echo "=== Done ==="
echo "Image: $REPO:$VERSION"
echo "Cascading tags: $TAGS"
echo "Git tag: $GIT_TAG (publish with: git push origin $GIT_TAG)"
echo
case "$CHANNEL" in
stable)
echo "Reminder (channel discipline rule 4): freshen alpha + beta now"
echo "so users tracking those channels are not on stale code:"
echo " ./freshen-channel <tool> alpha"
echo " ./freshen-channel <tool> beta"
echo
echo "Bump tnd-zddc-chart's ZDDC_SERVER_TAG (push to develop) so the"
echo "chart's CI rebuilds the dev-shell image and helm-rolls."
;;
beta)
echo "Beta cut. Soak before promoting to stable."
;;
esac