feat(build): enforce clean repos on release builds — gate now covers iso/colibri/zot

This commit is contained in:
Sam & Claude 2026-06-15 16:47:38 +02:00
parent 67b6477119
commit 96fc1d3879

View file

@ -102,14 +102,7 @@ if [ -n "${SSH_PUBLIC_KEY:-}" ]; then
fi
if [ "${BUILD_CHANNEL}" = "release" ]; then
case "${CLAWDIE_REF}" in
v[0-9]*.[0-9]*.[0-9]*) ;;
*)
echo "ERROR: release builds must pin a Clawdie-AI tag with --clawdie-version X.Y.Z"
echo " Current Clawdie ref: ${CLAWDIE_REF}"
exit 1
;;
esac
check_release_gate
fi
# The ISO carries its own product version (ISO_VERSION in build.cfg). It does not
@ -467,6 +460,69 @@ is_pinned_clawdie_ref() {
printf '%s' "$_ref" | grep -Eq '^[0-9a-fA-F]{40}$|^v[0-9]+\.[0-9]+\.[0-9]+$'
}
# Release builds require clean, committed sources across the whole stack.
# A release ISO must be a reproducible artifact — no uncommitted local patches.
check_release_gate() {
case "${CLAWDIE_REF}" in
v[0-9]*.[0-9]*.[0-9]*) ;;
*)
echo "ERROR: release builds must pin a Clawdie-AI tag with --clawdie-version X.Y.Z"
echo " Current Clawdie ref: ${CLAWDIE_REF}"
exit 1
;;
esac
_release_errors=0
# Clawdie-AI local checkout
resolve_clawdie_ai_repo
if command -v git >/dev/null 2>&1 && git -C "${_resolved_clawdie_ai_repo}" rev-parse --git-dir >/dev/null 2>&1; then
if ! git -C "${_resolved_clawdie_ai_repo}" diff --quiet 2>/dev/null || ! git -C "${_resolved_clawdie_ai_repo}" diff --cached --quiet 2>/dev/null; then
echo "ERROR: release builds require a clean clawdie-ai repo"
echo " Uncommitted changes detected in: ${_resolved_clawdie_ai_repo}"
_release_errors=$((_release_errors + 1))
fi
fi
# ISO repo itself
if command -v git >/dev/null 2>&1 && git -C "${SCRIPT_DIR}" rev-parse --git-dir >/dev/null 2>&1; then
if ! git -C "${SCRIPT_DIR}" diff --quiet 2>/dev/null || ! git -C "${SCRIPT_DIR}" diff --cached --quiet 2>/dev/null; then
echo "ERROR: release builds require a clean clawdie-iso repo"
echo " Uncommitted changes detected in: ${SCRIPT_DIR}"
_release_errors=$((_release_errors + 1))
fi
fi
# Colibri
if [ "${FEATURE_COLIBRI:-NO}" = "YES" ]; then
resolve_colibri_paths
if command -v git >/dev/null 2>&1 && git -C "${_resolved_colibri_repo}" rev-parse --git-dir >/dev/null 2>&1; then
if ! git -C "${_resolved_colibri_repo}" diff --quiet 2>/dev/null || ! git -C "${_resolved_colibri_repo}" diff --cached --quiet 2>/dev/null; then
echo "ERROR: release builds require a clean colibri repo"
echo " Uncommitted changes detected in: ${_resolved_colibri_repo}"
_release_errors=$((_release_errors + 1))
fi
fi
# Zot (agent binary)
if [ "${COLIBRI_STAGE_AGENT:-YES}" = "YES" ]; then
resolve_zot_paths
if command -v git >/dev/null 2>&1 && git -C "${_resolved_zot_repo}" rev-parse --git-dir >/dev/null 2>&1; then
if ! git -C "${_resolved_zot_repo}" diff --quiet 2>/dev/null || ! git -C "${_resolved_zot_repo}" diff --cached --quiet 2>/dev/null; then
echo "ERROR: release builds require a clean zot repo"
echo " Uncommitted changes detected in: ${_resolved_zot_repo}"
_release_errors=$((_release_errors + 1))
fi
fi
fi
fi
if [ "${_release_errors}" -gt 0 ]; then
echo "ERROR: release build aborted — ${_release_errors} dirty repo(s). Use BUILD_CHANNEL=dev for iteration builds."
exit 1
fi
}
write_build_manifest() {
_manifest_path="$1"
_iso_repo_commit="unknown"
@ -500,6 +556,19 @@ write_build_manifest() {
fi
fi
fi
# Zot provenance (agent binary built from source — record if repo is dirty).
_zot_dirty="null"
if [ "${FEATURE_COLIBRI:-NO}" = "YES" ] && [ "${COLIBRI_STAGE_AGENT:-YES}" = "YES" ]; then
resolve_zot_paths
if command -v git >/dev/null 2>&1 && git -C "${_resolved_zot_repo}" rev-parse --git-dir >/dev/null 2>&1; then
if git -C "${_resolved_zot_repo}" diff --quiet 2>/dev/null && \
git -C "${_resolved_zot_repo}" diff --cached --quiet 2>/dev/null; then
_zot_dirty="false"
else
_zot_dirty="true"
fi
fi
fi
mkdir -p "$(dirname "$_manifest_path")"
cat > "$_manifest_path" <<EOF
{
@ -507,6 +576,7 @@ write_build_manifest() {
"version_scheme": "product",
"zot_version": "$(json_escape "${ZOT_RESOLVED_VERSION:-${ZOT_VERSION}}")",
"zot_commit": "$(json_escape "${ZOT_RESOLVED_COMMIT:-unknown}")",
"zot_dirty": ${_zot_dirty:-null},
"colibri_commit": "$(json_escape "${_colibri_commit:-unknown}")",
"colibri_dirty": ${_colibri_dirty:-null},
"build_channel": "$(json_escape "${BUILD_CHANNEL}")",