build-hub.sh v1.24.0: refuse a stale or dirty tree (R-1021)
gates / gates (push) Successful in 6m44s

Fetch, pull --ff-only, then refuse unless clean and HEAD == origin/main; the
commit label is read after the pull. Test with a stub docker: 6 cases; the
old script gets 5 wrong. Evidence for the catalog gate unclean-boot-images.
This commit is contained in:
2026-10-14 19:11:17 +02:00
parent 8e7dce3211
commit 621783b3b0
7 changed files with 409 additions and 12 deletions
+33 -12
View File
@@ -19,10 +19,12 @@
# =============================================================================
set -euo pipefail
SCRIPT_VERSION="1.23.0"
SCRIPT_VERSION="1.24.0"
# --- Configuration (edit these if your paths differ) ---
REPO_DIR="/mnt/5_hdd/felhom.eu/git/felhom.eu"
# FELHOM_HUB_REPO_DIR builds from another clone (a session's own clean clone; the script's own test) — the same
# clean-tree rule applies to it.
REPO_DIR="${FELHOM_HUB_REPO_DIR:-/mnt/5_hdd/felhom.eu/git/felhom.eu}"
HUB_SRC="${REPO_DIR}/hub"
REGISTRY="gitea.dooplex.hu/admin"
IMAGE="${REGISTRY}/felhom-hub"
@@ -54,8 +56,35 @@ if ! command -v docker &>/dev/null; then
exit 1
fi
# Get git commit for build metadata
GIT_COMMIT=$(cd "${REPO_DIR}" && git rev-parse --short HEAD 2>/dev/null || echo "unknown")
# =========================================================================
# Step 1: the clean-tree gate (R-1021) — fetch, pull, and REFUSE a stale or dirty tree
# =========================================================================
# Until v1.24.0 a failed pull only warned and the commit was read BEFORE it: on 2026-10-14 the shared checkout was
# 44 commits behind, its pull aborted on untracked leftovers, and this script would have shipped old hub code under a
# new version label. An unpushed or stale change does not exist (workspace CLAUDE.md, „Clean-tree gate"). There is
# no override: no current runbook builds the hub from a dirty tree. Test: scripts/test_build_hub_tree_gate.sh.
step "1/3 — Pulling latest code (the tree must be clean and at origin/main)..."
cd "${REPO_DIR}"
refuse() {
error "$1"
error "Refusing to build from ${REPO_DIR}: the hub image must be built from a clean tree at origin/main."
error "Leftover files in the shared checkout move to /mnt/5_hdd/felhom.eu/leftovers/<date>/ (never deleted; R-1021),"
error "or build from your own clean clone: FELHOM_HUB_REPO_DIR=<clone> ./build.sh <VER> --push"
exit 1
}
DIRTY=$(git status --porcelain 2>&1) || refuse "git status failed: ${DIRTY}"
[[ -z "${DIRTY}" ]] || refuse "the tree is not clean:
${DIRTY}"
git fetch -q origin 2>/dev/null || refuse "git fetch failed (offline?) — origin/main cannot be checked"
git pull -q --ff-only 2>/dev/null || refuse "git pull --ff-only failed (local commits, or files in the way)"
DIRTY=$(git status --porcelain 2>&1) || refuse "git status failed: ${DIRTY}"
[[ -z "${DIRTY}" ]] || refuse "the tree is not clean after the pull:
${DIRTY}"
HEAD_SHA=$(git rev-parse HEAD) ; MAIN_SHA=$(git rev-parse origin/main)
[[ "${HEAD_SHA}" == "${MAIN_SHA}" ]] || refuse "HEAD ${HEAD_SHA:0:10} is not origin/main ${MAIN_SHA:0:10} (unpushed commits?)"
# Read AFTER the pull: the label names the commit that is built.
GIT_COMMIT=$(git rev-parse --short HEAD)
echo ""
info "╔══════════════════════════════════════╗"
@@ -68,14 +97,6 @@ info "Build: ${BUILD_DIR}"
info "Image: ${IMAGE}:${VERSION}"
echo ""
# =========================================================================
# Step 1: Pull latest code
# =========================================================================
step "1/3 — Pulling latest code..."
cd "${REPO_DIR}"
git pull --ff-only 2>/dev/null || warn "git pull failed (offline or dirty tree?)"
# =========================================================================
# Step 2: Sync source to build workspace
# =========================================================================