chore(api): use .env.production on server, .env for local dev only

Load production env without .env override; sync-api-env targets .env.production; PM2 NODE_ENV=production; Prisma uses with-api-env.cjs on deploy.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-07-07 23:33:34 +08:00
parent c6af8480a4
commit 6dc051f26d
13 changed files with 68 additions and 41 deletions
+2 -8
View File
@@ -50,24 +50,18 @@ fi
log "PULL $LOCAL_SHA -> $REMOTE_SHA"
# 保留生产密钥,避免 reset 覆盖
# 保留服务器生产密钥,避免 reset 覆盖
ENV_BACKUP="$(mktemp)"
API_ENV_BACKUP="$(mktemp)"
API_ENV_DEV_BACKUP="$(mktemp)"
API_ENV_PROD_BACKUP="$(mktemp)"
cp "$ENV_FILE" "$ENV_BACKUP" 2>/dev/null || true
cp "$APP_ROOT/server/dukang-api/.env" "$API_ENV_BACKUP" 2>/dev/null || true
cp "$APP_ROOT/server/dukang-api/.env.development" "$API_ENV_DEV_BACKUP" 2>/dev/null || true
cp "$APP_ROOT/server/dukang-api/.env.production" "$API_ENV_PROD_BACKUP" 2>/dev/null || true
git checkout "$GIT_BRANCH"
git reset --hard "$GIT_REMOTE/$GIT_BRANCH"
cp "$ENV_BACKUP" "$ENV_FILE" 2>/dev/null || true
cp "$API_ENV_BACKUP" "$APP_ROOT/server/dukang-api/.env" 2>/dev/null || true
cp "$API_ENV_DEV_BACKUP" "$APP_ROOT/server/dukang-api/.env.development" 2>/dev/null || true
cp "$API_ENV_PROD_BACKUP" "$APP_ROOT/server/dukang-api/.env.production" 2>/dev/null || true
rm -f "$ENV_BACKUP" "$API_ENV_BACKUP" "$API_ENV_DEV_BACKUP" "$API_ENV_PROD_BACKUP"
rm -f "$ENV_BACKUP" "$API_ENV_PROD_BACKUP"
sed -i 's/\r$//' "$ENV_FILE" 2>/dev/null || true
# 修复 Windows 换行
+1 -2
View File
@@ -10,8 +10,7 @@ module.exports = {
instances: 1,
exec_mode: 'fork',
env: {
// 预发/联调阶段用 development;正式上线后改回 production
NODE_ENV: 'development',
NODE_ENV: 'production',
PORT: 8090,
},
},
+1 -1
View File
@@ -17,7 +17,7 @@ nginx -t
systemctl reload nginx
echo "==> 3. 更新 USER_H5_URL"
ENV_FILE="$APP_ROOT/server/dukang-api/.env"
ENV_FILE="$APP_ROOT/server/dukang-api/.env.production"
if grep -q '^USER_H5_URL=' "$ENV_FILE"; then
sed -i "s|^USER_H5_URL=.*|USER_H5_URL=${H5_BASE}/user|" "$ENV_FILE"
else
+1 -1
View File
@@ -10,7 +10,7 @@ export NODE_OPTIONS="--max-old-space-size=1024"
pnpm install --filter @dukang/api... --filter @dukang/domain --filter @dukang/shared-types
echo "==> env"
cat > "$APP_ROOT/server/dukang-api/.env" <<'ENV'
cat > "$APP_ROOT/server/dukang-api/.env.production" <<'ENV'
DATABASE_URL="mysql://dukang:Dukang2026!@localhost:3306/dukang_haoke"
REDIS_URL="redis://localhost:6379"
JWT_SECRET="dukang-prod-jwt-secret-2026"
+10 -6
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env bash
# 在服务器上执行:拉取后的常规发版(不覆盖 .env、默认不 seed)
# 在服务器上执行:拉取后的常规发版(不覆盖 .env.production、默认不 seed
set -euo pipefail
APP_ROOT="${APP_ROOT:-/opt/dukang-haoke}"
@@ -46,17 +46,21 @@ pnpm approve-builds --all 2>/dev/null || true
pnpm install --frozen-lockfile 2>/dev/null || pnpm install
if [[ "$SKIP_DB" == false ]]; then
echo "==> 3. 数据库 schema 同步(构建前)"
echo "==> 3. 数据库 schema 同步(构建前,读取 .env.production"
cd "$APP_ROOT/server/dukang-api"
pnpm prisma:generate
if [[ ! -f .env.production ]]; then
echo "错误: 未找到 server/dukang-api/.env.production" >&2
exit 1
fi
node scripts/with-api-env.cjs pnpm prisma:generate
if [[ "$DB_PUSH_ACCEPT_DATA_LOSS" == true ]]; then
npx prisma db push --accept-data-loss
node scripts/with-api-env.cjs npx prisma db push --accept-data-loss
else
npx prisma db push
node scripts/with-api-env.cjs npx prisma db push
fi
if [[ "$RUN_SEED" == true ]]; then
echo "==> 执行 seed"
pnpm prisma:seed
node scripts/with-api-env.cjs pnpm prisma:seed
fi
cd "$APP_ROOT"
else
+1 -1
View File
@@ -27,7 +27,7 @@ pnpm install --frozen-lockfile 2>/dev/null || pnpm install
pnpm build
echo "==> 5. 写入 API 生产环境变量"
cat > "$APP_ROOT/server/dukang-api/.env" <<'ENV'
cat > "$APP_ROOT/server/dukang-api/.env.production" <<'ENV'
DATABASE_URL="mysql://dukang:Dukang2026!@localhost:3306/dukang_haoke"
REDIS_URL="redis://localhost:6379"
JWT_SECRET="dukang-prod-jwt-secret-2026"
+1 -1
View File
@@ -1,4 +1,4 @@
# 服务器机器相关(覆盖 .env.development 中的同名项)
# 服务器机器相关(可合并到 .env.production 的参考项)
PORT=8090
DATABASE_URL="mysql://dukang:Dukang2026!@localhost:3306/dukang_haoke"
REDIS_URL="redis://localhost:6379"
+11 -8
View File
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
# 同步 API 环境变量到服务器
# 用法: deploy/sync-api-env.sh [development|production]
# 同步 API 生产环境变量到服务器 .env.production
# 用法: deploy/sync-api-env.sh [production]
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
@@ -13,12 +13,15 @@ DEPLOY_PORT="22"
DEPLOY_SSH_KEY=""
APP_ROOT="/opt/dukang-haoke"
TARGET="${1:-development}"
TARGET="${1:-production}"
case "$TARGET" in
development|dev) SRC_ENV="$REPO_ROOT/server/dukang-api/.env.development" ;;
production|prod) SRC_ENV="$REPO_ROOT/server/dukang-api/.env.production" ;;
development|dev)
echo "错误: development 仅用于本地开发,请使用 .env / .env.development,不同步到服务器" >&2
exit 1
;;
*)
echo "用法: $0 [development|production]" >&2
echo "用法: $0 [production]" >&2
exit 1
;;
esac
@@ -29,7 +32,7 @@ if [[ -f "$ENV_FILE" ]]; then
fi
if [[ ! -f "$SRC_ENV" ]]; then
echo "错误: 未找到 $SRC_ENV" >&2
echo "错误: 未找到 $SRC_ENV(可从 .env.production.example 复制)" >&2
exit 1
fi
@@ -42,7 +45,7 @@ SSH_OPTS=(-o "StrictHostKeyChecking=accept-new" -p "$DEPLOY_PORT")
[[ -n "$DEPLOY_SSH_KEY" ]] && SSH_OPTS+=(-i "$DEPLOY_SSH_KEY")
REMOTE="${DEPLOY_USER}@${DEPLOY_HOST}"
echo "==> 同步 $TARGET 环境到 $REMOTE:$APP_ROOT/server/dukang-api/.env"
scp "${SSH_OPTS[@]}" "$SRC_ENV" "$REMOTE:$APP_ROOT/server/dukang-api/.env"
echo "==> 同步 production 环境到 $REMOTE:$APP_ROOT/server/dukang-api/.env.production"
scp "${SSH_OPTS[@]}" "$SRC_ENV" "$REMOTE:$APP_ROOT/server/dukang-api/.env.production"
ssh "${SSH_OPTS[@]}" "$REMOTE" "pm2 restart dukang-api && sleep 2 && curl -sf -o /dev/null -w 'api-health:%{http_code}\n' http://127.0.0.1:8090/api/v1/health"
echo "==> 完成"