feat(release): version live-image, skip rebuild+redownload when unchanged
Splits the release workflow into three jobs (detect, build-live-image, bundle) so the ~9 min mkosi build only runs when live-image/VERSION bumps. The slim bundle (~30 MB: orchestrator + agent + deploy scripts + a live-image/VERSION pointer) rebuilds every push; the ~300 MB vmlinuz+initrd.img are published separately under the immutable live-image/<version>/ path. install.sh compares the pointer to /var/lib/vetting/live/VERSION and fetches the files only on mismatch, cutting repeat-install wall-clock from ~30 s + 300 MB to ~10 s + 0 MB on the common no-live-image-change release. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
+86
-10
@@ -18,10 +18,15 @@
|
||||
# - Fetch TFTP iPXE payloads (that's pxe-setup.sh's job — it also
|
||||
# writes the pxe: block of vetting.yaml with first-time args).
|
||||
#
|
||||
# When a live-image/{vmlinuz,initrd.img} is present next to this script
|
||||
# (release bundle) or under ../live-image/build/ (repo checkout), it's
|
||||
# staged into --live-dir automatically. This makes the one-liner
|
||||
# upgrade loop work end-to-end for PXE-enabled installs.
|
||||
# Live-image staging has two modes:
|
||||
# - Release bundle (new format): the bundle carries only a
|
||||
# live-image/VERSION pointer. We compare it to ${LIVE_DIR}/VERSION
|
||||
# and, on mismatch, fetch vmlinuz+initrd.img from the Gitea
|
||||
# generic registry at live-image/<VERSION>/. Matched versions
|
||||
# skip the fetch (set FORCE_LIVE_IMAGE=1 to override).
|
||||
# - Repo checkout / legacy bundle: if vmlinuz+initrd.img are present
|
||||
# next to this script (${SCRIPT_DIR}/live-image/) or under
|
||||
# ${REPO_ROOT}/live-image/build/, they're copied straight in.
|
||||
#
|
||||
# Usage:
|
||||
# sudo ./install.sh [--binary PATH] [--config-dir /etc/vetting]
|
||||
@@ -165,6 +170,59 @@ heal_pxe_config() {
|
||||
mv "${tmp}" "${config}"
|
||||
}
|
||||
|
||||
# refresh_live_image: pull vmlinuz+initrd.img from the Gitea generic
|
||||
# package registry when the bundle's live-image/VERSION pointer differs
|
||||
# from ${LIVE_DIR}/VERSION. Skips the fetch when versions match unless
|
||||
# FORCE_LIVE_IMAGE=1 (useful when on-disk files got corrupted). Set by
|
||||
# proxmox-install.sh; on a direct `install.sh` invocation the caller
|
||||
# must export REGISTRY_URL (and optionally PACKAGE_OWNER).
|
||||
refresh_live_image() {
|
||||
local pointer="${SCRIPT_DIR}/live-image/VERSION"
|
||||
local bundle_ver
|
||||
bundle_ver="$(tr -d '[:space:]' < "${pointer}" 2>/dev/null || true)"
|
||||
if [[ -z "${bundle_ver}" ]]; then
|
||||
echo "WARN: bundle's ${pointer} is empty; skipping live-image fetch" >&2
|
||||
return 0
|
||||
fi
|
||||
|
||||
local installed_ver=""
|
||||
if [[ -f "${LIVE_DIR}/VERSION" ]]; then
|
||||
installed_ver="$(tr -d '[:space:]' < "${LIVE_DIR}/VERSION")"
|
||||
fi
|
||||
|
||||
if [[ "${bundle_ver}" == "${installed_ver}" && "${FORCE_LIVE_IMAGE:-0}" != "1" ]]; then
|
||||
echo "==> live-image already at ${bundle_ver}; skipping fetch (FORCE_LIVE_IMAGE=1 to redownload)"
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [[ -z "${REGISTRY_URL:-}" ]]; then
|
||||
echo "WARN: REGISTRY_URL is not set; cannot fetch live-image ${bundle_ver}. Re-run via proxmox-install.sh or export REGISTRY_URL." >&2
|
||||
return 0
|
||||
fi
|
||||
local owner="${PACKAGE_OWNER:-josh}"
|
||||
local base="${REGISTRY_URL%/}/api/packages/${owner}/generic/live-image/${bundle_ver}"
|
||||
|
||||
echo "==> fetching live-image ${bundle_ver} (was '${installed_ver:-none}') from ${base}"
|
||||
local tmp
|
||||
tmp="$(mktemp -d)"
|
||||
# shellcheck disable=SC2064
|
||||
trap "rm -rf '${tmp}'" RETURN
|
||||
|
||||
# Default curl meter shows rate + ETA, which matters for the ~300 MB
|
||||
# initrd on slow links.
|
||||
curl -fL -o "${tmp}/vmlinuz" "${base}/vmlinuz"
|
||||
curl -fL -o "${tmp}/initrd.img" "${base}/initrd.img"
|
||||
|
||||
install -d -m 0755 -o "${SERVICE_USER}" -g "${SERVICE_USER}" "${LIVE_DIR}"
|
||||
install -m 0644 -o "${SERVICE_USER}" -g "${SERVICE_USER}" \
|
||||
"${tmp}/vmlinuz" "${LIVE_DIR}/vmlinuz"
|
||||
install -m 0644 -o "${SERVICE_USER}" -g "${SERVICE_USER}" \
|
||||
"${tmp}/initrd.img" "${LIVE_DIR}/initrd.img"
|
||||
printf '%s\n' "${bundle_ver}" > "${LIVE_DIR}/VERSION"
|
||||
chown "${SERVICE_USER}:${SERVICE_USER}" "${LIVE_DIR}/VERSION"
|
||||
chmod 0644 "${LIVE_DIR}/VERSION"
|
||||
}
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
REPO_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"
|
||||
|
||||
@@ -244,12 +302,14 @@ if [[ -f "${SCRIPT_DIR}/pxe-setup.sh" && -f "${SCRIPT_DIR}/ipxe-shas.txt" ]]; th
|
||||
ln -sfn /usr/local/share/vetting/pxe-setup.sh /usr/local/sbin/vetting-pxe-setup
|
||||
fi
|
||||
|
||||
# Stage the live image into LIVE_DIR if we can find one. Two layouts:
|
||||
# - release bundle: ${SCRIPT_DIR}/live-image/{vmlinuz,initrd.img}
|
||||
# - repo-tree dev run: ${REPO_ROOT}/live-image/build/{vmlinuz,initrd.img}
|
||||
# Silently skipped when no source is found — operators without PXE
|
||||
# don't need it, and dev checkouts that haven't run `make live-image`
|
||||
# shouldn't fail the install.
|
||||
# Stage the live image into LIVE_DIR. Preference order:
|
||||
# 1. --live-image-src explicitly given, or local files found in the
|
||||
# bundle/repo — copy straight in (dev and legacy bundle layouts).
|
||||
# 2. Bundle carries only live-image/VERSION — fetch from the Gitea
|
||||
# generic registry when the pointer differs from ${LIVE_DIR}/VERSION.
|
||||
# 3. Neither — skip quietly (no-PXE installs don't need a live image,
|
||||
# and dev checkouts that haven't run `make live-image` shouldn't
|
||||
# fail the install).
|
||||
if [[ -z "${LIVE_IMAGE_SRC}" ]]; then
|
||||
for cand in \
|
||||
"${SCRIPT_DIR}/live-image" \
|
||||
@@ -268,6 +328,22 @@ if [[ -n "${LIVE_IMAGE_SRC}" ]]; then
|
||||
"${LIVE_IMAGE_SRC}/vmlinuz" "${LIVE_DIR}/vmlinuz"
|
||||
install -m 0644 -o "${SERVICE_USER}" -g "${SERVICE_USER}" \
|
||||
"${LIVE_IMAGE_SRC}/initrd.img" "${LIVE_DIR}/initrd.img"
|
||||
# Record the version that produced these files if the source has
|
||||
# one (bundle with legacy layout carrying VERSION alongside the
|
||||
# kernel; dev tree has live-image/VERSION at repo root). Lets a
|
||||
# future bundle-based install decide whether to refetch.
|
||||
for vcand in \
|
||||
"${LIVE_IMAGE_SRC}/VERSION" \
|
||||
"${SCRIPT_DIR}/live-image/VERSION" \
|
||||
"${REPO_ROOT}/live-image/VERSION"; do
|
||||
if [[ -f "${vcand}" ]]; then
|
||||
install -m 0644 -o "${SERVICE_USER}" -g "${SERVICE_USER}" \
|
||||
"${vcand}" "${LIVE_DIR}/VERSION"
|
||||
break
|
||||
fi
|
||||
done
|
||||
elif [[ -f "${SCRIPT_DIR}/live-image/VERSION" ]]; then
|
||||
refresh_live_image
|
||||
else
|
||||
echo "==> no live image found (bundle/live-image or ../live-image/build); skipping live-dir staging"
|
||||
fi
|
||||
|
||||
+42
-30
@@ -3,26 +3,42 @@
|
||||
# any Debian/Ubuntu host). Fetches a prebuilt release bundle from the
|
||||
# Gitea package registry, extracts it, and hands off to install.sh.
|
||||
#
|
||||
# The bundle itself is slim (~30 MB: orchestrator + agent + deploy
|
||||
# scripts + a live-image/VERSION pointer). install.sh compares that
|
||||
# pointer against /var/lib/vetting/live/VERSION and fetches the
|
||||
# ~300 MB vmlinuz+initrd.img from the registry only when they differ,
|
||||
# so repeated runs cost ~10 s on no-live-image-change releases.
|
||||
#
|
||||
# Usage:
|
||||
# curl -fsSL https://gitea.thewrightserver.net/josh/Vetting/raw/branch/main/deploy/proxmox-install.sh | sudo bash
|
||||
#
|
||||
# To pin a specific build instead of "latest":
|
||||
# VETTING_VERSION=sha-abc1234 curl -fsSL .../proxmox-install.sh | sudo bash
|
||||
#
|
||||
# Env overrides:
|
||||
# REGISTRY_URL base URL of the Gitea instance hosting the package
|
||||
# registry (default: https://gitea.thewrightserver.net)
|
||||
# PACKAGE_OWNER Gitea owner who owns the `vetting` package
|
||||
# (default: josh)
|
||||
# VETTING_VERSION package version — either "latest" (rolling) or
|
||||
# "sha-<short-sha>" (immutable). Default: "latest".
|
||||
# Flags / env overrides:
|
||||
# REGISTRY_URL base URL of the Gitea instance hosting the
|
||||
# package registry (default: https://gitea.thewrightserver.net)
|
||||
# PACKAGE_OWNER Gitea owner of the `vetting` package
|
||||
# (default: josh)
|
||||
# FORCE_LIVE_IMAGE=1 or --force-live-image — re-download the live
|
||||
# image even when the on-disk version matches
|
||||
# (useful when the local files got corrupted).
|
||||
set -euo pipefail
|
||||
|
||||
REGISTRY_URL="${REGISTRY_URL:-https://gitea.thewrightserver.net}"
|
||||
PACKAGE_OWNER="${PACKAGE_OWNER:-josh}"
|
||||
VETTING_VERSION="${VETTING_VERSION:-latest}"
|
||||
FORCE_LIVE_IMAGE="${FORCE_LIVE_IMAGE:-0}"
|
||||
|
||||
BUNDLE_URL="${REGISTRY_URL}/api/packages/${PACKAGE_OWNER}/generic/vetting/${VETTING_VERSION}/vetting-bundle.tar.gz"
|
||||
for arg in "$@"; do
|
||||
case "${arg}" in
|
||||
--force-live-image) FORCE_LIVE_IMAGE=1 ;;
|
||||
*) echo "unknown arg: ${arg}" >&2; exit 2 ;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Exported so install.sh (run as a child process inside the extracted
|
||||
# bundle dir) sees them when deciding whether to fetch the live image
|
||||
# and where to fetch it from.
|
||||
export REGISTRY_URL PACKAGE_OWNER FORCE_LIVE_IMAGE
|
||||
|
||||
BUNDLE_URL="${REGISTRY_URL}/api/packages/${PACKAGE_OWNER}/generic/vetting/latest/vetting-bundle.tar.gz"
|
||||
|
||||
if [[ $EUID -ne 0 ]]; then
|
||||
echo "proxmox-install.sh must be run as root (try: sudo bash)" >&2
|
||||
@@ -38,25 +54,22 @@ apt-get install -y --no-install-recommends \
|
||||
tmp="$(mktemp -d)"
|
||||
trap 'rm -rf "${tmp}"' EXIT
|
||||
|
||||
echo "==> fetching bundle (${VETTING_VERSION}) from ${BUNDLE_URL}"
|
||||
# Default curl meter (no -s, no --progress-bar) shows transfer rate
|
||||
# and ETA, which matters now that bundles are ~300 MB — the live
|
||||
# image ships the full firmware+rootfs, so a bare percentage bar
|
||||
# with no speed/ETA makes slow links look like hangs.
|
||||
# -f fails on HTTP errors; -L follows redirects.
|
||||
echo "==> fetching bundle from ${BUNDLE_URL}"
|
||||
# -f fails on HTTP errors; -L follows redirects. Default meter (rate +
|
||||
# ETA) is fine now that the bundle is ~30 MB.
|
||||
curl -fL "${BUNDLE_URL}" -o "${tmp}/vetting-bundle.tar.gz"
|
||||
|
||||
bundle_size="$(du -h "${tmp}/vetting-bundle.tar.gz" | cut -f1)"
|
||||
echo "==> extracting (${bundle_size})"
|
||||
tar -C "${tmp}" -xzf "${tmp}/vetting-bundle.tar.gz"
|
||||
|
||||
# Bundle extracts to vetting-bundle-<sha>/; glob-match the single
|
||||
# top-level directory.
|
||||
# New bundle extracts to vetting-bundle/; legacy bundles used
|
||||
# vetting-bundle-<sha>/. Match both so a downgrade-pin still works.
|
||||
shopt -s nullglob
|
||||
candidates=( "${tmp}"/vetting-bundle-* )
|
||||
candidates=( "${tmp}"/vetting-bundle "${tmp}"/vetting-bundle-* )
|
||||
shopt -u nullglob
|
||||
if [[ ${#candidates[@]} -ne 1 || ! -d "${candidates[0]}" ]]; then
|
||||
echo "unexpected bundle layout: expected exactly one vetting-bundle-*/ dir" >&2
|
||||
echo "unexpected bundle layout: expected exactly one vetting-bundle* dir" >&2
|
||||
exit 1
|
||||
fi
|
||||
bundle_dir="${candidates[0]}"
|
||||
@@ -67,17 +80,16 @@ bash install.sh \
|
||||
--binary "${bundle_dir}/bin/vetting-linux-amd64" \
|
||||
--agent-binary "${bundle_dir}/bin/vetting-agent.linux-amd64"
|
||||
|
||||
orch_ver="$(cat "${bundle_dir}/VERSION" 2>/dev/null || echo unknown)"
|
||||
li_ver="$(cat "${bundle_dir}/live-image/VERSION" 2>/dev/null || echo unknown)"
|
||||
|
||||
cat <<EOF
|
||||
|
||||
vetting is installed from bundle $(cat "${bundle_dir}/VERSION" 2>/dev/null || echo unknown).
|
||||
vetting installed: orchestrator ${orch_ver}, live-image ${li_ver}.
|
||||
|
||||
To upgrade later, just rerun this one-liner; it always pulls "latest"
|
||||
unless VETTING_VERSION is set.
|
||||
|
||||
To pin a specific build:
|
||||
VETTING_VERSION=sha-abc1234 curl -fsSL \\
|
||||
${REGISTRY_URL}/${PACKAGE_OWNER}/Vetting/raw/branch/main/deploy/proxmox-install.sh \\
|
||||
| sudo bash
|
||||
To upgrade later, rerun this one-liner. It always pulls the current
|
||||
latest bundle; the live image is re-downloaded only when its VERSION
|
||||
has bumped (override with --force-live-image).
|
||||
|
||||
For PXE support, run:
|
||||
sudo vetting-pxe-setup \\
|
||||
|
||||
Reference in New Issue
Block a user