#!/usr/bin/env bash # scripts/setup-test-db.sh — 数据库重置脚本:drop + create 空库。 # schema apply 由 Flyway 在 Spring Boot 启动时自动处理(见 docs/04 技术栈 + sql/migrations/V*.sql)。 # seed 数据由测试框架负责(Spring @Sql / Flyway R__seed.sql / data.sql)。 # # 使用场景: # - scripts/test.sh 开头:清空库,让 Spring 启动时 Flyway 从 V1 开始重放所有 migration # - scripts/test.sh 结尾:清空库,避免测试遗留污染下次运行 # - 手动调试时:reset 到零状态 # # 防护:本脚本只允许在本地 host + 测试库名上执行;非预期目标会被拒绝, # 避免 .env.local 误指向 staging/prod 时触发不可逆 DROP。 set -euo pipefail # macOS Homebrew 的 mysql-client 是 keg-only,默认不在 PATH;非交互式 bash 也不读 ~/.zshrc。 # 这里幂等 prepend 常见安装路径,命中则用,未命中(如 Linux CI 已自带 mysql)则跳过。 for p in /opt/homebrew/opt/mysql-client/bin /usr/local/opt/mysql-client/bin; do [ -d "$p" ] && case ":$PATH:" in *":$p:"*) ;; *) PATH="$p:$PATH" ;; esac done ENV_FILE="$(dirname "$0")/../.env.local" [ -f "$ENV_FILE" ] || { echo "[setup-test-db] ⚠️ .env.local 不存在($ENV_FILE)" >&2; exit 1; } # 用 set -a 加载,让 KEY=VALUE 导出为环境变量;密码中含特殊字符时 .env.local 请用单引号包裹 set -a; . "$ENV_FILE"; set +a # 防护 1:默认只允许本地 host(localhost / 127.0.0.1 / ::1)。 # 若要为本项目额外允许某些远程 host(如公司测试 MySQL),在 .env.local 里设: # TEST_DB_ALLOWED_HOSTS="118.178.19.35 test-mysql.internal" # 空格或逗号分隔 # 被列入者可直接 DROP CREATE,不再需要 TEST_DB_ALLOW_REMOTE=1。 ALLOWED_HOSTS="localhost 127.0.0.1 ::1 ${TEST_DB_ALLOWED_HOSTS//,/ }" host_allowed=0 for h in $ALLOWED_HOSTS; do [ "${DB_HOST:-}" = "$h" ] && { host_allowed=1; break; } done if [ "$host_allowed" -ne 1 ]; then echo "[setup-test-db] ⚠️ 拒绝在非白名单 host (${DB_HOST}) 上执行 DROP DATABASE" >&2 echo " 当前白名单:${ALLOWED_HOSTS}" >&2 echo " 加入 host:在 .env.local 追加 TEST_DB_ALLOWED_HOSTS=\" \"" >&2 echo " 一次性绕过:TEST_DB_ALLOW_REMOTE=1 $0" >&2 [ "${TEST_DB_ALLOW_REMOTE:-0}" = "1" ] || exit 1 fi # 防护 2:schema 名需像测试/开发库(含 test / _dev / _local),否则要求显式确认 case "${DB_SCHEMA:-}" in *test*|*_dev|*_local|*_ci) ;; *) echo "[setup-test-db] ⚠️ schema '${DB_SCHEMA}' 不像测试库(期望命名含 test / _dev / _local / _ci)" >&2 echo " 如确为期望行为,请显式声明:TEST_DB_ALLOW_PROD_NAME=1 $0" >&2 [ "${TEST_DB_ALLOW_PROD_NAME:-0}" = "1" ] || exit 1 ;; esac # 防护 3:显式 banner,让人看见自己在 drop 什么;远程 host 额外提示白名单内容 echo "[setup-test-db] 即将 DROP + CREATE \`${DB_SCHEMA}\` on ${DB_HOST}:${DB_PORT}" case "${DB_HOST:-}" in localhost|127.0.0.1|::1) ;; *) echo "[setup-test-db] ⚠️ 目标是 **远程** host(已在 TEST_DB_ALLOWED_HOSTS 白名单中,每次 test.sh 都会 DROP)" echo "[setup-test-db] 当前白名单: ${ALLOWED_HOSTS}" echo "[setup-test-db] 若不希望每次自动 DROP,从 .env.local 的 TEST_DB_ALLOWED_HOSTS 删掉此 host" ;; esac MYSQL_CMD="mysql -h${DB_HOST} -P${DB_PORT} -u${DB_USER} -p${DB_PASSWORD}" $MYSQL_CMD -e "DROP DATABASE IF EXISTS \`${DB_SCHEMA}\`; CREATE DATABASE \`${DB_SCHEMA}\` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;" echo "[setup-test-db] done — schema will be applied by Flyway when Spring Boot starts"