pbl_evidence/scripts/setup_test_env.sh
2026-09-23 00:03:13 +08:00

91 lines
5.0 KiB
Bash
Executable File
Raw 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.

#!/usr/bin/env bash
# =====================================================================
# pbl_evidence 测试环境引导(发现项 DISC.2)
#
# 背景:测试机宿主 python3 **没有** pytest,`python3 -m pytest` 直接
# `No module named pytest`。此前靠临时注入
# PYTHONPATH=<workspace>/.pylibs(pytest 9.1.1)跑通,属一次性手段,
# 不可复现、且会让 test 角色误判为「用例失败/环境不可用」。
#
# 本脚本把「测试前置依赖」变成显式、可重放的步骤:
# 0) 仓库卫生门禁:确认 venv 落点已被 .gitignore 真正忽略
# (`git check-ignore -q`,不靠注释自称)——否则本脚本会往版本库里
# 灌 1171 个 site-packages 文件(QC #1 实测事故,见下「历史」)
# 1) 建独立测试 venv(默认 .venv-test,可用 PBL_EVIDENCE_TEST_VENV 改位置)
# 2) 安装 requirements-dev.txt(== pyproject [project.optional-dependencies].test)
# 3) 打印 pytest 版本自证可用
#
# 历史(QC #1 退回,已修正):`.venv-test/` 曾被 commit 0a87e13 误入库
# (`git ls-files | grep -c venv-test` = 1171),而当时 .gitignore 只有
# `.venv/`、`venv/` 两条,本脚本注释却声称「已在 .gitignore 排除」——注释与
# 实测矛盾。现已 ① .gitignore 补 `.venv-test/`;② `git rm -r --cached .venv-test`
# 清出版本跟踪(本地文件保留);③ 本脚本第 0 步把「被忽略」变成**可执行断言**,
# 不再靠注释。自证:
# git check-ignore -v .venv-test # 命中 .gitignore 规则
# git ls-files | grep -c 'venv-test' # 必须为 0
#
# 用法:
# bash scripts/setup_test_env.sh
# PBL_EVIDENCE_TEST_VENV=/tmp/ev-venv bash scripts/setup_test_env.sh # 换 venv 位置
# PBL_EVIDENCE_INSTALL_PKG=1 bash scripts/setup_test_env.sh # 顺带 pip install -e .
# PBL_EVIDENCE_SKIP_GITIGNORE_CHECK=1 bash scripts/setup_test_env.sh # 非 git 环境(如 CI 解包目录)
#
# 幂等:venv 已存在则复用,pip 已满足则秒退;可被 build.sh / CI 反复调用。
# =====================================================================
set -euo pipefail
MODULE_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
VENV="${PBL_EVIDENCE_TEST_VENV:-${MODULE_ROOT}/.venv-test}"
REQ_DEV="${MODULE_ROOT}/requirements-dev.txt"
HOST_PY="${PBL_EVIDENCE_HOST_PYTHON:-$(command -v python3)}"
log() { echo "[setup_test_env] $*"; }
die() { echo "[setup_test_env][FATAL] $*" >&2; exit 1; }
[ -f "${REQ_DEV}" ] || die "缺少测试依赖清单 ${REQ_DEV}"
[ -x "${HOST_PY}" ] || die "找不到宿主 python3(可用 PBL_EVIDENCE_HOST_PYTHON 指定)"
# ---- 0. 仓库卫生门禁:venv 落点必须真的被 .gitignore 忽略 ----
# 只在 venv 位于模块仓库内时检查(放到仓库外如 /tmp 天然不会污染版本库)。
if [ "${PBL_EVIDENCE_SKIP_GITIGNORE_CHECK:-0}" != "1" ] \
&& [ "${VENV#${MODULE_ROOT}/}" != "${VENV}" ] \
&& git -C "${MODULE_ROOT}" rev-parse --is-inside-work-tree >/dev/null 2>&1; then
REL="${VENV#${MODULE_ROOT}/}"
if ! git -C "${MODULE_ROOT}" check-ignore -q "${REL}"; then
die "${REL}/ 未被 .gitignore 忽略——在此安装依赖会把 site-packages 灌进版本库(QC #1)。
修法:在 ${MODULE_ROOT}/.gitignore 增加一行「${REL}/」,
若历史已入库再执行「git rm -r --cached ${REL}」(保留本地文件),
然后重跑本脚本自证:git check-ignore -v ${REL}"
fi
TRACKED="$(git -C "${MODULE_ROOT}" ls-files "${REL}" | wc -l | tr -d ' ')"
if [ "${TRACKED}" != "0" ]; then
die "${REL}/ 已被 .gitignore 忽略但仍有 ${TRACKED} 个文件在版本跟踪中(历史入库)。
执行「git rm -r --cached ${REL}」清出跟踪后重跑本脚本。"
fi
log "仓库卫生门禁通过:${REL}/ 已被 .gitignore 忽略且未被版本跟踪"
fi
if [ ! -x "${VENV}/bin/python" ]; then
log "创建测试 venv: ${VENV}"
"${HOST_PY}" -m venv "${VENV}" || die "python3 -m venv 失败(宿主缺 venv 模块?)"
else
log "复用已存在的测试 venv: ${VENV}"
fi
VPY="${VENV}/bin/python"
# 升级 pip 属尽力而为(离线/内网源可能不可达),失败不阻断——真正的门禁是下一步安装
"${VPY}" -m pip install --quiet --upgrade pip >/dev/null 2>&1 || log "pip 自升级跳过(不影响后续安装)"
log "安装测试依赖: ${REQ_DEV}"
"${VPY}" -m pip install -r "${REQ_DEV}" || die "安装 pytest 失败:检查内网 PyPI 源可达性(见 README「Running tests」排障)"
if [ "${PBL_EVIDENCE_INSTALL_PKG:-0}" = "1" ]; then
log "安装模块本体(可编辑):pip install -e ${MODULE_ROOT}"
"${VPY}" -m pip install -e "${MODULE_ROOT}" || die "pip install -e . 失败"
fi
log "自证可用:$("${VPY}" -m pytest --version 2>&1 | head -1)"
log "TEST ENV READY: ${VPY}"
log "直接跑测试(二选一,均不需要手工注入 PYTHONPATH):"
log " bash ${MODULE_ROOT}/scripts/run_tests.sh"
log " source ${MODULE_ROOT}/scripts/activate_test_env.sh && python3 -m pytest tests/test_m5a_idempotency.py -v"