Files
ServerKit/scripts/build-release.sh
T
Juan Denis edf6260dee fix(build-release): make release builder work on Windows/Git Bash
- Replace rsync with tar-based copy to avoid missing rsync on Windows/Git Bash
- Exclude backend/venv, backend/.venv, backend/.venv-wsl, and broken WSL symlinks
- Exclude ./backups, backend/dev-data/backups, backend/instance/backups, and scripts/test/output
- Exclude scratch images (PNG/JPEG/JPG), logs, and tmp files from the tarball
- Pack with tar --transform so /opt/serverkit prefix is created without cross-device moves
- Reduce release tarball from 13 GB back to ~6 MB
2026-06-22 16:52:34 -04:00

140 lines
5.8 KiB
Bash
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/bash
#
# ServerKit release builder.
#
# Produces a portable tarball that installs without compiling the frontend on
# the target: the full /opt/serverkit tree with a built frontend. The Python
# virtualenv is created locally by install.sh/update.sh so absolute paths in
# the venv always match the target machine.
#
# bash scripts/build-release.sh
# VERSION=v1.7.0 bash scripts/build-release.sh
#
set -euo pipefail
BUILD_DIR="/tmp/serverkit-release-build"
# ---------------------------------------------------------------------------
# Terminal styling (violet ServerKit identity, degrades to plain text)
# ---------------------------------------------------------------------------
if [ -t 1 ] && [ -z "${NO_COLOR:-}" ] && [ "${TERM:-dumb}" != "dumb" ]; then
ESC=$'\033'
RST="${ESC}[0m"; BLD="${ESC}[1m"
paint() { printf '%s[38;2;%d;%d;%dm' "$ESC" "$1" "$2" "$3"; }
else
RST=''; BLD=''
paint() { :; }
fi
HUE_OK="$(paint 52 211 153)"; HUE_ERR="$(paint 248 113 113)"
HUE_LINK="$(paint 103 232 249)"
good() { printf ' %s✔%s %s\n' "$HUE_OK" "$RST" "$1"; }
halt() { printf ' %s✘%s %s\n' "$HUE_ERR" "$RST" "$1" >&2; exit 1; }
step() { printf ' %s❯%s %s\n' "$HUE_LINK" "$RST" "$1"; }
# ---------------------------------------------------------------------------
# Resolve version + architecture into an output filename
# ---------------------------------------------------------------------------
if [ -n "${VERSION:-}" ]; then
RELEASE_TAG="$VERSION"
elif [ -f "VERSION" ]; then
RELEASE_TAG="v$(cat VERSION | tr -d '\n\r ')"
else
halt "Cannot determine version. Set VERSION or create a VERSION file."
fi
case "${BUILD_ARCH:-$(uname -m)}" in
x86_64|amd64) DL_ARCH="amd64" ;;
aarch64|arm64) DL_ARCH="arm64" ;;
*) halt "Unsupported architecture: ${BUILD_ARCH:-$(uname -m)}" ;;
esac
OUTPUT="serverkit-${RELEASE_TAG}-linux-${DL_ARCH}.tar.gz"
step "Building release ${RELEASE_TAG} for ${DL_ARCH}"
# ---------------------------------------------------------------------------
# Toolchain check
# ---------------------------------------------------------------------------
command -v node &>/dev/null || halt "Node.js is required."
# ---------------------------------------------------------------------------
# Stage a clean copy of the repository
# ---------------------------------------------------------------------------
step "Preparing the build directory..."
rm -rf "$BUILD_DIR"
mkdir -p "$BUILD_DIR"
step "Copying the source tree..."
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
# Copy the source tree with tar, which handles broken symlinks and avoids
# the long rm -rf timeouts that cp + rm can hit on Windows/Git Bash.
mkdir -p "$BUILD_DIR"
cd "$REPO_ROOT"
tar -cf - --exclude='./.git' --exclude='./node_modules' --exclude='./venv' --exclude='./.venv' --exclude='./.venv-wsl' --exclude='./backend/venv' --exclude='./backend/.venv' --exclude='./backend/.venv-wsl' --exclude='./__pycache__' --exclude='./.pytest_cache' --exclude='./instance' --exclude='./dist' --exclude='./backups' --exclude='./backend/dev-data/backups' --exclude='./backend/instance/backups' --exclude='./scripts/test/output' --exclude='*.png' --exclude='*.jpeg' --exclude='*.jpg' --exclude='*.log' --exclude='*.tmp' --exclude='*.pyc' . | tar -C "$BUILD_DIR" -xf -
# ---------------------------------------------------------------------------
# Build the frontend bundle
# ---------------------------------------------------------------------------
step "Building the frontend..."
cd "$BUILD_DIR/frontend"
npm ci --prefer-offline 2>&1 | tail -5
NODE_OPTIONS="--max-old-space-size=1024" npm run build 2>&1 | tail -10
# ---------------------------------------------------------------------------
# Strip development artifacts from the staged tree
# ---------------------------------------------------------------------------
step "Cleaning release artifacts..."
rm -rf "$BUILD_DIR/frontend/node_modules"
find "$BUILD_DIR" -type d -name __pycache__ -exec rm -rf {} + 2>/dev/null || true
find "$BUILD_DIR" -type d -name .pytest_cache -exec rm -rf {} + 2>/dev/null || true
find "$BUILD_DIR" -type f -name '*.pyc' -delete 2>/dev/null || true
find "$BUILD_DIR" -type f \( -name '*.png' -o -name '*.jpeg' -o -name '*.jpg' \) -delete 2>/dev/null || true
# Runtime directory the app expects to exist.
mkdir -p "$BUILD_DIR/backend/instance"
# ---------------------------------------------------------------------------
# Pack the tarball with an /opt/serverkit prefix
# ---------------------------------------------------------------------------
step "Creating the tarball..."
# Land the tarball at the repo root (matches .gitignore's /serverkit-*.tar.gz).
DEST_DIR="$REPO_ROOT"
# Pack from the parent of BUILD_DIR with a transform so the archive contains
# /opt/serverkit without moving directories across filesystems.
cd "$(dirname "$BUILD_DIR")"
tar czf "${DEST_DIR}/${OUTPUT}" \
--exclude='node_modules' \
--exclude='venv' \
--exclude='.venv' \
--exclude='.venv-wsl' \
--exclude='__pycache__' \
--exclude='.pytest_cache' \
--exclude='instance' \
--exclude='dist' \
--exclude='/backups' \
--exclude='/backend/instance/backups' \
--exclude='/backend/dev-data/backups' \
--exclude='/scripts/test/output' \
--exclude='*.png' \
--exclude='*.jpeg' \
--exclude='*.jpg' \
--exclude='*.log' \
--exclude='*.tmp' \
--exclude='*.pyc' \
--transform 's|^serverkit-release-build|opt/serverkit|' \
serverkit-release-build
cd "$DEST_DIR"
rm -rf "$BUILD_DIR"
good "Release built: ${OUTPUT}"
ls -lh "${OUTPUT}"
printf '\n'
printf 'Upload this file to GitHub Releases: %s\n' "$OUTPUT"
printf 'Install with:\n'
printf ' curl -fsSL https://serverkit.ai/install.sh | INSTALL_FROM_RELEASE=1 bash\n\n'