ai-project-manage-cli 6.0.107 → 6.0.109
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.
- package/dist/index.js +946 -872
- package/package.json +1 -1
- package/template/collaboration-prompt.md +0 -28
package/dist/index.js
CHANGED
|
@@ -110,8 +110,8 @@ function toFsPath(inputPath) {
|
|
|
110
110
|
}
|
|
111
111
|
return `\\\\?\\${normalized}`;
|
|
112
112
|
}
|
|
113
|
-
function normalizeWorkdirPath(
|
|
114
|
-
let normalized =
|
|
113
|
+
function normalizeWorkdirPath(path19) {
|
|
114
|
+
let normalized = path19.trim().replace(/\\/g, "/").normalize("NFC");
|
|
115
115
|
if (normalized.startsWith("//?/")) {
|
|
116
116
|
normalized = normalized.slice(4);
|
|
117
117
|
}
|
|
@@ -326,9 +326,9 @@ function assertTemplateCopiedToApm(apmDir, workdir) {
|
|
|
326
326
|
"sessions"
|
|
327
327
|
];
|
|
328
328
|
for (const item of required) {
|
|
329
|
-
const
|
|
330
|
-
if (!existsSync(toFsPath(
|
|
331
|
-
throw new Error(`[apm] \u521D\u59CB\u5316\u4E0D\u5B8C\u6574\uFF0C\u7F3A\u5C11: ${
|
|
329
|
+
const path19 = join2(apmDir, item);
|
|
330
|
+
if (!existsSync(toFsPath(path19))) {
|
|
331
|
+
throw new Error(`[apm] \u521D\u59CB\u5316\u4E0D\u5B8C\u6574\uFF0C\u7F3A\u5C11: ${path19}`);
|
|
332
332
|
}
|
|
333
333
|
}
|
|
334
334
|
const leakedRules = join2(workdir, "rules");
|
|
@@ -790,14 +790,14 @@ function projectDocumentLocalPath(apmRoot, documentPath) {
|
|
|
790
790
|
const normalized = normalizeLocalDocumentPath(documentPath);
|
|
791
791
|
return join4(projectDocumentsDir(apmRoot), ...normalized.split("/"));
|
|
792
792
|
}
|
|
793
|
-
function normalizeLocalDocumentPath(
|
|
794
|
-
const trimmed =
|
|
793
|
+
function normalizeLocalDocumentPath(path19) {
|
|
794
|
+
const trimmed = path19.trim().replace(/\\/g, "/");
|
|
795
795
|
if (!trimmed || trimmed.startsWith("/") || /^[a-zA-Z]:/.test(trimmed)) {
|
|
796
|
-
throw new Error(`\u975E\u6CD5\u6587\u6863\u8DEF\u5F84: ${
|
|
796
|
+
throw new Error(`\u975E\u6CD5\u6587\u6863\u8DEF\u5F84: ${path19}`);
|
|
797
797
|
}
|
|
798
798
|
const segments = trimmed.split("/").filter(Boolean);
|
|
799
799
|
if (segments.some((segment) => segment === ".." || segment === ".")) {
|
|
800
|
-
throw new Error(`\u975E\u6CD5\u6587\u6863\u8DEF\u5F84: ${
|
|
800
|
+
throw new Error(`\u975E\u6CD5\u6587\u6863\u8DEF\u5F84: ${path19}`);
|
|
801
801
|
}
|
|
802
802
|
return segments.join("/");
|
|
803
803
|
}
|
|
@@ -848,15 +848,15 @@ function diffManifestPaths(remote, local) {
|
|
|
848
848
|
(local?.documents ?? []).map((doc) => [doc.path, doc.contentHash])
|
|
849
849
|
);
|
|
850
850
|
const download = [];
|
|
851
|
-
for (const [
|
|
852
|
-
if (localMap.get(
|
|
853
|
-
download.push(
|
|
851
|
+
for (const [path19, hash] of remoteMap) {
|
|
852
|
+
if (localMap.get(path19) !== hash) {
|
|
853
|
+
download.push(path19);
|
|
854
854
|
}
|
|
855
855
|
}
|
|
856
856
|
const deleteLocal = [];
|
|
857
|
-
for (const
|
|
858
|
-
if (!remoteMap.has(
|
|
859
|
-
deleteLocal.push(
|
|
857
|
+
for (const path19 of localMap.keys()) {
|
|
858
|
+
if (!remoteMap.has(path19)) {
|
|
859
|
+
deleteLocal.push(path19);
|
|
860
860
|
}
|
|
861
861
|
}
|
|
862
862
|
return { download, deleteLocal };
|
|
@@ -916,8 +916,8 @@ ${diagnostic ?? ""}`
|
|
|
916
916
|
}
|
|
917
917
|
}
|
|
918
918
|
let deleted = 0;
|
|
919
|
-
for (const
|
|
920
|
-
const absPath = toFsPath(projectDocumentLocalPath(targetApmDir,
|
|
919
|
+
for (const path19 of deleteLocal) {
|
|
920
|
+
const absPath = toFsPath(projectDocumentLocalPath(targetApmDir, path19));
|
|
921
921
|
if (existsSync2(absPath)) {
|
|
922
922
|
rmSync(absPath, { force: true });
|
|
923
923
|
deleted += 1;
|
|
@@ -962,21 +962,21 @@ async function syncRepositoryProjectDocumentsPush(cfg, workdirPath, apmRoot) {
|
|
|
962
962
|
])
|
|
963
963
|
);
|
|
964
964
|
let synced = 0;
|
|
965
|
-
for (const
|
|
966
|
-
const absPath = toFsPath(projectDocumentLocalPath(targetApmDir,
|
|
965
|
+
for (const path19 of localPaths) {
|
|
966
|
+
const absPath = toFsPath(projectDocumentLocalPath(targetApmDir, path19));
|
|
967
967
|
const content = readFileSync3(absPath, "utf8");
|
|
968
968
|
const contentHash = hashLocalFileContent(content);
|
|
969
|
-
if (remoteHashByPath.get(
|
|
969
|
+
if (remoteHashByPath.get(path19) === contentHash) {
|
|
970
970
|
continue;
|
|
971
971
|
}
|
|
972
972
|
await api.cli.upsertRepositoryProjectDocument({
|
|
973
973
|
repositoryId,
|
|
974
|
-
path:
|
|
974
|
+
path: path19,
|
|
975
975
|
content,
|
|
976
|
-
description: remoteDescriptionByPath.get(
|
|
976
|
+
description: remoteDescriptionByPath.get(path19) ?? void 0
|
|
977
977
|
});
|
|
978
978
|
synced += 1;
|
|
979
|
-
console.log(`[apm] \u5DF2\u540C\u6B65\u4ED3\u5E93\u9879\u76EE\u6587\u6863: ${
|
|
979
|
+
console.log(`[apm] \u5DF2\u540C\u6B65\u4ED3\u5E93\u9879\u76EE\u6587\u6863: ${path19}`);
|
|
980
980
|
}
|
|
981
981
|
if (synced === 0) {
|
|
982
982
|
console.log("[apm] \u4ED3\u5E93\u9879\u76EE\u6587\u6863\u65E0\u53D8\u5316\uFF0C\u8DF3\u8FC7\u63A8\u9001");
|
|
@@ -1593,13 +1593,13 @@ async function downloadAttachment(cfg, attachmentId) {
|
|
|
1593
1593
|
return Buffer.from(await res.arrayBuffer());
|
|
1594
1594
|
}
|
|
1595
1595
|
function loadManifest(dir) {
|
|
1596
|
-
const
|
|
1597
|
-
if (!existsSync4(
|
|
1596
|
+
const path19 = join6(dir, MANIFEST_FILE2);
|
|
1597
|
+
if (!existsSync4(path19)) {
|
|
1598
1598
|
return { version: 1, attachments: {} };
|
|
1599
1599
|
}
|
|
1600
1600
|
try {
|
|
1601
1601
|
const parsed = JSON.parse(
|
|
1602
|
-
readFileSync5(
|
|
1602
|
+
readFileSync5(path19, "utf8")
|
|
1603
1603
|
);
|
|
1604
1604
|
if (parsed?.version === 1 && parsed.attachments && typeof parsed.attachments === "object") {
|
|
1605
1605
|
return parsed;
|
|
@@ -1680,8 +1680,8 @@ function sanitizeSkillDirName(name) {
|
|
|
1680
1680
|
function listBaseSkillDirNames() {
|
|
1681
1681
|
if (!existsSync5(BASE_SKILLS_TEMPLATE_DIR)) return [];
|
|
1682
1682
|
return readdirSync3(BASE_SKILLS_TEMPLATE_DIR).filter((name) => {
|
|
1683
|
-
const
|
|
1684
|
-
return statSync2(
|
|
1683
|
+
const path19 = join7(BASE_SKILLS_TEMPLATE_DIR, name);
|
|
1684
|
+
return statSync2(path19).isDirectory();
|
|
1685
1685
|
});
|
|
1686
1686
|
}
|
|
1687
1687
|
function syncAgentsGuide(apmDir) {
|
|
@@ -1693,8 +1693,8 @@ function syncAgentsGuide(apmDir) {
|
|
|
1693
1693
|
function listBaseRuleFileNames() {
|
|
1694
1694
|
if (!existsSync5(BASE_RULES_TEMPLATE_DIR)) return [];
|
|
1695
1695
|
return readdirSync3(BASE_RULES_TEMPLATE_DIR).filter((name) => {
|
|
1696
|
-
const
|
|
1697
|
-
return statSync2(
|
|
1696
|
+
const path19 = join7(BASE_RULES_TEMPLATE_DIR, name);
|
|
1697
|
+
return statSync2(path19).isFile();
|
|
1698
1698
|
});
|
|
1699
1699
|
}
|
|
1700
1700
|
function syncBaseRules(rulesDir) {
|
|
@@ -1757,13 +1757,13 @@ function ruleLocalFileName(ruleName) {
|
|
|
1757
1757
|
return `${sanitized}.md`;
|
|
1758
1758
|
}
|
|
1759
1759
|
function loadManifest2(rulesDir) {
|
|
1760
|
-
const
|
|
1761
|
-
if (!existsSync6(toFsPath(
|
|
1760
|
+
const path19 = join8(rulesDir, MANIFEST_FILE3);
|
|
1761
|
+
if (!existsSync6(toFsPath(path19))) {
|
|
1762
1762
|
return { version: 1, rules: {} };
|
|
1763
1763
|
}
|
|
1764
1764
|
try {
|
|
1765
1765
|
const parsed = JSON.parse(
|
|
1766
|
-
readFileSync6(toFsPath(
|
|
1766
|
+
readFileSync6(toFsPath(path19), "utf8")
|
|
1767
1767
|
);
|
|
1768
1768
|
if (parsed?.version === 1 && parsed.rules && typeof parsed.rules === "object") {
|
|
1769
1769
|
return parsed;
|
|
@@ -2658,93 +2658,17 @@ function validateAgentWsMessage(value, kind) {
|
|
|
2658
2658
|
return validateMessagePush(o);
|
|
2659
2659
|
}
|
|
2660
2660
|
|
|
2661
|
-
// src/commands/deploy/deploy-log-utils.ts
|
|
2662
|
-
import { setTimeout as delay } from "node:timers/promises";
|
|
2663
|
-
var DEPLOY_SPAWN_MAX_BUFFER_BYTES = 50 * 1024 * 1024;
|
|
2664
|
-
var DEPLOY_LOG_SYNC_MAX_CHUNK_BYTES = 4 * 1024 * 1024;
|
|
2665
|
-
var DEPLOY_COMPLETE_LOG_MAX_BYTES = 9 * 1024 * 1024;
|
|
2666
|
-
var DEPLOY_LOG_SYNC_MAX_ATTEMPTS = 3;
|
|
2667
|
-
async function retryDeployLogSync(fn, attempts = DEPLOY_LOG_SYNC_MAX_ATTEMPTS) {
|
|
2668
|
-
let lastError;
|
|
2669
|
-
for (let attempt = 1; attempt <= attempts; attempt += 1) {
|
|
2670
|
-
try {
|
|
2671
|
-
return await fn();
|
|
2672
|
-
} catch (error) {
|
|
2673
|
-
lastError = error;
|
|
2674
|
-
if (attempt < attempts) {
|
|
2675
|
-
await delay(1e3 * attempt);
|
|
2676
|
-
}
|
|
2677
|
-
}
|
|
2678
|
-
}
|
|
2679
|
-
throw lastError;
|
|
2680
|
-
}
|
|
2681
|
-
function splitUtf8StringByMaxBytes(value, maxBytes) {
|
|
2682
|
-
if (maxBytes <= 0) {
|
|
2683
|
-
throw new Error("maxBytes must be positive");
|
|
2684
|
-
}
|
|
2685
|
-
const bytes = Buffer.from(value, "utf8");
|
|
2686
|
-
if (bytes.length <= maxBytes) {
|
|
2687
|
-
return [value];
|
|
2688
|
-
}
|
|
2689
|
-
const chunks = [];
|
|
2690
|
-
let offset = 0;
|
|
2691
|
-
while (offset < bytes.length) {
|
|
2692
|
-
let end = Math.min(offset + maxBytes, bytes.length);
|
|
2693
|
-
while (end > offset && (bytes[end] & 192) === 128) {
|
|
2694
|
-
end -= 1;
|
|
2695
|
-
}
|
|
2696
|
-
if (end <= offset) {
|
|
2697
|
-
end = Math.min(offset + maxBytes, bytes.length);
|
|
2698
|
-
}
|
|
2699
|
-
chunks.push(bytes.subarray(offset, end).toString("utf8"));
|
|
2700
|
-
offset = end;
|
|
2701
|
-
}
|
|
2702
|
-
return chunks;
|
|
2703
|
-
}
|
|
2704
|
-
function truncateDeployLogForComplete(log2) {
|
|
2705
|
-
const bytes = Buffer.from(log2, "utf8");
|
|
2706
|
-
if (bytes.length <= DEPLOY_COMPLETE_LOG_MAX_BYTES) {
|
|
2707
|
-
return { log: log2, truncated: false };
|
|
2708
|
-
}
|
|
2709
|
-
const tailBudget = Math.max(DEPLOY_COMPLETE_LOG_MAX_BYTES - 512, 1024);
|
|
2710
|
-
const prefix = `[apm] \u65E5\u5FD7\u8FC7\u957F\uFF08${Math.ceil(bytes.length / 1024)}KB\uFF09\uFF0C\u4EC5\u4FDD\u7559\u672B\u5C3E ${Math.floor(tailBudget / 1024)}KB
|
|
2711
|
-
`;
|
|
2712
|
-
let tail = bytes.subarray(bytes.length - tailBudget).toString("utf8");
|
|
2713
|
-
const brokenPrefix = tail.indexOf("\uFFFD");
|
|
2714
|
-
if (brokenPrefix >= 0) {
|
|
2715
|
-
const newline = tail.indexOf("\n", brokenPrefix);
|
|
2716
|
-
tail = newline >= 0 ? tail.slice(newline + 1) : tail.slice(brokenPrefix + 1);
|
|
2717
|
-
}
|
|
2718
|
-
return { log: prefix + tail, truncated: true };
|
|
2719
|
-
}
|
|
2720
|
-
|
|
2721
2661
|
// src/commands/deploy/deploy-execute.ts
|
|
2722
|
-
import
|
|
2662
|
+
import path11 from "node:path";
|
|
2723
2663
|
|
|
2724
2664
|
// src/commands/deploy/internal/apm-config.ts
|
|
2725
|
-
import { existsSync as
|
|
2726
|
-
import {
|
|
2727
|
-
|
|
2728
|
-
|
|
2729
|
-
|
|
2730
|
-
process.cwd(),
|
|
2731
|
-
options?.configPath ?? resolve3(workspaceApmDir(), "apm.config.json")
|
|
2732
|
-
);
|
|
2733
|
-
if (!existsSync11(p)) {
|
|
2734
|
-
console.error(`\u672A\u627E\u5230\u914D\u7F6E\u6587\u4EF6\uFF1A${p}`);
|
|
2735
|
-
process.exit(1);
|
|
2736
|
-
}
|
|
2737
|
-
try {
|
|
2738
|
-
const raw = readFileSync10(p, "utf8");
|
|
2739
|
-
return JSON.parse(raw);
|
|
2740
|
-
} catch (e) {
|
|
2741
|
-
console.error(`\u65E0\u6CD5\u89E3\u6790 apm.config.json\uFF1A${p}`, e);
|
|
2742
|
-
process.exit(1);
|
|
2743
|
-
}
|
|
2744
|
-
}
|
|
2745
|
-
function req(v, field) {
|
|
2665
|
+
import { existsSync as existsSync12, readFileSync as readFileSync11 } from "node:fs";
|
|
2666
|
+
import { resolve as resolve4 } from "node:path";
|
|
2667
|
+
|
|
2668
|
+
// src/commands/deploy/internal/config/config-validation.ts
|
|
2669
|
+
function req(v, field, section) {
|
|
2746
2670
|
if (v === void 0 || v === null || typeof v === "string" && !v.trim()) {
|
|
2747
|
-
console.error(`apm.config.json \u4E2D
|
|
2671
|
+
console.error(`apm.config.json \u4E2D ${section}.${field} \u4E0D\u80FD\u4E3A\u7A7A`);
|
|
2748
2672
|
process.exit(1);
|
|
2749
2673
|
}
|
|
2750
2674
|
return v;
|
|
@@ -2759,17 +2683,19 @@ function reqTopLevelName(cfg) {
|
|
|
2759
2683
|
}
|
|
2760
2684
|
return n;
|
|
2761
2685
|
}
|
|
2762
|
-
function
|
|
2686
|
+
function reqPositiveInt(v, field, section) {
|
|
2763
2687
|
const n = Number(v);
|
|
2764
2688
|
if (!Number.isFinite(n) || !Number.isInteger(n) || n < 1) {
|
|
2765
|
-
console.error(`apm.config.json \u4E2D
|
|
2689
|
+
console.error(`apm.config.json \u4E2D ${section}.${field} \u987B\u4E3A\u6B63\u6574\u6570`);
|
|
2766
2690
|
process.exit(1);
|
|
2767
2691
|
}
|
|
2768
2692
|
return n;
|
|
2769
2693
|
}
|
|
2694
|
+
|
|
2695
|
+
// src/commands/deploy/internal/config/docker-backend-config.ts
|
|
2770
2696
|
function resolveBackendDeployFromApmConfig(cfg) {
|
|
2771
2697
|
const b = cfg.backendDeploy ?? {};
|
|
2772
|
-
const protoRaw = req(b.remoteProtocol, "remoteProtocol").trim().toLowerCase();
|
|
2698
|
+
const protoRaw = req(b.remoteProtocol, "remoteProtocol", "backendDeploy").trim().toLowerCase();
|
|
2773
2699
|
if (protoRaw !== "http" && protoRaw !== "https") {
|
|
2774
2700
|
console.error(
|
|
2775
2701
|
"apm.config.json \u4E2D backendDeploy.remoteProtocol \u53EA\u80FD\u4E3A http \u6216 https"
|
|
@@ -2790,12 +2716,20 @@ function resolveBackendDeployFromApmConfig(cfg) {
|
|
|
2790
2716
|
}
|
|
2791
2717
|
return {
|
|
2792
2718
|
name: reqTopLevelName(cfg),
|
|
2793
|
-
registryHost: req(b.registryHost, "registryHost").trim(),
|
|
2794
|
-
registryNamespace: req(
|
|
2795
|
-
|
|
2796
|
-
|
|
2797
|
-
|
|
2798
|
-
|
|
2719
|
+
registryHost: req(b.registryHost, "registryHost", "backendDeploy").trim(),
|
|
2720
|
+
registryNamespace: req(
|
|
2721
|
+
b.registryNamespace,
|
|
2722
|
+
"registryNamespace",
|
|
2723
|
+
"backendDeploy"
|
|
2724
|
+
).trim(),
|
|
2725
|
+
registryUser: req(b.registryUser, "registryUser", "backendDeploy").trim(),
|
|
2726
|
+
registryPassword: req(
|
|
2727
|
+
b.registryPassword,
|
|
2728
|
+
"registryPassword",
|
|
2729
|
+
"backendDeploy"
|
|
2730
|
+
).trim(),
|
|
2731
|
+
remoteHost: req(b.remoteHost, "remoteHost", "backendDeploy").trim(),
|
|
2732
|
+
remotePort: reqPositiveInt(b.remotePort, "remotePort", "backendDeploy"),
|
|
2799
2733
|
remoteProtocol,
|
|
2800
2734
|
caPath: b.caPath?.trim(),
|
|
2801
2735
|
certPath: b.certPath?.trim(),
|
|
@@ -2805,64 +2739,30 @@ function resolveBackendDeployFromApmConfig(cfg) {
|
|
|
2805
2739
|
dockerNetwork: b.dockerNetwork?.trim() || void 0
|
|
2806
2740
|
};
|
|
2807
2741
|
}
|
|
2808
|
-
|
|
2809
|
-
|
|
2810
|
-
console.error(`apm.config.json \u4E2D frontendDeploy.${field} \u4E0D\u80FD\u4E3A\u7A7A`);
|
|
2811
|
-
process.exit(1);
|
|
2812
|
-
}
|
|
2813
|
-
return v;
|
|
2814
|
-
}
|
|
2742
|
+
|
|
2743
|
+
// src/commands/deploy/internal/config/frontend-minio-config.ts
|
|
2815
2744
|
function resolveFrontendDeployFromApmConfig(cfg) {
|
|
2816
2745
|
const f = cfg.frontendDeploy ?? {};
|
|
2817
2746
|
const port = Number(f.port);
|
|
2818
2747
|
return {
|
|
2819
|
-
endpoint:
|
|
2748
|
+
endpoint: req(f.endpoint, "endpoint", "frontendDeploy").trim(),
|
|
2820
2749
|
port: Number.isFinite(port) && port > 0 ? port : 9e3,
|
|
2821
2750
|
useSsl: Boolean(f.useSsl),
|
|
2822
|
-
accessKey:
|
|
2823
|
-
secretKey:
|
|
2824
|
-
bucket:
|
|
2825
|
-
};
|
|
2826
|
-
}
|
|
2827
|
-
function reqWd(v, field) {
|
|
2828
|
-
if (v === void 0 || v === null || typeof v === "string" && !v.trim()) {
|
|
2829
|
-
console.error(`apm.config.json \u4E2D wisdomDeploy.${field} \u4E0D\u80FD\u4E3A\u7A7A`);
|
|
2830
|
-
process.exit(1);
|
|
2831
|
-
}
|
|
2832
|
-
return v;
|
|
2833
|
-
}
|
|
2834
|
-
function reqWisdomPositiveInt(v, field) {
|
|
2835
|
-
const n = Number(v);
|
|
2836
|
-
if (!Number.isFinite(n) || !Number.isInteger(n) || n < 1) {
|
|
2837
|
-
console.error(`apm.config.json \u4E2D wisdomDeploy.${field} \u987B\u4E3A\u6B63\u6574\u6570`);
|
|
2838
|
-
process.exit(1);
|
|
2839
|
-
}
|
|
2840
|
-
return n;
|
|
2841
|
-
}
|
|
2842
|
-
function resolveWisdomDeployFromApmConfig(cfg) {
|
|
2843
|
-
const w = cfg.wisdomDeploy ?? {};
|
|
2844
|
-
return {
|
|
2845
|
-
host: reqWd(w.host, "host").trim(),
|
|
2846
|
-
port: reqWisdomPositiveInt(w.port, "port"),
|
|
2847
|
-
username: reqWd(w.username, "username").trim(),
|
|
2848
|
-
password: reqWd(w.password, "password").trim(),
|
|
2849
|
-
remotePath: reqWd(w.remotePath, "remotePath").trim()
|
|
2751
|
+
accessKey: req(f.accessKey, "accessKey", "frontendDeploy").trim(),
|
|
2752
|
+
secretKey: req(f.secretKey, "secretKey", "frontendDeploy").trim(),
|
|
2753
|
+
bucket: req(f.bucket, "bucket", "frontendDeploy").trim()
|
|
2850
2754
|
};
|
|
2851
2755
|
}
|
|
2852
|
-
|
|
2853
|
-
|
|
2854
|
-
|
|
2855
|
-
|
|
2856
|
-
|
|
2857
|
-
|
|
2858
|
-
|
|
2859
|
-
|
|
2860
|
-
|
|
2861
|
-
|
|
2862
|
-
process.exit(1);
|
|
2863
|
-
}
|
|
2864
|
-
return v;
|
|
2865
|
-
}
|
|
2756
|
+
|
|
2757
|
+
// src/commands/deploy/internal/config/maven-repo.ts
|
|
2758
|
+
import { existsSync as existsSync11, readFileSync as readFileSync10 } from "node:fs";
|
|
2759
|
+
import { homedir as homedir2 } from "node:os";
|
|
2760
|
+
import { join as join13, resolve as resolve3 } from "node:path";
|
|
2761
|
+
var MAVEN_REPO_ENV_KEYS = [
|
|
2762
|
+
"MAVEN_LOCAL_REPO",
|
|
2763
|
+
"M2_REPO",
|
|
2764
|
+
"MAVEN_REPOSITORY"
|
|
2765
|
+
];
|
|
2866
2766
|
function readEnvVar(env, name) {
|
|
2867
2767
|
if (env[name] !== void 0) {
|
|
2868
2768
|
return env[name];
|
|
@@ -2892,11 +2792,6 @@ function expandUserPath(pathStr, env = process.env) {
|
|
|
2892
2792
|
}
|
|
2893
2793
|
return resolve3(expanded);
|
|
2894
2794
|
}
|
|
2895
|
-
var MAVEN_REPO_ENV_KEYS = [
|
|
2896
|
-
"MAVEN_LOCAL_REPO",
|
|
2897
|
-
"M2_REPO",
|
|
2898
|
-
"MAVEN_REPOSITORY"
|
|
2899
|
-
];
|
|
2900
2795
|
function readMavenLocalRepoFromMavenOpts(mavenOpts, env = process.env) {
|
|
2901
2796
|
const match = mavenOpts.match(/-Dmaven\.repo\.local=(?:"([^"]+)"|(\S+))/);
|
|
2902
2797
|
const raw = match?.[1]?.trim() || match?.[2]?.trim();
|
|
@@ -2911,9 +2806,9 @@ function readMavenLocalRepoFromEnv(env = process.env) {
|
|
|
2911
2806
|
}
|
|
2912
2807
|
const mavenOpts = readEnvVar(env, "MAVEN_OPTS")?.trim();
|
|
2913
2808
|
if (mavenOpts) {
|
|
2914
|
-
const
|
|
2915
|
-
if (
|
|
2916
|
-
return { path:
|
|
2809
|
+
const path19 = readMavenLocalRepoFromMavenOpts(mavenOpts, env);
|
|
2810
|
+
if (path19) {
|
|
2811
|
+
return { path: path19, key: "MAVEN_OPTS" };
|
|
2917
2812
|
}
|
|
2918
2813
|
}
|
|
2919
2814
|
return null;
|
|
@@ -2960,6 +2855,18 @@ function resolveMavenLocalRepoWithSource() {
|
|
|
2960
2855
|
sourceDetail: "~/.m2/repository"
|
|
2961
2856
|
};
|
|
2962
2857
|
}
|
|
2858
|
+
|
|
2859
|
+
// src/commands/deploy/internal/config/wisdom-config.ts
|
|
2860
|
+
function resolveWisdomDeployFromApmConfig(cfg) {
|
|
2861
|
+
const w = cfg.wisdomDeploy ?? {};
|
|
2862
|
+
return {
|
|
2863
|
+
host: req(w.host, "host", "wisdomDeploy").trim(),
|
|
2864
|
+
port: reqPositiveInt(w.port, "port", "wisdomDeploy"),
|
|
2865
|
+
username: req(w.username, "username", "wisdomDeploy").trim(),
|
|
2866
|
+
password: req(w.password, "password", "wisdomDeploy").trim(),
|
|
2867
|
+
remotePath: req(w.remotePath, "remotePath", "wisdomDeploy").trim()
|
|
2868
|
+
};
|
|
2869
|
+
}
|
|
2963
2870
|
function resolveWisdomDeployMode(raw) {
|
|
2964
2871
|
if (raw === void 0 || raw === null || raw === "") {
|
|
2965
2872
|
return "default";
|
|
@@ -2973,14 +2880,27 @@ function resolveWisdomDeployMode(raw) {
|
|
|
2973
2880
|
);
|
|
2974
2881
|
process.exit(1);
|
|
2975
2882
|
}
|
|
2883
|
+
function posixDirname(p) {
|
|
2884
|
+
const normalized = p.replace(/\\/g, "/");
|
|
2885
|
+
const idx = normalized.lastIndexOf("/");
|
|
2886
|
+
if (idx <= 0) {
|
|
2887
|
+
return normalized.startsWith("/") ? "/" : ".";
|
|
2888
|
+
}
|
|
2889
|
+
return normalized.slice(0, idx);
|
|
2890
|
+
}
|
|
2891
|
+
function posixBasename(p) {
|
|
2892
|
+
const normalized = p.replace(/\\/g, "/");
|
|
2893
|
+
const idx = normalized.lastIndexOf("/");
|
|
2894
|
+
return idx >= 0 ? normalized.slice(idx + 1) : normalized;
|
|
2895
|
+
}
|
|
2976
2896
|
function resolveWisdomBackendDeployFromApmConfig(cfg) {
|
|
2977
2897
|
const projectName = reqTopLevelName(cfg);
|
|
2978
2898
|
const w = cfg.wisdomDeploy ?? {};
|
|
2979
2899
|
const h = cfg.healthCheck ?? {};
|
|
2980
|
-
const jarPath =
|
|
2900
|
+
const jarPath = req(w.jarPath, "jarPath", "wisdomDeploy").trim();
|
|
2981
2901
|
const remoteAppDir = posixDirname(jarPath);
|
|
2982
|
-
const healthPort = Number(
|
|
2983
|
-
const healthTimeout = Number(
|
|
2902
|
+
const healthPort = Number(req(h.port, "port", "healthCheck"));
|
|
2903
|
+
const healthTimeout = Number(req(h.timeout, "timeout", "healthCheck"));
|
|
2984
2904
|
if (!Number.isFinite(healthPort) || !Number.isInteger(healthPort) || healthPort < 1) {
|
|
2985
2905
|
console.error("apm.config.json \u4E2D healthCheck.port \u987B\u4E3A\u6B63\u6574\u6570");
|
|
2986
2906
|
process.exit(1);
|
|
@@ -2992,11 +2912,11 @@ function resolveWisdomBackendDeployFromApmConfig(cfg) {
|
|
|
2992
2912
|
const mavenLocalRepo = resolveMavenLocalRepoWithSource();
|
|
2993
2913
|
return {
|
|
2994
2914
|
projectName,
|
|
2995
|
-
host:
|
|
2996
|
-
port:
|
|
2997
|
-
username:
|
|
2998
|
-
password:
|
|
2999
|
-
remoteVueDistDir:
|
|
2915
|
+
host: req(w.host, "host", "wisdomDeploy").trim(),
|
|
2916
|
+
port: reqPositiveInt(w.port, "port", "wisdomDeploy"),
|
|
2917
|
+
username: req(w.username, "username", "wisdomDeploy").trim(),
|
|
2918
|
+
password: req(w.password, "password", "wisdomDeploy").trim(),
|
|
2919
|
+
remoteVueDistDir: req(w.remotePath, "remotePath", "wisdomDeploy").trim(),
|
|
3000
2920
|
remoteAppDir,
|
|
3001
2921
|
remoteLibDir: `${remoteAppDir}/lib`,
|
|
3002
2922
|
startupJar: posixBasename(jarPath),
|
|
@@ -3005,23 +2925,29 @@ function resolveWisdomBackendDeployFromApmConfig(cfg) {
|
|
|
3005
2925
|
mavenLocalRepoSource: mavenLocalRepo.source,
|
|
3006
2926
|
mavenLocalRepoSourceDetail: mavenLocalRepo.sourceDetail,
|
|
3007
2927
|
healthCheckPort: healthPort,
|
|
3008
|
-
healthCheckContext:
|
|
2928
|
+
healthCheckContext: req(h.context, "context", "healthCheck").trim(),
|
|
3009
2929
|
healthCheckTimeout: healthTimeout,
|
|
3010
2930
|
mode: resolveWisdomDeployMode(w.mode)
|
|
3011
2931
|
};
|
|
3012
2932
|
}
|
|
3013
|
-
|
|
3014
|
-
|
|
3015
|
-
|
|
3016
|
-
|
|
3017
|
-
|
|
2933
|
+
|
|
2934
|
+
// src/commands/deploy/internal/apm-config.ts
|
|
2935
|
+
function loadApmConfig(options) {
|
|
2936
|
+
const p = resolve4(
|
|
2937
|
+
process.cwd(),
|
|
2938
|
+
options?.configPath ?? resolve4(workspaceApmDir(), "apm.config.json")
|
|
2939
|
+
);
|
|
2940
|
+
if (!existsSync12(p)) {
|
|
2941
|
+
console.error(`\u672A\u627E\u5230\u914D\u7F6E\u6587\u4EF6\uFF1A${p}`);
|
|
2942
|
+
process.exit(1);
|
|
2943
|
+
}
|
|
2944
|
+
try {
|
|
2945
|
+
const raw = readFileSync11(p, "utf8");
|
|
2946
|
+
return JSON.parse(raw);
|
|
2947
|
+
} catch (e) {
|
|
2948
|
+
console.error(`\u65E0\u6CD5\u89E3\u6790 apm.config.json\uFF1A${p}`, e);
|
|
2949
|
+
process.exit(1);
|
|
3018
2950
|
}
|
|
3019
|
-
return normalized.slice(0, idx);
|
|
3020
|
-
}
|
|
3021
|
-
function posixBasename(p) {
|
|
3022
|
-
const normalized = p.replace(/\\/g, "/");
|
|
3023
|
-
const idx = normalized.lastIndexOf("/");
|
|
3024
|
-
return idx >= 0 ? normalized.slice(idx + 1) : normalized;
|
|
3025
2951
|
}
|
|
3026
2952
|
|
|
3027
2953
|
// src/commands/deploy/internal/deploy-hints.ts
|
|
@@ -3061,7 +2987,7 @@ var DeployExecutionError = class extends Error {
|
|
|
3061
2987
|
|
|
3062
2988
|
// src/commands/deploy/deploy-debug-log.ts
|
|
3063
2989
|
import { spawnSync as spawnSync4 } from "node:child_process";
|
|
3064
|
-
import { existsSync as
|
|
2990
|
+
import { existsSync as existsSync15 } from "node:fs";
|
|
3065
2991
|
import { dirname as dirname5, join as join16 } from "node:path";
|
|
3066
2992
|
|
|
3067
2993
|
// src/commands/deploy/internal/deploy-artifact-minio.ts
|
|
@@ -3167,14 +3093,14 @@ var MinioClient = class {
|
|
|
3167
3093
|
async deleteObjectsByPrefix(bucket, prefix) {
|
|
3168
3094
|
const objectsStream = this.inner.listObjectsV2(bucket, prefix, true);
|
|
3169
3095
|
const keys = [];
|
|
3170
|
-
await new Promise((
|
|
3096
|
+
await new Promise((resolve6, reject) => {
|
|
3171
3097
|
objectsStream.on("data", (obj) => {
|
|
3172
3098
|
if (obj.name) {
|
|
3173
3099
|
keys.push(obj.name);
|
|
3174
3100
|
}
|
|
3175
3101
|
});
|
|
3176
3102
|
objectsStream.on("error", reject);
|
|
3177
|
-
objectsStream.on("end",
|
|
3103
|
+
objectsStream.on("end", resolve6);
|
|
3178
3104
|
});
|
|
3179
3105
|
const chunkSize = 500;
|
|
3180
3106
|
for (let i = 0; i < keys.length; i += chunkSize) {
|
|
@@ -3320,15 +3246,15 @@ import { dirname as dirname4 } from "node:path";
|
|
|
3320
3246
|
|
|
3321
3247
|
// src/commands/daemon.ts
|
|
3322
3248
|
import { spawnSync as spawnSync2 } from "child_process";
|
|
3323
|
-
import { setTimeout as
|
|
3324
|
-
import { existsSync as
|
|
3249
|
+
import { setTimeout as delay } from "node:timers/promises";
|
|
3250
|
+
import { existsSync as existsSync14, mkdirSync as mkdirSync6, unlinkSync as unlinkSync2, writeFileSync as writeFileSync11 } from "fs";
|
|
3325
3251
|
import { join as join15 } from "path";
|
|
3326
3252
|
|
|
3327
3253
|
// src/commands/connect-lock.ts
|
|
3328
3254
|
import {
|
|
3329
|
-
existsSync as
|
|
3255
|
+
existsSync as existsSync13,
|
|
3330
3256
|
mkdirSync as mkdirSync5,
|
|
3331
|
-
readFileSync as
|
|
3257
|
+
readFileSync as readFileSync12,
|
|
3332
3258
|
unlinkSync,
|
|
3333
3259
|
writeFileSync as writeFileSync10
|
|
3334
3260
|
} from "fs";
|
|
@@ -3360,9 +3286,9 @@ function waitForPm2LockHandoff(timeoutMs = 5e3) {
|
|
|
3360
3286
|
}
|
|
3361
3287
|
}
|
|
3362
3288
|
function readConnectLock() {
|
|
3363
|
-
if (!
|
|
3289
|
+
if (!existsSync13(CONNECT_LOCK_PATH)) return null;
|
|
3364
3290
|
try {
|
|
3365
|
-
const raw =
|
|
3291
|
+
const raw = readFileSync12(CONNECT_LOCK_PATH, "utf8");
|
|
3366
3292
|
const parsed = JSON.parse(raw);
|
|
3367
3293
|
if (typeof parsed.pid !== "number" || parsed.mode !== "foreground" && parsed.mode !== "pm2" || typeof parsed.startedAt !== "string") {
|
|
3368
3294
|
return null;
|
|
@@ -3419,7 +3345,7 @@ function releaseConnectLock() {
|
|
|
3419
3345
|
}
|
|
3420
3346
|
function forceReleaseConnectLock() {
|
|
3421
3347
|
try {
|
|
3422
|
-
if (
|
|
3348
|
+
if (existsSync13(CONNECT_LOCK_PATH)) {
|
|
3423
3349
|
unlinkSync(CONNECT_LOCK_PATH);
|
|
3424
3350
|
}
|
|
3425
3351
|
} catch {
|
|
@@ -3569,14 +3495,14 @@ function resolvePm2FromNpmRoot() {
|
|
|
3569
3495
|
if (!root) return null;
|
|
3570
3496
|
for (const rel of ["pm2/bin/pm2", "pm2/bin/pm2.js"]) {
|
|
3571
3497
|
const candidate = join15(root, ...rel.split("/"));
|
|
3572
|
-
if (
|
|
3498
|
+
if (existsSync14(candidate)) {
|
|
3573
3499
|
return candidate;
|
|
3574
3500
|
}
|
|
3575
3501
|
}
|
|
3576
3502
|
return null;
|
|
3577
3503
|
}
|
|
3578
|
-
function isPm2NodeScript(
|
|
3579
|
-
return
|
|
3504
|
+
function isPm2NodeScript(path19) {
|
|
3505
|
+
return path19.endsWith(".js") || /[\\/]pm2[\\/]bin[\\/]pm2$/.test(path19);
|
|
3580
3506
|
}
|
|
3581
3507
|
function buildPm2SpawnTarget(binPath) {
|
|
3582
3508
|
if (isPm2NodeScript(binPath)) {
|
|
@@ -3606,7 +3532,7 @@ function spawnPm2At(binPath, args, options = {}) {
|
|
|
3606
3532
|
return spawnPm2Target(buildPm2SpawnTarget(binPath), args, options);
|
|
3607
3533
|
}
|
|
3608
3534
|
function verifyPm2Bin(pm2Bin) {
|
|
3609
|
-
if (!pm2Bin.trim() || !
|
|
3535
|
+
if (!pm2Bin.trim() || !existsSync14(pm2Bin)) {
|
|
3610
3536
|
return false;
|
|
3611
3537
|
}
|
|
3612
3538
|
const result = spawnPm2At(pm2Bin, ["--version"], {
|
|
@@ -3745,7 +3671,7 @@ function ensureGlobalPm2(options) {
|
|
|
3745
3671
|
}
|
|
3746
3672
|
function resolveApmEntryPath(entryArg = process.argv[1]) {
|
|
3747
3673
|
const fromArgv = entryArg?.trim();
|
|
3748
|
-
if (fromArgv &&
|
|
3674
|
+
if (fromArgv && existsSync14(fromArgv)) {
|
|
3749
3675
|
return fromArgv;
|
|
3750
3676
|
}
|
|
3751
3677
|
const npmResult = spawnSync2(useNpmShell2 ? "npm.cmd" : "npm", ["root", "-g"], {
|
|
@@ -3757,7 +3683,7 @@ function resolveApmEntryPath(entryArg = process.argv[1]) {
|
|
|
3757
3683
|
const globalRoot = npmResult.stdout?.toString().trim();
|
|
3758
3684
|
if (globalRoot) {
|
|
3759
3685
|
const candidate = join15(globalRoot, CLI_PACKAGE_NAME, "dist", "index.js");
|
|
3760
|
-
if (
|
|
3686
|
+
if (existsSync14(candidate)) {
|
|
3761
3687
|
return candidate;
|
|
3762
3688
|
}
|
|
3763
3689
|
}
|
|
@@ -3948,7 +3874,7 @@ function writeEcosystemFile(options) {
|
|
|
3948
3874
|
formatConnectPm2EcosystemFile(ecosystem),
|
|
3949
3875
|
"utf8"
|
|
3950
3876
|
);
|
|
3951
|
-
if (
|
|
3877
|
+
if (existsSync14(LEGACY_PM2_ECOSYSTEM_PATH)) {
|
|
3952
3878
|
try {
|
|
3953
3879
|
unlinkSync2(LEGACY_PM2_ECOSYSTEM_PATH);
|
|
3954
3880
|
} catch {
|
|
@@ -3977,7 +3903,7 @@ async function runDaemonStart(options) {
|
|
|
3977
3903
|
const cfg = await prepareEcosystem(options.server);
|
|
3978
3904
|
removePm2ConnectProcesses();
|
|
3979
3905
|
runPm2(["start", PM2_ECOSYSTEM_PATH, "--update-env"], { inherit: true });
|
|
3980
|
-
await
|
|
3906
|
+
await delay(1e3);
|
|
3981
3907
|
if (!isPm2ConnectOnline()) {
|
|
3982
3908
|
console.error(
|
|
3983
3909
|
`[apm] ${PM2_APP_NAME} \u542F\u52A8\u540E\u672A\u5904\u4E8E online \u72B6\u6001\uFF0C\u8BF7\u6267\u884C: apm daemon logs -n 200`
|
|
@@ -4010,7 +3936,7 @@ async function runDaemonStop() {
|
|
|
4010
3936
|
});
|
|
4011
3937
|
for (let i = 0; i < 10; i += 1) {
|
|
4012
3938
|
if (!isPm2ConnectOnline()) break;
|
|
4013
|
-
await
|
|
3939
|
+
await delay(500);
|
|
4014
3940
|
}
|
|
4015
3941
|
if (isPm2ConnectOnline()) {
|
|
4016
3942
|
console.log(`[apm] \u4F18\u96C5\u505C\u6B62\u8D85\u65F6\uFF0C\u5F3A\u5236\u79FB\u9664 ${PM2_APP_NAME}\u2026`);
|
|
@@ -4245,12 +4171,12 @@ function logExecuteDeployContext(input) {
|
|
|
4245
4171
|
`cwdMatchProcess=${input.cwd === input.processCwd ? "yes" : "no"} (connect \u901A\u5E38\u4E3A no)`
|
|
4246
4172
|
);
|
|
4247
4173
|
logLine(
|
|
4248
|
-
`apm.config=${input.apmConfigPath} exists=${
|
|
4174
|
+
`apm.config=${input.apmConfigPath} exists=${existsSync15(
|
|
4249
4175
|
input.apmConfigPath
|
|
4250
4176
|
)}`
|
|
4251
4177
|
);
|
|
4252
4178
|
logLine(
|
|
4253
|
-
`package.json=${packageJsonPath} exists=${
|
|
4179
|
+
`package.json=${packageJsonPath} exists=${existsSync15(packageJsonPath)}`
|
|
4254
4180
|
);
|
|
4255
4181
|
logLine(
|
|
4256
4182
|
`flags captureOutput=${input.captureOutput} packOnly=${Boolean(
|
|
@@ -4306,18 +4232,64 @@ function logWisdomFrontendDeployContext(input) {
|
|
|
4306
4232
|
logLine(
|
|
4307
4233
|
`buildKey=build:${input.env} buildCmd=${input.buildCmd ?? "(missing)"}`
|
|
4308
4234
|
);
|
|
4309
|
-
logLine(`distDir=${input.distDir} exists=${
|
|
4235
|
+
logLine(`distDir=${input.distDir} exists=${existsSync15(input.distDir)}`);
|
|
4310
4236
|
logLine(
|
|
4311
4237
|
`packOnly=${input.packOnly} archiveDeployArtifact=${input.archiveDeployArtifact}`
|
|
4312
4238
|
);
|
|
4313
4239
|
}
|
|
4314
4240
|
|
|
4315
4241
|
// src/commands/deploy/internal/wisdom-deploy.ts
|
|
4316
|
-
import { existsSync as
|
|
4317
|
-
import
|
|
4242
|
+
import { existsSync as existsSync19, readFileSync as readFileSync15, statSync as statSync9 } from "node:fs";
|
|
4243
|
+
import path10 from "node:path";
|
|
4318
4244
|
|
|
4319
4245
|
// src/commands/deploy/deploy-shell-run.ts
|
|
4320
4246
|
import { spawnSync as spawnSync5 } from "node:child_process";
|
|
4247
|
+
|
|
4248
|
+
// src/commands/deploy/deploy-log-utils.ts
|
|
4249
|
+
import { setTimeout as delay2 } from "node:timers/promises";
|
|
4250
|
+
var DEPLOY_SPAWN_MAX_BUFFER_BYTES = 50 * 1024 * 1024;
|
|
4251
|
+
var DEPLOY_LOG_SYNC_MAX_CHUNK_BYTES = 4 * 1024 * 1024;
|
|
4252
|
+
var DEPLOY_LOG_SYNC_MAX_ATTEMPTS = 3;
|
|
4253
|
+
async function retryDeployLogSync(fn, attempts = DEPLOY_LOG_SYNC_MAX_ATTEMPTS) {
|
|
4254
|
+
let lastError;
|
|
4255
|
+
for (let attempt = 1; attempt <= attempts; attempt += 1) {
|
|
4256
|
+
try {
|
|
4257
|
+
return await fn();
|
|
4258
|
+
} catch (error) {
|
|
4259
|
+
lastError = error;
|
|
4260
|
+
if (attempt < attempts) {
|
|
4261
|
+
await delay2(1e3 * attempt);
|
|
4262
|
+
}
|
|
4263
|
+
}
|
|
4264
|
+
}
|
|
4265
|
+
throw lastError;
|
|
4266
|
+
}
|
|
4267
|
+
var retryDeployStatusComplete = retryDeployLogSync;
|
|
4268
|
+
function splitUtf8StringByMaxBytes(value, maxBytes) {
|
|
4269
|
+
if (maxBytes <= 0) {
|
|
4270
|
+
throw new Error("maxBytes must be positive");
|
|
4271
|
+
}
|
|
4272
|
+
const bytes = Buffer.from(value, "utf8");
|
|
4273
|
+
if (bytes.length <= maxBytes) {
|
|
4274
|
+
return [value];
|
|
4275
|
+
}
|
|
4276
|
+
const chunks = [];
|
|
4277
|
+
let offset = 0;
|
|
4278
|
+
while (offset < bytes.length) {
|
|
4279
|
+
let end = Math.min(offset + maxBytes, bytes.length);
|
|
4280
|
+
while (end > offset && (bytes[end] & 192) === 128) {
|
|
4281
|
+
end -= 1;
|
|
4282
|
+
}
|
|
4283
|
+
if (end <= offset) {
|
|
4284
|
+
end = Math.min(offset + maxBytes, bytes.length);
|
|
4285
|
+
}
|
|
4286
|
+
chunks.push(bytes.subarray(offset, end).toString("utf8"));
|
|
4287
|
+
offset = end;
|
|
4288
|
+
}
|
|
4289
|
+
return chunks;
|
|
4290
|
+
}
|
|
4291
|
+
|
|
4292
|
+
// src/commands/deploy/deploy-shell-run.ts
|
|
4321
4293
|
function runDeployShellCommand(command, cwd, captureOutput) {
|
|
4322
4294
|
logRunDeployShellContext({ command, cwd, captureOutput });
|
|
4323
4295
|
const shellEnv = buildDeployShellEnv();
|
|
@@ -4360,30 +4332,80 @@ function runDeployShellCommand(command, cwd, captureOutput) {
|
|
|
4360
4332
|
return output;
|
|
4361
4333
|
}
|
|
4362
4334
|
|
|
4363
|
-
// src/commands/deploy/internal/wisdom-backend
|
|
4335
|
+
// src/commands/deploy/internal/wisdom-backend/index.ts
|
|
4336
|
+
import path9 from "node:path";
|
|
4337
|
+
|
|
4338
|
+
// src/commands/deploy/internal/wisdom-backend/jar-incremental.ts
|
|
4364
4339
|
import {
|
|
4365
|
-
|
|
4366
|
-
mkdirSync as mkdirSync7,
|
|
4340
|
+
mkdirSync as mkdirSync8,
|
|
4367
4341
|
readdirSync as readdirSync5,
|
|
4368
|
-
readFileSync as
|
|
4342
|
+
readFileSync as readFileSync14,
|
|
4343
|
+
statSync as statSync7,
|
|
4344
|
+
writeFileSync as writeFileSync13
|
|
4345
|
+
} from "node:fs";
|
|
4346
|
+
import path6 from "node:path";
|
|
4347
|
+
import JSZip2 from "jszip";
|
|
4348
|
+
|
|
4349
|
+
// src/commands/deploy/internal/wisdom-backend/manifest.ts
|
|
4350
|
+
import {
|
|
4351
|
+
existsSync as existsSync16,
|
|
4352
|
+
mkdirSync as mkdirSync7,
|
|
4353
|
+
readFileSync as readFileSync13,
|
|
4369
4354
|
statSync as statSync6,
|
|
4370
4355
|
writeFileSync as writeFileSync12
|
|
4371
4356
|
} from "node:fs";
|
|
4372
|
-
import
|
|
4373
|
-
|
|
4374
|
-
|
|
4375
|
-
|
|
4376
|
-
|
|
4357
|
+
import path2 from "node:path";
|
|
4358
|
+
function deployCacheDir() {
|
|
4359
|
+
return path2.join(workspaceApmDir(), "deploy", ".deploy_cache");
|
|
4360
|
+
}
|
|
4361
|
+
function manifestFilePath() {
|
|
4362
|
+
return path2.join(deployCacheDir(), "manifest.json");
|
|
4363
|
+
}
|
|
4364
|
+
function relativeKey(projectRoot, filePath) {
|
|
4365
|
+
return path2.relative(projectRoot, filePath).split(path2.sep).join("/");
|
|
4366
|
+
}
|
|
4367
|
+
function fileSignature(filePath) {
|
|
4368
|
+
const stat2 = statSync6(filePath);
|
|
4369
|
+
return { size: stat2.size, mtime: stat2.mtimeMs / 1e3 };
|
|
4370
|
+
}
|
|
4371
|
+
function loadManifest3() {
|
|
4372
|
+
const manifestPath2 = manifestFilePath();
|
|
4373
|
+
if (!existsSync16(manifestPath2)) {
|
|
4374
|
+
return {};
|
|
4375
|
+
}
|
|
4376
|
+
return JSON.parse(readFileSync13(manifestPath2, "utf8"));
|
|
4377
|
+
}
|
|
4378
|
+
function saveManifest3(manifest) {
|
|
4379
|
+
const dir = deployCacheDir();
|
|
4380
|
+
mkdirSync7(dir, { recursive: true });
|
|
4381
|
+
writeFileSync12(manifestFilePath(), JSON.stringify(manifest, null, 2), "utf8");
|
|
4382
|
+
}
|
|
4383
|
+
function updateManifestEntries(manifest, entries, projectRoot) {
|
|
4384
|
+
for (const entry of entries) {
|
|
4385
|
+
manifest[relativeKey(projectRoot, entry.path)] = fileSignature(entry.path);
|
|
4386
|
+
}
|
|
4387
|
+
return manifest;
|
|
4388
|
+
}
|
|
4389
|
+
function deployCacheDirectory() {
|
|
4390
|
+
return deployCacheDir();
|
|
4391
|
+
}
|
|
4392
|
+
|
|
4393
|
+
// src/commands/deploy/internal/wisdom-backend/internal-utils.ts
|
|
4394
|
+
import path5 from "node:path";
|
|
4377
4395
|
|
|
4378
4396
|
// src/commands/deploy/internal/wisdom-sftp.ts
|
|
4397
|
+
import { unlink as unlink2 } from "node:fs/promises";
|
|
4398
|
+
import path4 from "node:path";
|
|
4399
|
+
import SftpClient from "ssh2-sftp-client";
|
|
4400
|
+
|
|
4401
|
+
// src/commands/deploy/internal/artifact-packaging.ts
|
|
4379
4402
|
import { readdir as readdir2, readFile as readFile3, unlink, writeFile } from "node:fs/promises";
|
|
4380
|
-
import
|
|
4403
|
+
import path3 from "node:path";
|
|
4381
4404
|
import JSZip from "jszip";
|
|
4382
|
-
import SftpClient from "ssh2-sftp-client";
|
|
4383
4405
|
async function addDirToZip(dir, zipFolder) {
|
|
4384
4406
|
const entries = await readdir2(dir, { withFileTypes: true });
|
|
4385
4407
|
for (const entry of entries) {
|
|
4386
|
-
const fullPath =
|
|
4408
|
+
const fullPath = path3.join(dir, entry.name);
|
|
4387
4409
|
if (entry.isDirectory()) {
|
|
4388
4410
|
const folder = zipFolder.folder(entry.name);
|
|
4389
4411
|
if (folder) {
|
|
@@ -4409,7 +4431,66 @@ async function zipDirectory(distDir, zipPath) {
|
|
|
4409
4431
|
console.error(`\u5DF2\u751F\u6210: ${zipPath} (${sizeMb} MB)`);
|
|
4410
4432
|
return content.length;
|
|
4411
4433
|
}
|
|
4412
|
-
|
|
4434
|
+
function resolveProjectNameForDeploy(cfg, cwd, options) {
|
|
4435
|
+
const name = (cfg.name ?? "").trim();
|
|
4436
|
+
if (options?.requireName && !name) {
|
|
4437
|
+
throw new DeployExecutionError(
|
|
4438
|
+
"\u8BF7\u5728 .apm/apm.config.json \u9876\u5C42\u914D\u7F6E name\uFF08\u4F5C\u4E3A\u90E8\u7F72\u4EA7\u7269\u9879\u76EE\u540D\uFF09",
|
|
4439
|
+
1
|
|
4440
|
+
);
|
|
4441
|
+
}
|
|
4442
|
+
if (name) {
|
|
4443
|
+
return name;
|
|
4444
|
+
}
|
|
4445
|
+
return path3.basename(cwd);
|
|
4446
|
+
}
|
|
4447
|
+
function resolveArtifactNamePrefix(cfg) {
|
|
4448
|
+
const nameRaw = resolveProjectNameForDeploy(cfg, process.cwd(), {
|
|
4449
|
+
requireName: true
|
|
4450
|
+
});
|
|
4451
|
+
if (nameRaw.includes(":")) {
|
|
4452
|
+
throw new DeployExecutionError("apm.config.json \u7684 name \u4E0D\u80FD\u5305\u542B ':'", 1);
|
|
4453
|
+
}
|
|
4454
|
+
try {
|
|
4455
|
+
return sanitizeRelativePath(nameRaw.replace(/\\/g, "/"));
|
|
4456
|
+
} catch {
|
|
4457
|
+
throw new DeployExecutionError(
|
|
4458
|
+
"apm.config.json \u7684 name \u975E\u6CD5\uFF08\u8DEF\u5F84\u7247\u6BB5\u4E0D\u80FD\u4E3A . \u6216 ..\uFF09",
|
|
4459
|
+
1
|
|
4460
|
+
);
|
|
4461
|
+
}
|
|
4462
|
+
}
|
|
4463
|
+
async function packDirectoryWithMinioArchive(input) {
|
|
4464
|
+
const resolvedZipPath = path3.resolve(input.zipPath);
|
|
4465
|
+
let zipSizeBytes = 0;
|
|
4466
|
+
let artifactUploaded = false;
|
|
4467
|
+
try {
|
|
4468
|
+
zipSizeBytes = await zipDirectory(input.localDir, resolvedZipPath);
|
|
4469
|
+
if (input.skipMessage) {
|
|
4470
|
+
console.error(input.skipMessage);
|
|
4471
|
+
}
|
|
4472
|
+
const artifact = await uploadDeployArtifactZip({
|
|
4473
|
+
zipPath: resolvedZipPath,
|
|
4474
|
+
projectName: input.projectName,
|
|
4475
|
+
kind: input.kind,
|
|
4476
|
+
uploadWithoutRunId: input.uploadWithoutRunId
|
|
4477
|
+
});
|
|
4478
|
+
artifactUploaded = artifact !== null;
|
|
4479
|
+
if (artifactUploaded && input.successMessage) {
|
|
4480
|
+
console.error(input.successMessage);
|
|
4481
|
+
}
|
|
4482
|
+
return { zipSizeBytes, artifactUploaded };
|
|
4483
|
+
} finally {
|
|
4484
|
+
try {
|
|
4485
|
+
await unlink(resolvedZipPath);
|
|
4486
|
+
console.error(`\u5DF2\u6E05\u7406\u672C\u5730\u4E34\u65F6\u6587\u4EF6: ${resolvedZipPath}`);
|
|
4487
|
+
} catch {
|
|
4488
|
+
}
|
|
4489
|
+
}
|
|
4490
|
+
}
|
|
4491
|
+
|
|
4492
|
+
// src/commands/deploy/internal/wisdom-sftp.ts
|
|
4493
|
+
var SFTP_UPLOAD_MAX_ATTEMPTS = 3;
|
|
4413
4494
|
var SFTP_FAST_PUT_OPTIONS = {
|
|
4414
4495
|
chunkSize: 64 * 1024,
|
|
4415
4496
|
concurrency: 4
|
|
@@ -4427,7 +4508,7 @@ function buildSftpConnectOptions(settings) {
|
|
|
4427
4508
|
};
|
|
4428
4509
|
}
|
|
4429
4510
|
async function sleep(ms) {
|
|
4430
|
-
await new Promise((
|
|
4511
|
+
await new Promise((resolve6) => setTimeout(resolve6, ms));
|
|
4431
4512
|
}
|
|
4432
4513
|
async function uploadZipWithRetry(settings, localZip, remoteZipPath) {
|
|
4433
4514
|
let lastError;
|
|
@@ -4471,7 +4552,7 @@ async function ensureRemoteDir(sftp, dir) {
|
|
|
4471
4552
|
}
|
|
4472
4553
|
}
|
|
4473
4554
|
function execCommand(client, command) {
|
|
4474
|
-
return new Promise((
|
|
4555
|
+
return new Promise((resolve6, reject) => {
|
|
4475
4556
|
client.exec(command, (err, stream) => {
|
|
4476
4557
|
if (err) return reject(err);
|
|
4477
4558
|
let stdout = "";
|
|
@@ -4481,7 +4562,7 @@ function execCommand(client, command) {
|
|
|
4481
4562
|
reject(new Error(`\u8FDC\u7A0B\u547D\u4EE4\u5931\u8D25 (${code}): ${stderr || stdout}`));
|
|
4482
4563
|
return;
|
|
4483
4564
|
}
|
|
4484
|
-
|
|
4565
|
+
resolve6(stdout);
|
|
4485
4566
|
}).on("data", (data) => {
|
|
4486
4567
|
stdout += data.toString();
|
|
4487
4568
|
});
|
|
@@ -4548,8 +4629,8 @@ function resolveDeployArtifactUpload(input) {
|
|
|
4548
4629
|
return { upload: false, uploadWithoutRunId: false };
|
|
4549
4630
|
}
|
|
4550
4631
|
async function runWisdomSftpDeploy(params) {
|
|
4551
|
-
const zipPath =
|
|
4552
|
-
const resolvedZipPath =
|
|
4632
|
+
const zipPath = path4.join(params.localDir, "..", ".deploy-sftp-dist.zip");
|
|
4633
|
+
const resolvedZipPath = path4.resolve(zipPath);
|
|
4553
4634
|
const packOnly = Boolean(params.packOnly);
|
|
4554
4635
|
const archiveDeployArtifact = Boolean(params.archiveDeployArtifact);
|
|
4555
4636
|
const deploymentRunId = resolveDeploymentRunIdFromEnv();
|
|
@@ -4560,38 +4641,44 @@ async function runWisdomSftpDeploy(params) {
|
|
|
4560
4641
|
});
|
|
4561
4642
|
let zipSizeBytes = 0;
|
|
4562
4643
|
let artifactUploaded = false;
|
|
4563
|
-
|
|
4564
|
-
|
|
4565
|
-
|
|
4644
|
+
if (packOnly && artifactUpload.upload) {
|
|
4645
|
+
const packed = await packDirectoryWithMinioArchive({
|
|
4646
|
+
localDir: params.localDir,
|
|
4647
|
+
zipPath: resolvedZipPath,
|
|
4648
|
+
projectName: params.projectName,
|
|
4649
|
+
kind: "frontend",
|
|
4650
|
+
uploadWithoutRunId: artifactUpload.uploadWithoutRunId,
|
|
4651
|
+
skipMessage: "[apm] \u4EC5\u6253\u5305\u6A21\u5F0F\uFF1A\u8DF3\u8FC7 SFTP \u8FDC\u7A0B\u4E0A\u4F20",
|
|
4652
|
+
successMessage: "\u6253\u5305\u5E76\u4E0A\u4F20 MinIO \u5B8C\u6210\uFF08\u672A\u4E0A\u4F20\u8FDC\u7A0B\u670D\u52A1\u5668\uFF09"
|
|
4653
|
+
});
|
|
4654
|
+
zipSizeBytes = packed.zipSizeBytes;
|
|
4655
|
+
artifactUploaded = packed.artifactUploaded;
|
|
4656
|
+
} else {
|
|
4657
|
+
try {
|
|
4658
|
+
zipSizeBytes = await zipDirectory(params.localDir, resolvedZipPath);
|
|
4566
4659
|
await uploadAndMaybeExtract(
|
|
4567
4660
|
params.settings,
|
|
4568
4661
|
resolvedZipPath,
|
|
4569
4662
|
params.extract
|
|
4570
4663
|
);
|
|
4571
|
-
|
|
4572
|
-
|
|
4573
|
-
|
|
4574
|
-
|
|
4575
|
-
|
|
4576
|
-
|
|
4577
|
-
|
|
4578
|
-
|
|
4579
|
-
|
|
4580
|
-
|
|
4581
|
-
artifactUploaded = artifact !== null;
|
|
4582
|
-
}
|
|
4583
|
-
if (artifactUploaded) {
|
|
4584
|
-
if (packOnly) {
|
|
4585
|
-
console.error("\u6253\u5305\u5E76\u4E0A\u4F20 MinIO \u5B8C\u6210\uFF08\u672A\u4E0A\u4F20\u8FDC\u7A0B\u670D\u52A1\u5668\uFF09");
|
|
4586
|
-
} else {
|
|
4664
|
+
if (artifactUpload.upload) {
|
|
4665
|
+
const artifact = await uploadDeployArtifactZip({
|
|
4666
|
+
zipPath: resolvedZipPath,
|
|
4667
|
+
projectName: params.projectName,
|
|
4668
|
+
kind: "frontend",
|
|
4669
|
+
uploadWithoutRunId: artifactUpload.uploadWithoutRunId
|
|
4670
|
+
});
|
|
4671
|
+
artifactUploaded = artifact !== null;
|
|
4672
|
+
}
|
|
4673
|
+
if (artifactUploaded) {
|
|
4587
4674
|
console.error("[apm] SFTP \u90E8\u7F72\u5B8C\u6210\uFF0C\u90E8\u7F72\u4EA7\u7269\u5DF2\u5F52\u6863 MinIO");
|
|
4588
4675
|
}
|
|
4589
|
-
}
|
|
4590
|
-
|
|
4591
|
-
|
|
4592
|
-
|
|
4593
|
-
|
|
4594
|
-
|
|
4676
|
+
} finally {
|
|
4677
|
+
try {
|
|
4678
|
+
await unlink2(resolvedZipPath);
|
|
4679
|
+
console.error(`\u5DF2\u6E05\u7406\u672C\u5730\u4E34\u65F6\u6587\u4EF6: ${resolvedZipPath}`);
|
|
4680
|
+
} catch {
|
|
4681
|
+
}
|
|
4595
4682
|
}
|
|
4596
4683
|
}
|
|
4597
4684
|
return {
|
|
@@ -4606,7 +4693,7 @@ async function runWisdomSftpDeploy(params) {
|
|
|
4606
4693
|
};
|
|
4607
4694
|
}
|
|
4608
4695
|
|
|
4609
|
-
// src/commands/deploy/internal/wisdom-backend-
|
|
4696
|
+
// src/commands/deploy/internal/wisdom-backend/internal-utils.ts
|
|
4610
4697
|
var SPRINGBOOT_JAVA_OPTS = "-XX:+UseG1GC -XX:+HeapDumpOnOutOfMemoryError -Xms512M -Xmx1G";
|
|
4611
4698
|
var MAVEN_MODULE = "jeecg-module-system/jeecg-system-start";
|
|
4612
4699
|
var MAVEN_PROFILE = "dev";
|
|
@@ -4619,11 +4706,11 @@ function log(message) {
|
|
|
4619
4706
|
}
|
|
4620
4707
|
function fail(message) {
|
|
4621
4708
|
log(`ERROR: ${message}`);
|
|
4622
|
-
|
|
4709
|
+
throw new DeployExecutionError(message, 1);
|
|
4623
4710
|
}
|
|
4624
4711
|
function expandPath(pathStr) {
|
|
4625
4712
|
const home = process.env.HOME ?? process.env.USERPROFILE ?? "";
|
|
4626
|
-
return
|
|
4713
|
+
return path5.resolve(pathStr.replace(/^~(?=\/|\\|$)/, home));
|
|
4627
4714
|
}
|
|
4628
4715
|
function quoteForShell(value) {
|
|
4629
4716
|
if (process.platform === "win32") {
|
|
@@ -4637,34 +4724,14 @@ function formatMavenLocalRepoArg(repoPath) {
|
|
|
4637
4724
|
}
|
|
4638
4725
|
return `-Dmaven.repo.local=${repoPath}`;
|
|
4639
4726
|
}
|
|
4640
|
-
function deployCacheDir() {
|
|
4641
|
-
return path3.join(workspaceApmDir(), "deploy", ".deploy_cache");
|
|
4642
|
-
}
|
|
4643
|
-
function manifestFilePath() {
|
|
4644
|
-
return path3.join(deployCacheDir(), "manifest.json");
|
|
4645
|
-
}
|
|
4646
4727
|
function getTargetDir(projectRoot) {
|
|
4647
|
-
return
|
|
4648
|
-
}
|
|
4649
|
-
function relativeKey(projectRoot, filePath) {
|
|
4650
|
-
return path3.relative(projectRoot, filePath).split(path3.sep).join("/");
|
|
4651
|
-
}
|
|
4652
|
-
function fileSignature(filePath) {
|
|
4653
|
-
const stat2 = statSync6(filePath);
|
|
4654
|
-
return { size: stat2.size, mtime: stat2.mtimeMs / 1e3 };
|
|
4728
|
+
return path5.join(projectRoot, MAVEN_MODULE, "target");
|
|
4655
4729
|
}
|
|
4656
|
-
function
|
|
4657
|
-
|
|
4658
|
-
if (!existsSync15(manifestPath2)) {
|
|
4659
|
-
return {};
|
|
4660
|
-
}
|
|
4661
|
-
return JSON.parse(readFileSync12(manifestPath2, "utf8"));
|
|
4662
|
-
}
|
|
4663
|
-
function saveManifest3(manifest) {
|
|
4664
|
-
const dir = deployCacheDir();
|
|
4665
|
-
mkdirSync7(dir, { recursive: true });
|
|
4666
|
-
writeFileSync12(manifestFilePath(), JSON.stringify(manifest, null, 2), "utf8");
|
|
4730
|
+
function stripAnsi(text) {
|
|
4731
|
+
return text.replace(/\x1b\[[0-?]*[ -/]*[@-~]/g, "");
|
|
4667
4732
|
}
|
|
4733
|
+
|
|
4734
|
+
// src/commands/deploy/internal/wisdom-backend/jar-incremental.ts
|
|
4668
4735
|
function isProjectLibJar(jarName) {
|
|
4669
4736
|
return jarName.startsWith("jeecg-");
|
|
4670
4737
|
}
|
|
@@ -4672,12 +4739,12 @@ function shouldUploadLibFile(localPath, remoteAttr, manifest, projectRoot) {
|
|
|
4672
4739
|
if (!remoteAttr) {
|
|
4673
4740
|
return [false, "\u8FDC\u7A0B\u4E0D\u5B58\u5728\uFF0C\u8DF3\u8FC7"];
|
|
4674
4741
|
}
|
|
4675
|
-
const localSize =
|
|
4742
|
+
const localSize = statSync7(localPath).size;
|
|
4676
4743
|
const remoteSize = remoteAttr.size;
|
|
4677
4744
|
if (localSize !== remoteSize) {
|
|
4678
4745
|
return [true, `\u5927\u5C0F\u53D8\u5316 ${remoteSize} -> ${localSize}`];
|
|
4679
4746
|
}
|
|
4680
|
-
if (isProjectLibJar(
|
|
4747
|
+
if (isProjectLibJar(path6.basename(localPath)) && manifest) {
|
|
4681
4748
|
const key = relativeKey(projectRoot, localPath);
|
|
4682
4749
|
const current = fileSignature(localPath);
|
|
4683
4750
|
const previous = manifest[key];
|
|
@@ -4697,7 +4764,7 @@ function listLibFilesToUpload(localLibDir, remoteStats, projectRoot, manifest =
|
|
|
4697
4764
|
const entries = [];
|
|
4698
4765
|
const jarFiles = readdirSync5(localLibDir).filter((name) => name.endsWith(".jar")).sort();
|
|
4699
4766
|
for (const jarName of jarFiles) {
|
|
4700
|
-
const jarPath =
|
|
4767
|
+
const jarPath = path6.join(localLibDir, jarName);
|
|
4701
4768
|
const remoteAttr = remoteStats.get(jarName);
|
|
4702
4769
|
const [shouldUpload, reason] = shouldUploadLibFile(
|
|
4703
4770
|
jarPath,
|
|
@@ -4711,20 +4778,14 @@ function listLibFilesToUpload(localLibDir, remoteStats, projectRoot, manifest =
|
|
|
4711
4778
|
}
|
|
4712
4779
|
return entries;
|
|
4713
4780
|
}
|
|
4714
|
-
function updateManifestEntries(manifest, entries, projectRoot) {
|
|
4715
|
-
for (const entry of entries) {
|
|
4716
|
-
manifest[relativeKey(projectRoot, entry.path)] = fileSignature(entry.path);
|
|
4717
|
-
}
|
|
4718
|
-
return manifest;
|
|
4719
|
-
}
|
|
4720
4781
|
async function createUpdatePackage(entries, packageName) {
|
|
4721
|
-
const dir =
|
|
4722
|
-
|
|
4723
|
-
const zipPath =
|
|
4724
|
-
log(`\u521B\u5EFA\u66F4\u65B0\u5305: ${
|
|
4782
|
+
const dir = deployCacheDirectory();
|
|
4783
|
+
mkdirSync8(dir, { recursive: true });
|
|
4784
|
+
const zipPath = path6.join(dir, packageName);
|
|
4785
|
+
log(`\u521B\u5EFA\u66F4\u65B0\u5305: ${path6.basename(zipPath)}\uFF08${entries.length} \u4E2A\u6587\u4EF6\uFF09`);
|
|
4725
4786
|
const zip = new JSZip2();
|
|
4726
4787
|
for (const entry of entries) {
|
|
4727
|
-
const content =
|
|
4788
|
+
const content = readFileSync14(entry.path);
|
|
4728
4789
|
zip.file(entry.arcname, content);
|
|
4729
4790
|
log(` \u6253\u5305: ${entry.arcname} (${entry.reason})`);
|
|
4730
4791
|
}
|
|
@@ -4733,9 +4794,21 @@ async function createUpdatePackage(entries, packageName) {
|
|
|
4733
4794
|
compression: "DEFLATE",
|
|
4734
4795
|
compressionOptions: { level: 6 }
|
|
4735
4796
|
});
|
|
4736
|
-
|
|
4797
|
+
writeFileSync13(zipPath, buffer);
|
|
4737
4798
|
return zipPath;
|
|
4738
4799
|
}
|
|
4800
|
+
function listAllLibFilesForArchive(libDir) {
|
|
4801
|
+
return readdirSync5(libDir).filter((name) => name.endsWith(".jar")).sort().map((jarName) => ({
|
|
4802
|
+
path: path6.join(libDir, jarName),
|
|
4803
|
+
arcname: jarName,
|
|
4804
|
+
reason: "\u4EC5\u6253\u5305\u5F52\u6863"
|
|
4805
|
+
}));
|
|
4806
|
+
}
|
|
4807
|
+
|
|
4808
|
+
// src/commands/deploy/internal/wisdom-backend/maven-build.ts
|
|
4809
|
+
import { existsSync as existsSync18, readdirSync as readdirSync6, statSync as statSync8 } from "node:fs";
|
|
4810
|
+
import path7 from "node:path";
|
|
4811
|
+
import { spawnSync as spawnSync6 } from "node:child_process";
|
|
4739
4812
|
function getMvnExecutable() {
|
|
4740
4813
|
const isWin = process.platform === "win32";
|
|
4741
4814
|
const candidates = isWin ? ["mvn.cmd", "mvn.bat", "mvn"] : ["mvn"];
|
|
@@ -4782,14 +4855,14 @@ function runMavenBuild(projectRoot, mavenLocalRepo, repoSource) {
|
|
|
4782
4855
|
}
|
|
4783
4856
|
function locateLibDir(projectRoot) {
|
|
4784
4857
|
const targetDir = getTargetDir(projectRoot);
|
|
4785
|
-
if (!
|
|
4858
|
+
if (!existsSync18(targetDir)) {
|
|
4786
4859
|
fail(`\u6784\u5EFA\u4EA7\u7269\u76EE\u5F55\u4E0D\u5B58\u5728: ${targetDir}`);
|
|
4787
4860
|
}
|
|
4788
|
-
const libDir =
|
|
4789
|
-
if (!
|
|
4861
|
+
const libDir = path7.join(targetDir, "lib");
|
|
4862
|
+
if (!existsSync18(libDir) || !statSync8(libDir).isDirectory()) {
|
|
4790
4863
|
fail(`lib \u76EE\u5F55\u4E0D\u5B58\u5728: ${libDir}`);
|
|
4791
4864
|
}
|
|
4792
|
-
const libJars =
|
|
4865
|
+
const libJars = readdirSync6(libDir).filter((name) => name.endsWith(".jar"));
|
|
4793
4866
|
if (libJars.length === 0) {
|
|
4794
4867
|
fail(`lib \u76EE\u5F55\u4E0B\u6CA1\u6709\u4F9D\u8D56 JAR: ${libDir}`);
|
|
4795
4868
|
}
|
|
@@ -4798,124 +4871,24 @@ function locateLibDir(projectRoot) {
|
|
|
4798
4871
|
}
|
|
4799
4872
|
function locateMainJar(projectRoot) {
|
|
4800
4873
|
const targetDir = getTargetDir(projectRoot);
|
|
4801
|
-
if (!
|
|
4874
|
+
if (!existsSync18(targetDir)) {
|
|
4802
4875
|
fail(`\u6784\u5EFA\u4EA7\u7269\u76EE\u5F55\u4E0D\u5B58\u5728: ${targetDir}`);
|
|
4803
4876
|
}
|
|
4804
|
-
const jarFiles =
|
|
4877
|
+
const jarFiles = readdirSync6(targetDir).filter((name) => name.endsWith(".jar") && !name.endsWith(".jar.original")).map((name) => path7.join(targetDir, name)).sort((a, b) => statSync8(b).mtimeMs - statSync8(a).mtimeMs);
|
|
4805
4878
|
if (jarFiles.length === 0) {
|
|
4806
4879
|
fail(`target \u76EE\u5F55\u4E0B\u6CA1\u6709\u4E3B JAR: ${targetDir}`);
|
|
4807
4880
|
}
|
|
4808
4881
|
const mainJar = jarFiles[0];
|
|
4809
|
-
log(`\u5B9A\u4F4D\u4E3B JAR \u4EA7\u7269: ${
|
|
4882
|
+
log(`\u5B9A\u4F4D\u4E3B JAR \u4EA7\u7269: ${path7.basename(mainJar)}`);
|
|
4810
4883
|
return mainJar;
|
|
4811
4884
|
}
|
|
4812
|
-
|
|
4813
|
-
|
|
4814
|
-
|
|
4815
|
-
|
|
4816
|
-
|
|
4817
|
-
|
|
4818
|
-
|
|
4819
|
-
username: config.username,
|
|
4820
|
-
password: config.password,
|
|
4821
|
-
readyTimeout: 3e4,
|
|
4822
|
-
tryKeyboard: true
|
|
4823
|
-
});
|
|
4824
|
-
});
|
|
4825
|
-
const sftp = new SftpClient2();
|
|
4826
|
-
await sftp.connect({
|
|
4827
|
-
host: config.host,
|
|
4828
|
-
port: config.port,
|
|
4829
|
-
username: config.username,
|
|
4830
|
-
password: config.password,
|
|
4831
|
-
readyTimeout: 3e4,
|
|
4832
|
-
tryKeyboard: true
|
|
4833
|
-
});
|
|
4834
|
-
return { client, sftp };
|
|
4835
|
-
}
|
|
4836
|
-
async function closeSsh(conn) {
|
|
4837
|
-
try {
|
|
4838
|
-
await conn.sftp.end();
|
|
4839
|
-
} catch {
|
|
4840
|
-
}
|
|
4841
|
-
conn.client.end();
|
|
4842
|
-
}
|
|
4843
|
-
async function getRemoteFileStats(sftp, remoteDir) {
|
|
4844
|
-
const stats = /* @__PURE__ */ new Map();
|
|
4845
|
-
try {
|
|
4846
|
-
const listing = await sftp.list(remoteDir);
|
|
4847
|
-
for (const item of listing) {
|
|
4848
|
-
if (item.name.endsWith(".jar")) {
|
|
4849
|
-
stats.set(item.name, { filename: item.name, size: item.size });
|
|
4850
|
-
}
|
|
4851
|
-
}
|
|
4852
|
-
} catch {
|
|
4853
|
-
}
|
|
4854
|
-
return stats;
|
|
4855
|
-
}
|
|
4856
|
-
async function uploadUpdatePackage(sftp, zipPath, config) {
|
|
4857
|
-
const remoteDir = config.remoteVueDistDir.replace(/\/$/, "");
|
|
4858
|
-
const remotePath = `${remoteDir}/${path3.basename(zipPath)}`;
|
|
4859
|
-
log(`\u4E0A\u4F20\u66F4\u65B0\u5305 -> ${remotePath}`);
|
|
4860
|
-
try {
|
|
4861
|
-
await sftp.fastPut(zipPath, remotePath);
|
|
4862
|
-
log("\u66F4\u65B0\u5305\u4E0A\u4F20\u6210\u529F");
|
|
4863
|
-
} catch (err) {
|
|
4864
|
-
fail(`\u66F4\u65B0\u5305\u4E0A\u4F20\u5931\u8D25: ${err instanceof Error ? err.message : err}`);
|
|
4865
|
-
}
|
|
4866
|
-
return remotePath;
|
|
4867
|
-
}
|
|
4868
|
-
async function uploadFullJar(sftp, localJarPath, config) {
|
|
4869
|
-
const remoteDir = config.remoteAppDir.replace(/\/$/, "");
|
|
4870
|
-
const remotePath = `${remoteDir}/${config.startupJar}`;
|
|
4871
|
-
log(`\u4E0A\u4F20\u5168\u91CF JAR (${path3.basename(localJarPath)}) -> ${remotePath}`);
|
|
4872
|
-
try {
|
|
4873
|
-
await sftp.mkdir(remoteDir, true);
|
|
4874
|
-
await sftp.fastPut(localJarPath, remotePath);
|
|
4875
|
-
log("\u5168\u91CF JAR \u4E0A\u4F20\u6210\u529F");
|
|
4876
|
-
} catch (err) {
|
|
4877
|
-
fail(`\u5168\u91CF JAR \u4E0A\u4F20\u5931\u8D25: ${err instanceof Error ? err.message : err}`);
|
|
4878
|
-
}
|
|
4879
|
-
}
|
|
4880
|
-
async function runRemoteCommand(client, command, options) {
|
|
4881
|
-
const check = options?.check ?? true;
|
|
4882
|
-
const stream = options?.stream ?? false;
|
|
4883
|
-
const label = options?.label ?? "\u8FDC\u7A0B\u547D\u4EE4";
|
|
4884
|
-
return new Promise((resolve5, reject) => {
|
|
4885
|
-
client.exec(command, (err, execStream) => {
|
|
4886
|
-
if (err) {
|
|
4887
|
-
reject(err);
|
|
4888
|
-
return;
|
|
4889
|
-
}
|
|
4890
|
-
let out = "";
|
|
4891
|
-
let errText = "";
|
|
4892
|
-
execStream.on("data", (data) => {
|
|
4893
|
-
const text = data.toString();
|
|
4894
|
-
out += text;
|
|
4895
|
-
if (stream) {
|
|
4896
|
-
process.stdout.write(text);
|
|
4897
|
-
}
|
|
4898
|
-
});
|
|
4899
|
-
execStream.stderr.on("data", (data) => {
|
|
4900
|
-
errText += data.toString();
|
|
4901
|
-
});
|
|
4902
|
-
execStream.on("close", (code) => {
|
|
4903
|
-
if (stream && out && !out.endsWith("\n")) {
|
|
4904
|
-
process.stdout.write("\n");
|
|
4905
|
-
}
|
|
4906
|
-
if (check && code !== 0) {
|
|
4907
|
-
const combined = `${out}
|
|
4908
|
-
${errText}`.trim();
|
|
4909
|
-
fail(
|
|
4910
|
-
`${label}\u5931\u8D25 (exit ${code})` + (combined ? `
|
|
4911
|
-
\u8F93\u51FA: ${combined}` : "")
|
|
4912
|
-
);
|
|
4913
|
-
}
|
|
4914
|
-
resolve5({ exitCode: code, out: out.trim(), err: errText.trim() });
|
|
4915
|
-
});
|
|
4916
|
-
});
|
|
4917
|
-
});
|
|
4918
|
-
}
|
|
4885
|
+
|
|
4886
|
+
// src/commands/deploy/internal/wisdom-backend/remote-deploy.ts
|
|
4887
|
+
import path8 from "node:path";
|
|
4888
|
+
import { Client as Client2 } from "ssh2";
|
|
4889
|
+
import SftpClient2 from "ssh2-sftp-client";
|
|
4890
|
+
|
|
4891
|
+
// src/commands/deploy/internal/wisdom-backend/remote-scripts.ts
|
|
4919
4892
|
function buildExtractUpdatePackageScript(remoteZipPath, remoteLibDir) {
|
|
4920
4893
|
const quotedZip = shellSingleQuote(remoteZipPath);
|
|
4921
4894
|
const quotedLib = shellSingleQuote(remoteLibDir);
|
|
@@ -4939,39 +4912,6 @@ done < <(find "$TMP" -name '*.jar' -type f -print0)
|
|
|
4939
4912
|
echo "UPDATED_COUNT=$updated"
|
|
4940
4913
|
`.trim();
|
|
4941
4914
|
}
|
|
4942
|
-
async function extractUpdatePackageOnRemote(client, config, remoteZipPath) {
|
|
4943
|
-
const script = buildExtractUpdatePackageScript(
|
|
4944
|
-
remoteZipPath,
|
|
4945
|
-
config.remoteLibDir
|
|
4946
|
-
);
|
|
4947
|
-
const { out } = await runRemoteCommand(client, script, {
|
|
4948
|
-
label: "\u8FDC\u7A0B\u89E3\u538B"
|
|
4949
|
-
});
|
|
4950
|
-
const match = out.match(/UPDATED_COUNT=(\d+)/);
|
|
4951
|
-
if (!match) {
|
|
4952
|
-
fail(`\u8FDC\u7A0B\u89E3\u538B\u5931\u8D25\uFF0C\u672A\u83B7\u53D6\u66F4\u65B0\u6570\u91CF
|
|
4953
|
-
\u8F93\u51FA: ${out || "(\u7A7A)"}`);
|
|
4954
|
-
}
|
|
4955
|
-
const updated = Number.parseInt(match[1], 10);
|
|
4956
|
-
log(`lib \u89E3\u538B\u5B8C\u6210: \u8986\u76D6 ${updated} \u4E2A`);
|
|
4957
|
-
return updated;
|
|
4958
|
-
}
|
|
4959
|
-
function springbootOutputIndicatesSuccess(action, combined) {
|
|
4960
|
-
const lower = combined.toLowerCase();
|
|
4961
|
-
if (action === "health") {
|
|
4962
|
-
return combined.includes("\u5065\u5EB7\u68C0\u67E5\u901A\u8FC7");
|
|
4963
|
-
}
|
|
4964
|
-
if (action === "start" || action === "restart") {
|
|
4965
|
-
return combined.includes("is starting") || lower.includes("is running");
|
|
4966
|
-
}
|
|
4967
|
-
if (action === "stop") {
|
|
4968
|
-
return combined.includes("is stopping") || lower.includes("not running") || lower.includes("please check it");
|
|
4969
|
-
}
|
|
4970
|
-
if (action === "status") {
|
|
4971
|
-
return lower.includes("running") || lower.includes("not running");
|
|
4972
|
-
}
|
|
4973
|
-
return true;
|
|
4974
|
-
}
|
|
4975
4915
|
function buildRemoteStatusScript(remoteAppDir, appName) {
|
|
4976
4916
|
const dir = shellSingleQuote(remoteAppDir);
|
|
4977
4917
|
const jar = shellSingleQuote(appName);
|
|
@@ -5070,6 +5010,150 @@ echo -e "\\033[31m\u5065\u5EB7\u68C0\u67E5\u8D85\u65F6 (\${timeout}s): \${check_
|
|
|
5070
5010
|
exit 1
|
|
5071
5011
|
`.trim();
|
|
5072
5012
|
}
|
|
5013
|
+
function springbootOutputIndicatesSuccess(action, combined) {
|
|
5014
|
+
const lower = combined.toLowerCase();
|
|
5015
|
+
if (action === "health") {
|
|
5016
|
+
return combined.includes("\u5065\u5EB7\u68C0\u67E5\u901A\u8FC7");
|
|
5017
|
+
}
|
|
5018
|
+
if (action === "start" || action === "restart") {
|
|
5019
|
+
return combined.includes("is starting") || lower.includes("is running");
|
|
5020
|
+
}
|
|
5021
|
+
if (action === "stop") {
|
|
5022
|
+
return combined.includes("is stopping") || lower.includes("not running") || lower.includes("please check it");
|
|
5023
|
+
}
|
|
5024
|
+
if (action === "status") {
|
|
5025
|
+
return lower.includes("running") || lower.includes("not running");
|
|
5026
|
+
}
|
|
5027
|
+
return true;
|
|
5028
|
+
}
|
|
5029
|
+
|
|
5030
|
+
// src/commands/deploy/internal/wisdom-backend/remote-deploy.ts
|
|
5031
|
+
async function connectSsh(config) {
|
|
5032
|
+
const client = new Client2();
|
|
5033
|
+
log(`\u8FDE\u63A5\u670D\u52A1\u5668 ${config.username}@${config.host}:${config.port}`);
|
|
5034
|
+
await new Promise((resolve6, reject) => {
|
|
5035
|
+
client.on("ready", () => resolve6()).on("error", (err) => reject(err)).connect({
|
|
5036
|
+
host: config.host,
|
|
5037
|
+
port: config.port,
|
|
5038
|
+
username: config.username,
|
|
5039
|
+
password: config.password,
|
|
5040
|
+
readyTimeout: 3e4,
|
|
5041
|
+
tryKeyboard: true
|
|
5042
|
+
});
|
|
5043
|
+
});
|
|
5044
|
+
const sftp = new SftpClient2();
|
|
5045
|
+
await sftp.connect({
|
|
5046
|
+
host: config.host,
|
|
5047
|
+
port: config.port,
|
|
5048
|
+
username: config.username,
|
|
5049
|
+
password: config.password,
|
|
5050
|
+
readyTimeout: 3e4,
|
|
5051
|
+
tryKeyboard: true
|
|
5052
|
+
});
|
|
5053
|
+
return { client, sftp };
|
|
5054
|
+
}
|
|
5055
|
+
async function closeSsh(conn) {
|
|
5056
|
+
try {
|
|
5057
|
+
await conn.sftp.end();
|
|
5058
|
+
} catch {
|
|
5059
|
+
}
|
|
5060
|
+
conn.client.end();
|
|
5061
|
+
}
|
|
5062
|
+
async function getRemoteFileStats(sftp, remoteDir) {
|
|
5063
|
+
const stats = /* @__PURE__ */ new Map();
|
|
5064
|
+
try {
|
|
5065
|
+
const listing = await sftp.list(remoteDir);
|
|
5066
|
+
for (const item of listing) {
|
|
5067
|
+
if (item.name.endsWith(".jar")) {
|
|
5068
|
+
stats.set(item.name, { filename: item.name, size: item.size });
|
|
5069
|
+
}
|
|
5070
|
+
}
|
|
5071
|
+
} catch {
|
|
5072
|
+
}
|
|
5073
|
+
return stats;
|
|
5074
|
+
}
|
|
5075
|
+
async function uploadUpdatePackage(sftp, zipPath, config) {
|
|
5076
|
+
const remoteDir = config.remoteVueDistDir.replace(/\/$/, "");
|
|
5077
|
+
const remotePath = `${remoteDir}/${path8.basename(zipPath)}`;
|
|
5078
|
+
log(`\u4E0A\u4F20\u66F4\u65B0\u5305 -> ${remotePath}`);
|
|
5079
|
+
try {
|
|
5080
|
+
await sftp.fastPut(zipPath, remotePath);
|
|
5081
|
+
log("\u66F4\u65B0\u5305\u4E0A\u4F20\u6210\u529F");
|
|
5082
|
+
} catch (err) {
|
|
5083
|
+
fail(`\u66F4\u65B0\u5305\u4E0A\u4F20\u5931\u8D25: ${err instanceof Error ? err.message : err}`);
|
|
5084
|
+
}
|
|
5085
|
+
return remotePath;
|
|
5086
|
+
}
|
|
5087
|
+
async function uploadFullJar(sftp, localJarPath, config) {
|
|
5088
|
+
const remoteDir = config.remoteAppDir.replace(/\/$/, "");
|
|
5089
|
+
const remotePath = `${remoteDir}/${config.startupJar}`;
|
|
5090
|
+
log(`\u4E0A\u4F20\u5168\u91CF JAR (${path8.basename(localJarPath)}) -> ${remotePath}`);
|
|
5091
|
+
try {
|
|
5092
|
+
await sftp.mkdir(remoteDir, true);
|
|
5093
|
+
await sftp.fastPut(localJarPath, remotePath);
|
|
5094
|
+
log("\u5168\u91CF JAR \u4E0A\u4F20\u6210\u529F");
|
|
5095
|
+
} catch (err) {
|
|
5096
|
+
fail(`\u5168\u91CF JAR \u4E0A\u4F20\u5931\u8D25: ${err instanceof Error ? err.message : err}`);
|
|
5097
|
+
}
|
|
5098
|
+
}
|
|
5099
|
+
async function runRemoteCommand(client, command, options) {
|
|
5100
|
+
const check = options?.check ?? true;
|
|
5101
|
+
const stream = options?.stream ?? false;
|
|
5102
|
+
const label = options?.label ?? "\u8FDC\u7A0B\u547D\u4EE4";
|
|
5103
|
+
return new Promise((resolve6, reject) => {
|
|
5104
|
+
client.exec(command, (err, execStream) => {
|
|
5105
|
+
if (err) {
|
|
5106
|
+
reject(err);
|
|
5107
|
+
return;
|
|
5108
|
+
}
|
|
5109
|
+
let out = "";
|
|
5110
|
+
let errText = "";
|
|
5111
|
+
execStream.on("data", (data) => {
|
|
5112
|
+
const text = data.toString();
|
|
5113
|
+
out += text;
|
|
5114
|
+
if (stream) {
|
|
5115
|
+
process.stdout.write(text);
|
|
5116
|
+
}
|
|
5117
|
+
});
|
|
5118
|
+
execStream.stderr.on("data", (data) => {
|
|
5119
|
+
errText += data.toString();
|
|
5120
|
+
});
|
|
5121
|
+
execStream.on("close", (code) => {
|
|
5122
|
+
if (stream && out && !out.endsWith("\n")) {
|
|
5123
|
+
process.stdout.write("\n");
|
|
5124
|
+
}
|
|
5125
|
+
if (check && code !== 0) {
|
|
5126
|
+
const combined = `${out}
|
|
5127
|
+
${errText}`.trim();
|
|
5128
|
+
fail(
|
|
5129
|
+
`${label}\u5931\u8D25 (exit ${code})` + (combined ? `
|
|
5130
|
+
\u8F93\u51FA: ${combined}` : "")
|
|
5131
|
+
);
|
|
5132
|
+
}
|
|
5133
|
+
resolve6({ exitCode: code, out: out.trim(), err: errText.trim() });
|
|
5134
|
+
});
|
|
5135
|
+
});
|
|
5136
|
+
});
|
|
5137
|
+
}
|
|
5138
|
+
async function extractUpdatePackageOnRemote(client, config, remoteZipPath) {
|
|
5139
|
+
const script = buildExtractUpdatePackageScript(
|
|
5140
|
+
remoteZipPath,
|
|
5141
|
+
config.remoteLibDir
|
|
5142
|
+
);
|
|
5143
|
+
const { out } = await runRemoteCommand(client, script, {
|
|
5144
|
+
label: "\u8FDC\u7A0B\u89E3\u538B"
|
|
5145
|
+
});
|
|
5146
|
+
const match = out.match(/UPDATED_COUNT=(\d+)/);
|
|
5147
|
+
if (!match) {
|
|
5148
|
+
fail(`\u8FDC\u7A0B\u89E3\u538B\u5931\u8D25\uFF0C\u672A\u83B7\u53D6\u66F4\u65B0\u6570\u91CF
|
|
5149
|
+
\u8F93\u51FA: ${out || "(\u7A7A)"}`);
|
|
5150
|
+
}
|
|
5151
|
+
const updated = Number.parseInt(match[1], 10);
|
|
5152
|
+
log(`lib \u89E3\u538B\u5B8C\u6210: \u8986\u76D6 ${updated} \u4E2A`);
|
|
5153
|
+
return updated;
|
|
5154
|
+
}
|
|
5155
|
+
|
|
5156
|
+
// src/commands/deploy/internal/wisdom-backend/health-check.ts
|
|
5073
5157
|
async function runRemoteServiceScript(client, script, action) {
|
|
5074
5158
|
const { exitCode, out, err } = await runRemoteCommand(client, script, {
|
|
5075
5159
|
check: false,
|
|
@@ -5095,9 +5179,6 @@ ${combined}`);
|
|
|
5095
5179
|
}
|
|
5096
5180
|
return combined;
|
|
5097
5181
|
}
|
|
5098
|
-
function stripAnsi(text) {
|
|
5099
|
-
return text.replace(/\x1b\[[0-?]*[ -/]*[@-~]/g, "");
|
|
5100
|
-
}
|
|
5101
5182
|
async function getRunningJar(client, config) {
|
|
5102
5183
|
const script = buildRemoteStatusScript(
|
|
5103
5184
|
config.remoteAppDir,
|
|
@@ -5126,19 +5207,14 @@ async function restartRemoteService(client, config) {
|
|
|
5126
5207
|
const script = buildRemoteRestartScript(config.remoteAppDir);
|
|
5127
5208
|
await runRemoteServiceScript(client, script, "restart");
|
|
5128
5209
|
}
|
|
5129
|
-
|
|
5130
|
-
|
|
5131
|
-
path: path3.join(libDir, jarName),
|
|
5132
|
-
arcname: jarName,
|
|
5133
|
-
reason: "\u4EC5\u6253\u5305\u5F52\u6863"
|
|
5134
|
-
}));
|
|
5135
|
-
}
|
|
5210
|
+
|
|
5211
|
+
// src/commands/deploy/internal/wisdom-backend/index.ts
|
|
5136
5212
|
async function runWisdomBackendDeploy(options) {
|
|
5137
|
-
const projectRoot =
|
|
5213
|
+
const projectRoot = path9.resolve(options.projectRoot ?? process.cwd());
|
|
5138
5214
|
const config = options.config;
|
|
5139
5215
|
const packOnly = Boolean(options.packOnly);
|
|
5140
5216
|
log(`=== \u81EA\u52A8\u90E8\u7F72: ${config.projectName} ===`);
|
|
5141
|
-
log(`\u914D\u7F6E\u6587\u4EF6: ${
|
|
5217
|
+
log(`\u914D\u7F6E\u6587\u4EF6: ${path9.join(workspaceApmDir(), "apm.config.json")}`);
|
|
5142
5218
|
log(`\u9879\u76EE\u6839\u76EE\u5F55: ${projectRoot}`);
|
|
5143
5219
|
log(
|
|
5144
5220
|
`\u90E8\u7F72\u6A21\u5F0F: ${config.mode}${config.mode === "full" ? "\uFF08\u5168\u91CF JAR\uFF0C\u8DF3\u8FC7 lib \u68C0\u67E5\uFF09" : "\uFF08\u589E\u91CF lib \u66F4\u65B0\uFF09"}${packOnly ? "\uFF1B\u4EC5\u6253\u5305\uFF08\u4E0D\u4E0A\u4F20\u8FDC\u7A0B\uFF09" : ""}`
|
|
@@ -5155,7 +5231,7 @@ async function runWisdomBackendDeploy(options) {
|
|
|
5155
5231
|
[
|
|
5156
5232
|
{
|
|
5157
5233
|
path: mainJar,
|
|
5158
|
-
arcname:
|
|
5234
|
+
arcname: path9.basename(mainJar),
|
|
5159
5235
|
reason: "\u5168\u91CF JAR \u5F52\u6863"
|
|
5160
5236
|
}
|
|
5161
5237
|
],
|
|
@@ -5193,7 +5269,7 @@ async function runWisdomBackendDeploy(options) {
|
|
|
5193
5269
|
[
|
|
5194
5270
|
{
|
|
5195
5271
|
path: mainJar,
|
|
5196
|
-
arcname:
|
|
5272
|
+
arcname: path9.basename(mainJar),
|
|
5197
5273
|
reason: "\u5168\u91CF JAR \u5F52\u6863"
|
|
5198
5274
|
}
|
|
5199
5275
|
],
|
|
@@ -5277,15 +5353,15 @@ function isWisdomDeployConfigured(cfg) {
|
|
|
5277
5353
|
return Boolean(w?.host?.trim() && w?.remotePath?.trim());
|
|
5278
5354
|
}
|
|
5279
5355
|
function detectWisdomProjectType(cwd) {
|
|
5280
|
-
return
|
|
5356
|
+
return existsSync19(path10.join(cwd, "package.json")) ? "frontend" : "backend";
|
|
5281
5357
|
}
|
|
5282
5358
|
function readPackageScripts(cwd) {
|
|
5283
|
-
const pkgPath =
|
|
5284
|
-
if (!
|
|
5359
|
+
const pkgPath = path10.join(cwd, "package.json");
|
|
5360
|
+
if (!existsSync19(pkgPath)) {
|
|
5285
5361
|
return {};
|
|
5286
5362
|
}
|
|
5287
5363
|
try {
|
|
5288
|
-
const raw =
|
|
5364
|
+
const raw = readFileSync15(pkgPath, "utf8");
|
|
5289
5365
|
const parsed = JSON.parse(raw);
|
|
5290
5366
|
return parsed.scripts ?? {};
|
|
5291
5367
|
} catch {
|
|
@@ -5306,15 +5382,15 @@ function resolveFrontendBuildCommand(env, cwd) {
|
|
|
5306
5382
|
function resolveFrontendDistDir(cwd) {
|
|
5307
5383
|
const candidates = ["dist", "apps/web/dist"];
|
|
5308
5384
|
for (const rel of candidates) {
|
|
5309
|
-
const full =
|
|
5385
|
+
const full = path10.join(cwd, rel);
|
|
5310
5386
|
try {
|
|
5311
|
-
if (
|
|
5387
|
+
if (existsSync19(full) && statSync9(full).isDirectory()) {
|
|
5312
5388
|
return full;
|
|
5313
5389
|
}
|
|
5314
5390
|
} catch {
|
|
5315
5391
|
}
|
|
5316
5392
|
}
|
|
5317
|
-
return
|
|
5393
|
+
return path10.join(cwd, "dist");
|
|
5318
5394
|
}
|
|
5319
5395
|
async function executeWisdomFrontendDeploy(options) {
|
|
5320
5396
|
const { cwd, cfg, captureOutput, packOnly, archiveDeployArtifact } = options;
|
|
@@ -5331,7 +5407,7 @@ async function executeWisdomFrontendDeploy(options) {
|
|
|
5331
5407
|
if (!buildCmd) {
|
|
5332
5408
|
const lines = formatWisdomFrontendBuildNotConfiguredLines(
|
|
5333
5409
|
options.env,
|
|
5334
|
-
|
|
5410
|
+
path10.join(cwd, "package.json")
|
|
5335
5411
|
);
|
|
5336
5412
|
throw new DeployExecutionError(lines.join("\n"), 1, lines.join("\n"));
|
|
5337
5413
|
}
|
|
@@ -5339,16 +5415,9 @@ async function executeWisdomFrontendDeploy(options) {
|
|
|
5339
5415
|
`[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" : ""))
|
|
5340
5416
|
);
|
|
5341
5417
|
runDeployShellCommand(buildCmd, cwd, captureOutput);
|
|
5342
|
-
|
|
5343
|
-
|
|
5344
|
-
|
|
5345
|
-
"\u8BF7\u5728 .apm/apm.config.json \u9876\u5C42\u914D\u7F6E name\uFF08\u4F5C\u4E3A\u90E8\u7F72\u4EA7\u7269\u9879\u76EE\u540D\uFF09",
|
|
5346
|
-
1
|
|
5347
|
-
);
|
|
5348
|
-
}
|
|
5349
|
-
if (!projectName) {
|
|
5350
|
-
projectName = path4.basename(cwd);
|
|
5351
|
-
}
|
|
5418
|
+
const projectName = resolveProjectNameForDeploy(cfg, cwd, {
|
|
5419
|
+
requireName: packOnly || archiveDeployArtifact
|
|
5420
|
+
});
|
|
5352
5421
|
const settings = resolveWisdomDeployFromApmConfig(cfg);
|
|
5353
5422
|
await runWisdomSftpDeploy({
|
|
5354
5423
|
localDir: distDir,
|
|
@@ -5376,12 +5445,12 @@ async function executeWisdomBackendDeployFlow(options) {
|
|
|
5376
5445
|
});
|
|
5377
5446
|
}
|
|
5378
5447
|
async function executeWisdomDeploy(options) {
|
|
5379
|
-
const cwd =
|
|
5448
|
+
const cwd = path10.resolve(options.cwd);
|
|
5380
5449
|
const captureOutput = options.captureOutput ?? false;
|
|
5381
5450
|
const packOnly = Boolean(options.packOnly);
|
|
5382
5451
|
const archiveDeployArtifact = Boolean(options.archiveDeployArtifact);
|
|
5383
5452
|
const projectType = detectWisdomProjectType(cwd);
|
|
5384
|
-
const configPath = options.configPath ??
|
|
5453
|
+
const configPath = options.configPath ?? path10.join(workspaceApmDir(cwd), "apm.config.json");
|
|
5385
5454
|
const cfg = loadApmConfig({ configPath });
|
|
5386
5455
|
console.error(
|
|
5387
5456
|
`[apm] ${projectType === "frontend" ? "Vue \u524D\u7AEF" : "Java \u540E\u7AEF"}${packOnly ? "\uFF08\u4EC5\u6253\u5305\uFF09" : ""}`
|
|
@@ -5544,7 +5613,7 @@ async function executeDeploy(options) {
|
|
|
5544
5613
|
throw new DeployExecutionError("[apm] executeDeploy \u7F3A\u5C11\u5DE5\u4F5C\u76EE\u5F55 cwd", 1);
|
|
5545
5614
|
}
|
|
5546
5615
|
const cwd = resolveWorkdirPath(cwdInput);
|
|
5547
|
-
const apmConfigPath = options.configPath ??
|
|
5616
|
+
const apmConfigPath = options.configPath ?? path11.join(workspaceApmDir(cwd), "apm.config.json");
|
|
5548
5617
|
const captureOutput = options.captureOutput ?? false;
|
|
5549
5618
|
const outputParts = [];
|
|
5550
5619
|
logExecuteDeployContext({
|
|
@@ -5613,11 +5682,36 @@ function printDeployExecutionError(error) {
|
|
|
5613
5682
|
console.error(error.message);
|
|
5614
5683
|
}
|
|
5615
5684
|
|
|
5616
|
-
// src/commands/
|
|
5617
|
-
|
|
5618
|
-
|
|
5619
|
-
|
|
5685
|
+
// src/commands/deploy/platform/deploy-console-capture.ts
|
|
5686
|
+
function captureDeployConsole(logSyncer) {
|
|
5687
|
+
const chunks = [];
|
|
5688
|
+
const appendLog = (line) => {
|
|
5689
|
+
if (!line) return;
|
|
5690
|
+
chunks.push(line);
|
|
5691
|
+
logSyncer.updateLog(chunks.join("\n"));
|
|
5692
|
+
};
|
|
5693
|
+
const originalLog = console.log;
|
|
5694
|
+
const originalError = console.error;
|
|
5695
|
+
console.log = (...args) => {
|
|
5696
|
+
appendLog(args.map(String).join(" "));
|
|
5697
|
+
originalLog.apply(console, args);
|
|
5698
|
+
};
|
|
5699
|
+
console.error = (...args) => {
|
|
5700
|
+
appendLog(args.map(String).join(" "));
|
|
5701
|
+
originalError.apply(console, args);
|
|
5702
|
+
};
|
|
5703
|
+
return {
|
|
5704
|
+
appendLog,
|
|
5705
|
+
restore: () => {
|
|
5706
|
+
console.log = originalLog;
|
|
5707
|
+
console.error = originalError;
|
|
5708
|
+
},
|
|
5709
|
+
getLog: () => chunks.join("\n")
|
|
5710
|
+
};
|
|
5620
5711
|
}
|
|
5712
|
+
|
|
5713
|
+
// src/commands/deploy/platform/deploy-log-syncer.ts
|
|
5714
|
+
var DEPLOY_LOG_SYNC_INTERVAL_MS = 1e4;
|
|
5621
5715
|
function logDeploySyncFailure(error) {
|
|
5622
5716
|
console.error(
|
|
5623
5717
|
"[apm] deploy log sync failed:",
|
|
@@ -5627,7 +5721,9 @@ function logDeploySyncFailure(error) {
|
|
|
5627
5721
|
function createDeployLogSyncer(api, deploymentRunId) {
|
|
5628
5722
|
let lastSyncedLog = "";
|
|
5629
5723
|
let latestLog = "";
|
|
5630
|
-
let
|
|
5724
|
+
let lastRunAt = 0;
|
|
5725
|
+
let timer;
|
|
5726
|
+
let syncChain = Promise.resolve();
|
|
5631
5727
|
const syncDelta = async (delta, append) => {
|
|
5632
5728
|
const chunks = splitUtf8StringByMaxBytes(
|
|
5633
5729
|
delta,
|
|
@@ -5652,29 +5748,58 @@ function createDeployLogSyncer(api, deploymentRunId) {
|
|
|
5652
5748
|
if (!delta) {
|
|
5653
5749
|
return;
|
|
5654
5750
|
}
|
|
5655
|
-
await syncDelta(delta, lastSyncedLog.length > 0);
|
|
5656
|
-
lastSyncedLog = latestLog;
|
|
5751
|
+
await syncDelta(delta, lastSyncedLog.length > 0);
|
|
5752
|
+
lastSyncedLog = latestLog;
|
|
5753
|
+
};
|
|
5754
|
+
const enqueueSync = () => {
|
|
5755
|
+
syncChain = syncChain.then(async () => {
|
|
5756
|
+
try {
|
|
5757
|
+
await syncIfChanged();
|
|
5758
|
+
lastRunAt = Date.now();
|
|
5759
|
+
} catch (error) {
|
|
5760
|
+
logDeploySyncFailure(error);
|
|
5761
|
+
}
|
|
5762
|
+
});
|
|
5763
|
+
};
|
|
5764
|
+
const schedule = () => {
|
|
5765
|
+
const now = Date.now();
|
|
5766
|
+
const elapsed = now - lastRunAt;
|
|
5767
|
+
if (elapsed >= DEPLOY_LOG_SYNC_INTERVAL_MS) {
|
|
5768
|
+
if (timer) {
|
|
5769
|
+
clearTimeout(timer);
|
|
5770
|
+
timer = void 0;
|
|
5771
|
+
}
|
|
5772
|
+
enqueueSync();
|
|
5773
|
+
return;
|
|
5774
|
+
}
|
|
5775
|
+
if (timer) {
|
|
5776
|
+
return;
|
|
5777
|
+
}
|
|
5778
|
+
timer = setTimeout(() => {
|
|
5779
|
+
timer = void 0;
|
|
5780
|
+
enqueueSync();
|
|
5781
|
+
}, DEPLOY_LOG_SYNC_INTERVAL_MS - elapsed);
|
|
5782
|
+
};
|
|
5783
|
+
const stopTimer = () => {
|
|
5784
|
+
if (timer) {
|
|
5785
|
+
clearTimeout(timer);
|
|
5786
|
+
timer = void 0;
|
|
5787
|
+
}
|
|
5657
5788
|
};
|
|
5658
|
-
timer = setInterval(() => {
|
|
5659
|
-
void syncIfChanged().catch(logDeploySyncFailure);
|
|
5660
|
-
}, DEPLOY_LOG_SYNC_INTERVAL_MS);
|
|
5661
5789
|
return {
|
|
5662
5790
|
updateLog(log2) {
|
|
5663
5791
|
latestLog = log2;
|
|
5792
|
+
schedule();
|
|
5664
5793
|
},
|
|
5665
5794
|
async flush() {
|
|
5666
|
-
|
|
5667
|
-
|
|
5668
|
-
timer = null;
|
|
5669
|
-
}
|
|
5795
|
+
stopTimer();
|
|
5796
|
+
await syncChain;
|
|
5670
5797
|
await syncIfChanged();
|
|
5671
5798
|
},
|
|
5672
5799
|
async flushSafe() {
|
|
5673
|
-
|
|
5674
|
-
clearInterval(timer);
|
|
5675
|
-
timer = null;
|
|
5676
|
-
}
|
|
5800
|
+
stopTimer();
|
|
5677
5801
|
try {
|
|
5802
|
+
await syncChain;
|
|
5678
5803
|
await syncIfChanged();
|
|
5679
5804
|
return true;
|
|
5680
5805
|
} catch (error) {
|
|
@@ -5683,15 +5808,12 @@ function createDeployLogSyncer(api, deploymentRunId) {
|
|
|
5683
5808
|
}
|
|
5684
5809
|
},
|
|
5685
5810
|
dispose() {
|
|
5686
|
-
|
|
5687
|
-
clearInterval(timer);
|
|
5688
|
-
timer = null;
|
|
5689
|
-
}
|
|
5811
|
+
stopTimer();
|
|
5690
5812
|
}
|
|
5691
5813
|
};
|
|
5692
5814
|
}
|
|
5693
5815
|
async function finalizeTaskDeployment(api, deploymentRunId, logSyncer, input) {
|
|
5694
|
-
|
|
5816
|
+
await logSyncer.flushSafe();
|
|
5695
5817
|
const payload = {
|
|
5696
5818
|
id: deploymentRunId,
|
|
5697
5819
|
status: input.status
|
|
@@ -5699,76 +5821,48 @@ async function finalizeTaskDeployment(api, deploymentRunId, logSyncer, input) {
|
|
|
5699
5821
|
if (input.error) {
|
|
5700
5822
|
payload.error = input.error;
|
|
5701
5823
|
}
|
|
5702
|
-
|
|
5703
|
-
|
|
5704
|
-
|
|
5705
|
-
await retryDeployLogSync(() => api.cli.completeTaskDeployment(payload));
|
|
5824
|
+
await retryDeployStatusComplete(
|
|
5825
|
+
() => api.cli.completeTaskDeployment(payload)
|
|
5826
|
+
);
|
|
5706
5827
|
}
|
|
5707
|
-
function
|
|
5708
|
-
|
|
5709
|
-
const appendLog = (line) => {
|
|
5710
|
-
if (!line) return;
|
|
5711
|
-
chunks.push(line);
|
|
5712
|
-
logSyncer.updateLog(chunks.join("\n"));
|
|
5713
|
-
};
|
|
5714
|
-
const originalLog = console.log;
|
|
5715
|
-
const originalError = console.error;
|
|
5716
|
-
console.log = (...args) => {
|
|
5717
|
-
appendLog(args.map(String).join(" "));
|
|
5718
|
-
originalLog.apply(console, args);
|
|
5719
|
-
};
|
|
5720
|
-
console.error = (...args) => {
|
|
5721
|
-
appendLog(args.map(String).join(" "));
|
|
5722
|
-
originalError.apply(console, args);
|
|
5723
|
-
};
|
|
5724
|
-
return {
|
|
5725
|
-
appendLog,
|
|
5726
|
-
restore: () => {
|
|
5727
|
-
console.log = originalLog;
|
|
5728
|
-
console.error = originalError;
|
|
5729
|
-
},
|
|
5730
|
-
getLog: () => chunks.join("\n")
|
|
5731
|
-
};
|
|
5828
|
+
async function ensureDeploymentStatusSynced(api, deploymentRunId, logSyncer, outcome) {
|
|
5829
|
+
await finalizeTaskDeployment(api, deploymentRunId, logSyncer, outcome);
|
|
5732
5830
|
}
|
|
5733
|
-
|
|
5734
|
-
|
|
5735
|
-
|
|
5736
|
-
|
|
5737
|
-
|
|
5738
|
-
|
|
5739
|
-
status: "DEPLOYING"
|
|
5740
|
-
});
|
|
5741
|
-
const workdir = requireRemoteWorkdir(msg.workdir);
|
|
5742
|
-
const displayCommand = resolveDeployCommand(msg.environment, msg.packOnly);
|
|
5743
|
-
console.log(
|
|
5744
|
-
`[apm] deploy start id=${deploymentRunId} env=${msg.environment} cwd=${workdir}`
|
|
5831
|
+
|
|
5832
|
+
// src/commands/deploy/platform/deploy-run-coordinator.ts
|
|
5833
|
+
function logDeployStatusSyncFailure(error) {
|
|
5834
|
+
console.error(
|
|
5835
|
+
"[apm] deploy status sync failed:",
|
|
5836
|
+
error instanceof Error ? error.message : String(error)
|
|
5745
5837
|
);
|
|
5746
|
-
|
|
5838
|
+
}
|
|
5839
|
+
async function runTrackedDeploy(input) {
|
|
5840
|
+
const { api, deploymentRunId, run } = input;
|
|
5841
|
+
let deploymentStarted = true;
|
|
5842
|
+
let outcome = null;
|
|
5843
|
+
let statusSynced = false;
|
|
5844
|
+
let deployError;
|
|
5747
5845
|
const logSyncer = createDeployLogSyncer(api, deploymentRunId);
|
|
5748
5846
|
const previousDeploymentRunId = process.env[APM_DEPLOYMENT_RUN_ID_ENV];
|
|
5749
5847
|
process.env[APM_DEPLOYMENT_RUN_ID_ENV] = deploymentRunId;
|
|
5750
5848
|
const capture = captureDeployConsole(logSyncer);
|
|
5751
|
-
const
|
|
5752
|
-
|
|
5753
|
-
|
|
5754
|
-
|
|
5755
|
-
|
|
5756
|
-
|
|
5757
|
-
|
|
5849
|
+
const ensureStatusSynced = async () => {
|
|
5850
|
+
if (statusSynced || !outcome) {
|
|
5851
|
+
return;
|
|
5852
|
+
}
|
|
5853
|
+
logSyncer.updateLog(capture.getLog());
|
|
5854
|
+
await ensureDeploymentStatusSynced(
|
|
5855
|
+
api,
|
|
5856
|
+
deploymentRunId,
|
|
5857
|
+
logSyncer,
|
|
5858
|
+
outcome
|
|
5859
|
+
);
|
|
5860
|
+
statusSynced = true;
|
|
5758
5861
|
};
|
|
5759
5862
|
try {
|
|
5760
|
-
|
|
5761
|
-
const output = await executeDeploy(deployOptions);
|
|
5762
|
-
if (output.trim()) {
|
|
5763
|
-
capture.appendLog(output);
|
|
5764
|
-
}
|
|
5765
|
-
await finalizeTaskDeployment(api, deploymentRunId, logSyncer, {
|
|
5766
|
-
status: "SUCCESS",
|
|
5767
|
-
fullLog: capture.getLog()
|
|
5768
|
-
});
|
|
5769
|
-
console.log(`[apm] deploy success id=${deploymentRunId}`);
|
|
5863
|
+
outcome = await run(capture.appendLog);
|
|
5770
5864
|
} catch (error) {
|
|
5771
|
-
|
|
5865
|
+
deployError = error instanceof DeployExecutionError ? error : new DeployExecutionError(
|
|
5772
5866
|
error instanceof Error ? error.message : String(error),
|
|
5773
5867
|
1
|
|
5774
5868
|
);
|
|
@@ -5777,22 +5871,18 @@ async function handleInboundDeploy(cfg, msg, signal) {
|
|
|
5777
5871
|
} else {
|
|
5778
5872
|
capture.appendLog(deployError.message);
|
|
5779
5873
|
}
|
|
5780
|
-
|
|
5781
|
-
await finalizeTaskDeployment(api, deploymentRunId, logSyncer, {
|
|
5782
|
-
status: "FAILED",
|
|
5783
|
-
fullLog: capture.getLog(),
|
|
5784
|
-
error: deployError.message
|
|
5785
|
-
});
|
|
5786
|
-
} catch (finalizeError) {
|
|
5787
|
-
console.error(
|
|
5788
|
-
`[apm] deploy finalize failed id=${deploymentRunId}:`,
|
|
5789
|
-
finalizeError instanceof Error ? finalizeError.message : String(finalizeError)
|
|
5790
|
-
);
|
|
5791
|
-
}
|
|
5792
|
-
console.error(
|
|
5793
|
-
`[apm] deploy failed id=${deploymentRunId}: ${deployError.message}`
|
|
5794
|
-
);
|
|
5874
|
+
outcome = { status: "FAILED", error: deployError.message };
|
|
5795
5875
|
} finally {
|
|
5876
|
+
if (deploymentStarted && !statusSynced) {
|
|
5877
|
+
if (!outcome) {
|
|
5878
|
+
outcome = { status: "FAILED", error: "\u90E8\u7F72\u672A\u5B8C\u6210" };
|
|
5879
|
+
}
|
|
5880
|
+
try {
|
|
5881
|
+
await ensureStatusSynced();
|
|
5882
|
+
} catch (error) {
|
|
5883
|
+
logDeployStatusSyncFailure(error);
|
|
5884
|
+
}
|
|
5885
|
+
}
|
|
5796
5886
|
capture.restore();
|
|
5797
5887
|
if (previousDeploymentRunId === void 0) {
|
|
5798
5888
|
delete process.env[APM_DEPLOYMENT_RUN_ID_ENV];
|
|
@@ -5801,6 +5891,58 @@ async function handleInboundDeploy(cfg, msg, signal) {
|
|
|
5801
5891
|
}
|
|
5802
5892
|
logSyncer.dispose();
|
|
5803
5893
|
}
|
|
5894
|
+
return { outcome, error: deployError };
|
|
5895
|
+
}
|
|
5896
|
+
|
|
5897
|
+
// src/commands/connect/deploy-run.ts
|
|
5898
|
+
function resolveDeployCommand(environment, packOnly) {
|
|
5899
|
+
return packOnly ? `apm deploy ${environment} --pack-only` : `apm deploy ${environment}`;
|
|
5900
|
+
}
|
|
5901
|
+
async function handleInboundDeploy(cfg, msg, signal) {
|
|
5902
|
+
if (signal.aborted) return;
|
|
5903
|
+
const api = createApmApiClient(cfg);
|
|
5904
|
+
const deploymentRunId = msg.deploymentRunId;
|
|
5905
|
+
await api.cli.updateTaskDeploymentStatus({
|
|
5906
|
+
id: deploymentRunId,
|
|
5907
|
+
status: "DEPLOYING"
|
|
5908
|
+
});
|
|
5909
|
+
const { error: deployError } = await runTrackedDeploy({
|
|
5910
|
+
api,
|
|
5911
|
+
deploymentRunId,
|
|
5912
|
+
run: async (appendLog) => {
|
|
5913
|
+
const workdir = requireRemoteWorkdir(msg.workdir);
|
|
5914
|
+
const displayCommand = resolveDeployCommand(
|
|
5915
|
+
msg.environment,
|
|
5916
|
+
msg.packOnly
|
|
5917
|
+
);
|
|
5918
|
+
console.log(
|
|
5919
|
+
`[apm] deploy start id=${deploymentRunId} env=${msg.environment} cwd=${workdir}`
|
|
5920
|
+
);
|
|
5921
|
+
console.log(`[apm] deploy command: ${displayCommand}`);
|
|
5922
|
+
if (signal.aborted) {
|
|
5923
|
+
return { status: "FAILED", error: "\u90E8\u7F72\u5DF2\u53D6\u6D88" };
|
|
5924
|
+
}
|
|
5925
|
+
const deployOptions = {
|
|
5926
|
+
env: msg.environment,
|
|
5927
|
+
cwd: workdir,
|
|
5928
|
+
packOnly: msg.packOnly,
|
|
5929
|
+
captureOutput: true,
|
|
5930
|
+
archiveDeployArtifact: true,
|
|
5931
|
+
deployTrigger: "connect"
|
|
5932
|
+
};
|
|
5933
|
+
const output = await executeDeploy(deployOptions);
|
|
5934
|
+
if (output.trim()) {
|
|
5935
|
+
appendLog(output);
|
|
5936
|
+
}
|
|
5937
|
+
console.log(`[apm] deploy success id=${deploymentRunId}`);
|
|
5938
|
+
return { status: "SUCCESS" };
|
|
5939
|
+
}
|
|
5940
|
+
});
|
|
5941
|
+
if (deployError) {
|
|
5942
|
+
console.error(
|
|
5943
|
+
`[apm] deploy failed id=${deploymentRunId}: ${deployError.message}`
|
|
5944
|
+
);
|
|
5945
|
+
}
|
|
5804
5946
|
}
|
|
5805
5947
|
|
|
5806
5948
|
// src/commands/connect/abort-signal-debug.ts
|
|
@@ -6070,17 +6212,17 @@ ${JSON.stringify(event, null, 2)}
|
|
|
6070
6212
|
}
|
|
6071
6213
|
|
|
6072
6214
|
// src/commands/connect/agent-session-registry.ts
|
|
6073
|
-
import { existsSync as
|
|
6074
|
-
import { dirname as dirname6, resolve as
|
|
6215
|
+
import { existsSync as existsSync20, mkdirSync as mkdirSync9, readFileSync as readFileSync16, writeFileSync as writeFileSync14 } from "node:fs";
|
|
6216
|
+
import { dirname as dirname6, resolve as resolve5 } from "node:path";
|
|
6075
6217
|
function registryPath(workdir, sessionId) {
|
|
6076
|
-
return
|
|
6218
|
+
return resolve5(workdir, ".apm", "sessions", sessionId, "cursor-agents.json");
|
|
6077
6219
|
}
|
|
6078
|
-
function readRegistry(
|
|
6079
|
-
if (!
|
|
6220
|
+
function readRegistry(path19) {
|
|
6221
|
+
if (!existsSync20(path19)) {
|
|
6080
6222
|
return {};
|
|
6081
6223
|
}
|
|
6082
6224
|
try {
|
|
6083
|
-
const parsed = JSON.parse(
|
|
6225
|
+
const parsed = JSON.parse(readFileSync16(path19, "utf8"));
|
|
6084
6226
|
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
6085
6227
|
const result = {};
|
|
6086
6228
|
for (const [key, value] of Object.entries(
|
|
@@ -6096,9 +6238,9 @@ function readRegistry(path13) {
|
|
|
6096
6238
|
}
|
|
6097
6239
|
return {};
|
|
6098
6240
|
}
|
|
6099
|
-
function writeRegistry(
|
|
6100
|
-
|
|
6101
|
-
|
|
6241
|
+
function writeRegistry(path19, registry) {
|
|
6242
|
+
mkdirSync9(dirname6(path19), { recursive: true });
|
|
6243
|
+
writeFileSync14(path19, `${JSON.stringify(registry, null, 2)}
|
|
6102
6244
|
`, "utf8");
|
|
6103
6245
|
}
|
|
6104
6246
|
function loadSessionAgentId(workdir, sessionId, user) {
|
|
@@ -6106,19 +6248,19 @@ function loadSessionAgentId(workdir, sessionId, user) {
|
|
|
6106
6248
|
return registry[user];
|
|
6107
6249
|
}
|
|
6108
6250
|
function saveSessionAgentId(workdir, sessionId, user, agentId) {
|
|
6109
|
-
const
|
|
6110
|
-
const registry = readRegistry(
|
|
6251
|
+
const path19 = registryPath(workdir, sessionId);
|
|
6252
|
+
const registry = readRegistry(path19);
|
|
6111
6253
|
registry[user] = agentId;
|
|
6112
|
-
writeRegistry(
|
|
6254
|
+
writeRegistry(path19, registry);
|
|
6113
6255
|
}
|
|
6114
6256
|
function clearSessionAgentId(workdir, sessionId, user) {
|
|
6115
|
-
const
|
|
6116
|
-
const registry = readRegistry(
|
|
6257
|
+
const path19 = registryPath(workdir, sessionId);
|
|
6258
|
+
const registry = readRegistry(path19);
|
|
6117
6259
|
if (!(user in registry)) {
|
|
6118
6260
|
return;
|
|
6119
6261
|
}
|
|
6120
6262
|
delete registry[user];
|
|
6121
|
-
writeRegistry(
|
|
6263
|
+
writeRegistry(path19, registry);
|
|
6122
6264
|
}
|
|
6123
6265
|
|
|
6124
6266
|
// src/commands/connect/cursor-message-log.ts
|
|
@@ -6548,20 +6690,20 @@ async function ensureMessageHasReply(cfg, sessionId, messageId, fallback) {
|
|
|
6548
6690
|
}
|
|
6549
6691
|
|
|
6550
6692
|
// src/commands/connect/cli-version-sync.ts
|
|
6551
|
-
import { existsSync as
|
|
6693
|
+
import { existsSync as existsSync21, readFileSync as readFileSync17, writeFileSync as writeFileSync15 } from "fs";
|
|
6552
6694
|
import { join as join17 } from "path";
|
|
6553
6695
|
var CLI_VERSION_FILE = ".cli-version.json";
|
|
6554
6696
|
function manifestPath(apmDir) {
|
|
6555
6697
|
return join17(apmDir, CLI_VERSION_FILE);
|
|
6556
6698
|
}
|
|
6557
6699
|
function loadManifest4(apmDir) {
|
|
6558
|
-
const
|
|
6559
|
-
if (!
|
|
6700
|
+
const path19 = toFsPath(manifestPath(apmDir));
|
|
6701
|
+
if (!existsSync21(path19)) {
|
|
6560
6702
|
return null;
|
|
6561
6703
|
}
|
|
6562
6704
|
try {
|
|
6563
6705
|
const parsed = JSON.parse(
|
|
6564
|
-
|
|
6706
|
+
readFileSync17(path19, "utf8")
|
|
6565
6707
|
);
|
|
6566
6708
|
if (parsed?.version === 1 && typeof parsed.cliVersion === "string" && parsed.cliVersion.trim()) {
|
|
6567
6709
|
return parsed;
|
|
@@ -6572,7 +6714,7 @@ function loadManifest4(apmDir) {
|
|
|
6572
6714
|
}
|
|
6573
6715
|
function saveManifest4(apmDir, cliVersion) {
|
|
6574
6716
|
const manifest = { version: 1, cliVersion };
|
|
6575
|
-
|
|
6717
|
+
writeFileSync15(
|
|
6576
6718
|
toFsPath(manifestPath(apmDir)),
|
|
6577
6719
|
`${JSON.stringify(manifest, null, 2)}
|
|
6578
6720
|
`,
|
|
@@ -6651,7 +6793,7 @@ function createRunSlotPool(maxConcurrent = DEFAULT_MAX_CONCURRENT, options = {})
|
|
|
6651
6793
|
);
|
|
6652
6794
|
}
|
|
6653
6795
|
const queuedAt = Date.now();
|
|
6654
|
-
return new Promise((
|
|
6796
|
+
return new Promise((resolve6) => {
|
|
6655
6797
|
waiters.push(() => {
|
|
6656
6798
|
active += 1;
|
|
6657
6799
|
const waitedMs = Date.now() - queuedAt;
|
|
@@ -6662,7 +6804,7 @@ function createRunSlotPool(maxConcurrent = DEFAULT_MAX_CONCURRENT, options = {})
|
|
|
6662
6804
|
)}s\uFF0C\u5F53\u524D\u5360\u7528 ${active}/${maxConcurrent}`
|
|
6663
6805
|
);
|
|
6664
6806
|
}
|
|
6665
|
-
|
|
6807
|
+
resolve6();
|
|
6666
6808
|
});
|
|
6667
6809
|
});
|
|
6668
6810
|
};
|
|
@@ -6837,11 +6979,11 @@ async function handleInboundMessage(cfg, msg, signal, ctx) {
|
|
|
6837
6979
|
}
|
|
6838
6980
|
function interruptibleSleep(ms, signal) {
|
|
6839
6981
|
if (signal.aborted) return Promise.resolve();
|
|
6840
|
-
return new Promise((
|
|
6841
|
-
const timer = setTimeout(
|
|
6982
|
+
return new Promise((resolve6) => {
|
|
6983
|
+
const timer = setTimeout(resolve6, ms);
|
|
6842
6984
|
const onAbort = () => {
|
|
6843
6985
|
clearTimeout(timer);
|
|
6844
|
-
|
|
6986
|
+
resolve6();
|
|
6845
6987
|
};
|
|
6846
6988
|
signal.addEventListener("abort", onAbort, { once: true });
|
|
6847
6989
|
});
|
|
@@ -6981,7 +7123,7 @@ function attachWsHandlers(ws, ctx, onOpen) {
|
|
|
6981
7123
|
});
|
|
6982
7124
|
}
|
|
6983
7125
|
function connectOnce(url, ctx, connectionAbort, onConnected) {
|
|
6984
|
-
return new Promise((
|
|
7126
|
+
return new Promise((resolve6, reject) => {
|
|
6985
7127
|
const ws = new WebSocket(url);
|
|
6986
7128
|
let stopHeartbeat;
|
|
6987
7129
|
let settled = false;
|
|
@@ -7010,7 +7152,7 @@ function connectOnce(url, ctx, connectionAbort, onConnected) {
|
|
|
7010
7152
|
finish(() => reject(new Error("shutdown")));
|
|
7011
7153
|
return;
|
|
7012
7154
|
}
|
|
7013
|
-
finish(
|
|
7155
|
+
finish(resolve6);
|
|
7014
7156
|
});
|
|
7015
7157
|
ws.on("error", (err) => {
|
|
7016
7158
|
console.error("[apm] WebSocket \u9519\u8BEF:", err.message);
|
|
@@ -7290,14 +7432,6 @@ function normalizeDeployEnvironment(env) {
|
|
|
7290
7432
|
if (normalized === "online") return "ONLINE";
|
|
7291
7433
|
return null;
|
|
7292
7434
|
}
|
|
7293
|
-
async function completeTrackedDeploy(api, deploymentRunId, logSyncer, input) {
|
|
7294
|
-
logSyncer.updateLog(input.log);
|
|
7295
|
-
await finalizeTaskDeployment(api, deploymentRunId, logSyncer, {
|
|
7296
|
-
status: input.status,
|
|
7297
|
-
fullLog: input.log,
|
|
7298
|
-
error: input.error
|
|
7299
|
-
});
|
|
7300
|
-
}
|
|
7301
7435
|
async function runDeployWithBackendTracking(options) {
|
|
7302
7436
|
const cfg = await tryReadApmConfig();
|
|
7303
7437
|
if (!cfg || !resolveApiKey(cfg)) {
|
|
@@ -7319,7 +7453,7 @@ async function runDeployWithBackendTracking(options) {
|
|
|
7319
7453
|
const run = await api.cli.createTaskDeployment({
|
|
7320
7454
|
sessionId: options.sessionId,
|
|
7321
7455
|
environment,
|
|
7322
|
-
workdirPath: options.cwd
|
|
7456
|
+
workdirPath: resolveWorkdirPath(options.cwd)
|
|
7323
7457
|
});
|
|
7324
7458
|
deploymentRunId = run.id;
|
|
7325
7459
|
console.log(
|
|
@@ -7335,67 +7469,25 @@ async function runDeployWithBackendTracking(options) {
|
|
|
7335
7469
|
id: deploymentRunId,
|
|
7336
7470
|
status: "DEPLOYING"
|
|
7337
7471
|
});
|
|
7338
|
-
const
|
|
7339
|
-
|
|
7340
|
-
|
|
7341
|
-
|
|
7342
|
-
|
|
7343
|
-
|
|
7344
|
-
|
|
7345
|
-
|
|
7346
|
-
|
|
7347
|
-
|
|
7348
|
-
|
|
7349
|
-
|
|
7350
|
-
|
|
7351
|
-
|
|
7352
|
-
};
|
|
7353
|
-
console.error = (...args) => {
|
|
7354
|
-
appendLog(args.map(String).join(" "));
|
|
7355
|
-
originalError.apply(console, args);
|
|
7356
|
-
};
|
|
7357
|
-
try {
|
|
7358
|
-
const output = await executeDeploy({
|
|
7359
|
-
...options,
|
|
7360
|
-
captureOutput: true,
|
|
7361
|
-
archiveDeployArtifact: true
|
|
7362
|
-
});
|
|
7363
|
-
if (output.trim()) {
|
|
7364
|
-
appendLog(output);
|
|
7365
|
-
}
|
|
7366
|
-
const log2 = chunks.join("\n");
|
|
7367
|
-
await completeTrackedDeploy(api, deploymentRunId, logSyncer, {
|
|
7368
|
-
status: "SUCCESS",
|
|
7369
|
-
log: log2
|
|
7370
|
-
});
|
|
7371
|
-
console.log(`[apm] deploy success id=${deploymentRunId}`);
|
|
7372
|
-
} catch (error) {
|
|
7373
|
-
const deployError = error instanceof DeployExecutionError ? error : new DeployExecutionError(
|
|
7374
|
-
error instanceof Error ? error.message : String(error),
|
|
7375
|
-
1
|
|
7376
|
-
);
|
|
7377
|
-
if (deployError.output.trim()) {
|
|
7378
|
-
appendLog(deployError.output);
|
|
7379
|
-
} else {
|
|
7380
|
-
appendLog(deployError.message);
|
|
7472
|
+
const { error: deployError } = await runTrackedDeploy({
|
|
7473
|
+
api,
|
|
7474
|
+
deploymentRunId,
|
|
7475
|
+
run: async (appendLog) => {
|
|
7476
|
+
const output = await executeDeploy({
|
|
7477
|
+
...options,
|
|
7478
|
+
captureOutput: true,
|
|
7479
|
+
archiveDeployArtifact: true
|
|
7480
|
+
});
|
|
7481
|
+
if (output.trim()) {
|
|
7482
|
+
appendLog(output);
|
|
7483
|
+
}
|
|
7484
|
+
console.log(`[apm] deploy success id=${deploymentRunId}`);
|
|
7485
|
+
return { status: "SUCCESS" };
|
|
7381
7486
|
}
|
|
7382
|
-
|
|
7383
|
-
|
|
7384
|
-
status: "FAILED",
|
|
7385
|
-
log: log2,
|
|
7386
|
-
error: deployError.message
|
|
7387
|
-
});
|
|
7487
|
+
});
|
|
7488
|
+
if (deployError) {
|
|
7388
7489
|
printDeployExecutionError(deployError);
|
|
7389
7490
|
process.exit(deployError.exitCode);
|
|
7390
|
-
} finally {
|
|
7391
|
-
if (previousDeploymentRunId === void 0) {
|
|
7392
|
-
delete process.env[APM_DEPLOYMENT_RUN_ID_ENV];
|
|
7393
|
-
} else {
|
|
7394
|
-
process.env[APM_DEPLOYMENT_RUN_ID_ENV] = previousDeploymentRunId;
|
|
7395
|
-
}
|
|
7396
|
-
console.log = originalLog;
|
|
7397
|
-
console.error = originalError;
|
|
7398
|
-
logSyncer.dispose();
|
|
7399
7491
|
}
|
|
7400
7492
|
}
|
|
7401
7493
|
|
|
@@ -7448,29 +7540,29 @@ function registerDeployMainCommand(program) {
|
|
|
7448
7540
|
}
|
|
7449
7541
|
|
|
7450
7542
|
// src/commands/deploy/backend.ts
|
|
7451
|
-
import
|
|
7543
|
+
import path16 from "node:path";
|
|
7452
7544
|
|
|
7453
7545
|
// src/commands/deploy/internal/backend-deploy/backend-deploy-workflow.ts
|
|
7454
|
-
import
|
|
7546
|
+
import path15 from "node:path";
|
|
7455
7547
|
|
|
7456
7548
|
// src/commands/deploy/internal/backend-deploy/dockerode-client/client.ts
|
|
7457
7549
|
import Docker from "dockerode";
|
|
7458
7550
|
|
|
7459
7551
|
// src/commands/deploy/internal/backend-deploy/dockerode-client/connection-options.ts
|
|
7460
|
-
import { existsSync as
|
|
7461
|
-
import
|
|
7552
|
+
import { existsSync as existsSync22, readFileSync as readFileSync18 } from "node:fs";
|
|
7553
|
+
import path12 from "node:path";
|
|
7462
7554
|
function asOptionalTlsBuffer(value) {
|
|
7463
7555
|
if (typeof value !== "string") {
|
|
7464
7556
|
console.log("tls filepath not exist");
|
|
7465
7557
|
return void 0;
|
|
7466
7558
|
}
|
|
7467
|
-
console.log("tls filepath",
|
|
7559
|
+
console.log("tls filepath", path12.join(process.cwd(), value));
|
|
7468
7560
|
const normalized = value.trim();
|
|
7469
7561
|
if (normalized === "") {
|
|
7470
7562
|
return void 0;
|
|
7471
7563
|
}
|
|
7472
|
-
if (
|
|
7473
|
-
return
|
|
7564
|
+
if (existsSync22(normalized)) {
|
|
7565
|
+
return readFileSync18(normalized);
|
|
7474
7566
|
}
|
|
7475
7567
|
const looksLikePath = /[\\/]/.test(normalized) || normalized.endsWith(".pem");
|
|
7476
7568
|
if (looksLikePath) {
|
|
@@ -7595,17 +7687,17 @@ var DockerodeClient = class {
|
|
|
7595
7687
|
await this.client.getImage(image).remove({ force: true });
|
|
7596
7688
|
}
|
|
7597
7689
|
async pullImage(image, auth) {
|
|
7598
|
-
const stream = await new Promise((
|
|
7690
|
+
const stream = await new Promise((resolve6, reject) => {
|
|
7599
7691
|
const pullOptions = auth ? { authconfig: auth } : void 0;
|
|
7600
7692
|
this.client.pull(image, pullOptions, (err, output) => {
|
|
7601
7693
|
if (err || !output) {
|
|
7602
7694
|
reject(err ?? new Error("docker pull \u8FD4\u56DE\u7A7A\u8F93\u51FA"));
|
|
7603
7695
|
return;
|
|
7604
7696
|
}
|
|
7605
|
-
|
|
7697
|
+
resolve6(output);
|
|
7606
7698
|
});
|
|
7607
7699
|
});
|
|
7608
|
-
await new Promise((
|
|
7700
|
+
await new Promise((resolve6, reject) => {
|
|
7609
7701
|
this.client.modem.followProgress(
|
|
7610
7702
|
stream,
|
|
7611
7703
|
(err) => {
|
|
@@ -7613,7 +7705,7 @@ var DockerodeClient = class {
|
|
|
7613
7705
|
reject(err);
|
|
7614
7706
|
return;
|
|
7615
7707
|
}
|
|
7616
|
-
|
|
7708
|
+
resolve6();
|
|
7617
7709
|
},
|
|
7618
7710
|
() => void 0
|
|
7619
7711
|
);
|
|
@@ -7680,8 +7772,8 @@ var DockerodeClient = class {
|
|
|
7680
7772
|
var createDockerodeClient = (config) => new DockerodeClient(config);
|
|
7681
7773
|
|
|
7682
7774
|
// src/commands/deploy/internal/backend-deploy/dockerode-client/env.ts
|
|
7683
|
-
import { existsSync as
|
|
7684
|
-
import
|
|
7775
|
+
import { existsSync as existsSync23, readFileSync as readFileSync19, statSync as statSync10 } from "node:fs";
|
|
7776
|
+
import path13 from "node:path";
|
|
7685
7777
|
function stripSurroundingQuotes(value) {
|
|
7686
7778
|
const t = value.trim();
|
|
7687
7779
|
if (t.length >= 2) {
|
|
@@ -7696,11 +7788,11 @@ function loadEnvFromFile(envFilePath) {
|
|
|
7696
7788
|
if (!envFilePath) {
|
|
7697
7789
|
return {};
|
|
7698
7790
|
}
|
|
7699
|
-
const targetPath =
|
|
7700
|
-
if (!
|
|
7791
|
+
const targetPath = path13.resolve(envFilePath);
|
|
7792
|
+
if (!existsSync23(targetPath) || !statSync10(targetPath).isFile()) {
|
|
7701
7793
|
return {};
|
|
7702
7794
|
}
|
|
7703
|
-
const raw =
|
|
7795
|
+
const raw = readFileSync19(targetPath, "utf-8");
|
|
7704
7796
|
const result = {};
|
|
7705
7797
|
for (const line of raw.split(/\r?\n/)) {
|
|
7706
7798
|
const normalized = line.trim();
|
|
@@ -7871,12 +7963,12 @@ function dockerPushImage(params, cwd) {
|
|
|
7871
7963
|
}
|
|
7872
7964
|
|
|
7873
7965
|
// src/commands/deploy/internal/backend-deploy/resolve-dockerfile.ts
|
|
7874
|
-
import { existsSync as
|
|
7875
|
-
import
|
|
7966
|
+
import { existsSync as existsSync24 } from "node:fs";
|
|
7967
|
+
import path14 from "node:path";
|
|
7876
7968
|
function resolveDockerBuildPaths(cwd) {
|
|
7877
|
-
const dockerfilePath =
|
|
7969
|
+
const dockerfilePath = path14.join(cwd, "Dockerfile");
|
|
7878
7970
|
Logger.info(`\u67E5\u627EDockerfile\u6587\u4EF6\uFF0C\u8DEF\u5F84: ${dockerfilePath}`);
|
|
7879
|
-
if (!
|
|
7971
|
+
if (!existsSync24(dockerfilePath)) {
|
|
7880
7972
|
throw new Error(`Dockerfile \u4E0D\u5B58\u5728\uFF1A${dockerfilePath}`);
|
|
7881
7973
|
}
|
|
7882
7974
|
Logger.info("\u2713 Dockerfile \u5B58\u5728");
|
|
@@ -7931,7 +8023,7 @@ var BackendDeployWorkflow = class {
|
|
|
7931
8023
|
serveraddress
|
|
7932
8024
|
});
|
|
7933
8025
|
Logger.success("\u8FDC\u7A0B\u62C9\u53D6\u955C\u50CF\u5B8C\u6210");
|
|
7934
|
-
const envFilePath =
|
|
8026
|
+
const envFilePath = path15.resolve(cwd, this.params.envFilePath || ".env");
|
|
7935
8027
|
const envObj = loadEnvFromFile(envFilePath);
|
|
7936
8028
|
if (this.params.dockerNetwork?.trim()) {
|
|
7937
8029
|
Logger.info(`\u8FDC\u7A0B\u5BB9\u5668\u5C06\u52A0\u5165 Docker \u7F51\u7EDC\uFF1A${this.params.dockerNetwork.trim()}`);
|
|
@@ -7971,7 +8063,7 @@ function registerDeployBackendCommands(program) {
|
|
|
7971
8063
|
assertDeployImageTag(tag);
|
|
7972
8064
|
const cfg = loadApmConfig({ configPath: opts.config });
|
|
7973
8065
|
const fromApm = resolveBackendDeployFromApmConfig(cfg);
|
|
7974
|
-
const dirAbs =
|
|
8066
|
+
const dirAbs = path16.resolve(process.cwd(), opts.dir || "servers/api");
|
|
7975
8067
|
const params = {
|
|
7976
8068
|
image: fromApm.name,
|
|
7977
8069
|
tag,
|
|
@@ -8001,34 +8093,15 @@ function registerDeployBackendCommands(program) {
|
|
|
8001
8093
|
}
|
|
8002
8094
|
|
|
8003
8095
|
// src/commands/deploy/frontend.ts
|
|
8004
|
-
import { copyFile, readdir as readdir3, stat
|
|
8005
|
-
import
|
|
8006
|
-
function resolveArtifactNamePrefix(cfg) {
|
|
8007
|
-
const nameRaw = (cfg.name ?? "").trim();
|
|
8008
|
-
if (!nameRaw) {
|
|
8009
|
-
console.error(
|
|
8010
|
-
"\u8BF7\u5728 .apm/apm.config.json \u9876\u5C42\u914D\u7F6E name\uFF08\u4F5C\u4E3A MinIO \u5BF9\u8C61\u952E\u524D\u7F00\uFF09"
|
|
8011
|
-
);
|
|
8012
|
-
process.exit(1);
|
|
8013
|
-
}
|
|
8014
|
-
if (nameRaw.includes(":")) {
|
|
8015
|
-
console.error("apm.config.json \u7684 name \u4E0D\u80FD\u5305\u542B ':'");
|
|
8016
|
-
process.exit(1);
|
|
8017
|
-
}
|
|
8018
|
-
try {
|
|
8019
|
-
return sanitizeRelativePath(nameRaw.replace(/\\/g, "/"));
|
|
8020
|
-
} catch {
|
|
8021
|
-
console.error("apm.config.json \u7684 name \u975E\u6CD5\uFF08\u8DEF\u5F84\u7247\u6BB5\u4E0D\u80FD\u4E3A . \u6216 ..\uFF09");
|
|
8022
|
-
process.exit(1);
|
|
8023
|
-
}
|
|
8024
|
-
}
|
|
8096
|
+
import { copyFile, readdir as readdir3, stat } from "node:fs/promises";
|
|
8097
|
+
import path17 from "node:path";
|
|
8025
8098
|
function artifactObjectKey(namePrefix, branchSegment, relativePath) {
|
|
8026
8099
|
const base = sanitizeRelativePath(namePrefix);
|
|
8027
8100
|
const rel = sanitizeRelativePath(relativePath);
|
|
8028
8101
|
return `${base}/${branchSegment}/dist/${rel}`;
|
|
8029
8102
|
}
|
|
8030
8103
|
async function ensureArtifactRootIndexHtml(root) {
|
|
8031
|
-
const indexHtmlPath =
|
|
8104
|
+
const indexHtmlPath = path17.join(root, "index.html");
|
|
8032
8105
|
try {
|
|
8033
8106
|
const st = await stat(indexHtmlPath);
|
|
8034
8107
|
if (st.isFile()) {
|
|
@@ -8040,12 +8113,11 @@ async function ensureArtifactRootIndexHtml(root) {
|
|
|
8040
8113
|
try {
|
|
8041
8114
|
entries = await readdir3(root, { withFileTypes: true });
|
|
8042
8115
|
} catch (e) {
|
|
8043
|
-
|
|
8044
|
-
process.exit(1);
|
|
8116
|
+
throw new DeployExecutionError(`\u65E0\u6CD5\u8BFB\u53D6\u4EA7\u7269\u76EE\u5F55\uFF1A${root}`, 1, String(e));
|
|
8045
8117
|
}
|
|
8046
8118
|
const dirNames = entries.filter((e) => e.isDirectory()).map((e) => String(e.name)).sort();
|
|
8047
8119
|
for (const name of dirNames) {
|
|
8048
|
-
const candidate =
|
|
8120
|
+
const candidate = path17.join(root, name, "index.html");
|
|
8049
8121
|
try {
|
|
8050
8122
|
const st = await stat(candidate);
|
|
8051
8123
|
if (!st.isFile()) {
|
|
@@ -8056,52 +8128,39 @@ async function ensureArtifactRootIndexHtml(root) {
|
|
|
8056
8128
|
}
|
|
8057
8129
|
await copyFile(candidate, indexHtmlPath);
|
|
8058
8130
|
console.error(
|
|
8059
|
-
`\u4EA7\u7269\u534F\u8BAE\uFF1A\u5DF2\u5C06 ${
|
|
8131
|
+
`\u4EA7\u7269\u534F\u8BAE\uFF1A\u5DF2\u5C06 ${path17.join(name, "index.html")} \u590D\u5236\u4E3A\u6839\u76EE\u5F55 index.html`
|
|
8060
8132
|
);
|
|
8061
8133
|
return;
|
|
8062
8134
|
}
|
|
8063
|
-
|
|
8064
|
-
`\u4EA7\u7269\u534F\u8BAE\uFF1A\u9700\u5728\u4EA7\u7269\u6839\u76EE\u5F55\u5B58\u5728 index.html\uFF0C\u6216\u5728\u5176\u4E00\u7EA7\u5B50\u76EE\u5F55\u4E2D\u5B58\u5728\u53EF\u590D\u5236\u7684 index.html\uFF08\u672A\u5728 ${root} \u4E0B\u627E\u5230\uFF09
|
|
8135
|
+
throw new DeployExecutionError(
|
|
8136
|
+
`\u4EA7\u7269\u534F\u8BAE\uFF1A\u9700\u5728\u4EA7\u7269\u6839\u76EE\u5F55\u5B58\u5728 index.html\uFF0C\u6216\u5728\u5176\u4E00\u7EA7\u5B50\u76EE\u5F55\u4E2D\u5B58\u5728\u53EF\u590D\u5236\u7684 index.html\uFF08\u672A\u5728 ${root} \u4E0B\u627E\u5230\uFF09`,
|
|
8137
|
+
1
|
|
8065
8138
|
);
|
|
8066
|
-
process.exit(1);
|
|
8067
8139
|
}
|
|
8068
8140
|
async function runFrontendPackOnlyDeploy(root, namePrefix) {
|
|
8069
|
-
const zipPath =
|
|
8070
|
-
|
|
8071
|
-
|
|
8072
|
-
|
|
8073
|
-
|
|
8074
|
-
|
|
8075
|
-
|
|
8076
|
-
|
|
8077
|
-
|
|
8078
|
-
|
|
8079
|
-
|
|
8080
|
-
|
|
8081
|
-
|
|
8082
|
-
|
|
8083
|
-
|
|
8084
|
-
|
|
8085
|
-
|
|
8086
|
-
|
|
8087
|
-
|
|
8088
|
-
|
|
8089
|
-
|
|
8090
|
-
|
|
8091
|
-
|
|
8092
|
-
artifactUploaded
|
|
8093
|
-
},
|
|
8094
|
-
null,
|
|
8095
|
-
2
|
|
8096
|
-
)
|
|
8097
|
-
);
|
|
8098
|
-
} finally {
|
|
8099
|
-
try {
|
|
8100
|
-
await unlink2(zipPath);
|
|
8101
|
-
console.error(`\u5DF2\u6E05\u7406\u672C\u5730\u4E34\u65F6\u6587\u4EF6: ${zipPath}`);
|
|
8102
|
-
} catch {
|
|
8103
|
-
}
|
|
8104
|
-
}
|
|
8141
|
+
const zipPath = path17.resolve(root, "..", ".deploy-frontend-dist.zip");
|
|
8142
|
+
const { zipSizeBytes, artifactUploaded } = await packDirectoryWithMinioArchive({
|
|
8143
|
+
localDir: root,
|
|
8144
|
+
zipPath,
|
|
8145
|
+
projectName: namePrefix,
|
|
8146
|
+
kind: "frontend",
|
|
8147
|
+
uploadWithoutRunId: true,
|
|
8148
|
+
skipMessage: "[apm] \u4EC5\u6253\u5305\u6A21\u5F0F\uFF1A\u8DF3\u8FC7\u524D\u7AEF\u8BBF\u95EE\u6876\u4E0A\u4F20",
|
|
8149
|
+
successMessage: "\u6253\u5305\u5E76\u4E0A\u4F20 MinIO \u5F52\u6863\u5B8C\u6210\uFF08\u672A\u4E0A\u4F20\u81F3\u524D\u7AEF\u8BBF\u95EE\u6876\uFF09"
|
|
8150
|
+
});
|
|
8151
|
+
console.log(
|
|
8152
|
+
JSON.stringify(
|
|
8153
|
+
{
|
|
8154
|
+
ok: true,
|
|
8155
|
+
packOnly: true,
|
|
8156
|
+
namePrefix,
|
|
8157
|
+
zipSizeBytes,
|
|
8158
|
+
artifactUploaded
|
|
8159
|
+
},
|
|
8160
|
+
null,
|
|
8161
|
+
2
|
|
8162
|
+
)
|
|
8163
|
+
);
|
|
8105
8164
|
}
|
|
8106
8165
|
function registerDeployFrontendCommands(program) {
|
|
8107
8166
|
program.command("deploy-frontend").description(
|
|
@@ -8122,91 +8181,97 @@ function registerDeployFrontendCommands(program) {
|
|
|
8122
8181
|
"\u4EC5\u6253\u5305\u5E76\u4E0A\u4F20 MinIO \u5F52\u6863\uFF0C\u4E0D\u4E0A\u4F20\u81F3\u524D\u7AEF\u8BBF\u95EE\u6876\uFF08\u9ED8\u8BA4\u5173\u95ED\uFF09"
|
|
8123
8182
|
).action(
|
|
8124
8183
|
async (name, opts) => {
|
|
8125
|
-
|
|
8126
|
-
|
|
8127
|
-
|
|
8128
|
-
|
|
8129
|
-
|
|
8130
|
-
|
|
8131
|
-
|
|
8132
|
-
|
|
8133
|
-
|
|
8134
|
-
|
|
8135
|
-
|
|
8136
|
-
|
|
8137
|
-
|
|
8138
|
-
|
|
8139
|
-
|
|
8140
|
-
|
|
8141
|
-
|
|
8142
|
-
|
|
8143
|
-
|
|
8144
|
-
|
|
8145
|
-
|
|
8146
|
-
|
|
8147
|
-
|
|
8148
|
-
|
|
8149
|
-
|
|
8150
|
-
|
|
8151
|
-
|
|
8152
|
-
|
|
8153
|
-
|
|
8154
|
-
|
|
8155
|
-
|
|
8156
|
-
|
|
8157
|
-
|
|
8158
|
-
|
|
8159
|
-
|
|
8160
|
-
|
|
8161
|
-
|
|
8162
|
-
|
|
8163
|
-
|
|
8164
|
-
|
|
8165
|
-
|
|
8166
|
-
|
|
8184
|
+
try {
|
|
8185
|
+
const cfg = loadApmConfig({ configPath: opts.config });
|
|
8186
|
+
const namePrefix = resolveArtifactNamePrefix(cfg);
|
|
8187
|
+
const root = path17.resolve(process.cwd(), opts.dir || "apps/web/dist");
|
|
8188
|
+
if (!await isDirectoryPath(root)) {
|
|
8189
|
+
throw new DeployExecutionError(`\u4EA7\u7269\u76EE\u5F55\u4E0D\u5B58\u5728\uFF1A${root}`, 1);
|
|
8190
|
+
}
|
|
8191
|
+
await ensureArtifactRootIndexHtml(root);
|
|
8192
|
+
if (opts.packOnly) {
|
|
8193
|
+
await runFrontendPackOnlyDeploy(root, namePrefix);
|
|
8194
|
+
return;
|
|
8195
|
+
}
|
|
8196
|
+
const settings = resolveFrontendDeployFromApmConfig(cfg);
|
|
8197
|
+
const minio = new MinioClient({
|
|
8198
|
+
endPoint: settings.endpoint,
|
|
8199
|
+
port: settings.port,
|
|
8200
|
+
useSSL: settings.useSsl,
|
|
8201
|
+
accessKey: settings.accessKey,
|
|
8202
|
+
secretKey: settings.secretKey
|
|
8203
|
+
});
|
|
8204
|
+
const bucket = settings.bucket;
|
|
8205
|
+
const maxBytes = Math.max(
|
|
8206
|
+
1,
|
|
8207
|
+
Number.isFinite(opts.maxFileSizeMb) ? Math.floor(
|
|
8208
|
+
(opts.maxFileSizeMb ?? DEFAULT_MAX_FILE_SIZE_MB) * 1024 * 1024
|
|
8209
|
+
) : DEFAULT_MAX_FILE_SIZE_MB * 1024 * 1024
|
|
8210
|
+
);
|
|
8211
|
+
const files = await collectFiles(root);
|
|
8212
|
+
if (files.length === 0) {
|
|
8213
|
+
throw new DeployExecutionError(`\u76EE\u5F55\u4E3A\u7A7A\uFF1A${root}`, 1);
|
|
8214
|
+
}
|
|
8215
|
+
let uploaded = 0;
|
|
8216
|
+
let totalBytes = 0;
|
|
8217
|
+
console.error(`\u5F00\u59CB\u76F4\u8FDE MinIO \u4E0A\u4F20\uFF0C\u5171 ${files.length} \u4E2A\u6587\u4EF6\u2026`);
|
|
8218
|
+
await minio.ensureBucket(bucket);
|
|
8219
|
+
await minio.deleteObjectsByPrefix(
|
|
8220
|
+
bucket,
|
|
8221
|
+
`${namePrefix}/${name}/dist/`
|
|
8222
|
+
);
|
|
8223
|
+
for (const f of files) {
|
|
8224
|
+
if (f.size > maxBytes) {
|
|
8225
|
+
throw new DeployExecutionError(
|
|
8226
|
+
`\u6587\u4EF6\u8FC7\u5927\uFF0C\u5DF2\u62D2\u7EDD\uFF1A${f.relativePath}\uFF08${toMB(
|
|
8227
|
+
f.size
|
|
8228
|
+
)}MB > ${toMB(maxBytes)}MB\uFF09`,
|
|
8229
|
+
1
|
|
8230
|
+
);
|
|
8231
|
+
}
|
|
8232
|
+
const buf = await readArtifactFile(f.absPath);
|
|
8233
|
+
const cleanRel = sanitizeRelativePath(f.relativePath);
|
|
8234
|
+
const objectKey = artifactObjectKey(namePrefix, name, cleanRel);
|
|
8235
|
+
const mimeType = detectMimeType(f.relativePath).trim().toLowerCase() || "application/octet-stream";
|
|
8236
|
+
await minio.putObject(bucket, objectKey, buf, {
|
|
8237
|
+
"Content-Type": mimeType
|
|
8238
|
+
});
|
|
8239
|
+
uploaded += 1;
|
|
8240
|
+
totalBytes += buf.length;
|
|
8167
8241
|
console.error(
|
|
8168
|
-
|
|
8169
|
-
maxBytes
|
|
8170
|
-
)}MB\uFF09`
|
|
8242
|
+
`[${uploaded}/${files.length}] ${f.relativePath} -> ${objectKey}`
|
|
8171
8243
|
);
|
|
8172
|
-
process.exit(1);
|
|
8173
8244
|
}
|
|
8174
|
-
|
|
8175
|
-
|
|
8176
|
-
|
|
8177
|
-
|
|
8178
|
-
|
|
8179
|
-
|
|
8180
|
-
|
|
8181
|
-
|
|
8182
|
-
|
|
8183
|
-
|
|
8184
|
-
|
|
8245
|
+
console.error("\u6B63\u5728\u8BBE\u7F6E\u6876\u7B56\u7565\uFF08\u533F\u540D\u53EF\u8BFB\u5BF9\u8C61\uFF0C\u4FBF\u4E8E HTTP \u76F4\u94FE\uFF09\u2026");
|
|
8246
|
+
await minio.setBucketPublicRead(bucket);
|
|
8247
|
+
console.log(
|
|
8248
|
+
JSON.stringify(
|
|
8249
|
+
{
|
|
8250
|
+
ok: true,
|
|
8251
|
+
namePrefix,
|
|
8252
|
+
envName: name,
|
|
8253
|
+
bucket,
|
|
8254
|
+
fileCount: uploaded,
|
|
8255
|
+
totalBytes,
|
|
8256
|
+
bucketPublicRead: true
|
|
8257
|
+
},
|
|
8258
|
+
null,
|
|
8259
|
+
2
|
|
8260
|
+
)
|
|
8185
8261
|
);
|
|
8262
|
+
} catch (error) {
|
|
8263
|
+
if (error instanceof DeployExecutionError) {
|
|
8264
|
+
printDeployExecutionError(error);
|
|
8265
|
+
process.exit(error.exitCode);
|
|
8266
|
+
}
|
|
8267
|
+
throw error;
|
|
8186
8268
|
}
|
|
8187
|
-
console.error("\u6B63\u5728\u8BBE\u7F6E\u6876\u7B56\u7565\uFF08\u533F\u540D\u53EF\u8BFB\u5BF9\u8C61\uFF0C\u4FBF\u4E8E HTTP \u76F4\u94FE\uFF09\u2026");
|
|
8188
|
-
await minio.setBucketPublicRead(bucket);
|
|
8189
|
-
console.log(
|
|
8190
|
-
JSON.stringify(
|
|
8191
|
-
{
|
|
8192
|
-
ok: true,
|
|
8193
|
-
namePrefix,
|
|
8194
|
-
envName: name,
|
|
8195
|
-
bucket,
|
|
8196
|
-
fileCount: uploaded,
|
|
8197
|
-
totalBytes,
|
|
8198
|
-
bucketPublicRead: true
|
|
8199
|
-
},
|
|
8200
|
-
null,
|
|
8201
|
-
2
|
|
8202
|
-
)
|
|
8203
|
-
);
|
|
8204
8269
|
}
|
|
8205
8270
|
);
|
|
8206
8271
|
}
|
|
8207
8272
|
|
|
8208
8273
|
// src/commands/deploy/sftp.ts
|
|
8209
|
-
import
|
|
8274
|
+
import path18 from "node:path";
|
|
8210
8275
|
function registerDeploySftpCommands(program) {
|
|
8211
8276
|
program.command("deploy-sftp").description(
|
|
8212
8277
|
"\u5C06\u6307\u5B9A\u76EE\u5F55\u538B\u7F29\u4E3A zip \u540E\u901A\u8FC7 SFTP \u4E0A\u4F20\u5230\u8FDC\u7A0B\u670D\u52A1\u5668\uFF08\u8FDE\u63A5\u4FE1\u606F\u89C1 apm.config.json wisdomDeploy\uFF09"
|
|
@@ -8222,25 +8287,22 @@ function registerDeploySftpCommands(program) {
|
|
|
8222
8287
|
"\u4EC5\u6253\u5305\u5E76\u4E0A\u4F20 MinIO \u5F52\u6863\uFF0C\u4E0D\u4E0A\u4F20\u8FDC\u7A0B\u670D\u52A1\u5668\uFF08\u4E0E --extract \u4E92\u65A5\uFF09"
|
|
8223
8288
|
).action(
|
|
8224
8289
|
async (opts) => {
|
|
8225
|
-
const cfg = loadApmConfig({ configPath: opts.config });
|
|
8226
|
-
const settings = resolveWisdomDeployFromApmConfig(cfg);
|
|
8227
|
-
const projectName = (cfg.name ?? "").trim();
|
|
8228
|
-
if (!projectName) {
|
|
8229
|
-
console.error(
|
|
8230
|
-
"\u8BF7\u5728 .apm/apm.config.json \u9876\u5C42\u914D\u7F6E name\uFF08\u4F5C\u4E3A\u90E8\u7F72\u4EA7\u7269\u9879\u76EE\u540D\uFF09"
|
|
8231
|
-
);
|
|
8232
|
-
process.exit(1);
|
|
8233
|
-
}
|
|
8234
|
-
const root = path12.resolve(process.cwd(), opts.dir || "apps/web/dist");
|
|
8235
|
-
if (!await isDirectoryPath(root)) {
|
|
8236
|
-
console.error(`\u4EA7\u7269\u76EE\u5F55\u4E0D\u5B58\u5728\uFF1A${root}`);
|
|
8237
|
-
process.exit(1);
|
|
8238
|
-
}
|
|
8239
8290
|
try {
|
|
8291
|
+
const cfg = loadApmConfig({ configPath: opts.config });
|
|
8292
|
+
const settings = resolveWisdomDeployFromApmConfig(cfg);
|
|
8293
|
+
const projectName = resolveProjectNameForDeploy(cfg, process.cwd(), {
|
|
8294
|
+
requireName: true
|
|
8295
|
+
});
|
|
8296
|
+
const root = path18.resolve(process.cwd(), opts.dir || "apps/web/dist");
|
|
8297
|
+
if (!await isDirectoryPath(root)) {
|
|
8298
|
+
throw new DeployExecutionError(`\u4EA7\u7269\u76EE\u5F55\u4E0D\u5B58\u5728\uFF1A${root}`, 1);
|
|
8299
|
+
}
|
|
8240
8300
|
const packOnly = Boolean(opts.packOnly);
|
|
8241
8301
|
if (packOnly && opts.extract) {
|
|
8242
|
-
|
|
8243
|
-
|
|
8302
|
+
throw new DeployExecutionError(
|
|
8303
|
+
"--pack-only \u4E0E --extract \u4E0D\u80FD\u540C\u65F6\u4F7F\u7528",
|
|
8304
|
+
1
|
|
8305
|
+
);
|
|
8244
8306
|
}
|
|
8245
8307
|
const result = await runWisdomSftpDeploy({
|
|
8246
8308
|
localDir: root,
|
|
@@ -8250,8 +8312,12 @@ function registerDeploySftpCommands(program) {
|
|
|
8250
8312
|
packOnly
|
|
8251
8313
|
});
|
|
8252
8314
|
console.log(JSON.stringify(result, null, 2));
|
|
8253
|
-
} catch (
|
|
8254
|
-
|
|
8315
|
+
} catch (error) {
|
|
8316
|
+
if (error instanceof DeployExecutionError) {
|
|
8317
|
+
printDeployExecutionError(error);
|
|
8318
|
+
process.exit(error.exitCode);
|
|
8319
|
+
}
|
|
8320
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
8255
8321
|
const action = opts.packOnly ? "\u6253\u5305" : opts.extract ? "\u90E8\u7F72" : "\u4E0A\u4F20";
|
|
8256
8322
|
console.error(`${action}\u5931\u8D25:`, message);
|
|
8257
8323
|
process.exit(1);
|
|
@@ -8268,11 +8334,19 @@ function registerDeployWisdomBackendCommands(program) {
|
|
|
8268
8334
|
"--config <path>",
|
|
8269
8335
|
"apm.config.json \u8DEF\u5F84\uFF08\u9ED8\u8BA4 .apm/apm.config.json\uFF09"
|
|
8270
8336
|
).action(async (opts) => {
|
|
8271
|
-
|
|
8272
|
-
|
|
8273
|
-
|
|
8274
|
-
|
|
8275
|
-
|
|
8337
|
+
try {
|
|
8338
|
+
const cfg = loadApmConfig({ configPath: opts.config });
|
|
8339
|
+
const settings = resolveWisdomBackendDeployFromApmConfig(cfg);
|
|
8340
|
+
await runWisdomBackendDeploy({
|
|
8341
|
+
config: settings
|
|
8342
|
+
});
|
|
8343
|
+
} catch (error) {
|
|
8344
|
+
if (error instanceof DeployExecutionError) {
|
|
8345
|
+
printDeployExecutionError(error);
|
|
8346
|
+
process.exit(error.exitCode);
|
|
8347
|
+
}
|
|
8348
|
+
throw error;
|
|
8349
|
+
}
|
|
8276
8350
|
});
|
|
8277
8351
|
}
|
|
8278
8352
|
|