ai-project-manage-cli 6.0.67 → 6.0.69

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +180 -85
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -2588,7 +2588,7 @@ async function runWisdomSftpDeploy(params) {
2588
2588
  }
2589
2589
 
2590
2590
  // src/commands/deploy/internal/wisdom-backend-deploy.ts
2591
- var SPRINGBOOT_SCRIPT = "springboot.sh";
2591
+ var SPRINGBOOT_JAVA_OPTS = "-XX:+UseG1GC -XX:+HeapDumpOnOutOfMemoryError -Xms512M -Xmx1G";
2592
2592
  var MAVEN_MODULE = "jeecg-module-system/jeecg-system-start";
2593
2593
  var MAVEN_PROFILE = "dev";
2594
2594
  function log(message) {
@@ -2603,7 +2603,20 @@ function fail(message) {
2603
2603
  process.exit(1);
2604
2604
  }
2605
2605
  function expandPath(pathStr) {
2606
- return path2.resolve(pathStr.replace(/^~(?=\/|$)/, process.env.HOME ?? ""));
2606
+ const home = process.env.HOME ?? process.env.USERPROFILE ?? "";
2607
+ return path2.resolve(pathStr.replace(/^~(?=\/|\\|$)/, home));
2608
+ }
2609
+ function quoteForShell(value) {
2610
+ if (process.platform === "win32") {
2611
+ return `"${value.replace(/"/g, '""')}"`;
2612
+ }
2613
+ return shellSingleQuote(value);
2614
+ }
2615
+ function formatMavenLocalRepoArg(repoPath) {
2616
+ if (process.platform === "win32") {
2617
+ return `-Dmaven.repo.local=${quoteForShell(repoPath)}`;
2618
+ }
2619
+ return `-Dmaven.repo.local=${repoPath}`;
2607
2620
  }
2608
2621
  function deployCacheDir() {
2609
2622
  return path2.join(workspaceApmDir(), "deploy", ".deploy_cache");
@@ -2708,33 +2721,40 @@ function getMvnExecutable() {
2708
2721
  const isWin = process.platform === "win32";
2709
2722
  const candidates = isWin ? ["mvn.cmd", "mvn.bat", "mvn"] : ["mvn"];
2710
2723
  for (const name of candidates) {
2711
- const result = spawnSync2(isWin ? "where" : "which", [name], {
2712
- encoding: "utf8"
2724
+ const result = spawnSync2(isWin ? `where ${name}` : `which ${name}`, {
2725
+ encoding: "utf8",
2726
+ shell: true
2713
2727
  });
2714
2728
  if (result.status === 0 && result.stdout.trim()) {
2715
- return result.stdout.trim().split(/\r?\n/)[0];
2729
+ return result.stdout.trim().split(/\r?\n/)[0].trim();
2716
2730
  }
2717
2731
  }
2718
2732
  fail("\u672A\u627E\u5230 mvn \u547D\u4EE4\uFF0C\u8BF7\u786E\u8BA4 Maven \u5DF2\u5B89\u88C5\u5E76\u52A0\u5165 PATH");
2719
2733
  }
2720
2734
  function runMavenBuild(projectRoot, mavenLocalRepo) {
2721
2735
  const mavenRepo = expandPath(mavenLocalRepo);
2722
- const cmd = [
2723
- getMvnExecutable(),
2736
+ const mvn = getMvnExecutable();
2737
+ const command = [
2738
+ quoteForShell(mvn),
2724
2739
  "clean",
2725
2740
  "package",
2726
2741
  `-P${MAVEN_PROFILE}`,
2727
- `-Dmaven.repo.local=${mavenRepo}`,
2742
+ formatMavenLocalRepoArg(mavenRepo),
2728
2743
  "-DskipTests"
2729
- ];
2730
- log(`\u5F00\u59CB Maven \u6784\u5EFA: ${cmd.join(" ")}`);
2744
+ ].join(" ");
2745
+ log(`\u5F00\u59CB Maven \u6784\u5EFA: ${command}`);
2731
2746
  log(`Maven \u672C\u5730\u4ED3\u5E93: ${mavenRepo}`);
2732
- const result = spawnSync2(cmd[0], cmd.slice(1), {
2747
+ log(`\u6784\u5EFA\u76EE\u5F55: ${projectRoot}`);
2748
+ const result = spawnSync2(command, {
2733
2749
  cwd: projectRoot,
2734
- stdio: "inherit"
2750
+ stdio: "inherit",
2751
+ shell: true,
2752
+ env: process.env
2735
2753
  });
2736
2754
  if (result.status !== 0) {
2737
- fail(`Maven \u6784\u5EFA\u5931\u8D25\uFF0C\u9000\u51FA\u7801: ${result.status ?? 1}`);
2755
+ fail(
2756
+ `Maven \u6784\u5EFA\u5931\u8D25\uFF0C\u9000\u51FA\u7801: ${result.status ?? 1}\u3002\u8BF7\u5728\u9879\u76EE\u6839\u76EE\u5F55\u624B\u52A8\u6267\u884C\u4EE5\u67E5\u770B\u8BE6\u7EC6\u9519\u8BEF: ${command}`
2757
+ );
2738
2758
  }
2739
2759
  }
2740
2760
  function locateLibDir(projectRoot) {
@@ -2904,22 +2924,106 @@ function springbootOutputIndicatesSuccess(action, combined) {
2904
2924
  }
2905
2925
  return true;
2906
2926
  }
2907
- async function runSpringbootAction(client, config, action, ...args) {
2908
- if (action === "start" || action === "restart") {
2909
- if (args.length === 0) {
2910
- fail(`\u8FDC\u7A0B ${action} \u7F3A\u5C11 jar \u53C2\u6570`);
2911
- }
2912
- const jar = args[0].trim().split(/\r?\n/)[0].trim();
2913
- if (!jar) {
2914
- fail(`\u65E0\u6548\u7684 jar \u540D\u79F0: ${JSON.stringify(args[0])}`);
2915
- }
2927
+ function buildRemoteStatusScript(remoteAppDir, appName) {
2928
+ const dir = shellSingleQuote(remoteAppDir);
2929
+ const jar = shellSingleQuote(appName);
2930
+ return `
2931
+ set -e
2932
+ cd ${dir}
2933
+ appName=${jar}
2934
+ appIds=$(ps -ef | grep java | grep "$appName" | awk '{print $2}')
2935
+ if [ -z "$appIds" ]; then
2936
+ echo -e "\\033[31m Not running \\033[0m"
2937
+ else
2938
+ echo -e "\\033[32m Running [$appIds] \\033[0m"
2939
+ fi
2940
+ `.trim();
2941
+ }
2942
+ function buildRemoteRestartScript(remoteAppDir) {
2943
+ const dir = shellSingleQuote(remoteAppDir);
2944
+ const javaOpts = shellSingleQuote(SPRINGBOOT_JAVA_OPTS);
2945
+ return `
2946
+ set -e
2947
+ cd ${dir}
2948
+ releaseApp=$(ls -t | grep '.jar$' | head -n1)
2949
+ lastVersionApp=$(ls -t | grep '.jar$' | head -n2 | tail -n1)
2950
+ appName=$lastVersionApp
2951
+ appIds=$(ps -ef | grep java | grep "$appName" | awk '{print $2}')
2952
+ if [ -z "$appIds" ]; then
2953
+ echo "Maybe $appName not running, please check it..."
2954
+ else
2955
+ echo "The $appName is stopping..."
2956
+ echo "$appIds" | xargs kill
2957
+ fi
2958
+ for i in $(seq 15 -1 1); do
2959
+ echo -n "$i "
2960
+ sleep 1
2961
+ done
2962
+ echo 0
2963
+ if [ ! -d "backup" ]; then
2964
+ mkdir backup
2965
+ fi
2966
+ for i in $(ls | grep '.jar$' | grep -vFx "$releaseApp"); do
2967
+ echo "backup $i"
2968
+ mv "$i" backup/
2969
+ done
2970
+ appName=$releaseApp
2971
+ count=$(ps -ef | grep java | grep "$appName" | wc -l)
2972
+ if [ "$count" != "0" ]; then
2973
+ echo "Maybe $appName is running, please check it..."
2974
+ else
2975
+ echo "The $appName is starting..."
2976
+ nohup java -jar "./$appName" ${javaOpts} > nohup.out 2>&1 &
2977
+ fi
2978
+ `.trim();
2979
+ }
2980
+ function normalizeHealthContext(context) {
2981
+ let normalized = context.trim() || "/";
2982
+ if (!normalized.startsWith("/")) {
2983
+ normalized = `/${normalized}`;
2916
2984
  }
2917
- const quotedArgs = [action, ...args].map((arg) => shellSingleQuote(arg));
2918
- const command = [
2919
- `cd ${shellSingleQuote(config.remoteAppDir)}`,
2920
- `./${SPRINGBOOT_SCRIPT} ${quotedArgs.join(" ")}`
2921
- ].join(" && ");
2922
- const { exitCode, out, err } = await runRemoteCommand(client, command, {
2985
+ if (!normalized.endsWith("/")) {
2986
+ normalized = `${normalized}/`;
2987
+ }
2988
+ return normalized;
2989
+ }
2990
+ function buildRemoteHealthScript(port, context, timeoutSecs) {
2991
+ const normalizedContext = normalizeHealthContext(context);
2992
+ const portStr = String(port);
2993
+ const timeoutStr = String(timeoutSecs);
2994
+ return `
2995
+ set -e
2996
+ port=${shellSingleQuote(portStr)}
2997
+ context=${shellSingleQuote(normalizedContext)}
2998
+ timeout=${shellSingleQuote(timeoutStr)}
2999
+ check_url="http://127.0.0.1:${portStr}${normalizedContext}"
3000
+ echo "\u5065\u5EB7\u68C0\u67E5: \${check_url} (\u8D85\u65F6 \${timeout}s)"
3001
+ deadline=$(($(date +%s) + timeout))
3002
+ attempt=0
3003
+ while [ $(date +%s) -lt $deadline ]; do
3004
+ attempt=$((attempt + 1))
3005
+ code=$(curl -s -o /dev/null -w "%{http_code}" "$check_url" 2>/dev/null || echo "000")
3006
+ code=$(echo "$code" | tail -n1 | tr -d '[:space:]')
3007
+ if [ \${#code} -ge 3 ]; then
3008
+ status=\${code:0:3}
3009
+ if echo "$status" | grep -qE '^[0-9]+$' && [ "$status" -ge 200 ] && [ "$status" -lt 500 ]; then
3010
+ echo -e "\\033[32m\u5065\u5EB7\u68C0\u67E5\u901A\u8FC7 (HTTP \${status})\\033[0m"
3011
+ exit 0
3012
+ fi
3013
+ fi
3014
+ remaining=$((deadline - $(date +%s)))
3015
+ if [ $remaining -lt 0 ]; then
3016
+ remaining=0
3017
+ fi
3018
+ echo "\u7B49\u5F85\u670D\u52A1\u542F\u52A8... \u7B2C \${attempt} \u6B21\uFF0C\u5269\u4F59 \${remaining}s"
3019
+ sleep 5
3020
+ done
3021
+ echo -e "\\033[31m\u5065\u5EB7\u68C0\u67E5\u8D85\u65F6 (\${timeout}s): \${check_url}\\033[0m"
3022
+ exit 1
3023
+ `.trim();
3024
+ }
3025
+ async function runRemoteServiceScript(client, script, action) {
3026
+ const { exitCode, out, err } = await runRemoteCommand(client, script, {
2923
3027
  check: false
2924
3028
  });
2925
3029
  const combined = `${out}
@@ -2928,21 +3032,17 @@ ${err}`.trim();
2928
3032
  if (action === "health") {
2929
3033
  if (exitCode !== 0 || !outputOk) {
2930
3034
  fail(`\u5065\u5EB7\u68C0\u67E5\u5931\u8D25
2931
- \u547D\u4EE4: ${command}
2932
3035
  \u8F93\u51FA: ${combined || "(\u7A7A)"}`);
2933
3036
  }
2934
3037
  return combined;
2935
3038
  }
2936
3039
  if (exitCode !== 0 && !outputOk) {
2937
- fail(`\u8FDC\u7A0B ${action} \u5931\u8D25: ${args.join(" ")}
3040
+ fail(`\u8FDC\u7A0B ${action} \u5931\u8D25
2938
3041
  ${combined}`);
2939
3042
  }
2940
- if ((action === "start" || action === "restart") && !outputOk) {
2941
- fail(
2942
- `\u8FDC\u7A0B ${action} \u672A\u6210\u529F: ${args.join(" ")}
2943
- \u547D\u4EE4: ${command}
2944
- \u8F93\u51FA: ${combined || "(\u7A7A)"}`
2945
- );
3043
+ if (action === "restart" && !outputOk) {
3044
+ fail(`\u8FDC\u7A0B restart \u672A\u6210\u529F
3045
+ \u8F93\u51FA: ${combined || "(\u7A7A)"}`);
2946
3046
  }
2947
3047
  return combined;
2948
3048
  }
@@ -2950,12 +3050,11 @@ function stripAnsi(text) {
2950
3050
  return text.replace(/\x1b\[[0-?]*[ -/]*[@-~]/g, "");
2951
3051
  }
2952
3052
  async function getRunningJar(client, config) {
2953
- const combined = await runSpringbootAction(
2954
- client,
2955
- config,
2956
- "status",
3053
+ const script = buildRemoteStatusScript(
3054
+ config.remoteAppDir,
2957
3055
  config.startupJar
2958
3056
  );
3057
+ const combined = await runRemoteServiceScript(client, script, "status");
2959
3058
  const text = stripAnsi(combined).trim().toLowerCase();
2960
3059
  if (text.includes("not running")) {
2961
3060
  return null;
@@ -2966,11 +3065,19 @@ async function getRunningJar(client, config) {
2966
3065
  return null;
2967
3066
  }
2968
3067
  async function healthCheckService(client, config) {
2969
- const port = String(config.healthCheckPort);
2970
- const context = config.healthCheckContext;
2971
- const timeout = String(config.healthCheckTimeout);
2972
- log(`\u5065\u5EB7\u68C0\u67E5: springboot.sh health ${port} ${context} ${timeout}`);
2973
- await runSpringbootAction(client, config, "health", port, context, timeout);
3068
+ log(
3069
+ `\u5065\u5EB7\u68C0\u67E5: http://127.0.0.1:${config.healthCheckPort}${normalizeHealthContext(config.healthCheckContext)} (\u8D85\u65F6 ${config.healthCheckTimeout}s)`
3070
+ );
3071
+ const script = buildRemoteHealthScript(
3072
+ config.healthCheckPort,
3073
+ config.healthCheckContext,
3074
+ config.healthCheckTimeout
3075
+ );
3076
+ await runRemoteServiceScript(client, script, "health");
3077
+ }
3078
+ async function restartRemoteService(client, config) {
3079
+ const script = buildRemoteRestartScript(config.remoteAppDir);
3080
+ await runRemoteServiceScript(client, script, "restart");
2974
3081
  }
2975
3082
  async function runWisdomBackendDeploy(options) {
2976
3083
  const projectRoot = path2.resolve(options.projectRoot ?? process.cwd());
@@ -2978,9 +3085,7 @@ async function runWisdomBackendDeploy(options) {
2978
3085
  log(`=== \u81EA\u52A8\u90E8\u7F72: ${config.projectName} ===`);
2979
3086
  log(`\u914D\u7F6E\u6587\u4EF6: ${path2.join(workspaceApmDir(), "apm.config.json")}`);
2980
3087
  log(`\u9879\u76EE\u6839\u76EE\u5F55: ${projectRoot}`);
2981
- if (!options.skipMaven) {
2982
- runMavenBuild(projectRoot, config.mavenLocalRepo);
2983
- }
3088
+ runMavenBuild(projectRoot, config.mavenLocalRepo);
2984
3089
  const libDir = locateLibDir(projectRoot);
2985
3090
  let manifest = loadManifest3();
2986
3091
  const conn = await connectSsh(config);
@@ -3026,12 +3131,7 @@ async function runWisdomBackendDeploy(options) {
3026
3131
  }
3027
3132
  if (needRestart) {
3028
3133
  log("\u91CD\u542F\u670D\u52A1...");
3029
- await runSpringbootAction(
3030
- conn.client,
3031
- config,
3032
- "restart",
3033
- config.startupJar
3034
- );
3134
+ await restartRemoteService(conn.client, config);
3035
3135
  }
3036
3136
  await healthCheckService(conn.client, config);
3037
3137
  if (libUploadEntries.length > 0) {
@@ -3115,8 +3215,7 @@ async function runWisdomAutoDeploy(options) {
3115
3215
  );
3116
3216
  await runWisdomBackendDeploy({
3117
3217
  config: settings,
3118
- projectRoot: cwd,
3119
- skipMaven: Boolean(options.skipMaven)
3218
+ projectRoot: cwd
3120
3219
  });
3121
3220
  return { projectType };
3122
3221
  }
@@ -4505,33 +4604,30 @@ function registerDeployMainCommand(program) {
4505
4604
  ).argument("<env>", "\u90E8\u7F72\u73AF\u5883\u540D\uFF08\u5982 test\u3001online\uFF09").option(
4506
4605
  "--config <path>",
4507
4606
  "apm.config.json \u8DEF\u5F84\uFF08\u9ED8\u8BA4 .apm/apm.config.json\uFF09"
4508
- ).option("--skip-maven", "\u8DF3\u8FC7 Maven \u6784\u5EFA\uFF08\u4EC5\u533B\u52A1\u540E\u7AEF\uFF09").action(
4509
- async (env, opts) => {
4510
- const cwd = process.cwd();
4511
- const cfg = loadApmConfig({ configPath: opts.config });
4512
- if (isWisdomLegacyDeploy(cfg)) {
4513
- await runWisdomAutoDeploy({
4514
- env,
4515
- cwd,
4516
- configPath: opts.config,
4517
- skipMaven: opts.skipMaven
4518
- });
4519
- return;
4520
- }
4521
- const deployCommands = cfg.deploy ?? {};
4522
- const command = deployCommands[env]?.trim();
4523
- if (!command) {
4524
- const keys = Object.keys(deployCommands);
4525
- console.error(
4526
- keys.length > 0 ? `apm.config.json \u4E2D\u672A\u914D\u7F6E deploy.${env}\uFF0C\u53EF\u7528\u73AF\u5883: ${keys.join(
4527
- ", "
4528
- )}` : `apm.config.json \u4E2D\u672A\u914D\u7F6E deploy \u6BB5`
4529
- );
4530
- process.exit(1);
4531
- }
4532
- runShellCommand3(command, cwd);
4607
+ ).action(async (env, opts) => {
4608
+ const cwd = process.cwd();
4609
+ const cfg = loadApmConfig({ configPath: opts.config });
4610
+ if (isWisdomLegacyDeploy(cfg)) {
4611
+ await runWisdomAutoDeploy({
4612
+ env,
4613
+ cwd,
4614
+ configPath: opts.config
4615
+ });
4616
+ return;
4533
4617
  }
4534
- );
4618
+ const deployCommands = cfg.deploy ?? {};
4619
+ const command = deployCommands[env]?.trim();
4620
+ if (!command) {
4621
+ const keys = Object.keys(deployCommands);
4622
+ console.error(
4623
+ keys.length > 0 ? `apm.config.json \u4E2D\u672A\u914D\u7F6E deploy.${env}\uFF0C\u53EF\u7528\u73AF\u5883: ${keys.join(
4624
+ ", "
4625
+ )}` : `apm.config.json \u4E2D\u672A\u914D\u7F6E deploy \u6BB5`
4626
+ );
4627
+ process.exit(1);
4628
+ }
4629
+ runShellCommand3(command, cwd);
4630
+ });
4535
4631
  }
4536
4632
 
4537
4633
  // src/commands/deploy/backend.ts
@@ -5431,12 +5527,11 @@ function registerDeployWisdomBackendCommands(program) {
5431
5527
  ).option(
5432
5528
  "--config <path>",
5433
5529
  "apm.config.json \u8DEF\u5F84\uFF08\u9ED8\u8BA4 .apm/apm.config.json\uFF09"
5434
- ).option("--skip-maven", "\u8DF3\u8FC7 Maven \u6784\u5EFA\uFF0C\u4EC5\u4E0A\u4F20\u5E76\u91CD\u542F").action(async (opts) => {
5530
+ ).action(async (opts) => {
5435
5531
  const cfg = loadApmConfig({ configPath: opts.config });
5436
5532
  const settings = resolveWisdomBackendDeployFromApmConfig(cfg);
5437
5533
  await runWisdomBackendDeploy({
5438
- config: settings,
5439
- skipMaven: Boolean(opts.skipMaven)
5534
+ config: settings
5440
5535
  });
5441
5536
  });
5442
5537
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai-project-manage-cli",
3
- "version": "6.0.67",
3
+ "version": "6.0.69",
4
4
  "description": "命令行工具:后续用于调用平台后端 API 完成运维与自动化操作",
5
5
  "type": "module",
6
6
  "private": false,