#!/bin/sh # release.sh — cut a zddc-server release: tag, compile binaries, # publish them as assets to a Codeberg release. # # Usage: # sh zddc/release.sh # alpha cut (default), version auto-derived # sh zddc/release.sh alpha # same # sh zddc/release.sh beta # beta cut, version auto-derived # sh zddc/release.sh stable # stable cut, patch++ from latest stable # sh zddc/release.sh stable 0.1.0 # stable cut, explicit version # # What this is NOT: there's no container image build, no registry push. # Those went away when the upstream codeberg.org/varasys/zddc-server # image lost its only consumers (tnd-zddc-chart's two Dockerfiles now # compile from source directly, fetching this Codeberg release tarball # / binary). See AGENTS.md "Releasing" for the full flow. # # Prerequisites: # - Go 1.24+ on PATH. # - $CODEBERG_TOKEN exported, scoped to write the VARASYS/ZDDC repo. # - curl, jq, git. # # What it does: # 1. Determine version per the pre-release semver scheme: # alpha/beta → next_prerelease (vX.Y.Z-CHANNEL.N from latest stable) # stable → operator-supplied or patch-bumped from latest stable # 2. Tag the current commit zddc-server-v. # 3. Cross-compile binaries (linux/darwin/windows × amd64/arm64) # into zddc/dist/zddc-server--[.exe]. Native Go preferred. # 4. Upload each binary as an asset to the new Codeberg release. # 5. Print the operator's next steps (push the tag). # # The script does NOT push the tag itself — that's a deliberate `git push` # you do after reviewing. set -eu usage() { cat >&2 <<'EOF' usage: release.sh [alpha|beta|stable] [] alpha (default) cut alpha. Auto-derive version from the latest clean zddc-server-vX.Y.Z tag plus next-patch + -alpha.N. beta cut beta. Auto-derive version (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 if [ -z "${CODEBERG_TOKEN:-}" ]; then echo "error: CODEBERG_TOKEN must be exported in the environment" >&2 echo " (Codeberg user → Settings → Applications → generate a token" >&2 echo " with scope sufficient to create releases on VARASYS/ZDDC.)" >&2 exit 1 fi SCRIPT_DIR=$(cd "$(dirname "$0")/.." && pwd) TAG_PREFIX="zddc-server-v" REPO="VARASYS/ZDDC" # Source build-lib.sh for next_prerelease + _validate_semver. It # requires root_dir set; pointing at the repo root works. root_dir="$SCRIPT_DIR" . "$SCRIPT_DIR/shared/build-lib.sh" . "$SCRIPT_DIR/shared/publish-codeberg-release.sh" # --- Determine 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 _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 GIT_TAG="${TAG_PREFIX}${VERSION}" echo "=== zddc-server release ===" echo "Channel: $CHANNEL" echo "Version: $VERSION" echo "Git tag: $GIT_TAG" echo # --- 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" fi # --- Cross-compile binaries (native Go) ------------------------------------ if ! command -v go >/dev/null 2>&1; then echo "error: go not found on PATH" >&2 echo " (install Go 1.24+, or run this script from inside a Go" >&2 echo " container — there's no podman fallback anymore.)" >&2 exit 1 fi DIST="$SCRIPT_DIR/zddc/dist" mkdir -p "$DIST" echo echo "=== Cross-compiling ===" cd "$SCRIPT_DIR/zddc" LDFLAGS="-s -w -X main.version=${VERSION}" 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="$LDFLAGS" -o "$DIST/$out" ./cmd/zddc-server done cd "$SCRIPT_DIR" # --- Publish to Codeberg --------------------------------------------------- echo echo "=== Publishing to Codeberg release $GIT_TAG ===" publish_codeberg_release "$REPO" "$GIT_TAG" \ "$DIST/zddc-server-linux-amd64" \ "$DIST/zddc-server-darwin-amd64" \ "$DIST/zddc-server-darwin-arm64" \ "$DIST/zddc-server-windows-amd64.exe" echo echo "=== Done ===" echo "Release: https://codeberg.org/$REPO/releases/tag/$GIT_TAG" 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 the floating channels resolve to at-least-current code:" echo " ./freshen-channel zddc-server alpha" echo " ./freshen-channel zddc-server beta" ;; beta) echo "Beta cut. Soak before promoting to stable." ;; esac echo echo "Don't forget to also regenerate the website releases page:" echo " sh build.sh" echo " git add website/releases/index.html website/releases/manifest.json" echo " git commit && git push"