Compress the comment blocks across the clean-machine workflows and scripts. The explanations of why each check is written the way it is stay; the padding, restatement and duplication go. No code or workflow logic changes.
143 lines
6.4 KiB
Bash
Executable file
143 lines
6.4 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
# SPDX-License-Identifier: AGPL-3.0-only
|
|
# Copyright 2026-present the Unsloth AI Inc. team. All rights reserved.
|
|
#
|
|
# Assert the clean-machine contract after an install attempt.
|
|
#
|
|
# absent The toolchain really was absent for the whole run. Guards against a leg
|
|
# that "passed" only because masking silently failed, or because the
|
|
# installer quietly installed Xcode CLT behind our back.
|
|
# notools The trace recorded no compiler/git/brew invocation (trace mode).
|
|
# nobuild The wheels-only contract: no "Building wheel" from pip, no
|
|
# "Building <pkg>==<ver>" from uv. Needs UNSLOTH_VERBOSE=1, else
|
|
# run_install_cmd (install.sh:193-243) discards the uv output on success
|
|
# and there is nothing here to read.
|
|
#
|
|
# Usage: bash .github/scripts/clean-machine-assert.sh absent notools nobuild
|
|
set -uo pipefail
|
|
|
|
LOG="${INSTALL_LOG:-logs/install.log}"
|
|
TRACE="${UNSLOTH_TOOL_TRACE:-}"
|
|
rc=0
|
|
|
|
fail() { echo "::error::$*"; rc=1; }
|
|
ok() { echo "[assert] OK $*"; }
|
|
|
|
for check in "$@"; do
|
|
case "$check" in
|
|
|
|
absent)
|
|
# Deliberately NOT `command -v`: on a virgin Mac /usr/bin/{git,cc} EXIST as CLT
|
|
# stubs, so `command -v` succeeds and only RUNNING them fails ("xcrun: error:
|
|
# invalid active developer path"). The honest invariant is: must not WORK.
|
|
if xcode-select -p >/dev/null 2>&1; then
|
|
fail "xcode-select -p still resolves to $(xcode-select -p 2>/dev/null); not a clean Mac"
|
|
else
|
|
ok "xcode-select -p fails (the gate a virgin Mac hits)"
|
|
fi
|
|
for tool in git cc clang cmake; do
|
|
command -v "$tool" >/dev/null 2>&1 || { ok "$tool not on PATH"; continue; }
|
|
if "$tool" --version >/dev/null 2>&1; then
|
|
# On Intel runners /usr/bin/git is not CLT-provided and keeps working once
|
|
# the CLT are gone, so no masking can remove it. cc and clang do become
|
|
# stubs and the macOS consumer path needs no git, so report rather than
|
|
# call the simulation broken.
|
|
case " ${UNSLOTH_CLEAN_ALLOW_WORKING:-} " in
|
|
*" $tool "*)
|
|
echo "[assert] NOTE $tool still works ($(command -v "$tool")); allowed on this runner"
|
|
continue
|
|
;;
|
|
esac
|
|
fail "toolchain still usable: '$tool --version' succeeded ($(command -v "$tool")); masking failed"
|
|
else
|
|
ok "$tool present but non-functional (CLT stub), as on a clean Mac"
|
|
fi
|
|
done
|
|
# brew is a plain binary with no stub, so absence from PATH is the right test.
|
|
if command -v brew >/dev/null 2>&1; then
|
|
fail "Homebrew still on PATH at $(command -v brew); masking failed"
|
|
else
|
|
ok "brew absent"
|
|
fi
|
|
;;
|
|
|
|
notools)
|
|
if [ -z "$TRACE" ] || [ ! -f "$TRACE" ]; then
|
|
fail "notools requested but no trace file (\$UNSLOTH_TOOL_TRACE=$TRACE)"
|
|
else
|
|
# git is legitimate under --local (unsloth-zoo comes from a git URL), so that
|
|
# leg allow-lists it via UNSLOTH_ALLOW_TOOLS.
|
|
allow="${UNSLOTH_ALLOW_TOOLS:-}"
|
|
hits=""
|
|
while IFS=$'\t' read -r tool rest; do
|
|
[ -n "$tool" ] || continue
|
|
case " $allow " in *" $tool "*) continue ;; esac
|
|
# `xcode-select -p` only ASKS whether a toolchain is selected; the installer
|
|
# has to ask, and the point of the fix is that it carries on without one.
|
|
# Counting the question as toolchain USE would fail the very leg that proves
|
|
# the toolchain was never used. `--install`, which pops the CLT installer,
|
|
# stays a hit.
|
|
if [ "$tool" = "xcode-select" ]; then
|
|
case "$rest" in
|
|
-p|--print-path|-v|--version|"") continue ;;
|
|
esac
|
|
fi
|
|
hits="$hits $tool"
|
|
done < "$TRACE"
|
|
if [ -n "$hits" ]; then
|
|
fail "installer invoked toolchain:$(echo "$hits" | tr ' ' '\n' | sort -u | tr '\n' ' ')"
|
|
echo "---- tool trace ----"; sort -u "$TRACE" | head -50
|
|
else
|
|
ok "no compiler/git/brew invocation recorded"
|
|
fi
|
|
fi
|
|
;;
|
|
|
|
nobuild)
|
|
# "Built an sdist" is NOT "needed a compiler". Four packages on the macOS path
|
|
# are sdist-only PURE PYTHON (verified against cp313/macos-arm64):
|
|
# openai-whisper, argbind, randomname -- no version ever ships a wheel
|
|
# antlr4-python3-runtime==4.9.3 -- pinned below the 4.13.2 wheel
|
|
# Failing on those is a false alarm, so the contract is "nothing needing a
|
|
# COMPILER was built". UNSLOTH_ALLOW_SDIST extends the allowlist.
|
|
_allow="openai-whisper argbind randomname antlr4-python3-runtime ${UNSLOTH_ALLOW_SDIST:-}"
|
|
if [ ! -f "$LOG" ]; then
|
|
fail "nobuild requested but $LOG is missing"
|
|
else
|
|
# uv does NOT use pip's phrasing: it prints `Building <name>==<version>` to
|
|
# stderr (astral-sh/uv#11165), so the pip-only pattern left _built empty on
|
|
# every uv source build. Match both spellings. Requiring `==` or ` @ ` after
|
|
# the name keeps this off the installer's own lowercase "building frontend..."
|
|
# progress text. Strip ANSI first so a coloured run (FORCE_COLOR) parses.
|
|
_esc=$(printf '\033')
|
|
_built="$(sed -E "s/${_esc}\[[0-9;]*[A-Za-z]//g" "$LOG" 2>/dev/null \
|
|
| grep -oiE "building wheel for [a-z0-9._-]+|building [a-z0-9._-]+(==| @ )" \
|
|
| tr 'A-Z' 'a-z' \
|
|
| sed -E -e 's/^building wheel for //' -e 's/^building //' -e 's/(==| @ )$//' \
|
|
| sort -u || true)"
|
|
_bad=""
|
|
for pkg in $_built; do
|
|
case " $_allow " in *" $pkg "*) continue ;; esac
|
|
_bad="$_bad $pkg"
|
|
done
|
|
if [ -n "$_bad" ]; then
|
|
fail "built from source:$_bad -- these must resolve to wheels on a clean machine"
|
|
else
|
|
[ -n "$_built" ] && say_built="$(echo "$_built" | tr '\n' ' ')" || say_built="none"
|
|
ok "no non-allowlisted source build (built: $say_built)"
|
|
fi
|
|
# Independent of package names: a compiler error means a toolchain was needed.
|
|
if grep -qiE "error: command '(cc|gcc|clang|cl)' failed|no such file or directory: 'cc'|clang: error|cargo: not found|error: linker \`cc\` not found" "$LOG"; then
|
|
fail "compiler invocation appears in the install log"
|
|
grep -iE "error: command '(cc|gcc|clang|cl)' failed|clang: error" "$LOG" | head -10
|
|
fi
|
|
fi
|
|
;;
|
|
|
|
*)
|
|
fail "unknown check '$check'"
|
|
;;
|
|
esac
|
|
done
|
|
|
|
exit "$rc"
|