fix: improve stack build on venv

Added a pre_run_checks function to ensure a smooth environment setup by
verifying prerequisites. It checks for an existing virtual environment,
ensures uv is installed, and deactivates any active
environment if necessary.

Run the full build inside a venv created by 'uv'.

Improved string handling in printf statements and added
shellcheck suppressions for expected word splitting in pip
commands.

These enhancements improve robustness, prevent
conflicts, and ensure a seamless setup process.

Additionally, the `build_file_path` has been removed since it was not
used anywhere, the caller is also not passing it anymore.

Signed-off-by: Sébastien Han <seb@redhat.com>
This commit is contained in:
Sébastien Han 2025-02-06 10:25:36 +01:00
parent 418645696a
commit f49fe5b87b
No known key found for this signature in database
4 changed files with 51 additions and 16 deletions

View file

@ -56,9 +56,8 @@ class StackBuild(Subcommand):
"--image-name", "--image-name",
type=str, type=str,
help=textwrap.dedent( help=textwrap.dedent(
"""[for image-type=conda] Name of the conda environment to use for the build. If """[for image-type=conda|venv] Name of the conda or virtual environment to use for
not specified, currently active Conda environment will be used. If no Conda the build. If not specified, currently active Conda environment will be used if found.
environment is active, you must specify a name.
""" """
), ),
default=None, default=None,

View file

@ -130,7 +130,6 @@ def build_image(
args = [ args = [
script, script,
str(image_name), str(image_name),
str(build_file_path),
" ".join(normal_deps), " ".join(normal_deps),
] ]

View file

@ -24,23 +24,21 @@ if [ -n "$LLAMA_MODELS_DIR" ]; then
fi fi
if [ "$#" -lt 3 ]; then if [ "$#" -lt 3 ]; then
echo "Usage: $0 <distribution_type> <build_name> <build_file_path> <pip_dependencies> [<special_pip_deps>]" >&2 echo "Usage: $0 <distribution_type> <build_name> <pip_dependencies> [<special_pip_deps>]" >&2
echo "Example: $0 <distribution_type> mybuild ./my-stack-build.yaml 'numpy pandas scipy'" >&2 echo "Example: $0 <distribution_type> mybuild ./my-stack-build.yaml 'numpy pandas scipy'" >&2
exit 1 exit 1
fi fi
special_pip_deps="$4" special_pip_deps="$3"
set -euo pipefail set -euo pipefail
build_name="$1" build_name="$1"
env_name="llamastack-$build_name" env_name="llamastack-$build_name"
build_file_path="$2" pip_dependencies="$2"
pip_dependencies="$3"
# Define color codes # Define color codes
RED='\033[0;31m' RED='\033[0;31m'
GREEN='\033[0;32m'
NC='\033[0m' # No Color NC='\033[0m' # No Color
# this is set if we actually create a new conda in which case we need to clean up # this is set if we actually create a new conda in which case we need to clean up
@ -49,34 +47,63 @@ ENVNAME=""
SCRIPT_DIR=$(dirname "$(readlink -f "$0")") SCRIPT_DIR=$(dirname "$(readlink -f "$0")")
source "$SCRIPT_DIR/common.sh" source "$SCRIPT_DIR/common.sh"
# pre-run checks to make sure we can proceed with the installation
pre_run_checks() {
local env_name="$1"
if ! is_command_available uv; then
echo "uv is not installed, trying to install it."
if ! is_command_available pip; then
echo "pip is not installed, cannot automatically install 'uv'."
echo "Follow this link to install it:"
echo "https://docs.astral.sh/uv/getting-started/installation/"
exit 1
else
pip install uv
fi
fi
# checking if an environment with the same name already exists
if [ -d "$env_name" ]; then
echo "Environment '$env_name' already exists, re-using it."
fi
}
run() { run() {
local env_name="$1" local env_name="$1"
local pip_dependencies="$2" local pip_dependencies="$2"
local special_pip_deps="$3" local special_pip_deps="$3"
pip install uv echo "Using virtual environment $env_name"
uv venv "$env_name"
# shellcheck source=/dev/null
source "$env_name/bin/activate"
if [ -n "$TEST_PYPI_VERSION" ]; then if [ -n "$TEST_PYPI_VERSION" ]; then
# these packages are damaged in test-pypi, so install them first # these packages are damaged in test-pypi, so install them first
uv pip install fastapi libcst uv pip install fastapi libcst
# shellcheck disable=SC2086
# we are building a command line so word splitting is expected
uv pip install --extra-index-url https://test.pypi.org/simple/ \ uv pip install --extra-index-url https://test.pypi.org/simple/ \
llama-models==$TEST_PYPI_VERSION llama-stack==$TEST_PYPI_VERSION \ llama-models=="$TEST_PYPI_VERSION" llama-stack=="$TEST_PYPI_VERSION" \
$pip_dependencies $pip_dependencies
if [ -n "$special_pip_deps" ]; then if [ -n "$special_pip_deps" ]; then
IFS='#' read -ra parts <<<"$special_pip_deps" IFS='#' read -ra parts <<<"$special_pip_deps"
for part in "${parts[@]}"; do for part in "${parts[@]}"; do
echo "$part" echo "$part"
# shellcheck disable=SC2086
# we are building a command line so word splitting is expected
uv pip install $part uv pip install $part
done done
fi fi
else else
# Re-installing llama-stack in the new conda environment # Re-installing llama-stack in the new virtual environment
if [ -n "$LLAMA_STACK_DIR" ]; then if [ -n "$LLAMA_STACK_DIR" ]; then
if [ ! -d "$LLAMA_STACK_DIR" ]; then if [ ! -d "$LLAMA_STACK_DIR" ]; then
printf "${RED}Warning: LLAMA_STACK_DIR is set but directory does not exist: $LLAMA_STACK_DIR${NC}\n" >&2 printf "${RED}Warning: LLAMA_STACK_DIR is set but directory does not exist: %s${NC}\n" "$LLAMA_STACK_DIR" >&2
exit 1 exit 1
fi fi
printf "Installing from LLAMA_STACK_DIR: $LLAMA_STACK_DIR\n" printf "Installing from LLAMA_STACK_DIR: %s\n" "$LLAMA_STACK_DIR"
uv pip install --no-cache-dir -e "$LLAMA_STACK_DIR" uv pip install --no-cache-dir -e "$LLAMA_STACK_DIR"
else else
uv pip install --no-cache-dir llama-stack uv pip install --no-cache-dir llama-stack
@ -84,26 +111,31 @@ run() {
if [ -n "$LLAMA_MODELS_DIR" ]; then if [ -n "$LLAMA_MODELS_DIR" ]; then
if [ ! -d "$LLAMA_MODELS_DIR" ]; then if [ ! -d "$LLAMA_MODELS_DIR" ]; then
printf "${RED}Warning: LLAMA_MODELS_DIR is set but directory does not exist: $LLAMA_MODELS_DIR${NC}\n" >&2 printf "${RED}Warning: LLAMA_MODELS_DIR is set but directory does not exist: %s${NC}\n" "$LLAMA_MODELS_DIR" >&2
exit 1 exit 1
fi fi
printf "Installing from LLAMA_MODELS_DIR: $LLAMA_MODELS_DIR\n" printf "Installing from LLAMA_MODELS_DIR: %s\n" "$LLAMA_MODELS_DIR"
uv pip uninstall llama-models uv pip uninstall llama-models
uv pip install --no-cache-dir -e "$LLAMA_MODELS_DIR" uv pip install --no-cache-dir -e "$LLAMA_MODELS_DIR"
fi fi
# Install pip dependencies # Install pip dependencies
printf "Installing pip dependencies\n" printf "Installing pip dependencies\n"
# shellcheck disable=SC2086
# we are building a command line so word splitting is expected
uv pip install $pip_dependencies uv pip install $pip_dependencies
if [ -n "$special_pip_deps" ]; then if [ -n "$special_pip_deps" ]; then
IFS='#' read -ra parts <<<"$special_pip_deps" IFS='#' read -ra parts <<<"$special_pip_deps"
for part in "${parts[@]}"; do for part in "${parts[@]}"; do
echo "$part" echo "$part"
# shellcheck disable=SC2086
# we are building a command line so word splitting is expected
uv pip install $part uv pip install $part
done done
fi fi
fi fi
} }
pre_run_checks "$env_name"
run "$env_name" "$pip_dependencies" "$special_pip_deps" run "$env_name" "$pip_dependencies" "$special_pip_deps"

View file

@ -38,3 +38,8 @@ setup_cleanup_handlers() {
conda deactivate conda deactivate
} }
# check if a command is present
is_command_available() {
command -v "$1" &>/dev/null
}