R105/A2-A5 补强试运行自动化验收
这个提交包含在:
@@ -14,7 +14,7 @@ const scanRoots = [
|
||||
"client/src/pages",
|
||||
];
|
||||
const sourceExtensions = new Set([".js", ".jsx", ".ts", ".tsx"]);
|
||||
const forbiddenCopy = ["先处理这几件事", "清爽"];
|
||||
const forbiddenCopy = ["先处理", "清爽"];
|
||||
const findings = [];
|
||||
|
||||
function toPosix(value) {
|
||||
|
||||
+212
@@ -0,0 +1,212 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
||||
CLIENT_DIR="$ROOT_DIR/client"
|
||||
SERVER_DIR="$ROOT_DIR/server"
|
||||
ISSUE_CSV="$ROOT_DIR/issues/2026-05-07_12-34-21-r105-pretrial-readiness-automation.csv"
|
||||
ISSUE_VALIDATOR="/home/shunli/.codex/skills/plan/scripts/validate_issues_csv.py"
|
||||
PUBLIC_BASE_URL="${LIVE_SMOKE_BASE_URL:-https://oa.hyinda.com}"
|
||||
MODE="static"
|
||||
|
||||
usage() {
|
||||
cat <<USAGE
|
||||
Usage: bash scripts/qa/run-pretrial-readiness.sh [--static|--live-smoke|--visual|--ocr|--all]
|
||||
|
||||
R105 真实试运行前门禁。
|
||||
|
||||
默认:
|
||||
--static CSV 校验、部署契约、Prisma、UI 规则、audit-smoke-data 语法、client typecheck
|
||||
|
||||
可选公网项:
|
||||
--live-smoke 需要完整 LIVE_SMOKE_*,执行 bash scripts/qa/run-web-gates.sh smoke-live
|
||||
--visual 需要完整 LIVE_SMOKE_*,执行 R105 公网视觉 Playwright
|
||||
--ocr 需要 PLAYWRIGHT_OCR_LIVE_FILE 和 smoke 员工凭据,执行真实 OCR 辅助复核
|
||||
--all static + live-smoke + visual + ocr
|
||||
|
||||
本脚本不会打印 LIVE_SMOKE_* 密码或第三方 secret。
|
||||
USAGE
|
||||
}
|
||||
|
||||
require_cmd() {
|
||||
command -v "$1" >/dev/null 2>&1 || {
|
||||
echo "[pretrial][FAIL] 缺少命令: $1" >&2
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
|
||||
has_live_smoke_credentials() {
|
||||
[[ -n "${LIVE_SMOKE_ADMIN_IDENTIFIER:-}" ]] &&
|
||||
[[ -n "${LIVE_SMOKE_ADMIN_PASSWORD:-}" ]] &&
|
||||
[[ -n "${LIVE_SMOKE_EMPLOYEE_IDENTIFIER:-}" ]] &&
|
||||
[[ -n "${LIVE_SMOKE_EMPLOYEE_PASSWORD:-}" ]]
|
||||
}
|
||||
|
||||
has_live_ocr_credentials() {
|
||||
if [[ -n "${PLAYWRIGHT_OCR_LIVE_IDENTIFIER:-}" && -n "${PLAYWRIGHT_OCR_LIVE_PASSWORD:-}" ]]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
[[ -n "${LIVE_SMOKE_EMPLOYEE_IDENTIFIER:-}" ]] && [[ -n "${LIVE_SMOKE_EMPLOYEE_PASSWORD:-}" ]]
|
||||
}
|
||||
|
||||
run_static() {
|
||||
require_cmd python3
|
||||
require_cmd node
|
||||
require_cmd npm
|
||||
|
||||
echo ">>> [pretrial] CSV 校验"
|
||||
python3 "$ISSUE_VALIDATOR" "$ISSUE_CSV"
|
||||
|
||||
echo ">>> [pretrial] 部署契约校验"
|
||||
node "$ROOT_DIR/deploy/trialrun/validate-env-contract.js"
|
||||
|
||||
echo ">>> [pretrial] Prisma schema 校验"
|
||||
(
|
||||
cd "$SERVER_DIR"
|
||||
npm run prisma:validate
|
||||
)
|
||||
|
||||
echo ">>> [pretrial] smoke 数据审计脚本语法"
|
||||
(
|
||||
cd "$SERVER_DIR"
|
||||
node --check src/scripts/audit-smoke-data.js
|
||||
node src/scripts/audit-smoke-data.js --help >/dev/null
|
||||
)
|
||||
|
||||
if [[ -n "${DATABASE_URL:-}" ]]; then
|
||||
echo ">>> [pretrial] smoke 数据足迹只读审计"
|
||||
(
|
||||
cd "$SERVER_DIR"
|
||||
npm run audit:smoke-data -- --format=text
|
||||
)
|
||||
else
|
||||
echo ">>> [pretrial] 跳过 smoke 数据足迹审计:当前 shell 未设置 DATABASE_URL"
|
||||
fi
|
||||
|
||||
echo ">>> [pretrial] UI 设计规则"
|
||||
node "$ROOT_DIR/scripts/qa/check-ui-design-rules.mjs"
|
||||
|
||||
echo ">>> [pretrial] client typecheck"
|
||||
(
|
||||
cd "$CLIENT_DIR"
|
||||
npm run typecheck
|
||||
)
|
||||
}
|
||||
|
||||
run_live_smoke() {
|
||||
require_cmd curl
|
||||
require_cmd node
|
||||
require_cmd npm
|
||||
|
||||
if ! has_live_smoke_credentials; then
|
||||
echo ">>> [pretrial] 跳过 live smoke:缺少完整 LIVE_SMOKE_* 凭据"
|
||||
return 0
|
||||
fi
|
||||
|
||||
echo ">>> [pretrial] live smoke: ${PUBLIC_BASE_URL}"
|
||||
LIVE_SMOKE_BASE_URL="$PUBLIC_BASE_URL" bash "$ROOT_DIR/scripts/qa/run-web-gates.sh" smoke-live
|
||||
}
|
||||
|
||||
run_visual() {
|
||||
require_cmd node
|
||||
require_cmd npm
|
||||
|
||||
if ! has_live_smoke_credentials; then
|
||||
echo ">>> [pretrial] 跳过 R105 视觉自动化:缺少完整 LIVE_SMOKE_* 凭据"
|
||||
return 0
|
||||
fi
|
||||
|
||||
echo ">>> [pretrial] R105 公网视觉自动化: ${PUBLIC_BASE_URL}"
|
||||
(
|
||||
cd "$CLIENT_DIR"
|
||||
LIVE_SMOKE_BASE_URL="$PUBLIC_BASE_URL" \
|
||||
E2E_MODE=live \
|
||||
npx playwright test tests/e2e/r105-pretrial-visual.spec.ts --reporter=list
|
||||
)
|
||||
}
|
||||
|
||||
run_ocr() {
|
||||
require_cmd node
|
||||
require_cmd npm
|
||||
|
||||
if [[ -z "${PLAYWRIGHT_OCR_LIVE_FILE:-}" ]]; then
|
||||
echo ">>> [pretrial] 跳过真实 OCR:未设置 PLAYWRIGHT_OCR_LIVE_FILE"
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [[ ! -f "$PLAYWRIGHT_OCR_LIVE_FILE" ]]; then
|
||||
echo ">>> [pretrial] 跳过真实 OCR:文件不存在 ${PLAYWRIGHT_OCR_LIVE_FILE}"
|
||||
return 0
|
||||
fi
|
||||
|
||||
if ! has_live_ocr_credentials; then
|
||||
echo ">>> [pretrial] 跳过真实 OCR:缺少 smoke 员工凭据"
|
||||
return 0
|
||||
fi
|
||||
|
||||
echo ">>> [pretrial] 真实 OCR 辅助复核: ${PUBLIC_BASE_URL}"
|
||||
(
|
||||
cd "$CLIENT_DIR"
|
||||
PLAYWRIGHT_MANUAL=1 \
|
||||
PLAYWRIGHT_OCR_LIVE=1 \
|
||||
E2E_BASE_URL="$PUBLIC_BASE_URL" \
|
||||
npx playwright test tests/e2e/manual/live-invoice-ocr.spec.ts --workers=1 --reporter=list
|
||||
)
|
||||
}
|
||||
|
||||
if [[ "$#" -eq 0 ]]; then
|
||||
MODE="static"
|
||||
elif [[ "$#" -eq 1 ]]; then
|
||||
case "$1" in
|
||||
--help|-h)
|
||||
usage
|
||||
exit 0
|
||||
;;
|
||||
--static)
|
||||
MODE="static"
|
||||
;;
|
||||
--live-smoke)
|
||||
MODE="live-smoke"
|
||||
;;
|
||||
--visual)
|
||||
MODE="visual"
|
||||
;;
|
||||
--ocr)
|
||||
MODE="ocr"
|
||||
;;
|
||||
--all)
|
||||
MODE="all"
|
||||
;;
|
||||
*)
|
||||
usage >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
else
|
||||
usage >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
case "$MODE" in
|
||||
static)
|
||||
run_static
|
||||
;;
|
||||
live-smoke)
|
||||
run_live_smoke
|
||||
;;
|
||||
visual)
|
||||
run_visual
|
||||
;;
|
||||
ocr)
|
||||
run_ocr
|
||||
;;
|
||||
all)
|
||||
run_static
|
||||
run_live_smoke
|
||||
run_visual
|
||||
run_ocr
|
||||
;;
|
||||
esac
|
||||
|
||||
echo "[pretrial][PASS] mode=${MODE}"
|
||||
在新工单中引用
屏蔽一个用户