ai-project-manage-cli 6.0.103 → 6.0.104

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 +728 -466
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -2878,33 +2878,17 @@ function posixBasename(p) {
2878
2878
  }
2879
2879
 
2880
2880
  // src/commands/deploy/internal/deploy-hints.ts
2881
- function formatDeployNotConfiguredLines(env, deployCommands) {
2882
- const configuredEnvs = Object.keys(deployCommands).filter(
2883
- (key) => deployCommands[key]?.trim()
2884
- );
2885
- if (configuredEnvs.length > 0) {
2886
- return [
2887
- `[apm] \u65E0\u6CD5\u6267\u884C\u90E8\u7F72\uFF1Aapm.config.json \u4E2D\u672A\u914D\u7F6E deploy.${env}`,
2888
- `[apm] \u5F53\u524D\u5DF2\u914D\u7F6E\u7684\u73AF\u5883: ${configuredEnvs.join(", ")}`
2889
- ];
2890
- }
2881
+ function formatMissingWisdomDeployLines() {
2891
2882
  return [
2892
- "[apm] \u65E0\u6CD5\u6267\u884C\u90E8\u7F72\uFF1A\u5F53\u524D\u9879\u76EE\u672A\u914D\u7F6E\u81EA\u52A8\u5316\u90E8\u7F72\uFF08apm.config.json \u4E2D\u65E0 deploy \u6BB5\uFF09",
2893
- "[apm] \u90E8\u5206\u9879\u76EE\u4E0D\u652F\u6301\u6216\u672A\u542F\u7528\u81EA\u52A8\u5316\u90E8\u7F72\uFF0C\u5C5E\u6B63\u5E38\u60C5\u51B5\uFF0C\u53EF\u8DF3\u8FC7\u90E8\u7F72"
2883
+ "[apm] \u65E0\u6CD5\u6267\u884C apm deploy\uFF1A\u8BF7\u5728 apm.config.json \u4E2D\u914D\u7F6E wisdomDeploy\uFF08host\u3001remotePath\uFF09"
2894
2884
  ];
2895
2885
  }
2896
2886
  function formatWisdomFrontendBuildNotConfiguredLines(env, packageJsonPath) {
2897
2887
  return [
2898
- `[apm] \u65E0\u6CD5\u6267\u884C\u4EC5\u6253\u5305\uFF1A${packageJsonPath} \u4E2D\u672A\u627E\u5230 build:${env} \u811A\u672C`,
2888
+ `[apm] \u65E0\u6CD5\u6267\u884C\u524D\u7AEF\u90E8\u7F72\uFF1A${packageJsonPath} \u4E2D\u672A\u627E\u5230 build:${env} \u811A\u672C`,
2899
2889
  "[apm] \u8BF7\u914D\u7F6E npm run build:test / build:online \u540E\u518D\u8BD5"
2900
2890
  ];
2901
2891
  }
2902
- function formatWisdomFrontendDeployNotConfiguredLines(env, packageJsonPath) {
2903
- return [
2904
- `[apm] \u65E0\u6CD5\u6267\u884C\u90E8\u7F72\uFF1A${packageJsonPath} \u4E2D\u672A\u627E\u5230 deploy:${env} \u811A\u672C`,
2905
- "[apm] \u82E5\u672C\u9879\u76EE\u4E0D\u652F\u6301\u81EA\u52A8\u5316\u90E8\u7F72\uFF0C\u5C5E\u6B63\u5E38\u60C5\u51B5\uFF0C\u53EF\u8DF3\u8FC7\u90E8\u7F72"
2906
- ];
2907
- }
2908
2892
 
2909
2893
  // src/commands/deploy/deploy-errors.ts
2910
2894
  var DeployExecutionError = class extends Error {
@@ -2918,8 +2902,260 @@ var DeployExecutionError = class extends Error {
2918
2902
  }
2919
2903
  };
2920
2904
 
2921
- // src/commands/deploy/deploy-shell-run.ts
2905
+ // src/commands/deploy/deploy-debug-log.ts
2922
2906
  import { spawnSync as spawnSync4 } from "node:child_process";
2907
+ import { existsSync as existsSync14 } from "node:fs";
2908
+ import { dirname as dirname5, join as join16 } from "node:path";
2909
+
2910
+ // src/commands/deploy/internal/deploy-artifact-minio.ts
2911
+ import { readFile as readFile2 } from "node:fs/promises";
2912
+
2913
+ // src/commands/deploy/internal/minio.ts
2914
+ import { statSync as statSync5 } from "node:fs";
2915
+ import { readdir, readFile } from "node:fs/promises";
2916
+ import path from "node:path";
2917
+ import * as Minio from "minio";
2918
+ var DEFAULT_MAX_FILE_SIZE_MB = 50;
2919
+ async function isDirectoryPath(dir) {
2920
+ try {
2921
+ const st = statSync5(dir);
2922
+ return st.isDirectory();
2923
+ } catch {
2924
+ return false;
2925
+ }
2926
+ }
2927
+ function sanitizeRelativePath(rel) {
2928
+ const norm = rel.replace(/\\/g, "/").replace(/^\/+/, "");
2929
+ const segments = norm.split("/").filter(Boolean);
2930
+ for (const s of segments) {
2931
+ if (s === "." || s === "..") {
2932
+ throw new Error(`\u975E\u6CD5\u76F8\u5BF9\u8DEF\u5F84\u7247\u6BB5\uFF1A${s}`);
2933
+ }
2934
+ }
2935
+ return segments.join("/");
2936
+ }
2937
+ async function collectFiles(root) {
2938
+ const out = [];
2939
+ async function walk(dir, prefix) {
2940
+ const entries = await readdir(dir, { withFileTypes: true });
2941
+ for (const e of entries) {
2942
+ const name = e.name;
2943
+ if (name === "." || name === "..") {
2944
+ continue;
2945
+ }
2946
+ const abs = path.join(dir, name);
2947
+ const rel = prefix ? `${prefix}/${name}` : name;
2948
+ if (e.isDirectory()) {
2949
+ await walk(abs, rel);
2950
+ } else if (e.isFile()) {
2951
+ const st = statSync5(abs);
2952
+ out.push({
2953
+ absPath: abs,
2954
+ relativePath: rel.replace(/\\/g, "/"),
2955
+ size: st.size
2956
+ });
2957
+ }
2958
+ }
2959
+ }
2960
+ await walk(root, "");
2961
+ out.sort((a, b) => a.relativePath.localeCompare(b.relativePath));
2962
+ return out;
2963
+ }
2964
+ async function readArtifactFile(absPath) {
2965
+ return readFile(absPath);
2966
+ }
2967
+ function toMB(bytes) {
2968
+ return Math.round(bytes / (1024 * 1024) * 1e3) / 1e3;
2969
+ }
2970
+ var MIME = {
2971
+ ".html": "text/html; charset=utf-8",
2972
+ ".css": "text/css; charset=utf-8",
2973
+ ".js": "application/javascript; charset=utf-8",
2974
+ ".json": "application/json; charset=utf-8",
2975
+ ".svg": "image/svg+xml",
2976
+ ".png": "image/png",
2977
+ ".jpg": "image/jpeg",
2978
+ ".jpeg": "image/jpeg",
2979
+ ".gif": "image/gif",
2980
+ ".webp": "image/webp",
2981
+ ".woff": "font/woff",
2982
+ ".woff2": "font/woff2",
2983
+ ".ttf": "font/ttf",
2984
+ ".ico": "image/x-icon",
2985
+ ".txt": "text/plain; charset=utf-8",
2986
+ ".map": "application/json"
2987
+ };
2988
+ function detectMimeType(filePath) {
2989
+ const ext = path.extname(filePath).toLowerCase();
2990
+ return MIME[ext] ?? "";
2991
+ }
2992
+ var MinioClient = class {
2993
+ inner;
2994
+ constructor(opts) {
2995
+ const endPoint = opts.endPoint.replace(/^https?:\/\//i, "").split("/")[0] ?? opts.endPoint;
2996
+ this.inner = new Minio.Client({
2997
+ endPoint,
2998
+ port: opts.port,
2999
+ useSSL: opts.useSSL,
3000
+ accessKey: opts.accessKey,
3001
+ secretKey: opts.secretKey
3002
+ });
3003
+ }
3004
+ async ensureBucket(bucket) {
3005
+ const exists = await this.inner.bucketExists(bucket);
3006
+ if (!exists) {
3007
+ await this.inner.makeBucket(bucket);
3008
+ }
3009
+ }
3010
+ async deleteObjectsByPrefix(bucket, prefix) {
3011
+ const objectsStream = this.inner.listObjectsV2(bucket, prefix, true);
3012
+ const keys = [];
3013
+ await new Promise((resolve5, reject) => {
3014
+ objectsStream.on("data", (obj) => {
3015
+ if (obj.name) {
3016
+ keys.push(obj.name);
3017
+ }
3018
+ });
3019
+ objectsStream.on("error", reject);
3020
+ objectsStream.on("end", resolve5);
3021
+ });
3022
+ const chunkSize = 500;
3023
+ for (let i = 0; i < keys.length; i += chunkSize) {
3024
+ const chunk = keys.slice(i, i + chunkSize);
3025
+ await this.inner.removeObjects(
3026
+ bucket,
3027
+ chunk.map((name) => name)
3028
+ );
3029
+ }
3030
+ }
3031
+ async putObject(bucket, objectKey, body, meta) {
3032
+ await this.inner.putObject(bucket, objectKey, body, body.length, meta);
3033
+ }
3034
+ /** 匿名可读当前桶全部对象(便于静态站点直链) */
3035
+ async setBucketPublicRead(bucket) {
3036
+ const policy = {
3037
+ Version: "2012-10-17",
3038
+ Statement: [
3039
+ {
3040
+ Effect: "Allow",
3041
+ Principal: { AWS: ["*"] },
3042
+ Action: ["s3:GetObject"],
3043
+ Resource: [`arn:aws:s3:::${bucket}/*`]
3044
+ }
3045
+ ]
3046
+ };
3047
+ await this.inner.setBucketPolicy(bucket, JSON.stringify(policy));
3048
+ }
3049
+ };
3050
+
3051
+ // src/commands/deploy/internal/deploy-artifact-minio.ts
3052
+ var APM_DEPLOYMENT_RUN_ID_ENV = "APM_DEPLOYMENT_RUN_ID";
3053
+ function formatDeployArtifactTimestamp(date = /* @__PURE__ */ new Date()) {
3054
+ const pad = (n) => String(n).padStart(2, "0");
3055
+ return `${date.getFullYear()}${pad(date.getMonth() + 1)}${pad(date.getDate())}${pad(date.getHours())}${pad(date.getMinutes())}${pad(date.getSeconds())}`;
3056
+ }
3057
+ function sanitizeDeployProjectName(name) {
3058
+ const trimmed = name.trim().replace(/\\/g, "/");
3059
+ const base = trimmed.split("/").filter(Boolean).pop() ?? trimmed;
3060
+ try {
3061
+ return sanitizeRelativePath(base.replace(/[/\\:*?"<>|]/g, "_"));
3062
+ } catch {
3063
+ return "project";
3064
+ }
3065
+ }
3066
+ function buildDeployArtifactFileName(kind, projectName, timestamp = formatDeployArtifactTimestamp()) {
3067
+ const safeName = sanitizeDeployProjectName(projectName);
3068
+ const suffix = kind === "frontend" ? "dist.zip" : "jar.zip";
3069
+ return `${timestamp}-${safeName}.${suffix}`;
3070
+ }
3071
+ function buildDeployArtifactObjectKey(projectName, fileName) {
3072
+ const safeProject = sanitizeDeployProjectName(projectName);
3073
+ return `deploy/${safeProject}/${fileName}`;
3074
+ }
3075
+ function resolveDeploymentRunIdFromEnv() {
3076
+ const raw = process.env[APM_DEPLOYMENT_RUN_ID_ENV]?.trim();
3077
+ return raw || null;
3078
+ }
3079
+ async function fetchDeployArtifactStorage(api) {
3080
+ return api.cli.getDeployArtifactStorage(void 0);
3081
+ }
3082
+ async function uploadDeployArtifactZip(options) {
3083
+ const deploymentRunId = options.deploymentRunId ?? resolveDeploymentRunIdFromEnv();
3084
+ if (!deploymentRunId && !options.uploadWithoutRunId) {
3085
+ return null;
3086
+ }
3087
+ const cfg = await tryReadApmConfig();
3088
+ if (!cfg || !resolveApiKey(cfg)) {
3089
+ console.warn("[apm] \u672A\u767B\u5F55\uFF0C\u8DF3\u8FC7 MinIO \u90E8\u7F72\u4EA7\u7269\u5F52\u6863");
3090
+ return null;
3091
+ }
3092
+ const api = options.api ?? createApmApiClient(cfg);
3093
+ let storage;
3094
+ try {
3095
+ storage = await fetchDeployArtifactStorage(api);
3096
+ } catch (error) {
3097
+ const detail = error instanceof Error ? error.message : String(error);
3098
+ console.warn(`[apm] \u83B7\u53D6 MinIO \u914D\u7F6E\u5931\u8D25\uFF0C\u8DF3\u8FC7\u90E8\u7F72\u4EA7\u7269\u5F52\u6863: ${detail}`);
3099
+ return null;
3100
+ }
3101
+ const fileName = buildDeployArtifactFileName(
3102
+ options.kind,
3103
+ options.projectName,
3104
+ options.timestamp
3105
+ );
3106
+ const objectKey = buildDeployArtifactObjectKey(options.projectName, fileName);
3107
+ let body;
3108
+ try {
3109
+ body = await readFile2(options.zipPath);
3110
+ } catch (error) {
3111
+ const detail = error instanceof Error ? error.message : String(error);
3112
+ console.warn(`[apm] \u8BFB\u53D6\u90E8\u7F72\u4EA7\u7269 zip \u5931\u8D25\uFF0C\u8DF3\u8FC7 MinIO \u5F52\u6863: ${detail}`);
3113
+ return null;
3114
+ }
3115
+ try {
3116
+ const client = new MinioClient({
3117
+ endPoint: storage.endpoint,
3118
+ port: storage.port,
3119
+ useSSL: storage.useSsl,
3120
+ accessKey: storage.accessKey,
3121
+ secretKey: storage.secretKey
3122
+ });
3123
+ await client.ensureBucket(storage.bucket);
3124
+ await client.putObject(storage.bucket, objectKey, body, {
3125
+ "Content-Type": "application/zip"
3126
+ });
3127
+ console.error(
3128
+ `[apm] \u672C\u5730\u76F4\u4F20 MinIO\uFF08\u4E0D\u7ECF\u5E73\u53F0\u670D\u52A1\u5668\uFF09: ${storage.endpoint}:${storage.port}/${storage.bucket}/${objectKey} (${(body.length / 1024 / 1024).toFixed(
3129
+ 2
3130
+ )} MB)`
3131
+ );
3132
+ } catch (error) {
3133
+ const detail = error instanceof Error ? error.message : String(error);
3134
+ console.warn(`[apm] MinIO \u90E8\u7F72\u4EA7\u7269\u5F52\u6863\u5931\u8D25: ${detail}`);
3135
+ return null;
3136
+ }
3137
+ if (deploymentRunId) {
3138
+ try {
3139
+ await api.cli.attachTaskDeploymentArtifact({
3140
+ id: deploymentRunId,
3141
+ artifactObjectKey: objectKey,
3142
+ artifactFileName: fileName
3143
+ });
3144
+ console.error(
3145
+ `[apm] \u5DF2\u7ED1\u5B9A\u90E8\u7F72\u4EA7\u7269\u5230\u8BB0\u5F55 id=${deploymentRunId} file=${fileName}`
3146
+ );
3147
+ } catch (error) {
3148
+ const detail = error instanceof Error ? error.message : String(error);
3149
+ console.warn(`[apm] \u7ED1\u5B9A\u90E8\u7F72\u4EA7\u7269\u5230\u8BB0\u5F55\u5931\u8D25: ${detail}`);
3150
+ return null;
3151
+ }
3152
+ }
3153
+ return {
3154
+ objectKey,
3155
+ fileName,
3156
+ bucket: storage.bucket
3157
+ };
3158
+ }
2923
3159
 
2924
3160
  // src/commands/deploy/internal/deploy-shell-env.ts
2925
3161
  import { spawnSync as spawnSync3 } from "node:child_process";
@@ -3741,316 +3977,252 @@ function buildDeployShellEnv(extra) {
3741
3977
  return env;
3742
3978
  }
3743
3979
 
3744
- // src/commands/deploy/deploy-shell-run.ts
3745
- function runDeployShellCommand(command, cwd, captureOutput) {
3746
- const result = spawnSync4(command, {
3747
- cwd,
3748
- shell: true,
3749
- env: buildDeployShellEnv(),
3750
- encoding: "utf8",
3751
- maxBuffer: DEPLOY_SPAWN_MAX_BUFFER_BYTES,
3752
- stdio: captureOutput ? ["inherit", "pipe", "pipe"] : "inherit"
3753
- });
3754
- const stdout = captureOutput ? String(result.stdout ?? "") : "";
3755
- const stderr = captureOutput ? String(result.stderr ?? "") : "";
3756
- const output = [stdout, stderr].filter(Boolean).join("\n");
3757
- if (captureOutput) {
3758
- if (stdout) process.stdout.write(stdout);
3759
- if (stderr) process.stderr.write(stderr);
3760
- }
3761
- if (result.error) {
3762
- throw new DeployExecutionError(
3763
- `\u90E8\u7F72\u547D\u4EE4\u6267\u884C\u5931\u8D25: ${result.error.message}`,
3764
- 1,
3765
- output
3766
- );
3767
- }
3768
- if (result.status !== 0) {
3769
- throw new DeployExecutionError(
3770
- `\u90E8\u7F72\u547D\u4EE4\u9000\u51FA\u7801 ${result.status ?? "unknown"}: ${command}`,
3771
- result.status ?? 1,
3772
- output
3773
- );
3774
- }
3775
- return output;
3776
- }
3777
-
3778
- // src/commands/deploy/internal/wisdom-auto-deploy.ts
3779
- import { existsSync as existsSync15, readFileSync as readFileSync13, statSync as statSync7 } from "node:fs";
3780
- import path4 from "node:path";
3781
-
3782
- // src/commands/deploy/internal/wisdom-backend-deploy.ts
3783
- import {
3784
- existsSync as existsSync14,
3785
- mkdirSync as mkdirSync7,
3786
- readdirSync as readdirSync5,
3787
- readFileSync as readFileSync12,
3788
- statSync as statSync6,
3789
- writeFileSync as writeFileSync12
3790
- } from "node:fs";
3791
- import { spawnSync as spawnSync5 } from "node:child_process";
3792
- import path3 from "node:path";
3793
- import { Client as Client2 } from "ssh2";
3794
- import JSZip2 from "jszip";
3795
- import SftpClient2 from "ssh2-sftp-client";
3796
-
3797
- // src/commands/deploy/internal/wisdom-sftp.ts
3798
- import { readdir as readdir2, readFile as readFile3, unlink, writeFile } from "node:fs/promises";
3799
- import path2 from "node:path";
3800
- import JSZip from "jszip";
3801
- import SftpClient from "ssh2-sftp-client";
3802
-
3803
- // src/commands/deploy/internal/deploy-artifact-minio.ts
3804
- import { readFile as readFile2 } from "node:fs/promises";
3805
-
3806
- // src/commands/deploy/internal/minio.ts
3807
- import { statSync as statSync5 } from "node:fs";
3808
- import { readdir, readFile } from "node:fs/promises";
3809
- import path from "node:path";
3810
- import * as Minio from "minio";
3811
- var DEFAULT_MAX_FILE_SIZE_MB = 50;
3812
- async function isDirectoryPath(dir) {
3813
- try {
3814
- const st = statSync5(dir);
3815
- return st.isDirectory();
3816
- } catch {
3817
- return false;
3818
- }
3819
- }
3820
- function sanitizeRelativePath(rel) {
3821
- const norm = rel.replace(/\\/g, "/").replace(/^\/+/, "");
3822
- const segments = norm.split("/").filter(Boolean);
3823
- for (const s of segments) {
3824
- if (s === "." || s === "..") {
3825
- throw new Error(`\u975E\u6CD5\u76F8\u5BF9\u8DEF\u5F84\u7247\u6BB5\uFF1A${s}`);
3826
- }
3827
- }
3828
- return segments.join("/");
3829
- }
3830
- async function collectFiles(root) {
3831
- const out = [];
3832
- async function walk(dir, prefix) {
3833
- const entries = await readdir(dir, { withFileTypes: true });
3834
- for (const e of entries) {
3835
- const name = e.name;
3836
- if (name === "." || name === "..") {
3837
- continue;
3838
- }
3839
- const abs = path.join(dir, name);
3840
- const rel = prefix ? `${prefix}/${name}` : name;
3841
- if (e.isDirectory()) {
3842
- await walk(abs, rel);
3843
- } else if (e.isFile()) {
3844
- const st = statSync5(abs);
3845
- out.push({
3846
- absPath: abs,
3847
- relativePath: rel.replace(/\\/g, "/"),
3848
- size: st.size
3849
- });
3850
- }
3980
+ // src/commands/deploy/deploy-debug-log.ts
3981
+ var LOG_PREFIX = "[apm:deploy-debug]";
3982
+ var SENSITIVE_ENV_KEY = /(password|secret|token|api[_-]?key|authorization|credential|private|passwd)/i;
3983
+ var PATH_SEP2 = process.platform === "win32" ? ";" : ":";
3984
+ function logLine(message) {
3985
+ console.error(`${LOG_PREFIX} ${message}`);
3986
+ }
3987
+ function pathEntries(value) {
3988
+ if (!value?.trim()) return [];
3989
+ return value.split(PATH_SEP2).filter(Boolean);
3990
+ }
3991
+ function summarizePath(value, maxEntries = 12) {
3992
+ const entries = pathEntries(value);
3993
+ if (entries.length === 0) return "(empty)";
3994
+ const head = entries.slice(0, maxEntries).join(PATH_SEP2);
3995
+ if (entries.length <= maxEntries) return head;
3996
+ return `${head}${PATH_SEP2}\u2026 (+${entries.length - maxEntries} more)`;
3997
+ }
3998
+ function pickEnvKeys(env, keys) {
3999
+ const out = {};
4000
+ for (const key of keys) {
4001
+ const value = env[key];
4002
+ if (value !== void 0 && value !== "") {
4003
+ out[key] = value;
3851
4004
  }
3852
4005
  }
3853
- await walk(root, "");
3854
- out.sort((a, b) => a.relativePath.localeCompare(b.relativePath));
3855
4006
  return out;
3856
4007
  }
3857
- async function readArtifactFile(absPath) {
3858
- return readFile(absPath);
3859
- }
3860
- function toMB(bytes) {
3861
- return Math.round(bytes / (1024 * 1024) * 1e3) / 1e3;
3862
- }
3863
- var MIME = {
3864
- ".html": "text/html; charset=utf-8",
3865
- ".css": "text/css; charset=utf-8",
3866
- ".js": "application/javascript; charset=utf-8",
3867
- ".json": "application/json; charset=utf-8",
3868
- ".svg": "image/svg+xml",
3869
- ".png": "image/png",
3870
- ".jpg": "image/jpeg",
3871
- ".jpeg": "image/jpeg",
3872
- ".gif": "image/gif",
3873
- ".webp": "image/webp",
3874
- ".woff": "font/woff",
3875
- ".woff2": "font/woff2",
3876
- ".ttf": "font/ttf",
3877
- ".ico": "image/x-icon",
3878
- ".txt": "text/plain; charset=utf-8",
3879
- ".map": "application/json"
3880
- };
3881
- function detectMimeType(filePath) {
3882
- const ext = path.extname(filePath).toLowerCase();
3883
- return MIME[ext] ?? "";
3884
- }
3885
- var MinioClient = class {
3886
- inner;
3887
- constructor(opts) {
3888
- const endPoint = opts.endPoint.replace(/^https?:\/\//i, "").split("/")[0] ?? opts.endPoint;
3889
- this.inner = new Minio.Client({
3890
- endPoint,
3891
- port: opts.port,
3892
- useSSL: opts.useSSL,
3893
- accessKey: opts.accessKey,
3894
- secretKey: opts.secretKey
3895
- });
3896
- }
3897
- async ensureBucket(bucket) {
3898
- const exists = await this.inner.bucketExists(bucket);
3899
- if (!exists) {
3900
- await this.inner.makeBucket(bucket);
4008
+ function collectInterestingEnv(env) {
4009
+ const keys = /* @__PURE__ */ new Set([
4010
+ "PATH",
4011
+ "HOME",
4012
+ "USER",
4013
+ "LOGNAME",
4014
+ "SHELL",
4015
+ "LANG",
4016
+ "LC_ALL",
4017
+ "NODE_ENV",
4018
+ "npm_config_registry",
4019
+ "NPM_CONFIG_REGISTRY",
4020
+ "npm_config_prefix",
4021
+ "NPM_CONFIG_PREFIX",
4022
+ APM_DEPLOYMENT_RUN_ID_ENV
4023
+ ]);
4024
+ for (const key of Object.keys(env)) {
4025
+ if (/^npm_config_/i.test(key) || /^NPM_CONFIG_/i.test(key)) {
4026
+ keys.add(key);
3901
4027
  }
3902
- }
3903
- async deleteObjectsByPrefix(bucket, prefix) {
3904
- const objectsStream = this.inner.listObjectsV2(bucket, prefix, true);
3905
- const keys = [];
3906
- await new Promise((resolve5, reject) => {
3907
- objectsStream.on("data", (obj) => {
3908
- if (obj.name) {
3909
- keys.push(obj.name);
3910
- }
3911
- });
3912
- objectsStream.on("error", reject);
3913
- objectsStream.on("end", resolve5);
3914
- });
3915
- const chunkSize = 500;
3916
- for (let i = 0; i < keys.length; i += chunkSize) {
3917
- const chunk = keys.slice(i, i + chunkSize);
3918
- await this.inner.removeObjects(
3919
- bucket,
3920
- chunk.map((name) => name)
3921
- );
4028
+ if (/^APM_/i.test(key) && !SENSITIVE_ENV_KEY.test(key)) {
4029
+ keys.add(key);
3922
4030
  }
3923
4031
  }
3924
- async putObject(bucket, objectKey, body, meta) {
3925
- await this.inner.putObject(bucket, objectKey, body, body.length, meta);
3926
- }
3927
- /** 匿名可读当前桶全部对象(便于静态站点直链) */
3928
- async setBucketPublicRead(bucket) {
3929
- const policy = {
3930
- Version: "2012-10-17",
3931
- Statement: [
3932
- {
3933
- Effect: "Allow",
3934
- Principal: { AWS: ["*"] },
3935
- Action: ["s3:GetObject"],
3936
- Resource: [`arn:aws:s3:::${bucket}/*`]
3937
- }
3938
- ]
3939
- };
3940
- await this.inner.setBucketPolicy(bucket, JSON.stringify(policy));
3941
- }
3942
- };
3943
-
3944
- // src/commands/deploy/internal/deploy-artifact-minio.ts
3945
- var APM_DEPLOYMENT_RUN_ID_ENV = "APM_DEPLOYMENT_RUN_ID";
3946
- function formatDeployArtifactTimestamp(date = /* @__PURE__ */ new Date()) {
3947
- const pad = (n) => String(n).padStart(2, "0");
3948
- return `${date.getFullYear()}${pad(date.getMonth() + 1)}${pad(date.getDate())}${pad(date.getHours())}${pad(date.getMinutes())}${pad(date.getSeconds())}`;
3949
- }
3950
- function sanitizeDeployProjectName(name) {
3951
- const trimmed = name.trim().replace(/\\/g, "/");
3952
- const base = trimmed.split("/").filter(Boolean).pop() ?? trimmed;
3953
- try {
3954
- return sanitizeRelativePath(base.replace(/[/\\:*?"<>|]/g, "_"));
3955
- } catch {
3956
- return "project";
3957
- }
4032
+ const picked = {};
4033
+ for (const key of [...keys].sort()) {
4034
+ const value = env[key];
4035
+ if (value === void 0 || value === "") continue;
4036
+ picked[key] = SENSITIVE_ENV_KEY.test(key) ? "***" : value;
4037
+ }
4038
+ return picked;
3958
4039
  }
3959
- function buildDeployArtifactFileName(kind, projectName, timestamp = formatDeployArtifactTimestamp()) {
3960
- const safeName = sanitizeDeployProjectName(projectName);
3961
- const suffix = kind === "frontend" ? "dist.zip" : "jar.zip";
3962
- return `${timestamp}-${safeName}.${suffix}`;
4040
+ function describePathDelta(before, after) {
4041
+ const beforeSet = new Set(pathEntries(before));
4042
+ const added = pathEntries(after).filter((entry) => !beforeSet.has(entry));
4043
+ if (added.length === 0) return "buildDeployShellEnv \u672A prepend \u65B0 PATH \u6BB5";
4044
+ return `prepend: ${added.join(PATH_SEP2)}`;
3963
4045
  }
3964
- function buildDeployArtifactObjectKey(projectName, fileName) {
3965
- const safeProject = sanitizeDeployProjectName(projectName);
3966
- return `deploy/${safeProject}/${fileName}`;
4046
+ function probeCommand(label, command, cwd, env) {
4047
+ const result = spawnSync4(command, {
4048
+ cwd,
4049
+ shell: true,
4050
+ env,
4051
+ encoding: "utf8",
4052
+ stdio: ["ignore", "pipe", "pipe"]
4053
+ });
4054
+ const stdout = String(result.stdout ?? "").trim();
4055
+ const stderr = String(result.stderr ?? "").trim();
4056
+ const detail = stdout || stderr || "(no output)";
4057
+ logLine(
4058
+ `probe ${label}: exit=${result.status ?? "null"} output=${detail.slice(
4059
+ 0,
4060
+ 500
4061
+ )}`
4062
+ );
3967
4063
  }
3968
- function resolveDeploymentRunIdFromEnv() {
3969
- const raw = process.env[APM_DEPLOYMENT_RUN_ID_ENV]?.trim();
3970
- return raw || null;
4064
+ function probeShellTooling(cwd, env) {
4065
+ logLine("--- shell \u5DE5\u5177\u63A2\u6D4B\uFF08\u4E0E runDeployShellCommand \u76F8\u540C env/cwd\uFF09---");
4066
+ probeCommand("node -v", "node -v", cwd, env);
4067
+ probeCommand("npm -v", "npm -v", cwd, env);
4068
+ if (process.platform === "win32") {
4069
+ probeCommand("where node", "where node", cwd, env);
4070
+ probeCommand("where npm", "where npm", cwd, env);
4071
+ } else {
4072
+ probeCommand("which node", "which node", cwd, env);
4073
+ probeCommand("which npm", "which npm", cwd, env);
4074
+ }
4075
+ }
4076
+ function logExecuteDeployContext(input) {
4077
+ const trigger = input.trigger ?? "cli";
4078
+ const deploymentRunId = process.env[APM_DEPLOYMENT_RUN_ID_ENV]?.trim() || null;
4079
+ const shellEnv = buildDeployShellEnv();
4080
+ const npmGlobalBin = resolveNpmGlobalBin2();
4081
+ const packageJsonPath = join16(input.cwd, "package.json");
4082
+ logLine("========== executeDeploy \u4E0A\u4E0B\u6587 ==========");
4083
+ logLine(`trigger=${trigger} deployEnv=${input.env}`);
4084
+ logLine(`cwd(input)=${input.cwdInput}`);
4085
+ logLine(`cwd(resolved)=${input.cwd}`);
4086
+ logLine(`process.cwd()=${input.processCwd}`);
4087
+ logLine(
4088
+ `cwdMatchProcess=${input.cwd === input.processCwd ? "yes" : "no"} (connect \u901A\u5E38\u4E3A no)`
4089
+ );
4090
+ logLine(
4091
+ `apm.config=${input.apmConfigPath} exists=${existsSync14(
4092
+ input.apmConfigPath
4093
+ )}`
4094
+ );
4095
+ logLine(
4096
+ `package.json=${packageJsonPath} exists=${existsSync14(packageJsonPath)}`
4097
+ );
4098
+ logLine(
4099
+ `flags captureOutput=${input.captureOutput} packOnly=${Boolean(
4100
+ input.packOnly
4101
+ )} archiveDeployArtifact=${Boolean(input.archiveDeployArtifact)}`
4102
+ );
4103
+ logLine(`configPathOption=${input.configPathOption ?? "(default)"}`);
4104
+ logLine(`${APM_DEPLOYMENT_RUN_ID_ENV}=${deploymentRunId ?? "(unset)"}`);
4105
+ logLine(
4106
+ `process execPath=${process.execPath} pid=${process.pid} platform=${process.platform} arch=${process.arch}`
4107
+ );
4108
+ logLine(`process argv=${process.argv.join(" ")}`);
4109
+ logLine(`npmGlobalBin=${npmGlobalBin ?? "(resolve failed)"}`);
4110
+ logLine(`nodeDir=${dirname5(process.execPath)}`);
4111
+ logLine("--- process.env\uFF08\u8282\u9009\uFF09---");
4112
+ for (const [key, value] of Object.entries(
4113
+ collectInterestingEnv(process.env)
4114
+ )) {
4115
+ logLine(` ${key}=${value}`);
4116
+ }
4117
+ logLine(`process.env.PATH=${summarizePath(process.env.PATH)}`);
4118
+ logLine("--- buildDeployShellEnv()\uFF08\u5B50\u8FDB\u7A0B\u5B9E\u9645 env\uFF09---");
4119
+ logLine(describePathDelta(process.env.PATH, shellEnv.PATH));
4120
+ logLine(`shellEnv.PATH=${summarizePath(shellEnv.PATH)}`);
4121
+ for (const [key, value] of Object.entries(
4122
+ pickEnvKeys(shellEnv, [APM_DEPLOYMENT_RUN_ID_ENV, "NODE_ENV"])
4123
+ )) {
4124
+ logLine(` shellEnv.${key}=${value}`);
4125
+ }
4126
+ probeShellTooling(input.cwd, shellEnv);
4127
+ logLine("==========================================");
4128
+ }
4129
+ function logRunDeployShellContext(input) {
4130
+ const shellEnv = buildDeployShellEnv();
4131
+ logLine("---------- runDeployShellCommand ----------");
4132
+ logLine(`command=${input.command}`);
4133
+ logLine(`cwd=${input.cwd}`);
4134
+ logLine(`captureOutput=${input.captureOutput}`);
4135
+ logLine(
4136
+ `stdio=${input.captureOutput ? "stdin=inherit stdout=pipe stderr=pipe" : "inherit"}`
4137
+ );
4138
+ logLine(`shell=true maxBuffer=${50 * 1024 * 1024}`);
4139
+ logLine(`shellEnv.PATH(head)=${summarizePath(shellEnv.PATH, 8)}`);
4140
+ logLine("--------------------------------------------");
3971
4141
  }
3972
- async function fetchDeployArtifactStorage(api) {
3973
- return api.cli.getDeployArtifactStorage(void 0);
4142
+ function logRunDeployShellResult(input) {
4143
+ logLine(
4144
+ `runDeployShellCommand done command=${input.command} exit=${input.exitCode ?? "null"} signal=${input.signal ?? "null"} capturedBytes=${input.outputBytes}${input.errorMessage ? ` error=${input.errorMessage}` : ""}`
4145
+ );
3974
4146
  }
3975
- async function uploadDeployArtifactZip(options) {
3976
- const deploymentRunId = options.deploymentRunId ?? resolveDeploymentRunIdFromEnv();
3977
- if (!deploymentRunId && !options.uploadWithoutRunId) {
3978
- return null;
3979
- }
3980
- const cfg = await tryReadApmConfig();
3981
- if (!cfg || !resolveApiKey(cfg)) {
3982
- console.warn("[apm] \u672A\u767B\u5F55\uFF0C\u8DF3\u8FC7 MinIO \u90E8\u7F72\u4EA7\u7269\u5F52\u6863");
3983
- return null;
3984
- }
3985
- const api = options.api ?? createApmApiClient(cfg);
3986
- let storage;
3987
- try {
3988
- storage = await fetchDeployArtifactStorage(api);
3989
- } catch (error) {
3990
- const detail = error instanceof Error ? error.message : String(error);
3991
- console.warn(`[apm] \u83B7\u53D6 MinIO \u914D\u7F6E\u5931\u8D25\uFF0C\u8DF3\u8FC7\u90E8\u7F72\u4EA7\u7269\u5F52\u6863: ${detail}`);
3992
- return null;
3993
- }
3994
- const fileName = buildDeployArtifactFileName(
3995
- options.kind,
3996
- options.projectName,
3997
- options.timestamp
4147
+ function logWisdomFrontendDeployContext(input) {
4148
+ logLine("--- wisdom Vue \u524D\u7AEF ---");
4149
+ logLine(
4150
+ `buildKey=build:${input.env} buildCmd=${input.buildCmd ?? "(missing)"}`
3998
4151
  );
3999
- const objectKey = buildDeployArtifactObjectKey(options.projectName, fileName);
4000
- let body;
4001
- try {
4002
- body = await readFile2(options.zipPath);
4003
- } catch (error) {
4004
- const detail = error instanceof Error ? error.message : String(error);
4005
- console.warn(`[apm] \u8BFB\u53D6\u90E8\u7F72\u4EA7\u7269 zip \u5931\u8D25\uFF0C\u8DF3\u8FC7 MinIO \u5F52\u6863: ${detail}`);
4006
- return null;
4152
+ logLine(`distDir=${input.distDir} exists=${existsSync14(input.distDir)}`);
4153
+ logLine(
4154
+ `packOnly=${input.packOnly} archiveDeployArtifact=${input.archiveDeployArtifact}`
4155
+ );
4156
+ }
4157
+
4158
+ // src/commands/deploy/internal/wisdom-deploy.ts
4159
+ import { existsSync as existsSync16, readFileSync as readFileSync13, statSync as statSync7 } from "node:fs";
4160
+ import path4 from "node:path";
4161
+
4162
+ // src/commands/deploy/deploy-shell-run.ts
4163
+ import { spawnSync as spawnSync5 } from "node:child_process";
4164
+ function runDeployShellCommand(command, cwd, captureOutput) {
4165
+ logRunDeployShellContext({ command, cwd, captureOutput });
4166
+ const shellEnv = buildDeployShellEnv();
4167
+ const result = spawnSync5(command, {
4168
+ cwd,
4169
+ shell: true,
4170
+ env: shellEnv,
4171
+ encoding: "utf8",
4172
+ maxBuffer: DEPLOY_SPAWN_MAX_BUFFER_BYTES,
4173
+ stdio: captureOutput ? ["inherit", "pipe", "pipe"] : "inherit"
4174
+ });
4175
+ const stdout = captureOutput ? String(result.stdout ?? "") : "";
4176
+ const stderr = captureOutput ? String(result.stderr ?? "") : "";
4177
+ const output = [stdout, stderr].filter(Boolean).join("\n");
4178
+ logRunDeployShellResult({
4179
+ command,
4180
+ exitCode: result.status,
4181
+ signal: result.signal,
4182
+ errorMessage: result.error?.message,
4183
+ outputBytes: Buffer.byteLength(output, "utf8")
4184
+ });
4185
+ if (captureOutput) {
4186
+ if (stdout) process.stdout.write(stdout);
4187
+ if (stderr) process.stderr.write(stderr);
4007
4188
  }
4008
- try {
4009
- const client = new MinioClient({
4010
- endPoint: storage.endpoint,
4011
- port: storage.port,
4012
- useSSL: storage.useSsl,
4013
- accessKey: storage.accessKey,
4014
- secretKey: storage.secretKey
4015
- });
4016
- await client.ensureBucket(storage.bucket);
4017
- await client.putObject(storage.bucket, objectKey, body, {
4018
- "Content-Type": "application/zip"
4019
- });
4020
- console.error(
4021
- `[apm] \u672C\u5730\u76F4\u4F20 MinIO\uFF08\u4E0D\u7ECF\u5E73\u53F0\u670D\u52A1\u5668\uFF09: ${storage.endpoint}:${storage.port}/${storage.bucket}/${objectKey} (${(body.length / 1024 / 1024).toFixed(
4022
- 2
4023
- )} MB)`
4189
+ if (result.error) {
4190
+ throw new DeployExecutionError(
4191
+ `\u90E8\u7F72\u547D\u4EE4\u6267\u884C\u5931\u8D25: ${result.error.message}`,
4192
+ 1,
4193
+ output
4024
4194
  );
4025
- } catch (error) {
4026
- const detail = error instanceof Error ? error.message : String(error);
4027
- console.warn(`[apm] MinIO \u90E8\u7F72\u4EA7\u7269\u5F52\u6863\u5931\u8D25: ${detail}`);
4028
- return null;
4029
4195
  }
4030
- if (deploymentRunId) {
4031
- try {
4032
- await api.cli.attachTaskDeploymentArtifact({
4033
- id: deploymentRunId,
4034
- artifactObjectKey: objectKey,
4035
- artifactFileName: fileName
4036
- });
4037
- console.error(
4038
- `[apm] \u5DF2\u7ED1\u5B9A\u90E8\u7F72\u4EA7\u7269\u5230\u8BB0\u5F55 id=${deploymentRunId} file=${fileName}`
4039
- );
4040
- } catch (error) {
4041
- const detail = error instanceof Error ? error.message : String(error);
4042
- console.warn(`[apm] \u7ED1\u5B9A\u90E8\u7F72\u4EA7\u7269\u5230\u8BB0\u5F55\u5931\u8D25: ${detail}`);
4043
- return null;
4044
- }
4196
+ if (result.status !== 0) {
4197
+ throw new DeployExecutionError(
4198
+ `\u90E8\u7F72\u547D\u4EE4\u9000\u51FA\u7801 ${result.status ?? "unknown"}: ${command}`,
4199
+ result.status ?? 1,
4200
+ output
4201
+ );
4045
4202
  }
4046
- return {
4047
- objectKey,
4048
- fileName,
4049
- bucket: storage.bucket
4050
- };
4203
+ return output;
4051
4204
  }
4052
4205
 
4206
+ // src/commands/deploy/internal/wisdom-backend-deploy.ts
4207
+ import {
4208
+ existsSync as existsSync15,
4209
+ mkdirSync as mkdirSync7,
4210
+ readdirSync as readdirSync5,
4211
+ readFileSync as readFileSync12,
4212
+ statSync as statSync6,
4213
+ writeFileSync as writeFileSync12
4214
+ } from "node:fs";
4215
+ import { spawnSync as spawnSync6 } from "node:child_process";
4216
+ import path3 from "node:path";
4217
+ import { Client as Client2 } from "ssh2";
4218
+ import JSZip2 from "jszip";
4219
+ import SftpClient2 from "ssh2-sftp-client";
4220
+
4053
4221
  // src/commands/deploy/internal/wisdom-sftp.ts
4222
+ import { readdir as readdir2, readFile as readFile3, unlink, writeFile } from "node:fs/promises";
4223
+ import path2 from "node:path";
4224
+ import JSZip from "jszip";
4225
+ import SftpClient from "ssh2-sftp-client";
4054
4226
  async function addDirToZip(dir, zipFolder) {
4055
4227
  const entries = await readdir2(dir, { withFileTypes: true });
4056
4228
  for (const entry of entries) {
@@ -4208,10 +4380,27 @@ async function uploadAndMaybeExtract(settings, localZip, extract) {
4208
4380
  await sftp.end();
4209
4381
  }
4210
4382
  }
4383
+ function resolveDeployArtifactUpload(input) {
4384
+ const { packOnly, archiveDeployArtifact, deploymentRunId } = input;
4385
+ if (deploymentRunId) {
4386
+ return { upload: true, uploadWithoutRunId: false };
4387
+ }
4388
+ if (archiveDeployArtifact || packOnly) {
4389
+ return { upload: true, uploadWithoutRunId: true };
4390
+ }
4391
+ return { upload: false, uploadWithoutRunId: false };
4392
+ }
4211
4393
  async function runWisdomSftpDeploy(params) {
4212
4394
  const zipPath = path2.join(params.localDir, "..", ".deploy-sftp-dist.zip");
4213
4395
  const resolvedZipPath = path2.resolve(zipPath);
4214
4396
  const packOnly = Boolean(params.packOnly);
4397
+ const archiveDeployArtifact = Boolean(params.archiveDeployArtifact);
4398
+ const deploymentRunId = resolveDeploymentRunIdFromEnv();
4399
+ const artifactUpload = resolveDeployArtifactUpload({
4400
+ packOnly,
4401
+ archiveDeployArtifact,
4402
+ deploymentRunId
4403
+ });
4215
4404
  let zipSizeBytes = 0;
4216
4405
  let artifactUploaded = false;
4217
4406
  try {
@@ -4225,15 +4414,21 @@ async function runWisdomSftpDeploy(params) {
4225
4414
  } else {
4226
4415
  console.error("[apm] \u4EC5\u6253\u5305\u6A21\u5F0F\uFF1A\u8DF3\u8FC7 SFTP \u8FDC\u7A0B\u4E0A\u4F20");
4227
4416
  }
4228
- const artifact = await uploadDeployArtifactZip({
4229
- zipPath: resolvedZipPath,
4230
- projectName: params.projectName,
4231
- kind: "frontend",
4232
- uploadWithoutRunId: packOnly && !resolveDeploymentRunIdFromEnv()
4233
- });
4234
- artifactUploaded = artifact !== null;
4235
- if (packOnly && artifactUploaded) {
4236
- console.error("\u6253\u5305\u5E76\u4E0A\u4F20 MinIO \u5B8C\u6210\uFF08\u672A\u4E0A\u4F20\u8FDC\u7A0B\u670D\u52A1\u5668\uFF09");
4417
+ if (artifactUpload.upload) {
4418
+ const artifact = await uploadDeployArtifactZip({
4419
+ zipPath: resolvedZipPath,
4420
+ projectName: params.projectName,
4421
+ kind: "frontend",
4422
+ uploadWithoutRunId: artifactUpload.uploadWithoutRunId
4423
+ });
4424
+ artifactUploaded = artifact !== null;
4425
+ }
4426
+ if (artifactUploaded) {
4427
+ if (packOnly) {
4428
+ console.error("\u6253\u5305\u5E76\u4E0A\u4F20 MinIO \u5B8C\u6210\uFF08\u672A\u4E0A\u4F20\u8FDC\u7A0B\u670D\u52A1\u5668\uFF09");
4429
+ } else {
4430
+ console.error("[apm] SFTP \u90E8\u7F72\u5B8C\u6210\uFF0C\u90E8\u7F72\u4EA7\u7269\u5DF2\u5F52\u6863 MinIO");
4431
+ }
4237
4432
  }
4238
4433
  } finally {
4239
4434
  try {
@@ -4303,7 +4498,7 @@ function fileSignature(filePath) {
4303
4498
  }
4304
4499
  function loadManifest3() {
4305
4500
  const manifestPath2 = manifestFilePath();
4306
- if (!existsSync14(manifestPath2)) {
4501
+ if (!existsSync15(manifestPath2)) {
4307
4502
  return {};
4308
4503
  }
4309
4504
  return JSON.parse(readFileSync12(manifestPath2, "utf8"));
@@ -4388,7 +4583,7 @@ function getMvnExecutable() {
4388
4583
  const isWin = process.platform === "win32";
4389
4584
  const candidates = isWin ? ["mvn.cmd", "mvn.bat", "mvn"] : ["mvn"];
4390
4585
  for (const name of candidates) {
4391
- const result = spawnSync5(isWin ? `where ${name}` : `which ${name}`, {
4586
+ const result = spawnSync6(isWin ? `where ${name}` : `which ${name}`, {
4392
4587
  encoding: "utf8",
4393
4588
  shell: true
4394
4589
  });
@@ -4418,7 +4613,7 @@ function runMavenBuild(projectRoot, mavenLocalRepo, repoSource) {
4418
4613
  log(`Maven \u672C\u5730\u4ED3\u5E93: ${mavenRepo}`);
4419
4614
  }
4420
4615
  log(`\u6784\u5EFA\u76EE\u5F55: ${projectRoot}`);
4421
- const result = spawnSync5(command, {
4616
+ const result = spawnSync6(command, {
4422
4617
  cwd: projectRoot,
4423
4618
  stdio: "inherit",
4424
4619
  shell: true,
@@ -4430,11 +4625,11 @@ function runMavenBuild(projectRoot, mavenLocalRepo, repoSource) {
4430
4625
  }
4431
4626
  function locateLibDir(projectRoot) {
4432
4627
  const targetDir = getTargetDir(projectRoot);
4433
- if (!existsSync14(targetDir)) {
4628
+ if (!existsSync15(targetDir)) {
4434
4629
  fail(`\u6784\u5EFA\u4EA7\u7269\u76EE\u5F55\u4E0D\u5B58\u5728: ${targetDir}`);
4435
4630
  }
4436
4631
  const libDir = path3.join(targetDir, "lib");
4437
- if (!existsSync14(libDir) || !statSync6(libDir).isDirectory()) {
4632
+ if (!existsSync15(libDir) || !statSync6(libDir).isDirectory()) {
4438
4633
  fail(`lib \u76EE\u5F55\u4E0D\u5B58\u5728: ${libDir}`);
4439
4634
  }
4440
4635
  const libJars = readdirSync5(libDir).filter((name) => name.endsWith(".jar"));
@@ -4446,7 +4641,7 @@ function locateLibDir(projectRoot) {
4446
4641
  }
4447
4642
  function locateMainJar(projectRoot) {
4448
4643
  const targetDir = getTargetDir(projectRoot);
4449
- if (!existsSync14(targetDir)) {
4644
+ if (!existsSync15(targetDir)) {
4450
4645
  fail(`\u6784\u5EFA\u4EA7\u7269\u76EE\u5F55\u4E0D\u5B58\u5728: ${targetDir}`);
4451
4646
  }
4452
4647
  const jarFiles = readdirSync5(targetDir).filter((name) => name.endsWith(".jar") && !name.endsWith(".jar.original")).map((name) => path3.join(targetDir, name)).sort((a, b) => statSync6(b).mtimeMs - statSync6(a).mtimeMs);
@@ -4919,22 +5114,17 @@ async function runWisdomBackendDeploy(options) {
4919
5114
  log("\u90E8\u7F72\u5B8C\u6210");
4920
5115
  }
4921
5116
 
4922
- // src/commands/deploy/internal/wisdom-auto-deploy.ts
4923
- function isWisdomLegacyDeploy(cfg) {
5117
+ // src/commands/deploy/internal/wisdom-deploy.ts
5118
+ function isWisdomDeployConfigured(cfg) {
4924
5119
  const w = cfg.wisdomDeploy;
4925
- if (!w?.host?.trim() || !w.remotePath?.trim()) {
4926
- return false;
4927
- }
4928
- const hasNewFrontend = Boolean(cfg.frontendDeploy?.endpoint?.trim());
4929
- const hasNewBackend = Boolean(cfg.backendDeploy?.registryHost?.trim());
4930
- return !hasNewFrontend && !hasNewBackend;
5120
+ return Boolean(w?.host?.trim() && w?.remotePath?.trim());
4931
5121
  }
4932
5122
  function detectWisdomProjectType(cwd) {
4933
- return existsSync15(path4.join(cwd, "package.json")) ? "frontend" : "backend";
5123
+ return existsSync16(path4.join(cwd, "package.json")) ? "frontend" : "backend";
4934
5124
  }
4935
5125
  function readPackageScripts(cwd) {
4936
5126
  const pkgPath = path4.join(cwd, "package.json");
4937
- if (!existsSync15(pkgPath)) {
5127
+ if (!existsSync16(pkgPath)) {
4938
5128
  return {};
4939
5129
  }
4940
5130
  try {
@@ -4945,14 +5135,6 @@ function readPackageScripts(cwd) {
4945
5135
  return {};
4946
5136
  }
4947
5137
  }
4948
- function resolveFrontendDeployCommand(env, cwd) {
4949
- const scripts = readPackageScripts(cwd);
4950
- const deployKey = `deploy:${env}`;
4951
- if (scripts[deployKey]?.trim()) {
4952
- return `npm run deploy:${env}`;
4953
- }
4954
- return null;
4955
- }
4956
5138
  function resolveFrontendBuildCommand(env, cwd) {
4957
5139
  const scripts = readPackageScripts(cwd);
4958
5140
  const buildKey = `build:${env}`;
@@ -4966,7 +5148,7 @@ function resolveFrontendDistDir(cwd) {
4966
5148
  for (const rel of candidates) {
4967
5149
  const full = path4.join(cwd, rel);
4968
5150
  try {
4969
- if (existsSync15(full) && statSync7(full).isDirectory()) {
5151
+ if (existsSync16(full) && statSync7(full).isDirectory()) {
4970
5152
  return full;
4971
5153
  }
4972
5154
  } catch {
@@ -4974,62 +5156,57 @@ function resolveFrontendDistDir(cwd) {
4974
5156
  }
4975
5157
  return path4.join(cwd, "dist");
4976
5158
  }
4977
- async function runWisdomAutoDeploy(options) {
4978
- const cwd = path4.resolve(options.cwd ?? process.cwd());
4979
- const captureOutput = options.captureOutput ?? false;
4980
- const packOnly = Boolean(options.packOnly);
4981
- const projectType = detectWisdomProjectType(cwd);
4982
- const configPath = options.configPath ?? path4.join(workspaceApmDir(cwd), "apm.config.json");
4983
- const cfg = loadApmConfig({ configPath });
5159
+ async function executeWisdomFrontendDeploy(options) {
5160
+ const { cwd, cfg, captureOutput, packOnly, archiveDeployArtifact } = options;
5161
+ const buildCmd = resolveFrontendBuildCommand(options.env, cwd);
5162
+ const distDir = resolveFrontendDistDir(cwd);
5163
+ logWisdomFrontendDeployContext({
5164
+ env: options.env,
5165
+ cwd,
5166
+ buildCmd,
5167
+ distDir,
5168
+ packOnly,
5169
+ archiveDeployArtifact
5170
+ });
5171
+ if (!buildCmd) {
5172
+ const lines = formatWisdomFrontendBuildNotConfiguredLines(
5173
+ options.env,
5174
+ path4.join(cwd, "package.json")
5175
+ );
5176
+ throw new DeployExecutionError(lines.join("\n"), 1, lines.join("\n"));
5177
+ }
4984
5178
  console.error(
4985
- `[apm] \u533B\u52A1\u5B58\u91CF\u9879\u76EE\u81EA\u52A8\u8BC6\u522B: ${projectType === "frontend" ? "\u524D\u7AEF Vue" : "\u540E\u7AEF Java"}${packOnly ? "\uFF08\u4EC5\u6253\u5305\u6A21\u5F0F\uFF09" : ""}`
5179
+ `[apm] Vue\uFF1A${buildCmd}` + (packOnly ? "\uFF08\u4EC5\u6253\u5305\uFF0C\u8DF3\u8FC7 SFTP\uFF09" : " \u2192 SFTP \u4E0A\u4F20\u5E76\u8FDC\u7A0B\u89E3\u538B" + (archiveDeployArtifact ? " \u2192 \u5E73\u53F0\u90E8\u7F72\u4EA7\u7269\u5F52\u6863" : ""))
4986
5180
  );
4987
- if (projectType === "frontend") {
4988
- if (packOnly) {
4989
- const buildCmd = resolveFrontendBuildCommand(options.env, cwd);
4990
- if (!buildCmd) {
4991
- const lines = formatWisdomFrontendBuildNotConfiguredLines(
4992
- options.env,
4993
- path4.join(cwd, "package.json")
4994
- );
4995
- throw new DeployExecutionError(lines.join("\n"), 1, lines.join("\n"));
4996
- }
4997
- console.error(`[apm] \u524D\u7AEF\u4EC5\u6253\u5305\u6A21\u5F0F\uFF1A\u6267\u884C ${buildCmd}`);
4998
- runDeployShellCommand(buildCmd, cwd, captureOutput);
4999
- const projectName = (cfg.name ?? "").trim();
5000
- if (!projectName) {
5001
- throw new DeployExecutionError(
5002
- "\u8BF7\u5728 .apm/apm.config.json \u9876\u5C42\u914D\u7F6E name\uFF08\u4F5C\u4E3A\u90E8\u7F72\u4EA7\u7269\u9879\u76EE\u540D\uFF09",
5003
- 1
5004
- );
5005
- }
5006
- const settings2 = resolveWisdomDeployFromApmConfig(cfg);
5007
- await runWisdomSftpDeploy({
5008
- localDir: resolveFrontendDistDir(cwd),
5009
- settings: settings2,
5010
- extract: false,
5011
- projectName,
5012
- packOnly: true
5013
- });
5014
- return { projectType };
5015
- }
5016
- const deployCmd = resolveFrontendDeployCommand(options.env, cwd);
5017
- if (!deployCmd) {
5018
- const lines = formatWisdomFrontendDeployNotConfiguredLines(
5019
- options.env,
5020
- path4.join(cwd, "package.json")
5021
- );
5022
- throw new DeployExecutionError(lines.join("\n"), 1, lines.join("\n"));
5023
- }
5024
- runDeployShellCommand(deployCmd, cwd, captureOutput);
5025
- return { projectType };
5181
+ runDeployShellCommand(buildCmd, cwd, captureOutput);
5182
+ let projectName = (cfg.name ?? "").trim();
5183
+ if ((packOnly || archiveDeployArtifact) && !projectName) {
5184
+ throw new DeployExecutionError(
5185
+ "\u8BF7\u5728 .apm/apm.config.json \u9876\u5C42\u914D\u7F6E name\uFF08\u4F5C\u4E3A\u90E8\u7F72\u4EA7\u7269\u9879\u76EE\u540D\uFF09",
5186
+ 1
5187
+ );
5188
+ }
5189
+ if (!projectName) {
5190
+ projectName = path4.basename(cwd);
5026
5191
  }
5192
+ const settings = resolveWisdomDeployFromApmConfig(cfg);
5193
+ await runWisdomSftpDeploy({
5194
+ localDir: distDir,
5195
+ settings,
5196
+ extract: !packOnly,
5197
+ projectName,
5198
+ packOnly,
5199
+ archiveDeployArtifact
5200
+ });
5201
+ }
5202
+ async function executeWisdomBackendDeployFlow(options) {
5203
+ const { cwd, cfg, packOnly } = options;
5027
5204
  const settings = resolveWisdomBackendDeployFromApmConfig(cfg);
5028
5205
  if (packOnly) {
5029
- console.error(`[apm] \u540E\u7AEF\u4EC5\u6253\u5305\u6A21\u5F0F\uFF0C\u5FFD\u7565\u73AF\u5883\u53C2\u6570: ${options.env}`);
5206
+ console.error(`[apm] Java\uFF1AMaven \u6784\u5EFA\uFF08\u4EC5\u6253\u5305\uFF0C\u5FFD\u7565\u73AF\u5883 ${options.env}\uFF09`);
5030
5207
  } else {
5031
5208
  console.error(
5032
- `[apm] \u540E\u7AEF\u90E8\u7F72\u4E0D\u533A\u5206 test/online\uFF0C\u5FFD\u7565\u73AF\u5883\u53C2\u6570: ${options.env}`
5209
+ `[apm] Java\uFF1AMaven \u6784\u5EFA\u5E76\u90E8\u7F72\uFF08\u4E0D\u533A\u5206 test/online\uFF0C\u5FFD\u7565\u73AF\u5883 ${options.env}\uFF09`
5033
5210
  );
5034
5211
  }
5035
5212
  await runWisdomBackendDeploy({
@@ -5037,11 +5214,40 @@ async function runWisdomAutoDeploy(options) {
5037
5214
  projectRoot: cwd,
5038
5215
  packOnly
5039
5216
  });
5217
+ }
5218
+ async function executeWisdomDeploy(options) {
5219
+ const cwd = path4.resolve(options.cwd);
5220
+ const captureOutput = options.captureOutput ?? false;
5221
+ const packOnly = Boolean(options.packOnly);
5222
+ const archiveDeployArtifact = Boolean(options.archiveDeployArtifact);
5223
+ const projectType = detectWisdomProjectType(cwd);
5224
+ const configPath = options.configPath ?? path4.join(workspaceApmDir(cwd), "apm.config.json");
5225
+ const cfg = loadApmConfig({ configPath });
5226
+ console.error(
5227
+ `[apm] ${projectType === "frontend" ? "Vue \u524D\u7AEF" : "Java \u540E\u7AEF"}${packOnly ? "\uFF08\u4EC5\u6253\u5305\uFF09" : ""}`
5228
+ );
5229
+ if (projectType === "frontend") {
5230
+ await executeWisdomFrontendDeploy({
5231
+ ...options,
5232
+ cwd,
5233
+ cfg,
5234
+ captureOutput,
5235
+ packOnly,
5236
+ archiveDeployArtifact
5237
+ });
5238
+ return { projectType };
5239
+ }
5240
+ await executeWisdomBackendDeployFlow({
5241
+ ...options,
5242
+ cwd,
5243
+ cfg,
5244
+ packOnly
5245
+ });
5040
5246
  return { projectType };
5041
5247
  }
5042
5248
 
5043
5249
  // src/commands/deploy/internal/deploy-baseline-sync.ts
5044
- var LOG_PREFIX = "[apm] \u90E8\u7F72\u524D\u57FA\u7EBF\u540C\u6B65:";
5250
+ var LOG_PREFIX2 = "[apm] \u90E8\u7F72\u524D\u57FA\u7EBF\u540C\u6B65:";
5045
5251
  function formatGitError(error) {
5046
5252
  return error instanceof Error ? error.message : String(error);
5047
5253
  }
@@ -5077,20 +5283,20 @@ async function restoreWorkingTree(cwd) {
5077
5283
  }
5078
5284
  async function mergeBaselineBranch(cwd, baselineBranch, currentBranch, note) {
5079
5285
  const mergeTarget = `origin/${baselineBranch}`;
5080
- note(`${LOG_PREFIX} \u5F00\u59CB\u5408\u5E76 ${mergeTarget} \u5230\u5F53\u524D\u5206\u652F ${currentBranch}`);
5286
+ note(`${LOG_PREFIX2} \u5F00\u59CB\u5408\u5E76 ${mergeTarget} \u5230\u5F53\u524D\u5206\u652F ${currentBranch}`);
5081
5287
  try {
5082
5288
  if (currentBranch === baselineBranch) {
5083
5289
  await execGit(cwd, ["merge", "--ff-only", mergeTarget]);
5084
5290
  } else {
5085
5291
  await execGit(cwd, ["merge", mergeTarget, "--no-edit"]);
5086
5292
  }
5087
- note(`${LOG_PREFIX} \u5DF2\u5408\u5E76 ${mergeTarget} \u6700\u65B0\u4EE3\u7801`);
5293
+ note(`${LOG_PREFIX2} \u5DF2\u5408\u5E76 ${mergeTarget} \u6700\u65B0\u4EE3\u7801`);
5088
5294
  return { merged: true, conflictRollback: false };
5089
5295
  } catch (error) {
5090
5296
  await abortMergeIfNeeded(cwd);
5091
- note(`${LOG_PREFIX} \u5408\u5E76 ${mergeTarget} \u5931\u8D25: ${formatGitError(error)}`);
5092
- note(`${LOG_PREFIX} \u5DF2\u6267\u884C git merge --abort \u56DE\u9000\u5230\u5408\u5E76\u524D\u72B6\u6001`);
5093
- note(`${LOG_PREFIX} \u5C06\u4F7F\u7528\u56DE\u9000\u540E\u7684\u4EE3\u7801\u7EE7\u7EED\u90E8\u7F72`);
5297
+ note(`${LOG_PREFIX2} \u5408\u5E76 ${mergeTarget} \u5931\u8D25: ${formatGitError(error)}`);
5298
+ note(`${LOG_PREFIX2} \u5DF2\u6267\u884C git merge --abort \u56DE\u9000\u5230\u5408\u5E76\u524D\u72B6\u6001`);
5299
+ note(`${LOG_PREFIX2} \u5C06\u4F7F\u7528\u56DE\u9000\u540E\u7684\u4EE3\u7801\u7EE7\u7EED\u90E8\u7F72`);
5094
5300
  return { merged: false, conflictRollback: true };
5095
5301
  }
5096
5302
  }
@@ -5098,17 +5304,17 @@ async function restoreStashIfNeeded(cwd, stashed, note) {
5098
5304
  if (!stashed) {
5099
5305
  return false;
5100
5306
  }
5101
- note(`${LOG_PREFIX} \u6B63\u5728\u6062\u590D stash \u4E2D\u7684\u672A\u63D0\u4EA4\u6539\u52A8`);
5307
+ note(`${LOG_PREFIX2} \u6B63\u5728\u6062\u590D stash \u4E2D\u7684\u672A\u63D0\u4EA4\u6539\u52A8`);
5102
5308
  try {
5103
5309
  await execGit(cwd, ["stash", "pop"], true);
5104
- note(`${LOG_PREFIX} \u5DF2\u6062\u590D stash \u4E2D\u7684\u672A\u63D0\u4EA4\u6539\u52A8`);
5310
+ note(`${LOG_PREFIX2} \u5DF2\u6062\u590D stash \u4E2D\u7684\u672A\u63D0\u4EA4\u6539\u52A8`);
5105
5311
  return false;
5106
5312
  } catch (error) {
5107
5313
  await abortMergeIfNeeded(cwd);
5108
5314
  await restoreWorkingTree(cwd);
5109
- note(`${LOG_PREFIX} \u6062\u590D stash \u5931\u8D25: ${formatGitError(error)}`);
5110
- note(`${LOG_PREFIX} \u5DF2\u56DE\u9000\u5DE5\u4F5C\u533A\uFF08git reset --hard HEAD\uFF09\uFF0Cstash \u4ECD\u4FDD\u7559`);
5111
- note(`${LOG_PREFIX} \u5C06\u4F7F\u7528\u56DE\u9000\u540E\u7684\u4EE3\u7801\u7EE7\u7EED\u90E8\u7F72`);
5315
+ note(`${LOG_PREFIX2} \u6062\u590D stash \u5931\u8D25: ${formatGitError(error)}`);
5316
+ note(`${LOG_PREFIX2} \u5DF2\u56DE\u9000\u5DE5\u4F5C\u533A\uFF08git reset --hard HEAD\uFF09\uFF0Cstash \u4ECD\u4FDD\u7559`);
5317
+ note(`${LOG_PREFIX2} \u5C06\u4F7F\u7528\u56DE\u9000\u540E\u7684\u4EE3\u7801\u7EE7\u7EED\u90E8\u7F72`);
5112
5318
  return true;
5113
5319
  }
5114
5320
  }
@@ -5127,30 +5333,30 @@ async function syncDeployBaselineBeforeDeploy(cwd) {
5127
5333
  ...partial
5128
5334
  });
5129
5335
  if (!await isGitRepo(cwd)) {
5130
- note(`${LOG_PREFIX} \u5F53\u524D\u76EE\u5F55\u4E0D\u662F git \u4ED3\u5E93\uFF0C\u8DF3\u8FC7`);
5336
+ note(`${LOG_PREFIX2} \u5F53\u524D\u76EE\u5F55\u4E0D\u662F git \u4ED3\u5E93\uFF0C\u8DF3\u8FC7`);
5131
5337
  return emptyResult();
5132
5338
  }
5133
5339
  const cfg = await tryReadApmConfig();
5134
5340
  if (!cfg || !resolveApiKey(cfg)) {
5135
- note(`${LOG_PREFIX} \u672A\u767B\u5F55\uFF0C\u8DF3\u8FC7`);
5341
+ note(`${LOG_PREFIX2} \u672A\u767B\u5F55\uFF0C\u8DF3\u8FC7`);
5136
5342
  return emptyResult();
5137
5343
  }
5138
5344
  await ensureGitRepo(cwd);
5139
5345
  const api = createApmApiClient(cfg);
5140
5346
  const baselineBranch = await resolveBaselineBranch2(cwd, api);
5141
- note(`${LOG_PREFIX} \u57FA\u7EBF\u5206\u652F ${baselineBranch}`);
5142
- note(`${LOG_PREFIX} \u6B63\u5728 fetch origin ${baselineBranch}`);
5347
+ note(`${LOG_PREFIX2} \u57FA\u7EBF\u5206\u652F ${baselineBranch}`);
5348
+ note(`${LOG_PREFIX2} \u6B63\u5728 fetch origin ${baselineBranch}`);
5143
5349
  await execGit(cwd, ["fetch", "origin", baselineBranch], true);
5144
5350
  if (!await remoteBranchExists(cwd, baselineBranch)) {
5145
5351
  throw new Error(
5146
5352
  `\u8FDC\u7A0B\u4E0D\u5B58\u5728\u57FA\u7EBF\u5206\u652F origin/${baselineBranch}\uFF0C\u8BF7\u786E\u8BA4\u4ED3\u5E93\u9ED8\u8BA4\u5206\u652F\u5DF2\u63A8\u9001\u5230 origin`
5147
5353
  );
5148
5354
  }
5149
- note(`${LOG_PREFIX} fetch \u5B8C\u6210`);
5355
+ note(`${LOG_PREFIX2} fetch \u5B8C\u6210`);
5150
5356
  const currentBranch = await getCurrentBranch(cwd);
5151
5357
  let stashed = false;
5152
5358
  if (await isWorkingTreeDirty(cwd)) {
5153
- note(`${LOG_PREFIX} \u68C0\u6D4B\u5230\u672A\u63D0\u4EA4\u6539\u52A8\uFF0C\u5148 stash`);
5359
+ note(`${LOG_PREFIX2} \u68C0\u6D4B\u5230\u672A\u63D0\u4EA4\u6539\u52A8\uFF0C\u5148 stash`);
5154
5360
  await execGit(cwd, [
5155
5361
  "stash",
5156
5362
  "push",
@@ -5159,7 +5365,7 @@ async function syncDeployBaselineBeforeDeploy(cwd) {
5159
5365
  "apm: deploy baseline sync"
5160
5366
  ]);
5161
5367
  stashed = true;
5162
- note(`${LOG_PREFIX} \u5DF2 stash \u672A\u63D0\u4EA4\u6539\u52A8`);
5368
+ note(`${LOG_PREFIX2} \u5DF2 stash \u672A\u63D0\u4EA4\u6539\u52A8`);
5163
5369
  }
5164
5370
  const { merged, conflictRollback } = await mergeBaselineBranch(
5165
5371
  cwd,
@@ -5169,10 +5375,10 @@ async function syncDeployBaselineBeforeDeploy(cwd) {
5169
5375
  );
5170
5376
  const stashConflict = await restoreStashIfNeeded(cwd, stashed, note);
5171
5377
  if (conflictRollback || stashConflict) {
5172
- note(`${LOG_PREFIX} \u57FA\u7EBF\u540C\u6B65\u672A\u5B8C\u6210\uFF08\u5B58\u5728\u51B2\u7A81\u5E76\u5DF2\u56DE\u9000\uFF09\uFF0C\u7EE7\u7EED\u6267\u884C\u90E8\u7F72`);
5378
+ note(`${LOG_PREFIX2} \u57FA\u7EBF\u540C\u6B65\u672A\u5B8C\u6210\uFF08\u5B58\u5728\u51B2\u7A81\u5E76\u5DF2\u56DE\u9000\uFF09\uFF0C\u7EE7\u7EED\u6267\u884C\u90E8\u7F72`);
5173
5379
  } else if (merged) {
5174
5380
  note(
5175
- `${LOG_PREFIX} \u5B8C\u6210\uFF08\u5F53\u524D\u5206\u652F ${currentBranch} \u5DF2\u5305\u542B ${baselineBranch} \u6700\u65B0\u4EE3\u7801\uFF09`
5381
+ `${LOG_PREFIX2} \u5B8C\u6210\uFF08\u5F53\u524D\u5206\u652F ${currentBranch} \u5DF2\u5305\u542B ${baselineBranch} \u6700\u65B0\u4EE3\u7801\uFF09`
5176
5382
  );
5177
5383
  }
5178
5384
  return {
@@ -5186,10 +5392,26 @@ async function syncDeployBaselineBeforeDeploy(cwd) {
5186
5392
 
5187
5393
  // src/commands/deploy/deploy-execute.ts
5188
5394
  async function executeDeploy(options) {
5189
- const cwd = resolveWorkdirPath(options.cwd ?? process.cwd());
5395
+ const cwdInput = options.cwd.trim();
5396
+ if (!cwdInput) {
5397
+ throw new DeployExecutionError("[apm] executeDeploy \u7F3A\u5C11\u5DE5\u4F5C\u76EE\u5F55 cwd", 1);
5398
+ }
5399
+ const cwd = resolveWorkdirPath(cwdInput);
5190
5400
  const apmConfigPath = options.configPath ?? path5.join(workspaceApmDir(cwd), "apm.config.json");
5191
5401
  const captureOutput = options.captureOutput ?? false;
5192
5402
  const outputParts = [];
5403
+ logExecuteDeployContext({
5404
+ trigger: options.deployTrigger,
5405
+ env: options.env,
5406
+ cwd,
5407
+ cwdInput,
5408
+ processCwd: process.cwd(),
5409
+ apmConfigPath,
5410
+ captureOutput,
5411
+ packOnly: options.packOnly,
5412
+ archiveDeployArtifact: options.archiveDeployArtifact,
5413
+ configPathOption: options.configPath
5414
+ });
5193
5415
  try {
5194
5416
  const configSyncResult = await syncRemoteDeploymentConfig(
5195
5417
  cwd,
@@ -5212,36 +5434,29 @@ async function executeDeploy(options) {
5212
5434
  detail
5213
5435
  );
5214
5436
  }
5437
+ const preDeployLog = outputParts.join("\n");
5215
5438
  const cfg = loadApmConfig({ configPath: apmConfigPath });
5216
- if (isWisdomLegacyDeploy(cfg)) {
5217
- try {
5218
- await runWisdomAutoDeploy({
5219
- env: options.env,
5220
- cwd,
5221
- configPath: apmConfigPath,
5222
- captureOutput,
5223
- packOnly: options.packOnly
5224
- });
5225
- return outputParts.join("\n");
5226
- } catch (error) {
5227
- if (error instanceof DeployExecutionError) {
5228
- throw error;
5229
- }
5230
- const detail = error instanceof Error ? error.message : String(error);
5231
- throw new DeployExecutionError(detail, 1);
5232
- }
5233
- }
5234
- const deployCommands = cfg.deploy ?? {};
5235
- const command = deployCommands[options.env]?.trim();
5236
- if (!command) {
5237
- const lines = formatDeployNotConfiguredLines(options.env, deployCommands);
5439
+ if (!isWisdomDeployConfigured(cfg)) {
5440
+ const lines = formatMissingWisdomDeployLines();
5238
5441
  throw new DeployExecutionError(lines.join("\n"), 1, lines.join("\n"));
5239
5442
  }
5240
- const commandOutput = runDeployShellCommand(command, cwd, captureOutput);
5241
- if (commandOutput.trim()) {
5242
- outputParts.push(commandOutput);
5443
+ try {
5444
+ await executeWisdomDeploy({
5445
+ env: options.env,
5446
+ cwd,
5447
+ configPath: apmConfigPath,
5448
+ captureOutput,
5449
+ packOnly: options.packOnly,
5450
+ archiveDeployArtifact: options.archiveDeployArtifact
5451
+ });
5452
+ return preDeployLog;
5453
+ } catch (error) {
5454
+ if (error instanceof DeployExecutionError) {
5455
+ throw error;
5456
+ }
5457
+ const detail = error instanceof Error ? error.message : String(error);
5458
+ throw new DeployExecutionError(detail, 1);
5243
5459
  }
5244
- return outputParts.join("\n");
5245
5460
  }
5246
5461
  function printDeployExecutionError(error) {
5247
5462
  if (error.output.trim()) {
@@ -5390,7 +5605,9 @@ async function handleInboundDeploy(cfg, msg, signal) {
5390
5605
  env: msg.environment,
5391
5606
  cwd: workdir,
5392
5607
  packOnly: msg.packOnly,
5393
- captureOutput: true
5608
+ captureOutput: true,
5609
+ archiveDeployArtifact: true,
5610
+ deployTrigger: "connect"
5394
5611
  };
5395
5612
  try {
5396
5613
  if (signal.aborted) return;
@@ -5706,13 +5923,13 @@ ${JSON.stringify(event, null, 2)}
5706
5923
  }
5707
5924
 
5708
5925
  // src/commands/connect/agent-session-registry.ts
5709
- import { existsSync as existsSync16, mkdirSync as mkdirSync8, readFileSync as readFileSync14, writeFileSync as writeFileSync13 } from "node:fs";
5710
- import { dirname as dirname5, resolve as resolve4 } from "node:path";
5926
+ import { existsSync as existsSync17, mkdirSync as mkdirSync8, readFileSync as readFileSync14, writeFileSync as writeFileSync13 } from "node:fs";
5927
+ import { dirname as dirname6, resolve as resolve4 } from "node:path";
5711
5928
  function registryPath(workdir, sessionId) {
5712
5929
  return resolve4(workdir, ".apm", "sessions", sessionId, "cursor-agents.json");
5713
5930
  }
5714
5931
  function readRegistry(path13) {
5715
- if (!existsSync16(path13)) {
5932
+ if (!existsSync17(path13)) {
5716
5933
  return {};
5717
5934
  }
5718
5935
  try {
@@ -5733,7 +5950,7 @@ function readRegistry(path13) {
5733
5950
  return {};
5734
5951
  }
5735
5952
  function writeRegistry(path13, registry) {
5736
- mkdirSync8(dirname5(path13), { recursive: true });
5953
+ mkdirSync8(dirname6(path13), { recursive: true });
5737
5954
  writeFileSync13(path13, `${JSON.stringify(registry, null, 2)}
5738
5955
  `, "utf8");
5739
5956
  }
@@ -6184,15 +6401,15 @@ async function ensureMessageHasReply(cfg, sessionId, messageId, fallback) {
6184
6401
  }
6185
6402
 
6186
6403
  // src/commands/connect/cli-version-sync.ts
6187
- import { existsSync as existsSync17, readFileSync as readFileSync15, writeFileSync as writeFileSync14 } from "fs";
6188
- import { join as join16 } from "path";
6404
+ import { existsSync as existsSync18, readFileSync as readFileSync15, writeFileSync as writeFileSync14 } from "fs";
6405
+ import { join as join17 } from "path";
6189
6406
  var CLI_VERSION_FILE = ".cli-version.json";
6190
6407
  function manifestPath(apmDir) {
6191
- return join16(apmDir, CLI_VERSION_FILE);
6408
+ return join17(apmDir, CLI_VERSION_FILE);
6192
6409
  }
6193
6410
  function loadManifest4(apmDir) {
6194
6411
  const path13 = toFsPath(manifestPath(apmDir));
6195
- if (!existsSync17(path13)) {
6412
+ if (!existsSync18(path13)) {
6196
6413
  return null;
6197
6414
  }
6198
6415
  try {
@@ -6260,23 +6477,53 @@ function markPullDone(sessionId, workdir) {
6260
6477
 
6261
6478
  // src/commands/connect/run-slot-pool.ts
6262
6479
  var DEFAULT_MAX_CONCURRENT = 5;
6263
- function createRunSlotPool(maxConcurrent = DEFAULT_MAX_CONCURRENT) {
6480
+ function createRunSlotPool(maxConcurrent = DEFAULT_MAX_CONCURRENT, options = {}) {
6481
+ const label = options.label ?? "task";
6482
+ const isDeployPool = label === "deploy";
6264
6483
  let active = 0;
6265
6484
  const waiters = [];
6266
- const acquire = () => {
6485
+ const logDeploy = (message) => {
6486
+ if (isDeployPool) {
6487
+ console.error(`[apm] deploy \u4E32\u884C\u9650\u6D41\uFF1A${message}`);
6488
+ }
6489
+ };
6490
+ const acquire = (meta) => {
6267
6491
  if (active < maxConcurrent) {
6268
6492
  active += 1;
6493
+ if (isDeployPool) {
6494
+ logDeploy(
6495
+ `\u5F00\u59CB\u6267\u884C${meta ? `\uFF08${meta}\uFF09` : ""}\uFF0C\u5F53\u524D\u5360\u7528 ${active}/${maxConcurrent}`
6496
+ );
6497
+ }
6269
6498
  return Promise.resolve();
6270
6499
  }
6500
+ const queueIndex = waiters.length + 1;
6501
+ if (isDeployPool) {
6502
+ logDeploy(
6503
+ `\u5E76\u53D1\u5DF2\u6EE1\uFF08${maxConcurrent}/${maxConcurrent}\uFF09\uFF0C${meta ? `${meta} ` : ""}\u8FDB\u5165\u6392\u961F\uFF0C\u524D\u65B9 ${queueIndex} \u4E2A`
6504
+ );
6505
+ }
6506
+ const queuedAt = Date.now();
6271
6507
  return new Promise((resolve5) => {
6272
6508
  waiters.push(() => {
6273
6509
  active += 1;
6510
+ const waitedMs = Date.now() - queuedAt;
6511
+ if (isDeployPool) {
6512
+ logDeploy(
6513
+ `\u6392\u961F\u7ED3\u675F\uFF0C\u5F00\u59CB\u6267\u884C${meta ? `\uFF08${meta}\uFF09` : ""}\uFF0C\u7B49\u5F85 ${Math.ceil(
6514
+ waitedMs / 1e3
6515
+ )}s\uFF0C\u5F53\u524D\u5360\u7528 ${active}/${maxConcurrent}`
6516
+ );
6517
+ }
6274
6518
  resolve5();
6275
6519
  });
6276
6520
  });
6277
6521
  };
6278
6522
  const release = () => {
6279
6523
  active = Math.max(0, active - 1);
6524
+ if (isDeployPool) {
6525
+ logDeploy(`\u6267\u884C\u69FD\u91CA\u653E\uFF0C\u5F53\u524D\u5360\u7528 ${active}/${maxConcurrent}`);
6526
+ }
6280
6527
  const next = waiters.shift();
6281
6528
  if (next) {
6282
6529
  next();
@@ -6473,6 +6720,7 @@ function attachWsHandlers(ws, ctx, onOpen) {
6473
6720
  clientMachineId,
6474
6721
  shutdownAbort,
6475
6722
  runSlots,
6723
+ deployRunSlots,
6476
6724
  activeTasks,
6477
6725
  activeRuns,
6478
6726
  pendingCancels,
@@ -6511,12 +6759,13 @@ function attachWsHandlers(ws, ctx, onOpen) {
6511
6759
  shutdownAbort.signal,
6512
6760
  perDeployController.signal
6513
6761
  ]);
6762
+ const deploySlotMeta = `deploymentRunId=${msg2.deploymentRunId} env=${msg2.environment} workdir=${msg2.workdir}`;
6514
6763
  const task2 = (async () => {
6515
- await runSlots.acquire();
6764
+ await deployRunSlots.acquire(deploySlotMeta);
6516
6765
  try {
6517
6766
  await handleInboundDeploy(cfg, msg2, signal2);
6518
6767
  } finally {
6519
- runSlots.release();
6768
+ deployRunSlots.release();
6520
6769
  }
6521
6770
  })();
6522
6771
  activeTasks.add(task2);
@@ -6674,6 +6923,7 @@ async function runConnect(options) {
6674
6923
  const lifecycleAbort = new AbortController();
6675
6924
  const shutdownAbort = new AbortController();
6676
6925
  const runSlots = createRunSlotPool();
6926
+ const deployRunSlots = createRunSlotPool(1, { label: "deploy" });
6677
6927
  const activeTasks = /* @__PURE__ */ new Set();
6678
6928
  const activeRuns = /* @__PURE__ */ new Map();
6679
6929
  const pendingCancels = /* @__PURE__ */ new Set();
@@ -6683,6 +6933,7 @@ async function runConnect(options) {
6683
6933
  clientMachineId,
6684
6934
  shutdownAbort,
6685
6935
  runSlots,
6936
+ deployRunSlots,
6686
6937
  activeTasks,
6687
6938
  activeRuns,
6688
6939
  pendingCancels,
@@ -6921,7 +7172,7 @@ async function runDeployWithBackendTracking(options) {
6921
7172
  const run = await api.cli.createTaskDeployment({
6922
7173
  sessionId: options.sessionId,
6923
7174
  environment,
6924
- workdirPath: options.cwd ?? process.cwd()
7175
+ workdirPath: options.cwd
6925
7176
  });
6926
7177
  deploymentRunId = run.id;
6927
7178
  console.log(
@@ -6957,7 +7208,11 @@ async function runDeployWithBackendTracking(options) {
6957
7208
  originalError.apply(console, args);
6958
7209
  };
6959
7210
  try {
6960
- const output = await executeDeploy({ ...options, captureOutput: true });
7211
+ const output = await executeDeploy({
7212
+ ...options,
7213
+ captureOutput: true,
7214
+ archiveDeployArtifact: true
7215
+ });
6961
7216
  if (output.trim()) {
6962
7217
  appendLog(output);
6963
7218
  }
@@ -7000,8 +7255,8 @@ async function runDeployWithBackendTracking(options) {
7000
7255
  // src/commands/deploy/deploy.ts
7001
7256
  function registerDeployMainCommand(program) {
7002
7257
  program.command("deploy").description(
7003
- "\u7EDF\u4E00\u90E8\u7F72\uFF08\u6267\u884C\u524D\u81EA\u52A8\u540C\u6B65\u90E8\u7F72\u914D\u7F6E\u5E76\u5408\u5E76\u57FA\u7EBF\u5206\u652F\uFF09\uFF1A\u533B\u52A1\u5B58\u91CF\u81EA\u52A8\u8BC6\u522B\u524D\u540E\u7AEF\uFF1B\u5176\u4ED6\u9879\u76EE\u6309 deploy.<\u73AF\u5883> \u6267\u884C shell \u547D\u4EE4"
7004
- ).argument("<env>", "\u90E8\u7F72\u73AF\u5883\u540D\uFF08\u5982 test\u3001online\uFF09").option(
7258
+ "\u533B\u52A1\u90E8\u7F72\uFF1AVue build + SFTP / Java Maven + SSH\uFF08\u9700 apm.config.json wisdomDeploy\uFF09"
7259
+ ).argument("<env>", "\u90E8\u7F72\u73AF\u5883\u540D\uFF08\u5982 test\u3001online\uFF1BVue \u5BF9\u5E94 build:<env>\uFF09").option(
7005
7260
  "--config <path>",
7006
7261
  "apm.config.json \u8DEF\u5F84\uFF08\u9ED8\u8BA4 .apm/apm.config.json\uFF09"
7007
7262
  ).option(
@@ -7009,7 +7264,7 @@ function registerDeployMainCommand(program) {
7009
7264
  "\u6C9F\u901A\u7FA4 ID\uFF1B\u4F20\u5165\u65F6\u5728\u5E73\u53F0\u521B\u5EFA\u90E8\u7F72\u8BB0\u5F55\u5E76\u540C\u6B65\u65E5\u5FD7"
7010
7265
  ).option(
7011
7266
  "--pack-only",
7012
- "\u4EC5\u6784\u5EFA/\u6253\u5305\u5E76\u4E0A\u4F20 MinIO \u5F52\u6863\uFF0C\u4E0D\u4E0A\u4F20\u8FDC\u7A0B\u670D\u52A1\u5668\uFF08\u524D\u7AEF build:<env>\uFF0C\u540E\u7AEF Maven \u6784\u5EFA\uFF09"
7267
+ "\u4EC5\u6784\u5EFA/\u6253\u5305\uFF0C\u4E0D\u4E0A\u4F20\u8FDC\u7A0B SFTP/SSH\uFF1B\u53EF\u5F52\u6863\u5E73\u53F0\u90E8\u7F72\u4EA7\u7269"
7013
7268
  ).action(
7014
7269
  async (env, opts) => {
7015
7270
  const cwd = process.cwd();
@@ -7022,11 +7277,18 @@ function registerDeployMainCommand(program) {
7022
7277
  cwd,
7023
7278
  configPath: opts.config,
7024
7279
  sessionId,
7025
- packOnly
7280
+ packOnly,
7281
+ deployTrigger: "session"
7026
7282
  });
7027
7283
  return;
7028
7284
  }
7029
- await executeDeploy({ env, cwd, configPath: opts.config, packOnly });
7285
+ await executeDeploy({
7286
+ env,
7287
+ cwd,
7288
+ configPath: opts.config,
7289
+ packOnly,
7290
+ deployTrigger: "cli"
7291
+ });
7030
7292
  } catch (error) {
7031
7293
  if (error instanceof DeployExecutionError) {
7032
7294
  printDeployExecutionError(error);
@@ -7048,7 +7310,7 @@ import path9 from "node:path";
7048
7310
  import Docker from "dockerode";
7049
7311
 
7050
7312
  // src/commands/deploy/internal/backend-deploy/dockerode-client/connection-options.ts
7051
- import { existsSync as existsSync18, readFileSync as readFileSync16 } from "node:fs";
7313
+ import { existsSync as existsSync19, readFileSync as readFileSync16 } from "node:fs";
7052
7314
  import path6 from "node:path";
7053
7315
  function asOptionalTlsBuffer(value) {
7054
7316
  if (typeof value !== "string") {
@@ -7060,7 +7322,7 @@ function asOptionalTlsBuffer(value) {
7060
7322
  if (normalized === "") {
7061
7323
  return void 0;
7062
7324
  }
7063
- if (existsSync18(normalized)) {
7325
+ if (existsSync19(normalized)) {
7064
7326
  return readFileSync16(normalized);
7065
7327
  }
7066
7328
  const looksLikePath = /[\\/]/.test(normalized) || normalized.endsWith(".pem");
@@ -7271,7 +7533,7 @@ var DockerodeClient = class {
7271
7533
  var createDockerodeClient = (config) => new DockerodeClient(config);
7272
7534
 
7273
7535
  // src/commands/deploy/internal/backend-deploy/dockerode-client/env.ts
7274
- import { existsSync as existsSync19, readFileSync as readFileSync17, statSync as statSync8 } from "node:fs";
7536
+ import { existsSync as existsSync20, readFileSync as readFileSync17, statSync as statSync8 } from "node:fs";
7275
7537
  import path7 from "node:path";
7276
7538
  function stripSurroundingQuotes(value) {
7277
7539
  const t = value.trim();
@@ -7288,7 +7550,7 @@ function loadEnvFromFile(envFilePath) {
7288
7550
  return {};
7289
7551
  }
7290
7552
  const targetPath = path7.resolve(envFilePath);
7291
- if (!existsSync19(targetPath) || !statSync8(targetPath).isFile()) {
7553
+ if (!existsSync20(targetPath) || !statSync8(targetPath).isFile()) {
7292
7554
  return {};
7293
7555
  }
7294
7556
  const raw = readFileSync17(targetPath, "utf-8");
@@ -7462,12 +7724,12 @@ function dockerPushImage(params, cwd) {
7462
7724
  }
7463
7725
 
7464
7726
  // src/commands/deploy/internal/backend-deploy/resolve-dockerfile.ts
7465
- import { existsSync as existsSync20 } from "node:fs";
7727
+ import { existsSync as existsSync21 } from "node:fs";
7466
7728
  import path8 from "node:path";
7467
7729
  function resolveDockerBuildPaths(cwd) {
7468
7730
  const dockerfilePath = path8.join(cwd, "Dockerfile");
7469
7731
  Logger.info(`\u67E5\u627EDockerfile\u6587\u4EF6\uFF0C\u8DEF\u5F84: ${dockerfilePath}`);
7470
- if (!existsSync20(dockerfilePath)) {
7732
+ if (!existsSync21(dockerfilePath)) {
7471
7733
  throw new Error(`Dockerfile \u4E0D\u5B58\u5728\uFF1A${dockerfilePath}`);
7472
7734
  }
7473
7735
  Logger.info("\u2713 Dockerfile \u5B58\u5728");