feat: multi-module iteration

This commit is contained in:
2026-08-04 21:38:49 +08:00
parent 9d96c73246
commit 71f508e02b
1366 changed files with 202004 additions and 0 deletions
+183
View File
@@ -0,0 +1,183 @@
#!/usr/bin/env bash
# 在服务器上执行:拉取后的常规发版(不覆盖 env 文件、默认不 seed)
# 通过 DUKANG_DEPLOY_ENV=staging|production 区分同机双栈
set -euo pipefail
DUKANG_DEPLOY_ENV="${DUKANG_DEPLOY_ENV:-production}"
case "$DUKANG_DEPLOY_ENV" in
staging|stage|test) DUKANG_DEPLOY_ENV=staging ;;
production|prod) DUKANG_DEPLOY_ENV=production ;;
*)
echo "错误: DUKANG_DEPLOY_ENV 须为 staging 或 production,当前=$DUKANG_DEPLOY_ENV" >&2
exit 1
;;
esac
if [[ "$DUKANG_DEPLOY_ENV" == "staging" ]]; then
APP_ROOT="${APP_ROOT:-/opt/dukang-staging}"
ENV_FILE_NAME=".env.staging"
ECOSYSTEM_FILE="ecosystem.staging.config.cjs"
VITE_API_DEFAULT="https://api-test.dukanghaoke.com"
API_PORT=8190
USER_PORT=8191
PORT_GREP='819[0-4]'
PM2_API=dukang-stg-api
PM2_USER=dukang-stg-h5-user
PM2_SHOP=dukang-stg-h5-shop
PM2_PARTNER=dukang-stg-h5-partner
PM2_ADMIN=dukang-stg-admin-web
else
APP_ROOT="${APP_ROOT:-/opt/dukang}"
ENV_FILE_NAME=".env.production"
ECOSYSTEM_FILE="ecosystem.config.cjs"
VITE_API_DEFAULT="https://api.dukanghaoke.com"
API_PORT=8090
USER_PORT=8091
PORT_GREP='809[0-4]'
PM2_API=dukang-api
PM2_USER=dukang-h5-user
PM2_SHOP=dukang-h5-shop
PM2_PARTNER=dukang-h5-partner
PM2_ADMIN=dukang-admin-web
fi
DEPLOY_DIR="$APP_ROOT/deploy"
export APP_ROOT
export APP_ENV="$DUKANG_DEPLOY_ENV"
export DUKANG_ENV_FILE="$ENV_FILE_NAME"
SKIP_BUILD=false
SKIP_DB=false
RUN_SEED=false
DB_PUSH_ACCEPT_DATA_LOSS=false
usage() {
cat <<EOF
用法: remote-release.sh [选项]
环境: DUKANG_DEPLOY_ENV=${DUKANG_DEPLOY_ENV} APP_ROOT=${APP_ROOT} env=${ENV_FILE_NAME}
--skip-build 跳过 pnpm build(仅重启 PM2
--skip-db 跳过 Prisma generate / db push
--seed 执行 prisma:seed(默认不执行)
--accept-data-loss prisma db push 时允许数据丢失(慎用)
-h, --help 显示帮助
EOF
}
while [[ $# -gt 0 ]]; do
case "$1" in
--skip-build) SKIP_BUILD=true ;;
--skip-db) SKIP_DB=true ;;
--seed) RUN_SEED=true ;;
--accept-data-loss) DB_PUSH_ACCEPT_DATA_LOSS=true ;;
-h|--help) usage; exit 0 ;;
*) echo "未知参数: $1" >&2; usage; exit 1 ;;
esac
shift
done
cd "$APP_ROOT"
echo "==> 发版环境: $DUKANG_DEPLOY_ENV ($APP_ROOT)"
echo "==> 1. 启用 pnpm"
corepack enable 2>/dev/null || true
corepack prepare pnpm@11.2.2 --activate 2>/dev/null || true
echo "==> 2. 安装依赖"
# mini-user H5Taro)构建峰值内存较高
export NODE_OPTIONS="${NODE_OPTIONS:---max-old-space-size=8192}"
# C 端 H5 静态资源路径:staging 独立域名根路径;生产 nginx 入口为 /user/
if [[ "$DUKANG_DEPLOY_ENV" == "staging" ]]; then
export TARO_H5_PUBLIC_PATH="${TARO_H5_PUBLIC_PATH:-/}"
unset TARO_H5_ROUTER_BASENAME
else
export TARO_H5_PUBLIC_PATH="${TARO_H5_PUBLIC_PATH:-/user/}"
export TARO_H5_ROUTER_BASENAME="${TARO_H5_ROUTER_BASENAME:-/user}"
fi
# C 端 H5 编译期注入的 API origin(勿落到 localhost
export VITE_API_TARGET="${VITE_API_TARGET:-$VITE_API_DEFAULT}"
export VITE_APP_ENV="$DUKANG_DEPLOY_ENV"
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 同步(构建前,读取 $ENV_FILE_NAME"
cd "$APP_ROOT/server/dukang-api"
if [[ ! -f "$ENV_FILE_NAME" ]]; then
echo "错误: 未找到 server/dukang-api/$ENV_FILE_NAME" >&2
exit 1
fi
node scripts/with-api-env.cjs pnpm prisma:generate
if [[ "$DB_PUSH_ACCEPT_DATA_LOSS" == true ]]; then
node scripts/with-api-env.cjs npx prisma db push --accept-data-loss
else
node scripts/with-api-env.cjs npx prisma db push
fi
if [[ "$RUN_SEED" == true ]]; then
echo "==> 执行 seed"
node scripts/with-api-env.cjs pnpm prisma:seed
fi
cd "$APP_ROOT"
else
echo "==> 3. 跳过数据库"
fi
if [[ "$SKIP_BUILD" == false ]]; then
echo "==> 4. 构建(C 端使用 mini-user H5,跳过 h5-user"
pnpm --filter @dukang/shared-types \
--filter @dukang/domain \
--filter @dukang/api \
--filter @dukang/mini-user \
--filter @dukang/h5-shop \
--filter @dukang/h5-partner \
--filter @dukang/admin-web \
build
# serve 读取 dist/serve.json(相对静态根目录)
if [[ -f "$APP_ROOT/apps/mini-user/serve.json" ]]; then
cp -f "$APP_ROOT/apps/mini-user/serve.json" "$APP_ROOT/apps/mini-user/dist/serve.json"
fi
else
echo "==> 4. 跳过构建"
if [[ -f "$APP_ROOT/apps/mini-user/serve.json" && -d "$APP_ROOT/apps/mini-user/dist" ]]; then
cp -f "$APP_ROOT/apps/mini-user/serve.json" "$APP_ROOT/apps/mini-user/dist/serve.json"
fi
fi
echo "==> 5. 重启 PM2 ($ECOSYSTEM_FILE)"
if pm2 describe "$PM2_API" &>/dev/null; then
pm2 delete "$PM2_USER" 2>/dev/null || true
pm2 start "$DEPLOY_DIR/$ECOSYSTEM_FILE" --only "$PM2_USER"
pm2 restart "$PM2_API" "$PM2_SHOP" "$PM2_PARTNER" "$PM2_ADMIN" 2>/dev/null \
|| pm2 restart "$PM2_API" "$PM2_SHOP" "$PM2_PARTNER"
else
pm2 start "$DEPLOY_DIR/$ECOSYSTEM_FILE"
fi
pm2 save
echo "==> 6. 健康检查"
sleep 2
pm2 list
ss -tlnp | grep -E "$PORT_GREP" || true
curl -sf -o /dev/null -w "mini-user(h5): %{http_code}\n" "http://127.0.0.1:${USER_PORT}/" || echo "mini-user(h5): FAIL"
curl -sf -o /dev/null -w "api: %{http_code}\n" "http://127.0.0.1:${API_PORT}/api/v1/health" 2>/dev/null \
|| curl -sf -o /dev/null -w "api: %{http_code}\n" "http://127.0.0.1:${API_PORT}/" \
|| echo "api: FAIL"
echo "==> 7. 记录系统版本"
cd "$APP_ROOT/server/dukang-api"
APP_ROOT="$APP_ROOT" DEPLOY_TRIGGER="${DEPLOY_TRIGGER:-manual}" DUKANG_ENV_FILE="$ENV_FILE_NAME" \
node scripts/with-api-env.cjs node scripts/record-system-version.cjs \
|| echo "WARN: system_version 写入失败"
echo "==> 发版完成 ($DUKANG_DEPLOY_ENV)"
if [[ "$DUKANG_DEPLOY_ENV" == "staging" ]]; then
echo "==> 8. 重载 nginxstaging"
if command -v nginx >/dev/null 2>&1 && nginx -t 2>/dev/null; then
systemctl reload nginx || echo "WARN: nginx reload failed"
else
echo "WARN: nginx 未安装或配置校验失败,跳过重载"
fi
fi