From 5adbe9db33f4c91547c6a84c1eb02f8425b885e1 Mon Sep 17 00:00:00 2001 From: zichun Date: Thu, 28 May 2026 16:08:26 +0800 Subject: [PATCH] templates(test-db): drop ALLOW_REMOTE/ALLOW_PROD_NAME hatches and slim env-local warnings --- skills/plan/skeleton-gen/templates/env-local-template | 19 +++---------------- skills/plan/skeleton-gen/templates/scripts-setup-test-db-template.mjs | 33 ++++++--------------------------- 2 files changed, 9 insertions(+), 43 deletions(-) diff --git a/skills/plan/skeleton-gen/templates/env-local-template b/skills/plan/skeleton-gen/templates/env-local-template index 43a3bd2..015c5d5 100644 --- a/skills/plan/skeleton-gen/templates/env-local-template +++ b/skills/plan/skeleton-gen/templates/env-local-template @@ -1,12 +1,5 @@ -# .env.local — 本地开发凭据(入 .gitignore,不提交) -# -# 规则: -# 1. 值含 `$`、反引号、空格、`!` 等 shell 特殊字符时,必须用单引号包裹: -# DB_PASSWORD='p@ss$w0rd!' -# 否则 `set -a; . .env.local; set +a` 会做变量展开导致密码错乱。 -# 2. DB_HOST 建议保持 localhost / 127.0.0.1;非本地 host 默认会被 scripts/setup-test-db.mjs 防护拒绝。 -# 若必须用远程测试库,把 host 列入下方 TEST_DB_ALLOWED_HOSTS。 -# 3. DB_SCHEMA 建议命名含 test / _dev / _local / _ci,避免与生产库同名。 +# Local dev credentials — gitignored. +# Quote values containing $/space/!/backtick with single quotes: DB_PASSWORD='p@ss$w0rd!' DB_HOST=【人工填写:MySQL host,推荐 localhost】 DB_PORT=【人工填写:MySQL port,默认 3306】 @@ -15,11 +8,5 @@ DB_PASSWORD=【人工填写:对应密码,含特殊字符时用单引号包 DB_SCHEMA=【人工填写:schema 名,推荐含 test/_dev/_local,例如 erp_dev】 JWT_SECRET=【人工填写:JWT 签名密钥,256+ bit 随机串】 -# 可选:额外允许 DROP CREATE 的远程 host(空格或逗号分隔)。仅当 DB_HOST 指向公司测试 MySQL 等 -# 非本地服务器时填写;留空表示只允许 localhost / 127.0.0.1 / ::1。 -# 示例:TEST_DB_ALLOWED_HOSTS="118.178.19.35 test-mysql.internal" -# -# ⚠️ 列入后该 host 每次 test.mjs 都会被 DROP CREATE(无二次确认)。 -# 仅用于你完全可控的测试库;生产/共享库/多人共享的 staging 库**千万别列**。 -# (防护 2 还会检查 schema 名须含 test/_dev/_local/_ci,独立兜底。) +# 可选:额外允许 DROP CREATE 的远程 host(空格或逗号分隔)。 TEST_DB_ALLOWED_HOSTS= diff --git a/skills/plan/skeleton-gen/templates/scripts-setup-test-db-template.mjs b/skills/plan/skeleton-gen/templates/scripts-setup-test-db-template.mjs index ec56d45..675562f 100644 --- a/skills/plan/skeleton-gen/templates/scripts-setup-test-db-template.mjs +++ b/skills/plan/skeleton-gen/templates/scripts-setup-test-db-template.mjs @@ -1,19 +1,7 @@ #!/usr/bin/env node -// scripts/setup-test-db.mjs — 数据库重置脚本:drop + create 空库。 -// schema apply 由 Flyway 在 Spring Boot 启动时自动处理(见 docs/04 技术栈 + sql/migrations/V*.sql)。 -// seed 数据由测试框架负责(Spring @Sql / Flyway R__seed.sql / data.sql)。 -// -// 使用场景: -// - scripts/test.mjs 开头:清空库,让 Spring 启动时 Flyway 从 V1 开始重放所有 migration -// - scripts/test.mjs 结尾:清空库,避免测试遗留污染下次运行 -// - 手动调试时:reset 到零状态 -// -// 跨平台:用纯 JS 解析 .env.local(dotenv 风格,逐行 KEY=VALUE),**绝不** shell-source, -// 因此 mac / Windows 原生 node 均可运行,且消除 shell 注入 / 变量展开隐患。 -// DROP/CREATE 通过 `mysql` 客户端以 argv 数组方式执行(不经 shell),密码不进命令行解析层。 -// -// 防护:本脚本只允许在本地 host + 测试库名上执行;非预期目标会被拒绝, -// 避免 .env.local 误指向 staging/prod 时触发不可逆 DROP。 +// scripts/setup-test-db.mjs — DROP + CREATE 空测试库。 +// 由 coding.mjs 的 test-gate 调用;schema 由 Flyway 在 Spring Boot 启动时重放。 +// 只允许本地 host(或 TEST_DB_ALLOWED_HOSTS 白名单内的 host)+ 测试库名(含 test/_dev/_local/_ci)。 import { spawnSync } from 'node:child_process' import { existsSync, readFileSync } from 'node:fs' @@ -23,8 +11,6 @@ import { fileURLToPath } from 'node:url' const SCRIPT_DIR = dirname(fileURLToPath(import.meta.url)) const ENV_FILE = join(SCRIPT_DIR, '..', '.env.local') -// dotenv 风格解析:逐行 KEY=VALUE,跳过空行与 # 注释,去除两侧空白, -// 可选地剥离一层成对单/双引号。**不做**变量展开,特殊字符按字面保留。 function parseEnv(text) { const env = {} for (const rawLine of text.split(/\r?\n/)) { @@ -59,9 +45,6 @@ const DB_PORT = env.DB_PORT ?? '3306' const DB_USER = env.DB_USER ?? '' const DB_PASSWORD = env.DB_PASSWORD ?? '' const DB_SCHEMA = env.DB_SCHEMA ?? '' -const TEST_DB_ALLOW_REMOTE = env.TEST_DB_ALLOW_REMOTE ?? process.env.TEST_DB_ALLOW_REMOTE ?? '0' -const TEST_DB_ALLOW_PROD_NAME = - env.TEST_DB_ALLOW_PROD_NAME ?? process.env.TEST_DB_ALLOW_PROD_NAME ?? '0' // 防护 1:默认只允许本地 host(localhost / 127.0.0.1 / ::1)。 // 额外允许的远程 host 在 .env.local 的 TEST_DB_ALLOWED_HOSTS 中(空格或逗号分隔)。 @@ -73,22 +56,19 @@ if (!allowedHosts.includes(DB_HOST)) { console.error(`[setup-test-db] 拒绝在非白名单 host (${DB_HOST}) 上执行 DROP DATABASE`) console.error(` 当前白名单:${allowedHosts.join(' ')}`) console.error(' 加入 host:在 .env.local 追加 TEST_DB_ALLOWED_HOSTS=" "') - console.error(' 一次性绕过:在 .env.local 设 TEST_DB_ALLOW_REMOTE=1') - if (TEST_DB_ALLOW_REMOTE !== '1') process.exit(1) + process.exit(1) } -// 防护 2:schema 名需像测试/开发库(含 test / _dev / _local / _ci),否则要求显式确认。 +// 防护 2:schema 名需像测试/开发库(含 test / _dev / _local / _ci),否则拒绝。 const schemaLooksLikeTest = /test/.test(DB_SCHEMA) || /_dev$/.test(DB_SCHEMA) || /_local$/.test(DB_SCHEMA) || /_ci$/.test(DB_SCHEMA) if (!schemaLooksLikeTest) { console.error( `[setup-test-db] schema '${DB_SCHEMA}' 不像测试库(期望命名含 test / _dev / _local / _ci)` ) - console.error(' 如确为期望行为,请显式声明:在 .env.local 设 TEST_DB_ALLOW_PROD_NAME=1') - if (TEST_DB_ALLOW_PROD_NAME !== '1') process.exit(1) + process.exit(1) } -// 防护 3:显式 banner,让人看见自己在 drop 什么;远程 host 额外提示白名单内容。 console.log(`[setup-test-db] 即将 DROP + CREATE \`${DB_SCHEMA}\` on ${DB_HOST}:${DB_PORT}`) if (!['localhost', '127.0.0.1', '::1'].includes(DB_HOST)) { console.log( @@ -104,7 +84,6 @@ const sql = `DROP DATABASE IF EXISTS \`${DB_SCHEMA}\`; ` + `CREATE DATABASE \`${DB_SCHEMA}\` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;` -// 以 argv 数组调用 mysql(不经 shell):密码不进 shell 解析,跨平台一致。 const mysqlArgs = [ `-h${DB_HOST}`, `-P${DB_PORT}`, -- libgit2 0.22.2