#!/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 → : :alpha # beta → : :beta :alpha # stable → : :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. # 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] [] 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 , patch-bump from the latest clean stable tag. With , 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 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 alpha" echo " ./freshen-channel 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