问题 - 索引中该目录记为小写 `scripts/`,工作区实为 `Scripts/`。因 core.ignorecase=true, 本地 `git diff -- Scripts/bin/x.py` 会**静默返回空**(看似无改动), 且在大小写敏感环境(Linux CI / Docker 挂载)会检出 `scripts/`, 与全仓所有 `Scripts/...` 引用不匹配。 - 该目录此前 10 个脚本(check_python_version.py、perf_snapshot.py、 install_collector_launchd.py、mysql_toggle.sh 等)从未入库, 而 CI 第 31 行正调用 `Scripts/bin/check_python_version.py --strict` —— 全新检出必然失败。 改动 - 索引路径统一为 `Scripts/`(工作区文件未移动,仅索引改名)。 - 补齐上述 10 个未跟踪脚本及其测试。 影响 - 修正前索引 35 条(全为小写路径),修正后 45 条。
104 lines
3.6 KiB
Bash
104 lines
3.6 KiB
Bash
#!/bin/bash
|
|
# ==============================================================
|
|
# bundle-python.sh — 将 Python 运行时 + akshare-fetcher 打包进 .app
|
|
# ==============================================================
|
|
set -e
|
|
|
|
APP_DIR="${1:-.build/FinDataHub.app}"
|
|
PROJECT_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
|
# 数据源项目路径可通过环境变量覆盖
|
|
AKSHARE_SRC="${AKSHARE_SRC:-${PROJECT_ROOT}/Services/akshare_fetcher}"
|
|
FRAMEWORKS_DIR="${APP_DIR}/Contents/Frameworks"
|
|
RESOURCES_DIR="${APP_DIR}/Contents/Resources"
|
|
VENV_DIR="${FRAMEWORKS_DIR}/akshare-venv"
|
|
AKSHARE_DST="${RESOURCES_DIR}/akshare_fetcher"
|
|
|
|
echo "=== 打包 Python 运行时 ==="
|
|
echo " .app: ${APP_DIR}"
|
|
echo ""
|
|
|
|
# ---------- 1. 创建 venv ----------
|
|
if [ -d "${VENV_DIR}/bin" ]; then
|
|
echo "[1/3] 虚拟环境已存在,跳过创建"
|
|
else
|
|
echo "[1/3] 创建 Python 虚拟环境..."
|
|
mkdir -p "${FRAMEWORKS_DIR}"
|
|
cd "${PROJECT_ROOT}"
|
|
# uv venv 创建独立虚拟环境(与 bundle 内实际运行时保持一致)
|
|
uv venv --python 3.14 "${VENV_DIR}" 2>&1 | tail -3
|
|
echo " ✅ 虚拟环境已创建"
|
|
fi
|
|
|
|
source "${VENV_DIR}/bin/activate"
|
|
echo " Python: $(python3 --version)"
|
|
|
|
# ---------- 2. 安装依赖 ----------
|
|
echo "[2/3] 安装 akshare-fetcher 依赖..."
|
|
cd "${AKSHARE_SRC}"
|
|
|
|
# 从 pyproject.toml 安装依赖(版本约束由 pyproject.toml 管理,避免无版本锁定)
|
|
pip install --quiet --upgrade pip 2>/dev/null || true
|
|
|
|
install_time=$(date +%s)
|
|
# 以可编辑模式安装项目,读取 pyproject.toml 中声明的依赖及版本约束
|
|
pip install --quiet -e "${AKSHARE_SRC}" 2>&1 | tail -3
|
|
|
|
# 验证
|
|
python3 -c "import akshare; print(f' ✅ akshare {akshare.__version__} 可导入')" 2>&1
|
|
python3 -c "import pandas; print(f' ✅ pandas {pandas.__version__}')" 2>&1
|
|
python3 -c "import numpy; print(f' ✅ numpy {numpy.__version__}')" 2>&1
|
|
|
|
du -sh "${VENV_DIR}"
|
|
echo ""
|
|
|
|
# ---------- 3. 复制项目代码 ----------
|
|
echo "[3/3] 部署 akshare-fetcher 项目代码..."
|
|
mkdir -p "${AKSHARE_DST}"
|
|
rsync -a --delete \
|
|
--exclude='.venv' \
|
|
--exclude='.git' \
|
|
--exclude='__pycache__' \
|
|
--exclude='*.pyc' \
|
|
--exclude='*.pyo' \
|
|
--exclude='.DS_Store' \
|
|
--exclude='uv.lock' \
|
|
"${AKSHARE_SRC}/" "${AKSHARE_DST}/"
|
|
echo " ✅ 项目代码已部署 (${AKSHARE_DST})"
|
|
|
|
# ---------- 4. 创建入口脚本 ----------
|
|
echo " 创建入口脚本..."
|
|
mkdir -p "${RESOURCES_DIR}/bin"
|
|
cat > "${RESOURCES_DIR}/bin/akshare-fetcher.sh" << 'SCRIPT'
|
|
#!/bin/bash
|
|
# FinDataHub 内置 akshare-fetcher 入口
|
|
# 使用捆绑的虚拟环境
|
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
APP_DIR="$(cd "${SCRIPT_DIR}/../.." && pwd)"
|
|
VENV_PYTHON="${APP_DIR}/Contents/Frameworks/akshare-venv/bin/python3"
|
|
PROJECT_DIR="${APP_DIR}/Contents/Resources/akshare_fetcher"
|
|
export PYTHONUNBUFFERED=1
|
|
export AKSHARE_HOME="${PROJECT_DIR}"
|
|
export PYTHONPATH="${PROJECT_DIR}/src"
|
|
cd "${PROJECT_DIR}"
|
|
exec "${VENV_PYTHON}" -m akshare_fetcher "$@"
|
|
SCRIPT
|
|
chmod +x "${RESOURCES_DIR}/bin/akshare-fetcher.sh"
|
|
|
|
# 同时创建快捷入口: akshare-fetcher → 直接调项目源码
|
|
cat > "${AKSHARE_DST}/run_bundled.sh" << 'SCRIPT'
|
|
#!/bin/bash
|
|
# 捆绑环境入口 — 使用 FinDataHub 内建的 venv
|
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
VENV_PYTHON="${SCRIPT_DIR}/../../Frameworks/akshare-venv/bin/python3"
|
|
export PYTHONPATH="${SCRIPT_DIR}/src"
|
|
cd "${SCRIPT_DIR}"
|
|
exec "${VENV_PYTHON}" -m akshare_fetcher "$@"
|
|
SCRIPT
|
|
chmod +x "${AKSHARE_DST}/run_bundled.sh"
|
|
|
|
echo ""
|
|
echo "=== Python 运行时打包完成 ==="
|
|
du -sh "${VENV_DIR}" "${AKSHARE_DST}" 2>/dev/null
|
|
echo ""
|
|
echo "总大小:"
|
|
du -sh "${FRAMEWORKS_DIR}" "${RESOURCES_DIR}" 2>/dev/null |