From 92e64b7f107145f6de808f902a6ce40d1e6c9d33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=85=E5=BF=B5?= Date: Mon, 21 Sep 2026 11:32:07 +0800 Subject: [PATCH] fix(api): seed-admin works in production containers (no dotenv/workspace) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Production image installs prod deps only — dotenv is a devDep, and the pnpm-workspace.yaml root lookup throws in containers. Both now degrade gracefully: env comes from container env vars. Hot-patched into the running test deployment during 2026-09-21 deploy; committed for the next image build. Co-Authored-By: Claude Code --- services/api/src/scripts/seed-admin.ts | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/services/api/src/scripts/seed-admin.ts b/services/api/src/scripts/seed-admin.ts index 388d060..d763373 100644 --- a/services/api/src/scripts/seed-admin.ts +++ b/services/api/src/scripts/seed-admin.ts @@ -7,7 +7,7 @@ // 运维操作而非用户动作,actor 不存在,审计语义不成立(计划 Task 12 明确排除)。 import { existsSync } from 'node:fs'; import { dirname, join } from 'node:path'; -import { config } from 'dotenv'; +// dotenv 为 devDep(生产镜像不装):延迟 require,缺失时走容器 env。 import { PrismaClient } from '@photo/db-cn'; import { hashPassword } from '../auth/password'; @@ -44,17 +44,25 @@ export async function seedAdmin( return { created: true }; } -/** 从脚本所在目录向上找 pnpm-workspace.yaml 定位仓库根并载入根 .env(同 packages/storage/test/load-env.ts 约定;不覆盖已有进程环境变量)。 */ +/** 从脚本所在目录向上找 pnpm-workspace.yaml 定位仓库根并载入根 .env(同 packages/storage/test/load-env.ts 约定;不覆盖已有进程环境变量)。 + * 生产容器(docker seed-admin 角色):无仓库根、无 dotenv(devDep)——依赖容器 env, + * 两者缺失时静默跳过而非抛错。 */ function loadRootEnv(): void { let dir = __dirname; while (!existsSync(join(dir, 'pnpm-workspace.yaml'))) { const parent = dirname(dir); if (parent === dir) { - throw new Error('seed-admin: pnpm-workspace.yaml not found, cannot locate repo root (.env)'); + return; // 生产容器:env 由 --env-file/容器注入,无需 .env } dir = parent; } - config({ path: join(dir, '.env') }); + try { + // eslint-disable-next-line @typescript-eslint/no-require-imports + const { config } = require('dotenv') as typeof import('dotenv'); + config({ path: join(dir, '.env') }); + } catch { + // dotenv 为 devDep,生产镜像可能未装——env 已在进程环境中 + } } async function main(): Promise {