Files
AOS/.zscripts/python-runtime-build.sh

121 lines
4.1 KiB
Bash
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/bin/bash
set -euo pipefail
PROJECT_DIR="${PROJECT_DIR:-/home/z/my-project}"
BUILD_DIR="${BUILD_DIR:?BUILD_DIR is required}"
PYTHON_VERSION="${PYTHON_VERSION:-3.12}"
NEXT_DIST_DIR="$BUILD_DIR/next-service-dist"
PYTHON_RUNTIME_DIR="$BUILD_DIR/python-runtime"
PYTHON_PACKAGES_DIR="$PYTHON_RUNTIME_DIR/site-packages"
has_python_sources() {
find "$PROJECT_DIR" \
\( -type d \( -name '.git' \
-o -name '.next' \
-o -name '.venv' \
-o -name 'node_modules' \
-o -name '__pycache__' \
-o -name 'mini-services' \
-o -name 'upload' \
-o -name 'download' \
\) -prune \) \
-o -type f \( -name '*.py' -o -name '*.pyi' \) -print -quit | grep -q .
}
if ! has_python_sources \
&& [ ! -f "$PROJECT_DIR/requirements.txt" ] \
&& [ ! -f "$PROJECT_DIR/pyproject.toml" ]; then
echo "ℹ️ 未检测到 Python 源码或依赖清单,跳过 Python runtime 构建"
exit 0
fi
if ! command -v uv >/dev/null 2>&1; then
echo "❌ 检测到 Python 项目,但构建环境中没有 uv"
exit 1
fi
echo "🐍 检测到 Python runtime,目标版本: $PYTHON_VERSION"
mkdir -p "$NEXT_DIST_DIR" "$PYTHON_PACKAGES_DIR"
install_requirements() {
local requirements_file="$1"
local target_dir="${2:-$PYTHON_PACKAGES_DIR}"
if [ ! -s "$requirements_file" ]; then
echo "ℹ️ Python 依赖清单为空,跳过依赖安装"
return 0
fi
echo "📦 根据 $(basename "$requirements_file") 固化 Python 生产依赖..."
uv pip install \
--python "$PYTHON_VERSION" \
--target "$target_dir" \
--requirements "$requirements_file"
# --target 生成的 console scripts 会保留构建机 Python 的绝对 shebang。
# 改成 Runner 内可解析的 python,并由 start scripts 将该 bin 目录加入 PATH。
if [ -d "$target_dir/bin" ]; then
for script in "$target_dir"/bin/*; do
[ -f "$script" ] || continue
perl -0pi -e 's/\A#![^\n]*python[^\n]*\n/#!\/usr\/bin\/env python\n/' "$script"
done
fi
}
install_pyproject() {
local project_dir="$1"
local target_dir="$2"
local output_name="$3"
local requirements_file="$PYTHON_RUNTIME_DIR/$output_name"
if [ -f "$project_dir/uv.lock" ]; then
uv export \
--project "$project_dir" \
--frozen \
--no-dev \
--no-emit-project \
--format requirements.txt \
--output-file "$requirements_file"
else
uv pip compile \
"$project_dir/pyproject.toml" \
--python-version "$PYTHON_VERSION" \
--output-file "$requirements_file"
fi
install_requirements "$requirements_file" "$target_dir"
}
if [ -f "$PROJECT_DIR/pyproject.toml" ] && [ -f "$PROJECT_DIR/uv.lock" ]; then
echo "🔒 使用 pyproject.toml + uv.lock 导出生产依赖..."
install_pyproject "$PROJECT_DIR" "$PYTHON_PACKAGES_DIR" "requirements.lock.txt"
elif [ -f "$PROJECT_DIR/requirements.txt" ]; then
cp "$PROJECT_DIR/requirements.txt" "$PYTHON_RUNTIME_DIR/requirements.txt"
install_requirements "$PYTHON_RUNTIME_DIR/requirements.txt"
elif [ -f "$PROJECT_DIR/pyproject.toml" ]; then
echo "📦 pyproject.toml 未配套 uv.lock,解析生产依赖..."
install_pyproject "$PROJECT_DIR" "$PYTHON_PACKAGES_DIR" "requirements.txt"
else
echo "⚠️ 检测到 Python 源码,但没有 requirements.txt 或 pyproject.toml;仅支持 Python 标准库"
fi
if has_python_sources; then
echo "📄 复制 Python 源码到部署项目,保持相对路径..."
(
cd "$PROJECT_DIR"
find . \
\( -type d \( -name '.git' \
-o -name '.next' \
-o -name '.venv' \
-o -name 'node_modules' \
-o -name '__pycache__' \
-o -name 'mini-services' \
-o -name 'upload' \
-o -name 'download' \
\) -prune \) \
-o -type f \( -name '*.py' -o -name '*.pyi' \) -print0 \
| tar --null -T - -cf -
) | tar -C "$NEXT_DIST_DIR" -xf -
fi
echo "✅ Python runtime 已固化到部署产物"