ai-project-manage-cli 6.0.82 → 6.0.84
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 +407 -121
- package/package.json +1 -1
- package/template/skills/apm-deploy/SKILL.md +5 -3
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(path13) {
|
|
114
|
+
let normalized = path13.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 path13 = join2(apmDir, item);
|
|
330
|
+
if (!existsSync(toFsPath(path13))) {
|
|
331
|
+
throw new Error(`[apm] \u521D\u59CB\u5316\u4E0D\u5B8C\u6574\uFF0C\u7F3A\u5C11: ${path13}`);
|
|
332
332
|
}
|
|
333
333
|
}
|
|
334
334
|
const leakedRules = join2(workdir, "rules");
|
|
@@ -473,6 +473,10 @@ var requestConfig = {
|
|
|
473
473
|
method: "DELETE",
|
|
474
474
|
path: "/cli/repository-project-documents"
|
|
475
475
|
}),
|
|
476
|
+
createTaskDeployment: defineEndpoint({
|
|
477
|
+
method: "POST",
|
|
478
|
+
path: "/cli/task-deployments"
|
|
479
|
+
}),
|
|
476
480
|
updateTaskDeploymentStatus: defineEndpoint({
|
|
477
481
|
method: "PUT",
|
|
478
482
|
path: "/cli/task-deployments/status"
|
|
@@ -606,14 +610,14 @@ function projectDocumentLocalPath(apmRoot, documentPath) {
|
|
|
606
610
|
const normalized = normalizeLocalDocumentPath(documentPath);
|
|
607
611
|
return join4(projectDocumentsDir(apmRoot), ...normalized.split("/"));
|
|
608
612
|
}
|
|
609
|
-
function normalizeLocalDocumentPath(
|
|
610
|
-
const trimmed =
|
|
613
|
+
function normalizeLocalDocumentPath(path13) {
|
|
614
|
+
const trimmed = path13.trim().replace(/\\/g, "/");
|
|
611
615
|
if (!trimmed || trimmed.startsWith("/") || /^[a-zA-Z]:/.test(trimmed)) {
|
|
612
|
-
throw new Error(`\u975E\u6CD5\u6587\u6863\u8DEF\u5F84: ${
|
|
616
|
+
throw new Error(`\u975E\u6CD5\u6587\u6863\u8DEF\u5F84: ${path13}`);
|
|
613
617
|
}
|
|
614
618
|
const segments = trimmed.split("/").filter(Boolean);
|
|
615
619
|
if (segments.some((segment) => segment === ".." || segment === ".")) {
|
|
616
|
-
throw new Error(`\u975E\u6CD5\u6587\u6863\u8DEF\u5F84: ${
|
|
620
|
+
throw new Error(`\u975E\u6CD5\u6587\u6863\u8DEF\u5F84: ${path13}`);
|
|
617
621
|
}
|
|
618
622
|
return segments.join("/");
|
|
619
623
|
}
|
|
@@ -664,15 +668,15 @@ function diffManifestPaths(remote, local) {
|
|
|
664
668
|
(local?.documents ?? []).map((doc) => [doc.path, doc.contentHash])
|
|
665
669
|
);
|
|
666
670
|
const download = [];
|
|
667
|
-
for (const [
|
|
668
|
-
if (localMap.get(
|
|
669
|
-
download.push(
|
|
671
|
+
for (const [path13, hash] of remoteMap) {
|
|
672
|
+
if (localMap.get(path13) !== hash) {
|
|
673
|
+
download.push(path13);
|
|
670
674
|
}
|
|
671
675
|
}
|
|
672
676
|
const deleteLocal = [];
|
|
673
|
-
for (const
|
|
674
|
-
if (!remoteMap.has(
|
|
675
|
-
deleteLocal.push(
|
|
677
|
+
for (const path13 of localMap.keys()) {
|
|
678
|
+
if (!remoteMap.has(path13)) {
|
|
679
|
+
deleteLocal.push(path13);
|
|
676
680
|
}
|
|
677
681
|
}
|
|
678
682
|
return { download, deleteLocal };
|
|
@@ -732,8 +736,8 @@ ${diagnostic ?? ""}`
|
|
|
732
736
|
}
|
|
733
737
|
}
|
|
734
738
|
let deleted = 0;
|
|
735
|
-
for (const
|
|
736
|
-
const absPath = toFsPath(projectDocumentLocalPath(targetApmDir,
|
|
739
|
+
for (const path13 of deleteLocal) {
|
|
740
|
+
const absPath = toFsPath(projectDocumentLocalPath(targetApmDir, path13));
|
|
737
741
|
if (existsSync2(absPath)) {
|
|
738
742
|
rmSync(absPath, { force: true });
|
|
739
743
|
deleted += 1;
|
|
@@ -778,21 +782,21 @@ async function syncRepositoryProjectDocumentsPush(cfg, workdirPath, apmRoot) {
|
|
|
778
782
|
])
|
|
779
783
|
);
|
|
780
784
|
let synced = 0;
|
|
781
|
-
for (const
|
|
782
|
-
const absPath = toFsPath(projectDocumentLocalPath(targetApmDir,
|
|
785
|
+
for (const path13 of localPaths) {
|
|
786
|
+
const absPath = toFsPath(projectDocumentLocalPath(targetApmDir, path13));
|
|
783
787
|
const content = readFileSync3(absPath, "utf8");
|
|
784
788
|
const contentHash = hashLocalFileContent(content);
|
|
785
|
-
if (remoteHashByPath.get(
|
|
789
|
+
if (remoteHashByPath.get(path13) === contentHash) {
|
|
786
790
|
continue;
|
|
787
791
|
}
|
|
788
792
|
await api.cli.upsertRepositoryProjectDocument({
|
|
789
793
|
repositoryId,
|
|
790
|
-
path:
|
|
794
|
+
path: path13,
|
|
791
795
|
content,
|
|
792
|
-
description: remoteDescriptionByPath.get(
|
|
796
|
+
description: remoteDescriptionByPath.get(path13) ?? void 0
|
|
793
797
|
});
|
|
794
798
|
synced += 1;
|
|
795
|
-
console.log(`[apm] \u5DF2\u540C\u6B65\u4ED3\u5E93\u9879\u76EE\u6587\u6863: ${
|
|
799
|
+
console.log(`[apm] \u5DF2\u540C\u6B65\u4ED3\u5E93\u9879\u76EE\u6587\u6863: ${path13}`);
|
|
796
800
|
}
|
|
797
801
|
if (synced === 0) {
|
|
798
802
|
console.log("[apm] \u4ED3\u5E93\u9879\u76EE\u6587\u6863\u65E0\u53D8\u5316\uFF0C\u8DF3\u8FC7\u63A8\u9001");
|
|
@@ -1415,13 +1419,13 @@ async function downloadAttachment(cfg, attachmentId) {
|
|
|
1415
1419
|
return Buffer.from(await res.arrayBuffer());
|
|
1416
1420
|
}
|
|
1417
1421
|
function loadManifest(dir) {
|
|
1418
|
-
const
|
|
1419
|
-
if (!existsSync4(
|
|
1422
|
+
const path13 = join6(dir, MANIFEST_FILE2);
|
|
1423
|
+
if (!existsSync4(path13)) {
|
|
1420
1424
|
return { version: 1, attachments: {} };
|
|
1421
1425
|
}
|
|
1422
1426
|
try {
|
|
1423
1427
|
const parsed = JSON.parse(
|
|
1424
|
-
readFileSync5(
|
|
1428
|
+
readFileSync5(path13, "utf8")
|
|
1425
1429
|
);
|
|
1426
1430
|
if (parsed?.version === 1 && parsed.attachments && typeof parsed.attachments === "object") {
|
|
1427
1431
|
return parsed;
|
|
@@ -1502,8 +1506,8 @@ function sanitizeSkillDirName(name) {
|
|
|
1502
1506
|
function listBaseSkillDirNames() {
|
|
1503
1507
|
if (!existsSync5(BASE_SKILLS_TEMPLATE_DIR)) return [];
|
|
1504
1508
|
return readdirSync3(BASE_SKILLS_TEMPLATE_DIR).filter((name) => {
|
|
1505
|
-
const
|
|
1506
|
-
return statSync2(
|
|
1509
|
+
const path13 = join7(BASE_SKILLS_TEMPLATE_DIR, name);
|
|
1510
|
+
return statSync2(path13).isDirectory();
|
|
1507
1511
|
});
|
|
1508
1512
|
}
|
|
1509
1513
|
function syncAgentsGuide(apmDir) {
|
|
@@ -1515,8 +1519,8 @@ function syncAgentsGuide(apmDir) {
|
|
|
1515
1519
|
function listBaseRuleFileNames() {
|
|
1516
1520
|
if (!existsSync5(BASE_RULES_TEMPLATE_DIR)) return [];
|
|
1517
1521
|
return readdirSync3(BASE_RULES_TEMPLATE_DIR).filter((name) => {
|
|
1518
|
-
const
|
|
1519
|
-
return statSync2(
|
|
1522
|
+
const path13 = join7(BASE_RULES_TEMPLATE_DIR, name);
|
|
1523
|
+
return statSync2(path13).isFile();
|
|
1520
1524
|
});
|
|
1521
1525
|
}
|
|
1522
1526
|
function syncBaseRules(rulesDir) {
|
|
@@ -1579,13 +1583,13 @@ function ruleLocalFileName(ruleName) {
|
|
|
1579
1583
|
return `${sanitized}.md`;
|
|
1580
1584
|
}
|
|
1581
1585
|
function loadManifest2(rulesDir) {
|
|
1582
|
-
const
|
|
1583
|
-
if (!existsSync6(toFsPath(
|
|
1586
|
+
const path13 = join8(rulesDir, MANIFEST_FILE3);
|
|
1587
|
+
if (!existsSync6(toFsPath(path13))) {
|
|
1584
1588
|
return { version: 1, rules: {} };
|
|
1585
1589
|
}
|
|
1586
1590
|
try {
|
|
1587
1591
|
const parsed = JSON.parse(
|
|
1588
|
-
readFileSync6(toFsPath(
|
|
1592
|
+
readFileSync6(toFsPath(path13), "utf8")
|
|
1589
1593
|
);
|
|
1590
1594
|
if (parsed?.version === 1 && parsed.rules && typeof parsed.rules === "object") {
|
|
1591
1595
|
return parsed;
|
|
@@ -2684,12 +2688,12 @@ import { dirname as dirname4, resolve as resolve3 } from "node:path";
|
|
|
2684
2688
|
function registryPath(workdir, sessionId) {
|
|
2685
2689
|
return resolve3(workdir, ".apm", "sessions", sessionId, "cursor-agents.json");
|
|
2686
2690
|
}
|
|
2687
|
-
function readRegistry(
|
|
2688
|
-
if (!existsSync11(
|
|
2691
|
+
function readRegistry(path13) {
|
|
2692
|
+
if (!existsSync11(path13)) {
|
|
2689
2693
|
return {};
|
|
2690
2694
|
}
|
|
2691
2695
|
try {
|
|
2692
|
-
const parsed = JSON.parse(readFileSync9(
|
|
2696
|
+
const parsed = JSON.parse(readFileSync9(path13, "utf8"));
|
|
2693
2697
|
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
2694
2698
|
const result = {};
|
|
2695
2699
|
for (const [key, value] of Object.entries(
|
|
@@ -2705,9 +2709,9 @@ function readRegistry(path12) {
|
|
|
2705
2709
|
}
|
|
2706
2710
|
return {};
|
|
2707
2711
|
}
|
|
2708
|
-
function writeRegistry(
|
|
2709
|
-
mkdirSync5(dirname4(
|
|
2710
|
-
writeFileSync10(
|
|
2712
|
+
function writeRegistry(path13, registry) {
|
|
2713
|
+
mkdirSync5(dirname4(path13), { recursive: true });
|
|
2714
|
+
writeFileSync10(path13, `${JSON.stringify(registry, null, 2)}
|
|
2711
2715
|
`, "utf8");
|
|
2712
2716
|
}
|
|
2713
2717
|
function loadSessionAgentId(workdir, sessionId, user) {
|
|
@@ -2715,19 +2719,19 @@ function loadSessionAgentId(workdir, sessionId, user) {
|
|
|
2715
2719
|
return registry[user];
|
|
2716
2720
|
}
|
|
2717
2721
|
function saveSessionAgentId(workdir, sessionId, user, agentId) {
|
|
2718
|
-
const
|
|
2719
|
-
const registry = readRegistry(
|
|
2722
|
+
const path13 = registryPath(workdir, sessionId);
|
|
2723
|
+
const registry = readRegistry(path13);
|
|
2720
2724
|
registry[user] = agentId;
|
|
2721
|
-
writeRegistry(
|
|
2725
|
+
writeRegistry(path13, registry);
|
|
2722
2726
|
}
|
|
2723
2727
|
function clearSessionAgentId(workdir, sessionId, user) {
|
|
2724
|
-
const
|
|
2725
|
-
const registry = readRegistry(
|
|
2728
|
+
const path13 = registryPath(workdir, sessionId);
|
|
2729
|
+
const registry = readRegistry(path13);
|
|
2726
2730
|
if (!(user in registry)) {
|
|
2727
2731
|
return;
|
|
2728
2732
|
}
|
|
2729
2733
|
delete registry[user];
|
|
2730
|
-
writeRegistry(
|
|
2734
|
+
writeRegistry(path13, registry);
|
|
2731
2735
|
}
|
|
2732
2736
|
|
|
2733
2737
|
// src/commands/connect/cursor-message-log.ts
|
|
@@ -3164,13 +3168,13 @@ function manifestPath(apmDir) {
|
|
|
3164
3168
|
return join13(apmDir, CLI_VERSION_FILE);
|
|
3165
3169
|
}
|
|
3166
3170
|
function loadManifest3(apmDir) {
|
|
3167
|
-
const
|
|
3168
|
-
if (!existsSync12(
|
|
3171
|
+
const path13 = toFsPath(manifestPath(apmDir));
|
|
3172
|
+
if (!existsSync12(path13)) {
|
|
3169
3173
|
return null;
|
|
3170
3174
|
}
|
|
3171
3175
|
try {
|
|
3172
3176
|
const parsed = JSON.parse(
|
|
3173
|
-
readFileSync10(
|
|
3177
|
+
readFileSync10(path13, "utf8")
|
|
3174
3178
|
);
|
|
3175
3179
|
if (parsed?.version === 1 && typeof parsed.cliVersion === "string" && parsed.cliVersion.trim()) {
|
|
3176
3180
|
return parsed;
|
|
@@ -3935,6 +3939,99 @@ async function runConnect(options) {
|
|
|
3935
3939
|
});
|
|
3936
3940
|
}
|
|
3937
3941
|
|
|
3942
|
+
// src/commands/create-pr-errors.ts
|
|
3943
|
+
import { ApiError as ApiError2 } from "listpage-http";
|
|
3944
|
+
function extractMessage(error) {
|
|
3945
|
+
if (error instanceof ApiError2) {
|
|
3946
|
+
return String(error.message ?? "").trim();
|
|
3947
|
+
}
|
|
3948
|
+
if (error instanceof Error) {
|
|
3949
|
+
return error.message.trim();
|
|
3950
|
+
}
|
|
3951
|
+
return String(error).trim();
|
|
3952
|
+
}
|
|
3953
|
+
function extractHttpStatus(error) {
|
|
3954
|
+
if (error instanceof ApiError2) {
|
|
3955
|
+
return error.httpStatus;
|
|
3956
|
+
}
|
|
3957
|
+
return void 0;
|
|
3958
|
+
}
|
|
3959
|
+
function buildHints(message, httpStatus) {
|
|
3960
|
+
const hints = [];
|
|
3961
|
+
if (/未配置.*Gitee.*API Key/i.test(message)) {
|
|
3962
|
+
hints.push(
|
|
3963
|
+
"\u8BF7\u5728 APM Web \u2192 \u5BA2\u6237\u673A\u7BA1\u7406 \u2192 \u7F16\u8F91\u5F53\u524D\u5BA2\u6237\u673A \u2192 \u586B\u5199\u300CGitee API Key\u300D\uFF08Gitee \u79C1\u4EBA\u4EE4\u724C\uFF0C\u9700\u6709\u4ED3\u5E93 PR \u6743\u9650\uFF09"
|
|
3964
|
+
);
|
|
3965
|
+
} else if (/未配置.*GitHub.*API Key/i.test(message)) {
|
|
3966
|
+
hints.push(
|
|
3967
|
+
"\u8BF7\u5728 APM Web \u2192 \u5BA2\u6237\u673A\u7BA1\u7406 \u2192 \u7F16\u8F91\u5F53\u524D\u5BA2\u6237\u673A \u2192 \u586B\u5199\u300CGithub API Key\u300D\uFF08GitHub Personal Access Token\uFF0C\u9700\u6709 repo \u6743\u9650\uFF09"
|
|
3968
|
+
);
|
|
3969
|
+
} else if (httpStatus === 401 || /access token does not exist/i.test(message) || /bad credentials/i.test(message) || /Git 平台返回 401|认证失败 \(401\)/i.test(message)) {
|
|
3970
|
+
hints.push(
|
|
3971
|
+
"Git \u5E73\u53F0 Token \u65E0\u6548\u6216\u5DF2\u8FC7\u671F\uFF1A\u8BF7\u5728 Gitee/GitHub \u91CD\u65B0\u751F\u6210\u79C1\u4EBA\u4EE4\u724C\uFF0C\u5E76\u66F4\u65B0\u5230 APM\u300C\u5BA2\u6237\u673A\u7BA1\u7406\u300D"
|
|
3972
|
+
);
|
|
3973
|
+
}
|
|
3974
|
+
if (/未绑定仓库|未关联仓库|选择关联仓库/i.test(message)) {
|
|
3975
|
+
hints.push("\u5728 APM Web \u2192 \u5DE5\u4F5C\u76EE\u5F55 \u2192 \u4E3A\u5F53\u524D\u8DEF\u5F84\u5173\u8054\u5BF9\u5E94 Git \u4ED3\u5E93");
|
|
3976
|
+
}
|
|
3977
|
+
if (/路径.*不匹配|尚未登记任何工作目录/i.test(message)) {
|
|
3978
|
+
hints.push(
|
|
3979
|
+
"\u5728 APM Web \u2192 \u5DE5\u4F5C\u76EE\u5F55 \u2192 \u767B\u8BB0\u5F53\u524D\u9879\u76EE\u8DEF\u5F84\uFF08\u9700\u4E0E apm create-pr \u6267\u884C\u65F6\u7684 cwd \u4E00\u81F4\uFF09"
|
|
3980
|
+
);
|
|
3981
|
+
}
|
|
3982
|
+
if (/no commits between|分支不存在|branch.*not found|找不到.*分支/i.test(
|
|
3983
|
+
message
|
|
3984
|
+
)) {
|
|
3985
|
+
hints.push(
|
|
3986
|
+
"\u7279\u6027\u5206\u652F\u53EF\u80FD\u672A\u63A8\u9001\uFF1A\u5148\u6267\u884C apm branch <sessionId> \u521B\u5EFA\u5206\u652F\u5E76 push\uFF0C\u518D\u91CD\u8BD5 create-pr"
|
|
3987
|
+
);
|
|
3988
|
+
}
|
|
3989
|
+
if (/pull request already exists|已存在.*pull/i.test(message)) {
|
|
3990
|
+
hints.push("\u8BE5\u5206\u652F\u53EF\u80FD\u5DF2\u6709\u5F00\u542F\u7684 PR\uFF0C\u8BF7\u5230 Git \u5E73\u53F0\u6216 APM \u4F1A\u8BDD\u8BE6\u60C5\u67E5\u770B");
|
|
3991
|
+
}
|
|
3992
|
+
if (/403|无权限|forbidden/i.test(message)) {
|
|
3993
|
+
hints.push("\u786E\u8BA4 Token \u5BF9\u76EE\u6807\u4ED3\u5E93\u6709\u521B\u5EFA Pull Request \u7684\u6743\u9650");
|
|
3994
|
+
}
|
|
3995
|
+
if (hints.length === 0) {
|
|
3996
|
+
hints.push(
|
|
3997
|
+
"\u82E5\u65E0\u6CD5\u81EA\u884C\u6392\u67E5\uFF0C\u8BF7\u5728\u4F1A\u8BDD\u4E2D @\u9879\u76EE\u7ECF\u7406\uFF0C\u5E76\u63D0\u4F9B\u4E0A\u8FF0\u4F1A\u8BDD ID \u4E0E\u5DE5\u4F5C\u76EE\u5F55"
|
|
3998
|
+
);
|
|
3999
|
+
}
|
|
4000
|
+
return hints;
|
|
4001
|
+
}
|
|
4002
|
+
function formatCreatePrErrorLines(error, context) {
|
|
4003
|
+
const message = extractMessage(error);
|
|
4004
|
+
const httpStatus = extractHttpStatus(error);
|
|
4005
|
+
const headBranch = `feat/session-${context.sessionId}`;
|
|
4006
|
+
const lines = [
|
|
4007
|
+
"[apm] \u521B\u5EFA PR \u5931\u8D25",
|
|
4008
|
+
"",
|
|
4009
|
+
`\u4F1A\u8BDD ID: ${context.sessionId}`,
|
|
4010
|
+
`\u5DE5\u4F5C\u76EE\u5F55: ${context.workdir}`,
|
|
4011
|
+
`\u7279\u6027\u5206\u652F: ${headBranch}`
|
|
4012
|
+
];
|
|
4013
|
+
if (context.clientMachineId) {
|
|
4014
|
+
lines.push(`\u5BA2\u6237\u673A ID: ${context.clientMachineId}`);
|
|
4015
|
+
}
|
|
4016
|
+
lines.push("", "\u539F\u56E0:", message || "(\u672A\u77E5\u9519\u8BEF)");
|
|
4017
|
+
const hints = buildHints(message, httpStatus);
|
|
4018
|
+
if (hints.length > 0) {
|
|
4019
|
+
lines.push("", "\u5EFA\u8BAE:");
|
|
4020
|
+
hints.forEach((hint, index) => {
|
|
4021
|
+
lines.push(`${index + 1}. ${hint}`);
|
|
4022
|
+
});
|
|
4023
|
+
}
|
|
4024
|
+
if (httpStatus !== void 0) {
|
|
4025
|
+
lines.push("", `HTTP \u72B6\u6001: ${httpStatus}`);
|
|
4026
|
+
}
|
|
4027
|
+
return lines;
|
|
4028
|
+
}
|
|
4029
|
+
function printCreatePrError(error, context) {
|
|
4030
|
+
for (const line of formatCreatePrErrorLines(error, context)) {
|
|
4031
|
+
console.error(line);
|
|
4032
|
+
}
|
|
4033
|
+
}
|
|
4034
|
+
|
|
3938
4035
|
// src/commands/create-pr.ts
|
|
3939
4036
|
async function runCreatePr(options) {
|
|
3940
4037
|
const sessionId = options.sessionId.trim();
|
|
@@ -3950,17 +4047,27 @@ async function runCreatePr(options) {
|
|
|
3950
4047
|
const cfg = await ensureLoggedConfig();
|
|
3951
4048
|
const api = createApmApiClient(cfg);
|
|
3952
4049
|
const workdir = resolveWorkdirPath(options.cwd ?? process.cwd());
|
|
3953
|
-
|
|
3954
|
-
|
|
3955
|
-
|
|
3956
|
-
|
|
3957
|
-
|
|
3958
|
-
|
|
3959
|
-
|
|
4050
|
+
try {
|
|
4051
|
+
const pr = await api.cli.createPullRequest({
|
|
4052
|
+
sessionId,
|
|
4053
|
+
workdir,
|
|
4054
|
+
title,
|
|
4055
|
+
content: options.content ?? ""
|
|
4056
|
+
});
|
|
4057
|
+
console.log(`[apm] PR \u5DF2\u5C31\u7EEA #${pr.number} (${pr.state}): ${pr.url}`);
|
|
4058
|
+
} catch (error) {
|
|
4059
|
+
printCreatePrError(error, {
|
|
4060
|
+
sessionId,
|
|
4061
|
+
workdir,
|
|
4062
|
+
clientMachineId: resolveClientMachineId(cfg)
|
|
4063
|
+
});
|
|
4064
|
+
process.exit(1);
|
|
4065
|
+
}
|
|
3960
4066
|
}
|
|
3961
4067
|
|
|
3962
|
-
// src/commands/deploy/deploy.ts
|
|
4068
|
+
// src/commands/deploy/deploy-execute.ts
|
|
3963
4069
|
import { spawnSync as spawnSync5 } from "node:child_process";
|
|
4070
|
+
import path4 from "node:path";
|
|
3964
4071
|
|
|
3965
4072
|
// src/commands/deploy/internal/apm-config.ts
|
|
3966
4073
|
import { existsSync as existsSync15, readFileSync as readFileSync12 } from "node:fs";
|
|
@@ -4152,9 +4259,9 @@ function readMavenLocalRepoFromEnv(env = process.env) {
|
|
|
4152
4259
|
}
|
|
4153
4260
|
const mavenOpts = readEnvVar(env, "MAVEN_OPTS")?.trim();
|
|
4154
4261
|
if (mavenOpts) {
|
|
4155
|
-
const
|
|
4156
|
-
if (
|
|
4157
|
-
return { path:
|
|
4262
|
+
const path13 = readMavenLocalRepoFromMavenOpts(mavenOpts, env);
|
|
4263
|
+
if (path13) {
|
|
4264
|
+
return { path: path13, key: "MAVEN_OPTS" };
|
|
4158
4265
|
}
|
|
4159
4266
|
}
|
|
4160
4267
|
return null;
|
|
@@ -4287,19 +4394,18 @@ function formatWisdomFrontendDeployNotConfiguredLines(env, packageJsonPath) {
|
|
|
4287
4394
|
"[apm] \u82E5\u672C\u9879\u76EE\u4E0D\u652F\u6301\u81EA\u52A8\u5316\u90E8\u7F72\uFF0C\u5C5E\u6B63\u5E38\u60C5\u51B5\uFF0C\u53EF\u8DF3\u8FC7\u90E8\u7F72"
|
|
4288
4395
|
];
|
|
4289
4396
|
}
|
|
4290
|
-
|
|
4291
|
-
|
|
4292
|
-
|
|
4293
|
-
|
|
4294
|
-
|
|
4295
|
-
|
|
4296
|
-
|
|
4297
|
-
|
|
4298
|
-
|
|
4299
|
-
|
|
4300
|
-
console.error(line);
|
|
4397
|
+
|
|
4398
|
+
// src/commands/deploy/deploy-errors.ts
|
|
4399
|
+
var DeployExecutionError = class extends Error {
|
|
4400
|
+
exitCode;
|
|
4401
|
+
output;
|
|
4402
|
+
constructor(message, exitCode, output = "") {
|
|
4403
|
+
super(message);
|
|
4404
|
+
this.name = "DeployExecutionError";
|
|
4405
|
+
this.exitCode = exitCode;
|
|
4406
|
+
this.output = output;
|
|
4301
4407
|
}
|
|
4302
|
-
}
|
|
4408
|
+
};
|
|
4303
4409
|
|
|
4304
4410
|
// src/commands/deploy/internal/wisdom-auto-deploy.ts
|
|
4305
4411
|
import { existsSync as existsSync17, readFileSync as readFileSync14 } from "node:fs";
|
|
@@ -5105,19 +5211,33 @@ function resolveFrontendDeployCommand(env, cwd) {
|
|
|
5105
5211
|
}
|
|
5106
5212
|
return null;
|
|
5107
5213
|
}
|
|
5108
|
-
function runShellCommand2(command, cwd) {
|
|
5214
|
+
function runShellCommand2(command, cwd, captureOutput) {
|
|
5109
5215
|
const result = spawnSync4(command, {
|
|
5110
5216
|
cwd,
|
|
5111
|
-
stdio: "inherit",
|
|
5112
5217
|
shell: true,
|
|
5113
|
-
env: process.env
|
|
5218
|
+
env: process.env,
|
|
5219
|
+
encoding: "utf8",
|
|
5220
|
+
stdio: captureOutput ? ["inherit", "pipe", "pipe"] : "inherit"
|
|
5114
5221
|
});
|
|
5222
|
+
const stdout = captureOutput ? String(result.stdout ?? "") : "";
|
|
5223
|
+
const stderr = captureOutput ? String(result.stderr ?? "") : "";
|
|
5224
|
+
const output = [stdout, stderr].filter(Boolean).join("\n");
|
|
5225
|
+
if (captureOutput) {
|
|
5226
|
+
if (stdout) process.stdout.write(stdout);
|
|
5227
|
+
if (stderr) process.stderr.write(stderr);
|
|
5228
|
+
}
|
|
5115
5229
|
if (result.status !== 0) {
|
|
5116
|
-
|
|
5230
|
+
throw new DeployExecutionError(
|
|
5231
|
+
`\u90E8\u7F72\u547D\u4EE4\u9000\u51FA\u7801 ${result.status ?? "unknown"}: ${command}`,
|
|
5232
|
+
result.status ?? 1,
|
|
5233
|
+
output
|
|
5234
|
+
);
|
|
5117
5235
|
}
|
|
5236
|
+
return output;
|
|
5118
5237
|
}
|
|
5119
5238
|
async function runWisdomAutoDeploy(options) {
|
|
5120
5239
|
const cwd = path3.resolve(options.cwd ?? process.cwd());
|
|
5240
|
+
const captureOutput = options.captureOutput ?? false;
|
|
5121
5241
|
const projectType = detectWisdomProjectType(cwd);
|
|
5122
5242
|
console.error(
|
|
5123
5243
|
`[apm] \u533B\u52A1\u5B58\u91CF\u9879\u76EE\u81EA\u52A8\u8BC6\u522B: ${projectType === "frontend" ? "\u524D\u7AEF Vue" : "\u540E\u7AEF Java"}`
|
|
@@ -5125,13 +5245,13 @@ async function runWisdomAutoDeploy(options) {
|
|
|
5125
5245
|
if (projectType === "frontend") {
|
|
5126
5246
|
const deployCmd = resolveFrontendDeployCommand(options.env, cwd);
|
|
5127
5247
|
if (!deployCmd) {
|
|
5128
|
-
|
|
5248
|
+
const lines = formatWisdomFrontendDeployNotConfiguredLines(
|
|
5129
5249
|
options.env,
|
|
5130
5250
|
path3.join(cwd, "package.json")
|
|
5131
5251
|
);
|
|
5132
|
-
|
|
5252
|
+
throw new DeployExecutionError(lines.join("\n"), 1, lines.join("\n"));
|
|
5133
5253
|
}
|
|
5134
|
-
runShellCommand2(deployCmd, cwd);
|
|
5254
|
+
runShellCommand2(deployCmd, cwd, captureOutput);
|
|
5135
5255
|
return { projectType };
|
|
5136
5256
|
}
|
|
5137
5257
|
const configPath = options.configPath ?? path3.join(workspaceApmDir(cwd), "apm.config.json");
|
|
@@ -5147,63 +5267,229 @@ async function runWisdomAutoDeploy(options) {
|
|
|
5147
5267
|
return { projectType };
|
|
5148
5268
|
}
|
|
5149
5269
|
|
|
5150
|
-
// src/commands/deploy/deploy.ts
|
|
5151
|
-
function runShellCommand3(command, cwd) {
|
|
5270
|
+
// src/commands/deploy/deploy-execute.ts
|
|
5271
|
+
function runShellCommand3(command, cwd, captureOutput) {
|
|
5152
5272
|
const result = spawnSync5(command, {
|
|
5153
5273
|
cwd,
|
|
5154
|
-
stdio: "inherit",
|
|
5155
5274
|
shell: true,
|
|
5156
|
-
env: process.env
|
|
5275
|
+
env: process.env,
|
|
5276
|
+
encoding: "utf8",
|
|
5277
|
+
stdio: captureOutput ? ["inherit", "pipe", "pipe"] : "inherit"
|
|
5157
5278
|
});
|
|
5279
|
+
const stdout = captureOutput ? String(result.stdout ?? "") : "";
|
|
5280
|
+
const stderr = captureOutput ? String(result.stderr ?? "") : "";
|
|
5281
|
+
const output = [stdout, stderr].filter(Boolean).join("\n");
|
|
5282
|
+
if (captureOutput) {
|
|
5283
|
+
if (stdout) process.stdout.write(stdout);
|
|
5284
|
+
if (stderr) process.stderr.write(stderr);
|
|
5285
|
+
}
|
|
5158
5286
|
if (result.status !== 0) {
|
|
5159
|
-
|
|
5287
|
+
throw new DeployExecutionError(
|
|
5288
|
+
`\u90E8\u7F72\u547D\u4EE4\u9000\u51FA\u7801 ${result.status ?? "unknown"}: ${command}`,
|
|
5289
|
+
result.status ?? 1,
|
|
5290
|
+
output
|
|
5291
|
+
);
|
|
5292
|
+
}
|
|
5293
|
+
return output;
|
|
5294
|
+
}
|
|
5295
|
+
async function executeDeploy(options) {
|
|
5296
|
+
const cwd = path4.resolve(options.cwd ?? process.cwd());
|
|
5297
|
+
const captureOutput = options.captureOutput ?? false;
|
|
5298
|
+
const cfg = loadApmConfig({ configPath: options.configPath });
|
|
5299
|
+
if (isWisdomLegacyDeploy(cfg)) {
|
|
5300
|
+
try {
|
|
5301
|
+
await runWisdomAutoDeploy({
|
|
5302
|
+
env: options.env,
|
|
5303
|
+
cwd,
|
|
5304
|
+
configPath: options.configPath,
|
|
5305
|
+
captureOutput
|
|
5306
|
+
});
|
|
5307
|
+
return "";
|
|
5308
|
+
} catch (error) {
|
|
5309
|
+
if (error instanceof DeployExecutionError) {
|
|
5310
|
+
throw error;
|
|
5311
|
+
}
|
|
5312
|
+
const detail = error instanceof Error ? error.message : String(error);
|
|
5313
|
+
throw new DeployExecutionError(detail, 1);
|
|
5314
|
+
}
|
|
5315
|
+
}
|
|
5316
|
+
const deployCommands = cfg.deploy ?? {};
|
|
5317
|
+
const command = deployCommands[options.env]?.trim();
|
|
5318
|
+
if (!command) {
|
|
5319
|
+
const lines = formatDeployNotConfiguredLines(options.env, deployCommands);
|
|
5320
|
+
throw new DeployExecutionError(lines.join("\n"), 1, lines.join("\n"));
|
|
5321
|
+
}
|
|
5322
|
+
return runShellCommand3(command, cwd, captureOutput);
|
|
5323
|
+
}
|
|
5324
|
+
function printDeployExecutionError(error) {
|
|
5325
|
+
if (error.output.trim()) {
|
|
5326
|
+
console.error(error.output);
|
|
5327
|
+
return;
|
|
5328
|
+
}
|
|
5329
|
+
console.error(error.message);
|
|
5330
|
+
}
|
|
5331
|
+
|
|
5332
|
+
// src/commands/deploy/deploy-tracking.ts
|
|
5333
|
+
function normalizeDeployEnvironment(env) {
|
|
5334
|
+
const normalized = env.trim().toLowerCase();
|
|
5335
|
+
if (normalized === "test") return "TEST";
|
|
5336
|
+
if (normalized === "online") return "ONLINE";
|
|
5337
|
+
return null;
|
|
5338
|
+
}
|
|
5339
|
+
async function completeTrackedDeploy(api, deploymentRunId, logSyncer, input) {
|
|
5340
|
+
logSyncer.updateLog(input.log);
|
|
5341
|
+
await logSyncer.flush();
|
|
5342
|
+
await api.cli.completeTaskDeployment({
|
|
5343
|
+
id: deploymentRunId,
|
|
5344
|
+
status: input.status,
|
|
5345
|
+
log: input.log,
|
|
5346
|
+
error: input.error
|
|
5347
|
+
});
|
|
5348
|
+
}
|
|
5349
|
+
async function runDeployWithBackendTracking(options) {
|
|
5350
|
+
const cfg = await tryReadApmConfig();
|
|
5351
|
+
if (!cfg || !resolveApiKey(cfg)) {
|
|
5352
|
+
console.warn("[apm] \u672A\u767B\u5F55\uFF0C\u8DF3\u8FC7\u540E\u7AEF\u90E8\u7F72\u8BB0\u5F55");
|
|
5353
|
+
await executeDeploy(options);
|
|
5354
|
+
return;
|
|
5355
|
+
}
|
|
5356
|
+
const environment = normalizeDeployEnvironment(options.env);
|
|
5357
|
+
if (!environment) {
|
|
5358
|
+
console.warn(
|
|
5359
|
+
`[apm] \u672A\u77E5\u90E8\u7F72\u73AF\u5883 ${options.env}\uFF0C\u8DF3\u8FC7\u540E\u7AEF\u90E8\u7F72\u8BB0\u5F55\uFF08\u4EC5\u652F\u6301 test/online\uFF09`
|
|
5360
|
+
);
|
|
5361
|
+
await executeDeploy(options);
|
|
5362
|
+
return;
|
|
5363
|
+
}
|
|
5364
|
+
const api = createApmApiClient(cfg);
|
|
5365
|
+
let deploymentRunId;
|
|
5366
|
+
try {
|
|
5367
|
+
const run = await api.cli.createTaskDeployment({
|
|
5368
|
+
sessionId: options.sessionId,
|
|
5369
|
+
environment,
|
|
5370
|
+
workdirPath: options.cwd ?? process.cwd()
|
|
5371
|
+
});
|
|
5372
|
+
deploymentRunId = run.id;
|
|
5373
|
+
console.log(
|
|
5374
|
+
`[apm] \u5DF2\u521B\u5EFA\u90E8\u7F72\u8BB0\u5F55 id=${deploymentRunId} env=${environment}`
|
|
5375
|
+
);
|
|
5376
|
+
} catch (error) {
|
|
5377
|
+
const detail = error instanceof Error ? error.message : String(error);
|
|
5378
|
+
console.warn(`[apm] \u521B\u5EFA\u90E8\u7F72\u8BB0\u5F55\u5931\u8D25\uFF0C\u7EE7\u7EED\u90E8\u7F72: ${detail}`);
|
|
5379
|
+
await executeDeploy(options);
|
|
5380
|
+
return;
|
|
5381
|
+
}
|
|
5382
|
+
await api.cli.updateTaskDeploymentStatus({
|
|
5383
|
+
id: deploymentRunId,
|
|
5384
|
+
status: "DEPLOYING"
|
|
5385
|
+
});
|
|
5386
|
+
const logSyncer = createDeployLogSyncer(api, deploymentRunId);
|
|
5387
|
+
const chunks = [];
|
|
5388
|
+
const appendLog = (line) => {
|
|
5389
|
+
if (!line) return;
|
|
5390
|
+
chunks.push(line);
|
|
5391
|
+
logSyncer.updateLog(chunks.join("\n"));
|
|
5392
|
+
};
|
|
5393
|
+
const originalLog = console.log;
|
|
5394
|
+
const originalError = console.error;
|
|
5395
|
+
console.log = (...args) => {
|
|
5396
|
+
appendLog(args.map(String).join(" "));
|
|
5397
|
+
originalLog.apply(console, args);
|
|
5398
|
+
};
|
|
5399
|
+
console.error = (...args) => {
|
|
5400
|
+
appendLog(args.map(String).join(" "));
|
|
5401
|
+
originalError.apply(console, args);
|
|
5402
|
+
};
|
|
5403
|
+
try {
|
|
5404
|
+
const output = await executeDeploy({ ...options, captureOutput: true });
|
|
5405
|
+
if (output.trim()) {
|
|
5406
|
+
appendLog(output);
|
|
5407
|
+
}
|
|
5408
|
+
const log2 = chunks.join("\n");
|
|
5409
|
+
await completeTrackedDeploy(api, deploymentRunId, logSyncer, {
|
|
5410
|
+
status: "SUCCESS",
|
|
5411
|
+
log: log2
|
|
5412
|
+
});
|
|
5413
|
+
console.log(`[apm] deploy success id=${deploymentRunId}`);
|
|
5414
|
+
} catch (error) {
|
|
5415
|
+
const deployError = error instanceof DeployExecutionError ? error : new DeployExecutionError(
|
|
5416
|
+
error instanceof Error ? error.message : String(error),
|
|
5417
|
+
1
|
|
5418
|
+
);
|
|
5419
|
+
if (deployError.output.trim()) {
|
|
5420
|
+
appendLog(deployError.output);
|
|
5421
|
+
} else {
|
|
5422
|
+
appendLog(deployError.message);
|
|
5423
|
+
}
|
|
5424
|
+
const log2 = chunks.join("\n");
|
|
5425
|
+
await completeTrackedDeploy(api, deploymentRunId, logSyncer, {
|
|
5426
|
+
status: "FAILED",
|
|
5427
|
+
log: log2,
|
|
5428
|
+
error: deployError.message
|
|
5429
|
+
});
|
|
5430
|
+
printDeployExecutionError(deployError);
|
|
5431
|
+
process.exit(deployError.exitCode);
|
|
5432
|
+
} finally {
|
|
5433
|
+
console.log = originalLog;
|
|
5434
|
+
console.error = originalError;
|
|
5435
|
+
logSyncer.dispose();
|
|
5160
5436
|
}
|
|
5161
5437
|
}
|
|
5438
|
+
|
|
5439
|
+
// src/commands/deploy/deploy.ts
|
|
5162
5440
|
function registerDeployMainCommand(program) {
|
|
5163
5441
|
program.command("deploy").description(
|
|
5164
5442
|
"\u7EDF\u4E00\u90E8\u7F72\uFF1A\u533B\u52A1\u5B58\u91CF\u81EA\u52A8\u8BC6\u522B\u524D\u540E\u7AEF\uFF08\u524D\u7AEF\u6309 deploy:<env> \u811A\u672C\uFF1B\u540E\u7AEF test/online \u540C\u4E00\u5957\uFF09\uFF1B\u5176\u4ED6\u9879\u76EE\u6309 deploy.<\u73AF\u5883> \u6267\u884C shell \u547D\u4EE4"
|
|
5165
5443
|
).argument("<env>", "\u90E8\u7F72\u73AF\u5883\u540D\uFF08\u5982 test\u3001online\uFF09").option(
|
|
5166
5444
|
"--config <path>",
|
|
5167
5445
|
"apm.config.json \u8DEF\u5F84\uFF08\u9ED8\u8BA4 .apm/apm.config.json\uFF09"
|
|
5168
|
-
).
|
|
5169
|
-
|
|
5170
|
-
|
|
5171
|
-
|
|
5172
|
-
|
|
5173
|
-
|
|
5174
|
-
|
|
5175
|
-
|
|
5176
|
-
|
|
5177
|
-
|
|
5178
|
-
|
|
5179
|
-
|
|
5180
|
-
|
|
5181
|
-
|
|
5182
|
-
|
|
5183
|
-
|
|
5446
|
+
).option(
|
|
5447
|
+
"--session <sessionId>",
|
|
5448
|
+
"\u6C9F\u901A\u7FA4 ID\uFF1B\u4F20\u5165\u65F6\u5728\u5E73\u53F0\u521B\u5EFA\u90E8\u7F72\u8BB0\u5F55\u5E76\u540C\u6B65\u65E5\u5FD7"
|
|
5449
|
+
).action(
|
|
5450
|
+
async (env, opts) => {
|
|
5451
|
+
const cwd = process.cwd();
|
|
5452
|
+
const sessionId = opts.session?.trim();
|
|
5453
|
+
try {
|
|
5454
|
+
if (sessionId) {
|
|
5455
|
+
await runDeployWithBackendTracking({
|
|
5456
|
+
env,
|
|
5457
|
+
cwd,
|
|
5458
|
+
configPath: opts.config,
|
|
5459
|
+
sessionId
|
|
5460
|
+
});
|
|
5461
|
+
return;
|
|
5462
|
+
}
|
|
5463
|
+
await executeDeploy({ env, cwd, configPath: opts.config });
|
|
5464
|
+
} catch (error) {
|
|
5465
|
+
if (error instanceof DeployExecutionError) {
|
|
5466
|
+
printDeployExecutionError(error);
|
|
5467
|
+
process.exit(error.exitCode);
|
|
5468
|
+
}
|
|
5469
|
+
throw error;
|
|
5470
|
+
}
|
|
5184
5471
|
}
|
|
5185
|
-
|
|
5186
|
-
});
|
|
5472
|
+
);
|
|
5187
5473
|
}
|
|
5188
5474
|
|
|
5189
5475
|
// src/commands/deploy/backend.ts
|
|
5190
|
-
import
|
|
5476
|
+
import path9 from "node:path";
|
|
5191
5477
|
|
|
5192
5478
|
// src/commands/deploy/internal/backend-deploy/backend-deploy-workflow.ts
|
|
5193
|
-
import
|
|
5479
|
+
import path8 from "node:path";
|
|
5194
5480
|
|
|
5195
5481
|
// src/commands/deploy/internal/backend-deploy/dockerode-client/client.ts
|
|
5196
5482
|
import Docker from "dockerode";
|
|
5197
5483
|
|
|
5198
5484
|
// src/commands/deploy/internal/backend-deploy/dockerode-client/connection-options.ts
|
|
5199
5485
|
import { existsSync as existsSync18, readFileSync as readFileSync15 } from "node:fs";
|
|
5200
|
-
import
|
|
5486
|
+
import path5 from "node:path";
|
|
5201
5487
|
function asOptionalTlsBuffer(value) {
|
|
5202
5488
|
if (typeof value !== "string") {
|
|
5203
5489
|
console.log("tls filepath not exist");
|
|
5204
5490
|
return void 0;
|
|
5205
5491
|
}
|
|
5206
|
-
console.log("tls filepath",
|
|
5492
|
+
console.log("tls filepath", path5.join(process.cwd(), value));
|
|
5207
5493
|
const normalized = value.trim();
|
|
5208
5494
|
if (normalized === "") {
|
|
5209
5495
|
return void 0;
|
|
@@ -5420,7 +5706,7 @@ var createDockerodeClient = (config) => new DockerodeClient(config);
|
|
|
5420
5706
|
|
|
5421
5707
|
// src/commands/deploy/internal/backend-deploy/dockerode-client/env.ts
|
|
5422
5708
|
import { existsSync as existsSync19, readFileSync as readFileSync16, statSync as statSync6 } from "node:fs";
|
|
5423
|
-
import
|
|
5709
|
+
import path6 from "node:path";
|
|
5424
5710
|
function stripSurroundingQuotes(value) {
|
|
5425
5711
|
const t = value.trim();
|
|
5426
5712
|
if (t.length >= 2) {
|
|
@@ -5435,7 +5721,7 @@ function loadEnvFromFile(envFilePath) {
|
|
|
5435
5721
|
if (!envFilePath) {
|
|
5436
5722
|
return {};
|
|
5437
5723
|
}
|
|
5438
|
-
const targetPath =
|
|
5724
|
+
const targetPath = path6.resolve(envFilePath);
|
|
5439
5725
|
if (!existsSync19(targetPath) || !statSync6(targetPath).isFile()) {
|
|
5440
5726
|
return {};
|
|
5441
5727
|
}
|
|
@@ -5611,9 +5897,9 @@ function dockerPushImage(params, cwd) {
|
|
|
5611
5897
|
|
|
5612
5898
|
// src/commands/deploy/internal/backend-deploy/resolve-dockerfile.ts
|
|
5613
5899
|
import { existsSync as existsSync20 } from "node:fs";
|
|
5614
|
-
import
|
|
5900
|
+
import path7 from "node:path";
|
|
5615
5901
|
function resolveDockerBuildPaths(cwd) {
|
|
5616
|
-
const dockerfilePath =
|
|
5902
|
+
const dockerfilePath = path7.join(cwd, "Dockerfile");
|
|
5617
5903
|
Logger.info(`\u67E5\u627EDockerfile\u6587\u4EF6\uFF0C\u8DEF\u5F84: ${dockerfilePath}`);
|
|
5618
5904
|
if (!existsSync20(dockerfilePath)) {
|
|
5619
5905
|
throw new Error(`Dockerfile \u4E0D\u5B58\u5728\uFF1A${dockerfilePath}`);
|
|
@@ -5670,7 +5956,7 @@ var BackendDeployWorkflow = class {
|
|
|
5670
5956
|
serveraddress
|
|
5671
5957
|
});
|
|
5672
5958
|
Logger.success("\u8FDC\u7A0B\u62C9\u53D6\u955C\u50CF\u5B8C\u6210");
|
|
5673
|
-
const envFilePath =
|
|
5959
|
+
const envFilePath = path8.resolve(cwd, this.params.envFilePath || ".env");
|
|
5674
5960
|
const envObj = loadEnvFromFile(envFilePath);
|
|
5675
5961
|
if (this.params.dockerNetwork?.trim()) {
|
|
5676
5962
|
Logger.info(`\u8FDC\u7A0B\u5BB9\u5668\u5C06\u52A0\u5165 Docker \u7F51\u7EDC\uFF1A${this.params.dockerNetwork.trim()}`);
|
|
@@ -5710,7 +5996,7 @@ function registerDeployBackendCommands(program) {
|
|
|
5710
5996
|
assertDeployImageTag(tag);
|
|
5711
5997
|
const cfg = loadApmConfig({ configPath: opts.config });
|
|
5712
5998
|
const fromApm = resolveBackendDeployFromApmConfig(cfg);
|
|
5713
|
-
const dirAbs =
|
|
5999
|
+
const dirAbs = path9.resolve(process.cwd(), opts.dir || "servers/api");
|
|
5714
6000
|
const params = {
|
|
5715
6001
|
image: fromApm.name,
|
|
5716
6002
|
tag,
|
|
@@ -5741,12 +6027,12 @@ function registerDeployBackendCommands(program) {
|
|
|
5741
6027
|
|
|
5742
6028
|
// src/commands/deploy/frontend.ts
|
|
5743
6029
|
import { copyFile, readdir as readdir3, stat } from "node:fs/promises";
|
|
5744
|
-
import
|
|
6030
|
+
import path11 from "node:path";
|
|
5745
6031
|
|
|
5746
6032
|
// src/commands/deploy/internal/minio.ts
|
|
5747
6033
|
import { statSync as statSync7 } from "node:fs";
|
|
5748
6034
|
import { readdir as readdir2, readFile as readFile2 } from "node:fs/promises";
|
|
5749
|
-
import
|
|
6035
|
+
import path10 from "node:path";
|
|
5750
6036
|
import * as Minio from "minio";
|
|
5751
6037
|
var DEFAULT_MAX_FILE_SIZE_MB = 50;
|
|
5752
6038
|
async function isDirectoryPath(dir) {
|
|
@@ -5776,7 +6062,7 @@ async function collectFiles(root) {
|
|
|
5776
6062
|
if (name === "." || name === "..") {
|
|
5777
6063
|
continue;
|
|
5778
6064
|
}
|
|
5779
|
-
const abs =
|
|
6065
|
+
const abs = path10.join(dir, name);
|
|
5780
6066
|
const rel = prefix ? `${prefix}/${name}` : name;
|
|
5781
6067
|
if (e.isDirectory()) {
|
|
5782
6068
|
await walk(abs, rel);
|
|
@@ -5819,7 +6105,7 @@ var MIME = {
|
|
|
5819
6105
|
".map": "application/json"
|
|
5820
6106
|
};
|
|
5821
6107
|
function detectMimeType(filePath) {
|
|
5822
|
-
const ext =
|
|
6108
|
+
const ext = path10.extname(filePath).toLowerCase();
|
|
5823
6109
|
return MIME[ext] ?? "";
|
|
5824
6110
|
}
|
|
5825
6111
|
var MinioClient = class {
|
|
@@ -5907,7 +6193,7 @@ function artifactObjectKey(namePrefix, branchSegment, relativePath) {
|
|
|
5907
6193
|
return `${base}/${branchSegment}/dist/${rel}`;
|
|
5908
6194
|
}
|
|
5909
6195
|
async function ensureArtifactRootIndexHtml(root) {
|
|
5910
|
-
const indexHtmlPath =
|
|
6196
|
+
const indexHtmlPath = path11.join(root, "index.html");
|
|
5911
6197
|
try {
|
|
5912
6198
|
const st = await stat(indexHtmlPath);
|
|
5913
6199
|
if (st.isFile()) {
|
|
@@ -5924,7 +6210,7 @@ async function ensureArtifactRootIndexHtml(root) {
|
|
|
5924
6210
|
}
|
|
5925
6211
|
const dirNames = entries.filter((e) => e.isDirectory()).map((e) => String(e.name)).sort();
|
|
5926
6212
|
for (const name of dirNames) {
|
|
5927
|
-
const candidate =
|
|
6213
|
+
const candidate = path11.join(root, name, "index.html");
|
|
5928
6214
|
try {
|
|
5929
6215
|
const st = await stat(candidate);
|
|
5930
6216
|
if (!st.isFile()) {
|
|
@@ -5935,7 +6221,7 @@ async function ensureArtifactRootIndexHtml(root) {
|
|
|
5935
6221
|
}
|
|
5936
6222
|
await copyFile(candidate, indexHtmlPath);
|
|
5937
6223
|
console.error(
|
|
5938
|
-
`\u4EA7\u7269\u534F\u8BAE\uFF1A\u5DF2\u5C06 ${
|
|
6224
|
+
`\u4EA7\u7269\u534F\u8BAE\uFF1A\u5DF2\u5C06 ${path11.join(name, "index.html")} \u590D\u5236\u4E3A\u6839\u76EE\u5F55 index.html`
|
|
5939
6225
|
);
|
|
5940
6226
|
return;
|
|
5941
6227
|
}
|
|
@@ -5971,7 +6257,7 @@ function registerDeployFrontendCommands(program) {
|
|
|
5971
6257
|
secretKey: settings.secretKey
|
|
5972
6258
|
});
|
|
5973
6259
|
const bucket = settings.bucket;
|
|
5974
|
-
const root =
|
|
6260
|
+
const root = path11.resolve(process.cwd(), opts.dir || "apps/web/dist");
|
|
5975
6261
|
if (!await isDirectoryPath(root)) {
|
|
5976
6262
|
console.error(`\u4EA7\u7269\u76EE\u5F55\u4E0D\u5B58\u5728\uFF1A${root}`);
|
|
5977
6263
|
process.exit(1);
|
|
@@ -6040,7 +6326,7 @@ function registerDeployFrontendCommands(program) {
|
|
|
6040
6326
|
}
|
|
6041
6327
|
|
|
6042
6328
|
// src/commands/deploy/sftp.ts
|
|
6043
|
-
import
|
|
6329
|
+
import path12 from "node:path";
|
|
6044
6330
|
function registerDeploySftpCommands(program) {
|
|
6045
6331
|
program.command("deploy-sftp").description(
|
|
6046
6332
|
"\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"
|
|
@@ -6055,7 +6341,7 @@ function registerDeploySftpCommands(program) {
|
|
|
6055
6341
|
async (opts) => {
|
|
6056
6342
|
const cfg = loadApmConfig({ configPath: opts.config });
|
|
6057
6343
|
const settings = resolveWisdomDeployFromApmConfig(cfg);
|
|
6058
|
-
const root =
|
|
6344
|
+
const root = path12.resolve(process.cwd(), opts.dir || "apps/web/dist");
|
|
6059
6345
|
if (!await isDirectoryPath(root)) {
|
|
6060
6346
|
console.error(`\u4EA7\u7269\u76EE\u5F55\u4E0D\u5B58\u5728\uFF1A${root}`);
|
|
6061
6347
|
process.exit(1);
|
package/package.json
CHANGED
|
@@ -2,7 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
## 工作流程
|
|
4
4
|
|
|
5
|
-
在项目根目录执行 `apm deploy
|
|
5
|
+
在项目根目录执行 `apm deploy <环境名称> --session <sessionId>`,**以命令执行结果为准**。
|
|
6
|
+
|
|
7
|
+
**sessionId**:从当前工作项目录 `.apm/sessions/<sessionId>/` 或 `session.yaml` 获取;必须传入 `--session`,平台才会记录部署。
|
|
6
8
|
|
|
7
9
|
- **成功**:部署完成,在回信中说明测试环境地址或部署结果。
|
|
8
10
|
- **失败且输出含「未配置自动化部署」或「可跳过部署」**:本项目不支持自动化部署,属正常情况;放弃部署,在回信说明已跳过即可,无需修复配置或重试。
|
|
@@ -10,5 +12,5 @@
|
|
|
10
12
|
|
|
11
13
|
## 示例
|
|
12
14
|
|
|
13
|
-
1. 部署测试环境:`apm deploy test
|
|
14
|
-
2. 部署正式环境:`apm deploy online
|
|
15
|
+
1. 部署测试环境:`apm deploy test --session <sessionId>`
|
|
16
|
+
2. 部署正式环境:`apm deploy online --session <sessionId>`
|