Add draft scripts

This commit is contained in:
John A. Hoeven 2026-07-16 14:25:30 +02:00
commit a695324e38
Signed by: giovannino
GPG key ID: 306E507219506D4E
4 changed files with 606 additions and 0 deletions

View file

@ -0,0 +1,148 @@
#!/usr/bin/env bash
# Built standing on the shoulders of billions of dwarves
# Created by John A. Hoeven with the ethical assistance of Claude AI
# Licence: The Unlicense — https://unlicense.org
# ---------------------------------------------------------------------------
# llama-cpp-promote.sh
# /opt/llama-cpp/scripts/llama-cpp-promote.sh
# Version: v0.0.1 | Status: DEVELOPMENT
# Role: Orchestrator
# ---------------------------------------------------------------------------
# Purpose: Point the 'current' symlink at a given staged release and
# restart llama-server. Used for BOTH forward promotion (new
# monthly build) and rollback (point back at the previous tag) —
# the operation is identical either way, only the target tag
# differs. Verifies the API responds before declaring success;
# auto-reverts the symlink if the new build fails to come up.
# Target: BigBoy — AlmaLinux 10.2, systemd-managed llama-server.service
# Entry: sudo ./llama-cpp-promote.sh <build-tag>
# e.g. sudo ./llama-cpp-promote.sh b9985 (promote)
# sudo ./llama-cpp-promote.sh b9840 (roll back)
# Depends: curl, systemctl
# ---------------------------------------------------------------------------
# No 'set -e' — every operation is checked explicitly (CE OS standard §1.8).
# ── Configuration ────────────────────────────────────────────────────────
LLAMA_ROOT="/opt/llama-cpp"
RELEASES_DIR="${LLAMA_ROOT}/releases"
CURRENT_LINK="${LLAMA_ROOT}/current"
SERVICE_NAME="llama-server.service"
API_PORT="8080"
VERIFY_TIMEOUT_SECS=30
LOG_DIR="${HOME}/.local/logs/bigboy-llama-update"
LOG_FILE="${LOG_DIR}/promote-$(date '+%Y-%m-%d_%H%M%S').log"
TARGET_TAG="${1:-}"
# ── Logging ──────────────────────────────────────────────────────────────
mkdir -p "${LOG_DIR}"
_log() {
local level="${1}"
local msg="${2}"
local ts
ts="$(date '+%Y-%m-%d %H:%M:%S')"
printf '[%s] [%s] %s\n' "${ts}" "${level}" "${msg}" | tee -a "${LOG_FILE}"
}
log_info() { _log "INFO " "${1}"; }
log_warn() { _log "WARN " "${1}" >&2; }
log_error() { _log "ERROR" "${1}" >&2; }
# ── Pre-flight checks ────────────────────────────────────────────────────
if [[ "${EUID}" -eq 0 ]]; then
log_error "Do not run this script directly as root — it invokes sudo"
log_error "only for the specific steps that need it."
exit 1
fi
if [[ -z "${TARGET_TAG}" ]]; then
log_error "Usage: ${0} <build-tag>"
log_error "Available staged releases:"
ls -1 "${RELEASES_DIR}" 2>/dev/null | sed 's/^/ /' | tee -a "${LOG_FILE}"
exit 1
fi
TARGET_PATH="${RELEASES_DIR}/${TARGET_TAG}"
if [[ ! -x "${TARGET_PATH}/build/bin/llama-server" ]]; then
log_error "No valid build found at ${TARGET_PATH}/build/bin/llama-server"
log_error "Run llama-cpp-update.sh ${TARGET_TAG} first if this is a new tag."
exit 1
fi
PREVIOUS_TAG=""
if [[ -L "${CURRENT_LINK}" ]]; then
PREVIOUS_TAG="$(basename "$(readlink -f "${CURRENT_LINK}")")"
fi
if [[ "${PREVIOUS_TAG}" == "${TARGET_TAG}" ]]; then
log_warn "current already points at ${TARGET_TAG} — nothing to do."
exit 0
fi
# ── Confirmation ─────────────────────────────────────────────────────────
printf '\nCurrent live release: %s\n' "${PREVIOUS_TAG:-none}"
printf 'Switching to: %s\n' "${TARGET_TAG}"
printf '%s will be restarted.\n' "${SERVICE_NAME}"
printf '\nProceed? [y/N] '
read -r response
case "${response}" in
[yY]|[yY][eE][sS]) ;;
*) log_info "Aborted by user."; exit 0 ;;
esac
# ── Step 1: swap symlink ─────────────────────────────────────────────────
log_info "Repointing ${CURRENT_LINK} -> ${TARGET_PATH}"
if ! sudo ln -sfn "${TARGET_PATH}" "${CURRENT_LINK}"; then
log_error "Failed to update symlink. Service left untouched — no restart attempted."
exit 1
fi
# ── Step 2: restart service ───────────────────────────────────────────────
log_info "Restarting ${SERVICE_NAME}"
if ! sudo systemctl restart "${SERVICE_NAME}" >>"${LOG_FILE}" 2>&1; then
log_error "Service failed to restart. Rolling symlink back to ${PREVIOUS_TAG}."
if [[ -n "${PREVIOUS_TAG}" ]]; then
sudo ln -sfn "${RELEASES_DIR}/${PREVIOUS_TAG}" "${CURRENT_LINK}"
sudo systemctl restart "${SERVICE_NAME}" >>"${LOG_FILE}" 2>&1
fi
exit 1
fi
# ── Step 3: verify the API actually responds ─────────────────────────────
log_info "Waiting for API on port ${API_PORT} (up to ${VERIFY_TIMEOUT_SECS}s)"
elapsed=0
until curl -s -o /dev/null -w '%{http_code}' "http://127.0.0.1:${API_PORT}/health" \
2>/dev/null | grep -q '200'; do
sleep 2
elapsed=$((elapsed + 2))
if [[ "${elapsed}" -ge "${VERIFY_TIMEOUT_SECS}" ]]; then
log_error "API did not respond within ${VERIFY_TIMEOUT_SECS}s."
log_error "Auto-reverting to previous release: ${PREVIOUS_TAG:-none}"
if [[ -n "${PREVIOUS_TAG}" ]]; then
sudo ln -sfn "${RELEASES_DIR}/${PREVIOUS_TAG}" "${CURRENT_LINK}"
sudo systemctl restart "${SERVICE_NAME}" >>"${LOG_FILE}" 2>&1
log_warn "Reverted. Investigate ${TARGET_TAG} before retrying."
fi
exit 1
fi
done
log_info "API confirmed healthy on ${TARGET_TAG}."
log_info "Promotion complete: ${PREVIOUS_TAG:-none} -> ${TARGET_TAG}"
log_info ""
log_info "Previous release (${PREVIOUS_TAG:-none}) left in place at:"
log_info " ${RELEASES_DIR}/${PREVIOUS_TAG}"
log_info "Recommended: keep it for at least a week before removing, in case"
log_info "an issue surfaces after a few days of real use rather than immediately."
log_info ""
log_info "To roll back at any point:"
log_info " sudo ./llama-cpp-promote.sh ${PREVIOUS_TAG}"

View file

@ -0,0 +1,137 @@
#!/usr/bin/env bash
# Built standing on the shoulders of billions of dwarves
# Created by John A. Hoeven with the ethical assistance of Claude AI
# Licence: The Unlicense — https://unlicense.org
# ---------------------------------------------------------------------------
# llama-cpp-prune.sh
# /opt/llama-cpp/scripts/llama-cpp-prune.sh
# Version: v0.0.1 | Status: DEVELOPMENT
# Role: Orchestrator
# ---------------------------------------------------------------------------
# Purpose: Remove staged llama.cpp releases (and their matching pre-update
# btrfs snapshots) beyond a configurable retention count. Never
# removes the release currently pointed at by 'current', and
# never removes anything without listing it and asking first.
# Target: BigBoy — AlmaLinux 10.2, @llama-cpp btrfs subvolume
# Entry: sudo ./llama-cpp-prune.sh [keep-count]
# e.g. sudo ./llama-cpp-prune.sh (uses default: 6)
# sudo ./llama-cpp-prune.sh 12 (keep last 12 instead)
# Depends: btrfs-progs
# Note: Disk math at 6 releases (~1-1.5GB shallow-clone build each) is
# roughly 6-9GB against a 499GB OS partition — trivial. Raise
# KEEP_DEFAULT freely; there is no disk-pressure reason to prune
# aggressively on this hardware.
# ---------------------------------------------------------------------------
# No 'set -e' — every operation is checked explicitly (CE OS standard §1.8).
# ── Configuration ────────────────────────────────────────────────────────
LLAMA_ROOT="/opt/llama-cpp"
RELEASES_DIR="${LLAMA_ROOT}/releases"
CURRENT_LINK="${LLAMA_ROOT}/current"
SNAPSHOT_DIR="/opt/.snapshots/llama-cpp"
KEEP_DEFAULT=6
LOG_DIR="${HOME}/.local/logs/bigboy-llama-update"
LOG_FILE="${LOG_DIR}/prune-$(date '+%Y-%m-%d_%H%M%S').log"
KEEP_COUNT="${1:-${KEEP_DEFAULT}}"
# ── Logging ──────────────────────────────────────────────────────────────
mkdir -p "${LOG_DIR}"
_log() {
local level="${1}"
local msg="${2}"
local ts
ts="$(date '+%Y-%m-%d %H:%M:%S')"
printf '[%s] [%s] %s\n' "${ts}" "${level}" "${msg}" | tee -a "${LOG_FILE}"
}
log_info() { _log "INFO " "${1}"; }
log_warn() { _log "WARN " "${1}" >&2; }
log_error() { _log "ERROR" "${1}" >&2; }
# ── Pre-flight checks ────────────────────────────────────────────────────
if [[ "${EUID}" -eq 0 ]]; then
log_error "Do not run this script directly as root — it invokes sudo"
log_error "only for the specific steps that need it."
exit 1
fi
if ! [[ "${KEEP_COUNT}" =~ ^[0-9]+$ ]] || [[ "${KEEP_COUNT}" -lt 1 ]]; then
log_error "keep-count must be a positive integer. Got: ${KEEP_COUNT}"
exit 1
fi
CURRENT_TAG=""
if [[ -L "${CURRENT_LINK}" ]]; then
CURRENT_TAG="$(basename "$(readlink -f "${CURRENT_LINK}")")"
fi
# ── Build the candidate list (oldest first, by directory mtime) ─────────
mapfile -t ALL_RELEASES < <(ls -1t "${RELEASES_DIR}" 2>/dev/null | tac)
TOTAL="${#ALL_RELEASES[@]}"
if [[ "${TOTAL}" -le "${KEEP_COUNT}" ]]; then
log_info "Only ${TOTAL} release(s) present, keep-count is ${KEEP_COUNT} — nothing to prune."
exit 0
fi
PRUNE_COUNT=$((TOTAL - KEEP_COUNT))
TO_PRUNE=("${ALL_RELEASES[@]:0:${PRUNE_COUNT}}")
# Never prune the currently live release, even if it's old — pull it out
# of the candidate list and log that it's being kept for that reason.
FILTERED_PRUNE=()
for tag in "${TO_PRUNE[@]}"; do
if [[ "${tag}" == "${CURRENT_TAG}" ]]; then
log_warn "Skipping ${tag} — it is the currently live release."
continue
fi
FILTERED_PRUNE+=("${tag}")
done
if [[ "${#FILTERED_PRUNE[@]}" -eq 0 ]]; then
log_info "Nothing eligible to prune after excluding the live release."
exit 0
fi
# ── Confirmation ─────────────────────────────────────────────────────────
printf '\nCurrently live release: %s (never pruned)\n' "${CURRENT_TAG:-none}"
printf 'Keeping the %d most recent releases.\n' "${KEEP_COUNT}"
printf '\nThe following %d release(s) and their matching snapshots will be removed:\n' \
"${#FILTERED_PRUNE[@]}"
for tag in "${FILTERED_PRUNE[@]}"; do
printf ' - %s\n' "${tag}"
done
printf '\nProceed? [y/N] '
read -r response
case "${response}" in
[yY]|[yY][eE][sS]) ;;
*) log_info "Aborted by user."; exit 0 ;;
esac
# ── Prune ────────────────────────────────────────────────────────────────
for tag in "${FILTERED_PRUNE[@]}"; do
log_info "Removing release directory: ${RELEASES_DIR}/${tag}"
if ! sudo rm -rf "${RELEASES_DIR:?}/${tag}" >>"${LOG_FILE}" 2>&1; then
log_error "Failed to remove ${RELEASES_DIR}/${tag} — leaving it in place."
continue
fi
# Snapshots are named pre-<tag>-<date> — match by tag prefix.
for snap in "${SNAPSHOT_DIR}"/pre-"${tag}"-*; do
[[ -e "${snap}" ]] || continue
log_info "Removing matching snapshot: ${snap}"
if ! sudo btrfs subvolume delete "${snap}" >>"${LOG_FILE}" 2>&1; then
log_error "Failed to remove snapshot ${snap} — leaving it in place."
fi
done
done
log_info "Prune complete. Kept ${KEEP_COUNT} most recent release(s) plus the live one if older."

View file

@ -0,0 +1,146 @@
#!/usr/bin/env bash
# Built standing on the shoulders of billions of dwarves
# Created by John A. Hoeven with the ethical assistance of Claude AI
# Licence: The Unlicense — https://unlicense.org
# ---------------------------------------------------------------------------
# llama-cpp-publish.sh
# /opt/llama-cpp/scripts/llama-cpp-publish.sh
# Version: v0.0.1 | Status: DEVELOPMENT
# Role: Orchestrator
# ---------------------------------------------------------------------------
# Purpose: Push a llama.cpp tag that has already been built, validated, and
# promoted live on BigBoy onward to the CE Forgejo mirror. This is
# the vetting gate: client deployments clone the Forgejo mirror,
# never GitHub directly, so they only ever see tags BigBoy has
# already proven work on real hardware.
#
# This publishes SOURCE ONLY, not a compiled binary. Client
# hardware varies (GPU architecture, or CPU-only) — each client
# still builds locally from this tag with their own
# CMAKE_CUDA_ARCHITECTURES. "Validated on BigBoy" means the
# pinned source at this tag builds clean and behaves correctly
# on real hardware once — it does not mean the binary is portable.
#
# Target: BigBoy — AlmaLinux 10.2
# Entry: ./llama-cpp-publish.sh <build-tag>
# e.g. ./llama-cpp-publish.sh b9985
# Refuses to run unless <build-tag> is the currently LIVE release
# (i.e. you promoted it first) — publishing is the last step,
# not a shortcut around validation.
# Depends: git, network access to FORGEJO_MIRROR_URL
# Note: Shallow-cloned tags push fine to Forgejo for content purposes;
# `git log` on the mirror will show truncated history for that
# tag. This is cosmetic — the tree/blob content is complete.
# ---------------------------------------------------------------------------
# No 'set -e' — every operation is checked explicitly (CE OS standard §1.8).
# ── Configuration ────────────────────────────────────────────────────────
LLAMA_ROOT="/opt/llama-cpp"
RELEASES_DIR="${LLAMA_ROOT}/releases"
CURRENT_LINK="${LLAMA_ROOT}/current"
UPSTREAM_URL="https://github.com/ggml-org/llama.cpp"
# TODO: confirm this path matches the actual repo you create on Forgejo.
FORGEJO_MIRROR_URL="https://git.jhoeven.net/ceos/llama.cpp-vetted.git"
LOG_DIR="${HOME}/.local/logs/bigboy-llama-update"
LOG_FILE="${LOG_DIR}/publish-$(date '+%Y-%m-%d_%H%M%S').log"
BUILD_TAG="${1:-}"
# ── Logging ──────────────────────────────────────────────────────────────
mkdir -p "${LOG_DIR}"
_log() {
local level="${1}"
local msg="${2}"
local ts
ts="$(date '+%Y-%m-%d %H:%M:%S')"
printf '[%s] [%s] %s\n' "${ts}" "${level}" "${msg}" | tee -a "${LOG_FILE}"
}
log_info() { _log "INFO " "${1}"; }
log_warn() { _log "WARN " "${1}" >&2; }
log_error() { _log "ERROR" "${1}" >&2; }
# ── Cleanup ──────────────────────────────────────────────────────────────
PUBLISH_TMP=""
cleanup() {
if [[ -n "${PUBLISH_TMP}" && -d "${PUBLISH_TMP}" ]]; then
rm -rf "${PUBLISH_TMP}"
fi
log_info "Run finished. Log: ${LOG_FILE}"
}
trap cleanup EXIT INT TERM HUP
# ── Pre-flight checks ────────────────────────────────────────────────────
if [[ -z "${BUILD_TAG}" ]]; then
log_error "Usage: ${0} <build-tag>"
exit 1
fi
if [[ ! -d "${RELEASES_DIR}/${BUILD_TAG}" ]]; then
log_error "No staged release found for ${BUILD_TAG} at ${RELEASES_DIR}/${BUILD_TAG}"
exit 1
fi
CURRENT_TAG=""
if [[ -L "${CURRENT_LINK}" ]]; then
CURRENT_TAG="$(basename "$(readlink -f "${CURRENT_LINK}")")"
fi
if [[ "${CURRENT_TAG}" != "${BUILD_TAG}" ]]; then
log_error "${BUILD_TAG} is not the currently live release (live is: ${CURRENT_TAG:-none})."
log_error "Publish is the LAST step — promote it with llama-cpp-promote.sh first,"
log_error "and let it run long enough to confirm it's actually good before publishing."
exit 1
fi
# ── Confirmation ─────────────────────────────────────────────────────────
printf '\nThis will push tag %s to:\n %s\n' "${BUILD_TAG}" "${FORGEJO_MIRROR_URL}"
printf 'This makes it available to client deployments that clone from Forgejo.\n'
printf 'Confirm %s has been running live on BigBoy long enough to trust it.\n' "${BUILD_TAG}"
printf '\nProceed? [y/N] '
read -r response
case "${response}" in
[yY]|[yY][eE][sS]) ;;
*) log_info "Aborted by user."; exit 0 ;;
esac
# ── Push the tag (source only) to the Forgejo mirror ─────────────────────
PUBLISH_TMP="$(mktemp -d)"
log_info "Preparing tag ${BUILD_TAG} for publish via ${PUBLISH_TMP}"
if ! git clone --quiet --depth 1 --branch "${BUILD_TAG}" \
"${UPSTREAM_URL}" "${PUBLISH_TMP}/repo" >>"${LOG_FILE}" 2>&1; then
log_error "Could not re-fetch ${BUILD_TAG} from upstream for publishing."
exit 1
fi
if ! (cd "${PUBLISH_TMP}/repo" && git remote add forgejo-mirror "${FORGEJO_MIRROR_URL}") \
>>"${LOG_FILE}" 2>&1; then
log_error "Failed to add Forgejo remote."
exit 1
fi
log_info "Pushing ${BUILD_TAG} to Forgejo mirror"
if ! (cd "${PUBLISH_TMP}/repo" && git push forgejo-mirror "${BUILD_TAG}") \
>>"${LOG_FILE}" 2>&1; then
log_error "Push failed. Confirm the Forgejo repo exists at:"
log_error " ${FORGEJO_MIRROR_URL}"
log_error "and that this machine has push credentials configured."
exit 1
fi
log_info "Published: ${BUILD_TAG} is now available on the Forgejo mirror."
log_info "Client deployments cloning ${FORGEJO_MIRROR_URL} can now build this tag."
log_info ""
log_info "Reminder: this is source only. Each client still builds locally"
log_info "with CMAKE_CUDA_ARCHITECTURES matching their own hardware."

View file

@ -0,0 +1,175 @@
#!/usr/bin/env bash
# Built standing on the shoulders of billions of dwarves
# Created by John A. Hoeven with the ethical assistance of Claude AI
# Licence: The Unlicense — https://unlicense.org
# ---------------------------------------------------------------------------
# llama-cpp-update.sh
# /opt/llama-cpp/scripts/llama-cpp-update.sh
# Version: v0.0.1 | Status: DEVELOPMENT
# Role: Orchestrator
# ---------------------------------------------------------------------------
# Purpose: Build and stage a new pinned llama.cpp release on BigBoy, behind
# a btrfs snapshot safety net and a versioned-symlink release
# layout. Does NOT promote the new build automatically — that is
# a separate, deliberate step (see llama-cpp-promote.sh) taken
# only after Phase 12-style validation passes.
# Target: BigBoy — AlmaLinux 10.2, @llama-cpp btrfs subvolume at
# /opt/llama-cpp, NVIDIA RTX 5060 Ti (sm_120)
# Entry: sudo ./llama-cpp-update.sh <build-tag>
# e.g. sudo ./llama-cpp-update.sh b9985
# Depends: git, cmake, gcc, nvcc (CUDA toolkit), btrfs-progs
# Note: This is a standalone ops script for one Alma server, not part
# of the CEOS multi-distro installer framework — so it does not
# use ce_env.conf / pkg_* / CE_PRIV. Privilege is via sudo
# directly, detected explicitly below rather than assumed.
# ---------------------------------------------------------------------------
# No 'set -e' — every operation is checked explicitly (CE OS standard §1.8).
# ── Configuration ────────────────────────────────────────────────────────
LLAMA_ROOT="/opt/llama-cpp"
RELEASES_DIR="${LLAMA_ROOT}/releases"
SNAPSHOT_DIR="/opt/.snapshots/llama-cpp"
REPO_URL="https://github.com/ggml-org/llama.cpp"
CUDA_ARCH="120" # RTX 5060 Ti — Blackwell sm_120
LOG_DIR="${HOME}/.local/logs/bigboy-llama-update"
LOG_FILE="${LOG_DIR}/update-$(date '+%Y-%m-%d_%H%M%S').log"
BUILD_TAG="${1:-}"
# ── Logging ──────────────────────────────────────────────────────────────
mkdir -p "${LOG_DIR}"
_log() {
local level="${1}"
local msg="${2}"
local ts
ts="$(date '+%Y-%m-%d %H:%M:%S')"
printf '[%s] [%s] %s\n' "${ts}" "${level}" "${msg}" | tee -a "${LOG_FILE}"
}
log_info() { _log "INFO " "${1}"; }
log_warn() { _log "WARN " "${1}" >&2; }
log_error() { _log "ERROR" "${1}" >&2; }
# ── Cleanup ──────────────────────────────────────────────────────────────
BUILD_TMP=""
cleanup() {
local exit_code="${?}"
if [[ -n "${BUILD_TMP}" && -d "${BUILD_TMP}" && "${exit_code}" -ne 0 ]]; then
log_warn "Non-zero exit — leaving ${BUILD_TMP} in place for inspection."
log_warn "Remove it manually once reviewed: rm -rf ${BUILD_TMP}"
fi
log_info "Run finished. Log: ${LOG_FILE}"
}
trap cleanup EXIT INT TERM HUP
# ── Pre-flight checks ────────────────────────────────────────────────────
if [[ "${EUID}" -eq 0 ]]; then
log_error "Do not run this script directly as root. Run as your normal"
log_error "user; it will invoke sudo only for the specific steps that need it."
exit 1
fi
if [[ -z "${BUILD_TAG}" ]]; then
log_error "Usage: ${0} <build-tag> e.g. ${0} b9985"
log_error "Check https://github.com/ggml-org/llama.cpp/releases for current tags."
exit 1
fi
if [[ -d "${RELEASES_DIR}/${BUILD_TAG}" ]]; then
log_error "Release ${BUILD_TAG} already exists at ${RELEASES_DIR}/${BUILD_TAG}"
log_error "Remove it first if you intend to rebuild this tag."
exit 1
fi
for tool in git cmake nvcc; do
if ! command -v "${tool}" >/dev/null 2>&1; then
log_error "Required tool not found: ${tool}"
exit 1
fi
done
# ── Confirmation ─────────────────────────────────────────────────────────
printf '\nAbout to build llama.cpp %s into %s\n' "${BUILD_TAG}" "${RELEASES_DIR}/${BUILD_TAG}"
printf 'A btrfs snapshot of %s will be taken first.\n' "${LLAMA_ROOT}"
printf 'This will NOT restart the live service — that is a separate promote step.\n'
printf '\nProceed? [y/N] '
read -r response
case "${response}" in
[yY]|[yY][eE][sS]) ;;
*) log_info "Aborted by user."; exit 0 ;;
esac
# ── Step 1: btrfs snapshot (safety net) ──────────────────────────────────
mkdir -p "${SNAPSHOT_DIR}"
SNAPSHOT_PATH="${SNAPSHOT_DIR}/pre-${BUILD_TAG}-$(date '+%Y%m%d')"
log_info "Taking btrfs snapshot: ${SNAPSHOT_PATH}"
if ! sudo btrfs subvolume snapshot -r "${LLAMA_ROOT}" "${SNAPSHOT_PATH}" \
>>"${LOG_FILE}" 2>&1; then
log_error "Snapshot failed. Aborting before touching anything else."
exit 1
fi
log_info "Snapshot confirmed at ${SNAPSHOT_PATH}"
# ── Step 2: clone and checkout pinned tag ────────────────────────────────
BUILD_TMP="$(mktemp -d)"
log_info "Cloning llama.cpp (shallow, tag-only) into ${BUILD_TMP}"
# Shallow clone directly at the target tag — we only ever need this one
# pinned commit, not full history. Cuts clone size roughly in half versus
# a full clone + checkout, which matters once you're keeping many releases.
if ! git clone --quiet --depth 1 --branch "${BUILD_TAG}" \
"${REPO_URL}" "${BUILD_TMP}/llama.cpp" >>"${LOG_FILE}" 2>&1; then
log_error "Shallow clone of tag ${BUILD_TAG} failed."
log_error "Confirm the tag exists upstream: ${REPO_URL}/releases"
exit 1
fi
# ── Step 3: build (standard flags only — no exotic tuning, see notes) ────
log_info "Configuring CMake build (CUDA, sm_${CUDA_ARCH}, Release)"
if ! (cd "${BUILD_TMP}/llama.cpp" && cmake -B build \
-DGGML_CUDA=ON \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_CUDA_ARCHITECTURES="${CUDA_ARCH}") >>"${LOG_FILE}" 2>&1; then
log_error "CMake configure failed. See ${LOG_FILE} for details."
exit 1
fi
log_info "Building — this takes a while, watch ${LOG_FILE} for progress"
if ! (cd "${BUILD_TMP}/llama.cpp" && cmake --build build --config Release -j) \
>>"${LOG_FILE}" 2>&1; then
log_error "Build failed. See ${LOG_FILE} for details."
log_error "Known issue: MXFP4 quant kernels can fail to compile on sm_120."
log_error "This build does not require MXFP4 — check for unrelated errors first."
exit 1
fi
if [[ ! -x "${BUILD_TMP}/llama.cpp/build/bin/llama-server" ]]; then
log_error "Build reported success but llama-server binary is missing. Aborting."
exit 1
fi
# ── Step 4: stage into versioned release directory ──────────────────────
log_info "Staging build into ${RELEASES_DIR}/${BUILD_TAG}"
sudo mkdir -p "${RELEASES_DIR}"
if ! sudo cp -a "${BUILD_TMP}/llama.cpp" "${RELEASES_DIR}/${BUILD_TAG}" \
>>"${LOG_FILE}" 2>&1; then
log_error "Failed to stage build into ${RELEASES_DIR}/${BUILD_TAG}"
exit 1
fi
log_info "Build ${BUILD_TAG} staged successfully."
log_info "Current live release is untouched — 'current' symlink not modified."
log_info "Next step: run Phase 12 validation against this build, then:"
log_info " sudo ./llama-cpp-promote.sh ${BUILD_TAG}"