feat(admin): integrate Next.js admin panel (admin-next/) from feat/nextjs-admin
- Add admin-next/: full Next.js + Prisma + shadcn admin panel (45 API routes, 76 components) - docker-compose: tg_shop_admin service (port 3000, shared db/shop.db, prisma), bot talks to it via ADMIN_CHAT_URL=http://tg_shop_admin:3000/api/chat - tor-proxy now proxies onion admin to tg_shop_admin:3000 (new panel) - chatbotService: ADMIN_CHAT_URL default = http://tg_shop_admin:3000/api/chat (removed localhost:3100 anachronism) - .env admin secrets gitignored (admin-next/.env)
This commit is contained in:
120
admin-next/.zscripts/python-runtime-build.sh
Executable file
120
admin-next/.zscripts/python-runtime-build.sh
Executable file
@@ -0,0 +1,120 @@
|
||||
#!/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 已固化到部署产物"
|
||||
Reference in New Issue
Block a user