jcbtc's picture
Harden installer retries and validate release archive
f504162 verified
Raw
History Blame Contribute Delete
10.8 kB
#!/usr/bin/env bash
set -Eeuo pipefail
script_dir="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
release_name=Ling-3.0-Flash-CIRU-int4-Strix-native
export PATH="$HOME/.local/bin:$PATH"
usage() {
cat <<EOF
Install the CIRU Ling 3.0 Flash gfx1151 runtime.
Human-guided install:
bash install.sh --interactive
Non-interactive install for agents and automation:
bash install.sh --install-root PATH --model-path PATH [OPTIONS]
Engine-only upgrade of an existing installation:
bash install.sh --upgrade --install-root PATH
Options:
--interactive Ask for paths and optional actions.
--install-root PATH Runtime root; defaults to the current directory.
The vLLM environment is created at PATH/.venv.
PATH cannot contain whitespace or a colon because
the ROCr override is loaded through LD_PRELOAD.
--model-path PATH Exact checkpoint directory; defaults to
./Ling-3.0-Flash-CIRU-int4-Strix-native.
--install-host-deps Run scripts/install-host-deps.sh (may use sudo).
--download-model Download the pinned checkpoint from this repository
to MODEL_PATH. Without this flag, a missing model does
not block the runtime installation.
The checkpoint is approximately 77 GB.
--upgrade Upgrade only the CIRU engine in an existing runtime.
Model weights and ling3-runtime.env are not touched.
--skip-build Validate/configure an already-built runtime.
--dry-run Print the commands and resolved paths without running them.
--print-env Print launch exports for the resolved paths and exit.
-h, --help Show this help.
The installer writes PATH/ling3-runtime.env before downloads/builds. Agents can use:
source PATH/ling3-runtime.env
bash scripts/run-256k.sh
Environment variables can always be supplied directly:
VENV=PATH/.venv MODEL_PATH=MODEL_PATH bash scripts/run-256k.sh
EOF
}
die() {
printf 'install.sh: %s\n' "$*" >&2
exit 2
}
absolute_path() {
local path="$1"
case "$path" in
'~') path="$HOME" ;;
[~]/*) path="$HOME/${path#\~/}" ;;
'$HOME') path="$HOME" ;;
'$HOME/'*) path="$HOME/${path#\$HOME/}" ;;
'${HOME}') path="$HOME" ;;
'${HOME}/'*) path="$HOME/${path#\$\{HOME\}/}" ;;
'$PWD') path="$PWD" ;;
'$PWD/'*) path="$PWD/${path#\$PWD/}" ;;
'${PWD}') path="$PWD" ;;
'${PWD}/'*) path="$PWD/${path#\$\{PWD\}/}" ;;
esac
case "$path" in
*'$'*) die "unexpanded shell variable in path: $path" ;;
esac
if command -v realpath >/dev/null 2>&1; then
realpath -m -- "$path"
elif [[ "$path" = /* ]]; then
printf '%s\n' "$path"
else
printf '%s/%s\n' "$PWD" "${path#./}"
fi
}
write_runtime_env() {
local temporary_file="$env_file.tmp.$$"
mkdir -p "$install_root"
{
printf '# Generated by %s/install.sh\n' "$script_dir"
printf 'export VENV=%q\n' "$venv"
printf 'export MODEL_PATH=%q\n' "$model_path"
} >"$temporary_file"
mv -f -- "$temporary_file" "$env_file"
}
prompt_value() {
local variable_name="$1"
local label="$2"
local default_value="$3"
local reply
read -r -p "$label [$default_value]: " reply
printf -v "$variable_name" '%s' "${reply:-$default_value}"
}
ask_yes_no() {
local label="$1"
local default_answer="$2"
local suffix reply
if [ "$default_answer" = yes ]; then
suffix='[Y/n]'
else
suffix='[y/N]'
fi
while true; do
read -r -p "$label $suffix: " reply
reply="${reply:-$default_answer}"
case "${reply,,}" in
y|yes) return 0 ;;
n|no) return 1 ;;
*) printf 'Please answer yes or no.\n' >&2 ;;
esac
done
}
interactive=0
install_root=
model_path=
install_host_deps=0
download_model=0
build_runtime=1
dry_run=0
print_env=0
upgrade=0
if [ "$#" -eq 0 ]; then
usage
exit 0
fi
while [ "$#" -gt 0 ]; do
case "$1" in
--interactive)
interactive=1
shift
;;
--install-root)
[ "$#" -ge 2 ] || die '--install-root requires a path'
[ -n "$2" ] || die '--install-root requires a non-empty path'
install_root="$2"
shift 2
;;
--model-path)
[ "$#" -ge 2 ] || die '--model-path requires a path'
[ -n "$2" ] || die '--model-path requires a non-empty path'
model_path="$2"
shift 2
;;
--install-host-deps)
install_host_deps=1
shift
;;
--download-model)
download_model=1
shift
;;
--upgrade)
upgrade=1
shift
;;
--skip-build)
build_runtime=0
shift
;;
--dry-run)
dry_run=1
shift
;;
--print-env)
print_env=1
shift
;;
-h|--help)
usage
exit 0
;;
*)
die "unknown option: $1"
;;
esac
done
if [ "$upgrade" = 1 ]; then
[ -z "$model_path" ] || die '--model-path is not used with --upgrade'
[ "$download_model" = 0 ] || die '--download-model is not used with --upgrade'
[ "$build_runtime" = 1 ] || die '--skip-build is not used with --upgrade'
[ "$print_env" = 0 ] || die '--print-env is not used with --upgrade'
fi
if [ "$interactive" = 1 ]; then
[ -t 0 ] || die '--interactive requires a terminal; use explicit flags for automation'
prompt_value install_root 'Runtime install directory' "${install_root:-$PWD}"
if [ "$upgrade" != 1 ]; then
prompt_value model_path 'Ling checkpoint directory' \
"${model_path:-$PWD/$release_name}"
fi
if ask_yes_no 'Run the distro host-dependency installer (may use sudo)?' no; then
install_host_deps=1
fi
if [ "$upgrade" != 1 ] && [ ! -f "$model_path/config.json" ]; then
if ask_yes_no 'Checkpoint not found there. Download it from this repository (~77 GB)?' no; then
download_model=1
fi
fi
fi
install_root="$(absolute_path "${install_root:-$PWD}")"
case "$install_root" in
*[[:space:]:]*)
die "install root cannot contain whitespace or ':' because ROCr is loaded through LD_PRELOAD: $install_root"
;;
esac
venv="$install_root/.venv"
env_file="$install_root/ling3-runtime.env"
if [ "$upgrade" != 1 ]; then
model_path="$(absolute_path "${model_path:-$PWD/$release_name}")"
fi
if [ "$print_env" = 1 ]; then
printf 'export VENV=%q\n' "$venv"
printf 'export MODEL_PATH=%q\n' "$model_path"
exit 0
fi
if [ "$upgrade" = 1 ]; then
printf 'CIRU Ling engine-only upgrade\n'
printf ' package: %s\n install root: %s\n venv: %s\n' \
"$script_dir" "$install_root" "$venv"
printf ' host dependencies: %s\n model files: preserved\n' "$install_host_deps"
else
printf 'CIRU Ling runtime installation\n'
printf ' package: %s\n install root: %s\n venv: %s\n model: %s\n' \
"$script_dir" "$install_root" "$venv" "$model_path"
printf ' host dependencies: %s\n download model: %s\n build runtime: %s\n' \
"$install_host_deps" "$download_model" "$build_runtime"
fi
if [ "$interactive" = 1 ] && ! ask_yes_no 'Continue with these settings?' yes; then
printf 'Installation cancelled.\n'
exit 0
fi
if [ "$dry_run" = 1 ]; then
if [ "$install_host_deps" = 1 ]; then
printf 'DRY RUN: bash %q\n' "$script_dir/scripts/install-host-deps.sh"
fi
if [ "$upgrade" = 1 ]; then
printf 'DRY RUN: validate %q and preserve model files/configuration\n' "$venv"
printf 'DRY RUN: bash %q %q\n' \
"$script_dir/scripts/install-rocr-idle-fix.sh" "$install_root"
exit 0
fi
if [ "$download_model" = 1 ]; then
printf 'DRY RUN: bash %q --model-path %q\n' \
"$script_dir/scripts/download-model.sh" "$model_path"
fi
if [ "$build_runtime" = 1 ]; then
printf 'DRY RUN: bash %q %q\n' \
"$script_dir/scripts/build-vllm-gfx1151.sh" "$install_root"
fi
printf 'DRY RUN: bash %q %q\n' \
"$script_dir/scripts/install-rocr-idle-fix.sh" "$install_root"
printf 'DRY RUN: write %q\n' "$env_file"
exit 0
fi
if [ "$upgrade" = 1 ]; then
[ -x "$venv/bin/python" ] || \
die "existing CIRU runtime is missing Python: $venv/bin/python"
[ -x "$venv/bin/vllm" ] || \
die "existing CIRU runtime is missing vLLM: $venv/bin/vllm"
if [ "$install_host_deps" = 1 ]; then
bash "$script_dir/scripts/install-host-deps.sh"
fi
bash "$script_dir/scripts/install-rocr-idle-fix.sh" "$install_root"
printf '\nEngine upgrade complete. Model files and ling3-runtime.env were unchanged.\n'
printf 'Restart the CIRU launcher or service to load the corrected ROCr runtime.\n'
printf 'Emergency rollback: set CIRU_DISABLE_ROCR_IDLE_FIX=1 before launching.\n'
exit 0
fi
# The environment file contains only resolved paths, so create it before any
# download or build. A failed dependency/build step must still leave users a
# correct, sourceable record of the intended runtime and model locations.
write_runtime_env
printf 'Prepared environment file: %s\n' "$env_file"
if [ "$download_model" != 1 ] && [ ! -f "$model_path/config.json" ]; then
printf 'Model download skipped; the runtime will be installed without weights.\n'
printf 'Expected future model path: %s\n' "$model_path"
fi
if [ "$install_host_deps" = 1 ]; then
bash "$script_dir/scripts/install-host-deps.sh"
fi
if [ "$download_model" = 1 ]; then
bash "$script_dir/scripts/download-model.sh" --model-path "$model_path"
fi
if [ "$build_runtime" = 1 ]; then
bash "$script_dir/scripts/build-vllm-gfx1151.sh" "$install_root"
fi
bash "$script_dir/scripts/install-rocr-idle-fix.sh" "$install_root"
[ -x "$venv/bin/python" ] || die "runtime Python is missing after installation: $venv/bin/python"
[ -x "$venv/bin/vllm" ] || die "vLLM launcher is missing after installation: $venv/bin/vllm"
if [ -f "$model_path/config.json" ]; then
model_ready=1
elif [ "$download_model" = 1 ]; then
die "model download completed without the expected config: $model_path/config.json"
else
model_ready=0
fi
printf '\nInstallation complete.\n'
printf 'Environment file: %s\n\n' "$env_file"
if [ "$model_ready" = 1 ]; then
printf 'Launch the native 256K profile:\n'
printf ' source %q\n bash %q\n\n' "$env_file" "$script_dir/scripts/run-256k.sh"
else
printf 'The optional model download was skipped. Download it later with:\n'
printf ' bash %q --model-path %q\n\n' \
"$script_dir/scripts/download-model.sh" "$model_path"
printf 'Then launch with:\n'
printf ' source %q\n bash %q\n\n' "$env_file" "$script_dir/scripts/run-256k.sh"
fi
printf 'For agents or automation:\n'
printf ' export VENV=%q\n export MODEL_PATH=%q\n' "$venv" "$model_path"
if [ "$model_ready" = 1 ]; then
printf ' bash %q\n' "$script_dir/scripts/run-256k.sh"
else
printf ' # Provide the checkpoint before running %q\n' "$script_dir/scripts/run-256k.sh"
fi