#!/usr/bin/env bash # ============================================================ # flaky-scan.sh — Vitest 全量 shuffle 稳定性扫描(AGENTS.md §22) # # 用 --sequence.shuffle 打乱文件与测试执行顺序,暴露顺序依赖型 # flaky(共享 store 状态 / mock 实现污染 / 全局 stub 残留等)。 # 目标项目: gym-manage-web(vitest)。通过 --project 可切换。 # # 用法: # bash scripts/flaky-scan.sh # gym-manage-web 全量 shuffle 1 次 # bash scripts/flaky-scan.sh --runs 3 # 全量 shuffle 3 次 # bash scripts/flaky-scan.sh --spec # 单文件多次 shuffle # bash scripts/flaky-scan.sh --project uniapp # gym-manage-uniapp(jest,无 shuffle) # bash scripts/flaky-scan.sh --help # # 退出码: 0 = 全部通过;1 = 存在失败(flaky 或顺序依赖 bug) # 失败详情保留在 /tmp/flaky-scan-*.log 供根因定位 # ============================================================ set -uo pipefail SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" PROJECT_DIR="$(dirname "$SCRIPT_DIR")" RUNS=1 SPEC="" PROJECT="web" SHUFFLE="--sequence.shuffle" NEXT="" for arg in "$@"; do case "$arg" in --runs=*) RUNS="${arg#--runs=}" ;; --spec=*) SPEC="${arg#--spec=}" ;; --project=*) PROJECT="${arg#--project=}" ;; --runs|--spec|--project) NEXT="$arg" ;; --no-shuffle) SHUFFLE="" ;; --help|-h) sed -n '2,16p' "$0" | sed 's/^# \{0,1\}//' exit 0 ;; *) if [ -n "$NEXT" ]; then case "$NEXT" in --runs) RUNS="$arg" ;; --spec) SPEC="$arg" ;; --project) PROJECT="$arg" ;; esac NEXT="" else echo "未知参数: ${arg}(--help 查看用法)" >&2 exit 2 fi ;; esac done case "$PROJECT" in web) SUB_PROJ="gym-manage-web" ;; uniapp|coach) SUB_PROJ="gym-manage-${PROJECT}" ;; *) echo "未知项目: ${PROJECT}(web | uniapp | coach)" >&2; exit 2 ;; esac [ -d "${PROJECT_DIR}/${SUB_PROJ}" ] || { echo "子项目不存在: ${SUB_PROJ}" >&2; exit 2; } echo "============================================" echo " Gym Manage Flaky 稳定性扫描" echo " 项目: ${SUB_PROJ}" echo " 模式: ${SHUFFLE:-无 shuffle} × $RUNS 次${SPEC:+ (${SPEC})}" echo "============================================" FAILED=0 for i in $(seq 1 "$RUNS"); do LOG="/tmp/flaky-scan-$i.log" if [ -n "$SPEC" ]; then (cd "${PROJECT_DIR}/${SUB_PROJ}" && NODE_ENV=test npx vitest run $SHUFFLE "$SPEC" > "$LOG" 2>&1) else (cd "${PROJECT_DIR}/${SUB_PROJ}" && NODE_ENV=test npx vitest run $SHUFFLE > "$LOG" 2>&1) fi EXIT=$? SUMMARY=$(grep -E "Tests " "$LOG" | tail -1) if [ "$EXIT" -eq 0 ]; then echo "run $i/$RUNS: ✅ $SUMMARY" else echo "run $i/$RUNS: ❌ exit=$EXIT $SUMMARY" grep -E "^ FAIL" "$LOG" | head -10 FAILED=1 fi done echo "--------------------------------------------" if [ "$FAILED" -eq 0 ]; then echo " 扫描通过:${RUNS} 次运行 0 flaky ✅" exit 0 else echo " 发现 flaky/顺序依赖(详见 /tmp/flaky-scan-*.log) ❌" exit 1 fi