#!/usr/bin/env bash set -euo pipefail # ── helpers ──────────────────────────────────────────────────────────────────── die() { echo "Error: $*" >&2; exit 1; } # Returns the latest vX.Y.Z tag for a given X.Y prefix (or overall latest if no prefix) fetch_latest_version() { local prefix="$1" # e.g. "11.0" or "" for absolute latest local tags tags=$(curl -fsSL \ "https://codeberg.org/api/v1/repos/forgejo/forgejo/tags?limit=50" \ 2>/dev/null) || die "Could not reach Codeberg API — check your connection." # Extract tag names, filter to release tags (vX.Y.Z, no pre-release suffix) local versions versions=$(echo "$tags" | grep -oP '"name"\s*:\s*"\Kv[0-9]+\.[0-9]+\.[0-9]+"' \ | tr -d '"' | sort -V) if [[ -z "$prefix" ]]; then echo "$versions" | tail -1 else echo "$versions" | grep "^v${prefix}\." | tail -1 fi } # ── detect architecture ──────────────────────────────────────────────────────── case "$(uname -m)" in x86_64) ARCH="amd64" ;; aarch64) ARCH="arm64" ;; armv7l) ARCH="arm-6" ;; *) die "Unsupported architecture: $(uname -m)" ;; esac # ── version prompt ───────────────────────────────────────────────────────────── echo "Fetching latest Forgejo release…" LATEST_OVERALL=$(fetch_latest_version "") LATEST_OVERALL="${LATEST_OVERALL#v}" # strip leading 'v' echo echo "Latest available release: ${LATEST_OVERALL}" echo read -rp "Version to install [MAJOR.MINOR or MAJOR.MINOR.PATCH, Enter = ${LATEST_OVERALL}]: " INPUT INPUT="${INPUT:-$LATEST_OVERALL}" # Normalise: strip a leading 'v' if the user typed one INPUT="${INPUT#v}" # Determine if the user gave a full version (X.Y.Z) or a partial one (X.Y) if [[ "$INPUT" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then # Full version supplied — use as-is VERSION="$INPUT" elif [[ "$INPUT" =~ ^[0-9]+\.[0-9]+$ ]]; then # Partial (X.Y) — resolve the latest patch on that line echo "Resolving latest patch for ${INPUT}.x…" RESOLVED=$(fetch_latest_version "$INPUT") [[ -z "$RESOLVED" ]] && die "No releases found for ${INPUT}.x" VERSION="${RESOLVED#v}" echo "→ Using ${VERSION}" else die "Unrecognised version format '${INPUT}'. Use X.Y or X.Y.Z" fi # ── confirm ──────────────────────────────────────────────────────────────────── BINARY="forgejo-${VERSION}-linux-${ARCH}" echo echo " Version : ${VERSION}" echo " Binary : ${BINARY}" echo " Arch : ${ARCH}" echo read -rp "Proceed with installation? [Y/n]: " CONFIRM CONFIRM="${CONFIRM:-Y}" [[ "$CONFIRM" =~ ^[Yy]$ ]] || { echo "Aborted."; exit 0; } # ── download & install ───────────────────────────────────────────────────────── URL="https://codeberg.org/forgejo/forgejo/releases/download/v${VERSION}/${BINARY}" echo echo "Downloading ${URL}…" wget --show-progress -q "$URL" || die "Download failed — is v${VERSION} a valid release?" chmod +x "$BINARY" echo "Stopping forgejo…" systemctl stop forgejo echo "Installing binary…" cp "$BINARY" /usr/local/bin/forgejo rm -f "$BINARY" # clean up the downloaded file echo "Starting forgejo…" systemctl start forgejo echo echo "Done — Forgejo ${VERSION} is running."