ai-project-manage-cli 6.0.81 → 6.0.83
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 +324 -108
- package/package.json +1 -1
- package/template/skills/apm-deploy/SKILL.md +11 -3
- package/template/skills/apm-dev/SKILL.md +1 -1
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;
|
|
@@ -3959,8 +3963,9 @@ async function runCreatePr(options) {
|
|
|
3959
3963
|
console.log(`[apm] PR \u5DF2\u5C31\u7EEA #${pr.number} (${pr.state}): ${pr.url}`);
|
|
3960
3964
|
}
|
|
3961
3965
|
|
|
3962
|
-
// src/commands/deploy/deploy.ts
|
|
3966
|
+
// src/commands/deploy/deploy-execute.ts
|
|
3963
3967
|
import { spawnSync as spawnSync5 } from "node:child_process";
|
|
3968
|
+
import path4 from "node:path";
|
|
3964
3969
|
|
|
3965
3970
|
// src/commands/deploy/internal/apm-config.ts
|
|
3966
3971
|
import { existsSync as existsSync15, readFileSync as readFileSync12 } from "node:fs";
|
|
@@ -4152,9 +4157,9 @@ function readMavenLocalRepoFromEnv(env = process.env) {
|
|
|
4152
4157
|
}
|
|
4153
4158
|
const mavenOpts = readEnvVar(env, "MAVEN_OPTS")?.trim();
|
|
4154
4159
|
if (mavenOpts) {
|
|
4155
|
-
const
|
|
4156
|
-
if (
|
|
4157
|
-
return { path:
|
|
4160
|
+
const path13 = readMavenLocalRepoFromMavenOpts(mavenOpts, env);
|
|
4161
|
+
if (path13) {
|
|
4162
|
+
return { path: path13, key: "MAVEN_OPTS" };
|
|
4158
4163
|
}
|
|
4159
4164
|
}
|
|
4160
4165
|
return null;
|
|
@@ -4265,6 +4270,41 @@ function posixBasename(p) {
|
|
|
4265
4270
|
return idx >= 0 ? normalized.slice(idx + 1) : normalized;
|
|
4266
4271
|
}
|
|
4267
4272
|
|
|
4273
|
+
// src/commands/deploy/internal/deploy-hints.ts
|
|
4274
|
+
function formatDeployNotConfiguredLines(env, deployCommands) {
|
|
4275
|
+
const configuredEnvs = Object.keys(deployCommands).filter(
|
|
4276
|
+
(key) => deployCommands[key]?.trim()
|
|
4277
|
+
);
|
|
4278
|
+
if (configuredEnvs.length > 0) {
|
|
4279
|
+
return [
|
|
4280
|
+
`[apm] \u65E0\u6CD5\u6267\u884C\u90E8\u7F72\uFF1Aapm.config.json \u4E2D\u672A\u914D\u7F6E deploy.${env}`,
|
|
4281
|
+
`[apm] \u5F53\u524D\u5DF2\u914D\u7F6E\u7684\u73AF\u5883: ${configuredEnvs.join(", ")}`
|
|
4282
|
+
];
|
|
4283
|
+
}
|
|
4284
|
+
return [
|
|
4285
|
+
"[apm] \u65E0\u6CD5\u6267\u884C\u90E8\u7F72\uFF1A\u5F53\u524D\u9879\u76EE\u672A\u914D\u7F6E\u81EA\u52A8\u5316\u90E8\u7F72\uFF08apm.config.json \u4E2D\u65E0 deploy \u6BB5\uFF09",
|
|
4286
|
+
"[apm] \u90E8\u5206\u9879\u76EE\u4E0D\u652F\u6301\u6216\u672A\u542F\u7528\u81EA\u52A8\u5316\u90E8\u7F72\uFF0C\u5C5E\u6B63\u5E38\u60C5\u51B5\uFF0C\u53EF\u8DF3\u8FC7\u90E8\u7F72"
|
|
4287
|
+
];
|
|
4288
|
+
}
|
|
4289
|
+
function formatWisdomFrontendDeployNotConfiguredLines(env, packageJsonPath) {
|
|
4290
|
+
return [
|
|
4291
|
+
`[apm] \u65E0\u6CD5\u6267\u884C\u90E8\u7F72\uFF1A${packageJsonPath} \u4E2D\u672A\u627E\u5230 deploy:${env} \u811A\u672C`,
|
|
4292
|
+
"[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"
|
|
4293
|
+
];
|
|
4294
|
+
}
|
|
4295
|
+
|
|
4296
|
+
// src/commands/deploy/deploy-errors.ts
|
|
4297
|
+
var DeployExecutionError = class extends Error {
|
|
4298
|
+
exitCode;
|
|
4299
|
+
output;
|
|
4300
|
+
constructor(message, exitCode, output = "") {
|
|
4301
|
+
super(message);
|
|
4302
|
+
this.name = "DeployExecutionError";
|
|
4303
|
+
this.exitCode = exitCode;
|
|
4304
|
+
this.output = output;
|
|
4305
|
+
}
|
|
4306
|
+
};
|
|
4307
|
+
|
|
4268
4308
|
// src/commands/deploy/internal/wisdom-auto-deploy.ts
|
|
4269
4309
|
import { existsSync as existsSync17, readFileSync as readFileSync14 } from "node:fs";
|
|
4270
4310
|
import path3 from "node:path";
|
|
@@ -5069,19 +5109,33 @@ function resolveFrontendDeployCommand(env, cwd) {
|
|
|
5069
5109
|
}
|
|
5070
5110
|
return null;
|
|
5071
5111
|
}
|
|
5072
|
-
function runShellCommand2(command, cwd) {
|
|
5112
|
+
function runShellCommand2(command, cwd, captureOutput) {
|
|
5073
5113
|
const result = spawnSync4(command, {
|
|
5074
5114
|
cwd,
|
|
5075
|
-
stdio: "inherit",
|
|
5076
5115
|
shell: true,
|
|
5077
|
-
env: process.env
|
|
5116
|
+
env: process.env,
|
|
5117
|
+
encoding: "utf8",
|
|
5118
|
+
stdio: captureOutput ? ["inherit", "pipe", "pipe"] : "inherit"
|
|
5078
5119
|
});
|
|
5120
|
+
const stdout = captureOutput ? String(result.stdout ?? "") : "";
|
|
5121
|
+
const stderr = captureOutput ? String(result.stderr ?? "") : "";
|
|
5122
|
+
const output = [stdout, stderr].filter(Boolean).join("\n");
|
|
5123
|
+
if (captureOutput) {
|
|
5124
|
+
if (stdout) process.stdout.write(stdout);
|
|
5125
|
+
if (stderr) process.stderr.write(stderr);
|
|
5126
|
+
}
|
|
5079
5127
|
if (result.status !== 0) {
|
|
5080
|
-
|
|
5128
|
+
throw new DeployExecutionError(
|
|
5129
|
+
`\u90E8\u7F72\u547D\u4EE4\u9000\u51FA\u7801 ${result.status ?? "unknown"}: ${command}`,
|
|
5130
|
+
result.status ?? 1,
|
|
5131
|
+
output
|
|
5132
|
+
);
|
|
5081
5133
|
}
|
|
5134
|
+
return output;
|
|
5082
5135
|
}
|
|
5083
5136
|
async function runWisdomAutoDeploy(options) {
|
|
5084
5137
|
const cwd = path3.resolve(options.cwd ?? process.cwd());
|
|
5138
|
+
const captureOutput = options.captureOutput ?? false;
|
|
5085
5139
|
const projectType = detectWisdomProjectType(cwd);
|
|
5086
5140
|
console.error(
|
|
5087
5141
|
`[apm] \u533B\u52A1\u5B58\u91CF\u9879\u76EE\u81EA\u52A8\u8BC6\u522B: ${projectType === "frontend" ? "\u524D\u7AEF Vue" : "\u540E\u7AEF Java"}`
|
|
@@ -5089,12 +5143,13 @@ async function runWisdomAutoDeploy(options) {
|
|
|
5089
5143
|
if (projectType === "frontend") {
|
|
5090
5144
|
const deployCmd = resolveFrontendDeployCommand(options.env, cwd);
|
|
5091
5145
|
if (!deployCmd) {
|
|
5092
|
-
|
|
5093
|
-
|
|
5146
|
+
const lines = formatWisdomFrontendDeployNotConfiguredLines(
|
|
5147
|
+
options.env,
|
|
5148
|
+
path3.join(cwd, "package.json")
|
|
5094
5149
|
);
|
|
5095
|
-
|
|
5150
|
+
throw new DeployExecutionError(lines.join("\n"), 1, lines.join("\n"));
|
|
5096
5151
|
}
|
|
5097
|
-
runShellCommand2(deployCmd, cwd);
|
|
5152
|
+
runShellCommand2(deployCmd, cwd, captureOutput);
|
|
5098
5153
|
return { projectType };
|
|
5099
5154
|
}
|
|
5100
5155
|
const configPath = options.configPath ?? path3.join(workspaceApmDir(cwd), "apm.config.json");
|
|
@@ -5110,68 +5165,229 @@ async function runWisdomAutoDeploy(options) {
|
|
|
5110
5165
|
return { projectType };
|
|
5111
5166
|
}
|
|
5112
5167
|
|
|
5113
|
-
// src/commands/deploy/deploy.ts
|
|
5114
|
-
function runShellCommand3(command, cwd) {
|
|
5168
|
+
// src/commands/deploy/deploy-execute.ts
|
|
5169
|
+
function runShellCommand3(command, cwd, captureOutput) {
|
|
5115
5170
|
const result = spawnSync5(command, {
|
|
5116
5171
|
cwd,
|
|
5117
|
-
stdio: "inherit",
|
|
5118
5172
|
shell: true,
|
|
5119
|
-
env: process.env
|
|
5173
|
+
env: process.env,
|
|
5174
|
+
encoding: "utf8",
|
|
5175
|
+
stdio: captureOutput ? ["inherit", "pipe", "pipe"] : "inherit"
|
|
5120
5176
|
});
|
|
5177
|
+
const stdout = captureOutput ? String(result.stdout ?? "") : "";
|
|
5178
|
+
const stderr = captureOutput ? String(result.stderr ?? "") : "";
|
|
5179
|
+
const output = [stdout, stderr].filter(Boolean).join("\n");
|
|
5180
|
+
if (captureOutput) {
|
|
5181
|
+
if (stdout) process.stdout.write(stdout);
|
|
5182
|
+
if (stderr) process.stderr.write(stderr);
|
|
5183
|
+
}
|
|
5121
5184
|
if (result.status !== 0) {
|
|
5122
|
-
|
|
5185
|
+
throw new DeployExecutionError(
|
|
5186
|
+
`\u90E8\u7F72\u547D\u4EE4\u9000\u51FA\u7801 ${result.status ?? "unknown"}: ${command}`,
|
|
5187
|
+
result.status ?? 1,
|
|
5188
|
+
output
|
|
5189
|
+
);
|
|
5190
|
+
}
|
|
5191
|
+
return output;
|
|
5192
|
+
}
|
|
5193
|
+
async function executeDeploy(options) {
|
|
5194
|
+
const cwd = path4.resolve(options.cwd ?? process.cwd());
|
|
5195
|
+
const captureOutput = options.captureOutput ?? false;
|
|
5196
|
+
const cfg = loadApmConfig({ configPath: options.configPath });
|
|
5197
|
+
if (isWisdomLegacyDeploy(cfg)) {
|
|
5198
|
+
try {
|
|
5199
|
+
await runWisdomAutoDeploy({
|
|
5200
|
+
env: options.env,
|
|
5201
|
+
cwd,
|
|
5202
|
+
configPath: options.configPath,
|
|
5203
|
+
captureOutput
|
|
5204
|
+
});
|
|
5205
|
+
return "";
|
|
5206
|
+
} catch (error) {
|
|
5207
|
+
if (error instanceof DeployExecutionError) {
|
|
5208
|
+
throw error;
|
|
5209
|
+
}
|
|
5210
|
+
const detail = error instanceof Error ? error.message : String(error);
|
|
5211
|
+
throw new DeployExecutionError(detail, 1);
|
|
5212
|
+
}
|
|
5213
|
+
}
|
|
5214
|
+
const deployCommands = cfg.deploy ?? {};
|
|
5215
|
+
const command = deployCommands[options.env]?.trim();
|
|
5216
|
+
if (!command) {
|
|
5217
|
+
const lines = formatDeployNotConfiguredLines(options.env, deployCommands);
|
|
5218
|
+
throw new DeployExecutionError(lines.join("\n"), 1, lines.join("\n"));
|
|
5219
|
+
}
|
|
5220
|
+
return runShellCommand3(command, cwd, captureOutput);
|
|
5221
|
+
}
|
|
5222
|
+
function printDeployExecutionError(error) {
|
|
5223
|
+
if (error.output.trim()) {
|
|
5224
|
+
console.error(error.output);
|
|
5225
|
+
return;
|
|
5226
|
+
}
|
|
5227
|
+
console.error(error.message);
|
|
5228
|
+
}
|
|
5229
|
+
|
|
5230
|
+
// src/commands/deploy/deploy-tracking.ts
|
|
5231
|
+
function normalizeDeployEnvironment(env) {
|
|
5232
|
+
const normalized = env.trim().toLowerCase();
|
|
5233
|
+
if (normalized === "test") return "TEST";
|
|
5234
|
+
if (normalized === "online") return "ONLINE";
|
|
5235
|
+
return null;
|
|
5236
|
+
}
|
|
5237
|
+
async function completeTrackedDeploy(api, deploymentRunId, logSyncer, input) {
|
|
5238
|
+
logSyncer.updateLog(input.log);
|
|
5239
|
+
await logSyncer.flush();
|
|
5240
|
+
await api.cli.completeTaskDeployment({
|
|
5241
|
+
id: deploymentRunId,
|
|
5242
|
+
status: input.status,
|
|
5243
|
+
log: input.log,
|
|
5244
|
+
error: input.error
|
|
5245
|
+
});
|
|
5246
|
+
}
|
|
5247
|
+
async function runDeployWithBackendTracking(options) {
|
|
5248
|
+
const cfg = await tryReadApmConfig();
|
|
5249
|
+
if (!cfg || !resolveApiKey(cfg)) {
|
|
5250
|
+
console.warn("[apm] \u672A\u767B\u5F55\uFF0C\u8DF3\u8FC7\u540E\u7AEF\u90E8\u7F72\u8BB0\u5F55");
|
|
5251
|
+
await executeDeploy(options);
|
|
5252
|
+
return;
|
|
5253
|
+
}
|
|
5254
|
+
const environment = normalizeDeployEnvironment(options.env);
|
|
5255
|
+
if (!environment) {
|
|
5256
|
+
console.warn(
|
|
5257
|
+
`[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`
|
|
5258
|
+
);
|
|
5259
|
+
await executeDeploy(options);
|
|
5260
|
+
return;
|
|
5261
|
+
}
|
|
5262
|
+
const api = createApmApiClient(cfg);
|
|
5263
|
+
let deploymentRunId;
|
|
5264
|
+
try {
|
|
5265
|
+
const run = await api.cli.createTaskDeployment({
|
|
5266
|
+
sessionId: options.sessionId,
|
|
5267
|
+
environment,
|
|
5268
|
+
workdirPath: options.cwd ?? process.cwd()
|
|
5269
|
+
});
|
|
5270
|
+
deploymentRunId = run.id;
|
|
5271
|
+
console.log(
|
|
5272
|
+
`[apm] \u5DF2\u521B\u5EFA\u90E8\u7F72\u8BB0\u5F55 id=${deploymentRunId} env=${environment}`
|
|
5273
|
+
);
|
|
5274
|
+
} catch (error) {
|
|
5275
|
+
const detail = error instanceof Error ? error.message : String(error);
|
|
5276
|
+
console.warn(`[apm] \u521B\u5EFA\u90E8\u7F72\u8BB0\u5F55\u5931\u8D25\uFF0C\u7EE7\u7EED\u90E8\u7F72: ${detail}`);
|
|
5277
|
+
await executeDeploy(options);
|
|
5278
|
+
return;
|
|
5279
|
+
}
|
|
5280
|
+
await api.cli.updateTaskDeploymentStatus({
|
|
5281
|
+
id: deploymentRunId,
|
|
5282
|
+
status: "DEPLOYING"
|
|
5283
|
+
});
|
|
5284
|
+
const logSyncer = createDeployLogSyncer(api, deploymentRunId);
|
|
5285
|
+
const chunks = [];
|
|
5286
|
+
const appendLog = (line) => {
|
|
5287
|
+
if (!line) return;
|
|
5288
|
+
chunks.push(line);
|
|
5289
|
+
logSyncer.updateLog(chunks.join("\n"));
|
|
5290
|
+
};
|
|
5291
|
+
const originalLog = console.log;
|
|
5292
|
+
const originalError = console.error;
|
|
5293
|
+
console.log = (...args) => {
|
|
5294
|
+
appendLog(args.map(String).join(" "));
|
|
5295
|
+
originalLog.apply(console, args);
|
|
5296
|
+
};
|
|
5297
|
+
console.error = (...args) => {
|
|
5298
|
+
appendLog(args.map(String).join(" "));
|
|
5299
|
+
originalError.apply(console, args);
|
|
5300
|
+
};
|
|
5301
|
+
try {
|
|
5302
|
+
const output = await executeDeploy({ ...options, captureOutput: true });
|
|
5303
|
+
if (output.trim()) {
|
|
5304
|
+
appendLog(output);
|
|
5305
|
+
}
|
|
5306
|
+
const log2 = chunks.join("\n");
|
|
5307
|
+
await completeTrackedDeploy(api, deploymentRunId, logSyncer, {
|
|
5308
|
+
status: "SUCCESS",
|
|
5309
|
+
log: log2
|
|
5310
|
+
});
|
|
5311
|
+
console.log(`[apm] deploy success id=${deploymentRunId}`);
|
|
5312
|
+
} catch (error) {
|
|
5313
|
+
const deployError = error instanceof DeployExecutionError ? error : new DeployExecutionError(
|
|
5314
|
+
error instanceof Error ? error.message : String(error),
|
|
5315
|
+
1
|
|
5316
|
+
);
|
|
5317
|
+
if (deployError.output.trim()) {
|
|
5318
|
+
appendLog(deployError.output);
|
|
5319
|
+
} else {
|
|
5320
|
+
appendLog(deployError.message);
|
|
5321
|
+
}
|
|
5322
|
+
const log2 = chunks.join("\n");
|
|
5323
|
+
await completeTrackedDeploy(api, deploymentRunId, logSyncer, {
|
|
5324
|
+
status: "FAILED",
|
|
5325
|
+
log: log2,
|
|
5326
|
+
error: deployError.message
|
|
5327
|
+
});
|
|
5328
|
+
printDeployExecutionError(deployError);
|
|
5329
|
+
process.exit(deployError.exitCode);
|
|
5330
|
+
} finally {
|
|
5331
|
+
console.log = originalLog;
|
|
5332
|
+
console.error = originalError;
|
|
5333
|
+
logSyncer.dispose();
|
|
5123
5334
|
}
|
|
5124
5335
|
}
|
|
5336
|
+
|
|
5337
|
+
// src/commands/deploy/deploy.ts
|
|
5125
5338
|
function registerDeployMainCommand(program) {
|
|
5126
5339
|
program.command("deploy").description(
|
|
5127
5340
|
"\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"
|
|
5128
5341
|
).argument("<env>", "\u90E8\u7F72\u73AF\u5883\u540D\uFF08\u5982 test\u3001online\uFF09").option(
|
|
5129
5342
|
"--config <path>",
|
|
5130
5343
|
"apm.config.json \u8DEF\u5F84\uFF08\u9ED8\u8BA4 .apm/apm.config.json\uFF09"
|
|
5131
|
-
).
|
|
5132
|
-
|
|
5133
|
-
|
|
5134
|
-
|
|
5135
|
-
|
|
5136
|
-
|
|
5137
|
-
|
|
5138
|
-
|
|
5139
|
-
|
|
5140
|
-
|
|
5141
|
-
|
|
5142
|
-
|
|
5143
|
-
|
|
5144
|
-
|
|
5145
|
-
|
|
5146
|
-
|
|
5147
|
-
|
|
5148
|
-
|
|
5149
|
-
|
|
5150
|
-
|
|
5151
|
-
|
|
5344
|
+
).option(
|
|
5345
|
+
"--session <sessionId>",
|
|
5346
|
+
"\u6C9F\u901A\u7FA4 ID\uFF1B\u4F20\u5165\u65F6\u5728\u5E73\u53F0\u521B\u5EFA\u90E8\u7F72\u8BB0\u5F55\u5E76\u540C\u6B65\u65E5\u5FD7"
|
|
5347
|
+
).action(
|
|
5348
|
+
async (env, opts) => {
|
|
5349
|
+
const cwd = process.cwd();
|
|
5350
|
+
const sessionId = opts.session?.trim();
|
|
5351
|
+
try {
|
|
5352
|
+
if (sessionId) {
|
|
5353
|
+
await runDeployWithBackendTracking({
|
|
5354
|
+
env,
|
|
5355
|
+
cwd,
|
|
5356
|
+
configPath: opts.config,
|
|
5357
|
+
sessionId
|
|
5358
|
+
});
|
|
5359
|
+
return;
|
|
5360
|
+
}
|
|
5361
|
+
await executeDeploy({ env, cwd, configPath: opts.config });
|
|
5362
|
+
} catch (error) {
|
|
5363
|
+
if (error instanceof DeployExecutionError) {
|
|
5364
|
+
printDeployExecutionError(error);
|
|
5365
|
+
process.exit(error.exitCode);
|
|
5366
|
+
}
|
|
5367
|
+
throw error;
|
|
5368
|
+
}
|
|
5152
5369
|
}
|
|
5153
|
-
|
|
5154
|
-
});
|
|
5370
|
+
);
|
|
5155
5371
|
}
|
|
5156
5372
|
|
|
5157
5373
|
// src/commands/deploy/backend.ts
|
|
5158
|
-
import
|
|
5374
|
+
import path9 from "node:path";
|
|
5159
5375
|
|
|
5160
5376
|
// src/commands/deploy/internal/backend-deploy/backend-deploy-workflow.ts
|
|
5161
|
-
import
|
|
5377
|
+
import path8 from "node:path";
|
|
5162
5378
|
|
|
5163
5379
|
// src/commands/deploy/internal/backend-deploy/dockerode-client/client.ts
|
|
5164
5380
|
import Docker from "dockerode";
|
|
5165
5381
|
|
|
5166
5382
|
// src/commands/deploy/internal/backend-deploy/dockerode-client/connection-options.ts
|
|
5167
5383
|
import { existsSync as existsSync18, readFileSync as readFileSync15 } from "node:fs";
|
|
5168
|
-
import
|
|
5384
|
+
import path5 from "node:path";
|
|
5169
5385
|
function asOptionalTlsBuffer(value) {
|
|
5170
5386
|
if (typeof value !== "string") {
|
|
5171
5387
|
console.log("tls filepath not exist");
|
|
5172
5388
|
return void 0;
|
|
5173
5389
|
}
|
|
5174
|
-
console.log("tls filepath",
|
|
5390
|
+
console.log("tls filepath", path5.join(process.cwd(), value));
|
|
5175
5391
|
const normalized = value.trim();
|
|
5176
5392
|
if (normalized === "") {
|
|
5177
5393
|
return void 0;
|
|
@@ -5388,7 +5604,7 @@ var createDockerodeClient = (config) => new DockerodeClient(config);
|
|
|
5388
5604
|
|
|
5389
5605
|
// src/commands/deploy/internal/backend-deploy/dockerode-client/env.ts
|
|
5390
5606
|
import { existsSync as existsSync19, readFileSync as readFileSync16, statSync as statSync6 } from "node:fs";
|
|
5391
|
-
import
|
|
5607
|
+
import path6 from "node:path";
|
|
5392
5608
|
function stripSurroundingQuotes(value) {
|
|
5393
5609
|
const t = value.trim();
|
|
5394
5610
|
if (t.length >= 2) {
|
|
@@ -5403,7 +5619,7 @@ function loadEnvFromFile(envFilePath) {
|
|
|
5403
5619
|
if (!envFilePath) {
|
|
5404
5620
|
return {};
|
|
5405
5621
|
}
|
|
5406
|
-
const targetPath =
|
|
5622
|
+
const targetPath = path6.resolve(envFilePath);
|
|
5407
5623
|
if (!existsSync19(targetPath) || !statSync6(targetPath).isFile()) {
|
|
5408
5624
|
return {};
|
|
5409
5625
|
}
|
|
@@ -5579,9 +5795,9 @@ function dockerPushImage(params, cwd) {
|
|
|
5579
5795
|
|
|
5580
5796
|
// src/commands/deploy/internal/backend-deploy/resolve-dockerfile.ts
|
|
5581
5797
|
import { existsSync as existsSync20 } from "node:fs";
|
|
5582
|
-
import
|
|
5798
|
+
import path7 from "node:path";
|
|
5583
5799
|
function resolveDockerBuildPaths(cwd) {
|
|
5584
|
-
const dockerfilePath =
|
|
5800
|
+
const dockerfilePath = path7.join(cwd, "Dockerfile");
|
|
5585
5801
|
Logger.info(`\u67E5\u627EDockerfile\u6587\u4EF6\uFF0C\u8DEF\u5F84: ${dockerfilePath}`);
|
|
5586
5802
|
if (!existsSync20(dockerfilePath)) {
|
|
5587
5803
|
throw new Error(`Dockerfile \u4E0D\u5B58\u5728\uFF1A${dockerfilePath}`);
|
|
@@ -5638,7 +5854,7 @@ var BackendDeployWorkflow = class {
|
|
|
5638
5854
|
serveraddress
|
|
5639
5855
|
});
|
|
5640
5856
|
Logger.success("\u8FDC\u7A0B\u62C9\u53D6\u955C\u50CF\u5B8C\u6210");
|
|
5641
|
-
const envFilePath =
|
|
5857
|
+
const envFilePath = path8.resolve(cwd, this.params.envFilePath || ".env");
|
|
5642
5858
|
const envObj = loadEnvFromFile(envFilePath);
|
|
5643
5859
|
if (this.params.dockerNetwork?.trim()) {
|
|
5644
5860
|
Logger.info(`\u8FDC\u7A0B\u5BB9\u5668\u5C06\u52A0\u5165 Docker \u7F51\u7EDC\uFF1A${this.params.dockerNetwork.trim()}`);
|
|
@@ -5678,7 +5894,7 @@ function registerDeployBackendCommands(program) {
|
|
|
5678
5894
|
assertDeployImageTag(tag);
|
|
5679
5895
|
const cfg = loadApmConfig({ configPath: opts.config });
|
|
5680
5896
|
const fromApm = resolveBackendDeployFromApmConfig(cfg);
|
|
5681
|
-
const dirAbs =
|
|
5897
|
+
const dirAbs = path9.resolve(process.cwd(), opts.dir || "servers/api");
|
|
5682
5898
|
const params = {
|
|
5683
5899
|
image: fromApm.name,
|
|
5684
5900
|
tag,
|
|
@@ -5709,12 +5925,12 @@ function registerDeployBackendCommands(program) {
|
|
|
5709
5925
|
|
|
5710
5926
|
// src/commands/deploy/frontend.ts
|
|
5711
5927
|
import { copyFile, readdir as readdir3, stat } from "node:fs/promises";
|
|
5712
|
-
import
|
|
5928
|
+
import path11 from "node:path";
|
|
5713
5929
|
|
|
5714
5930
|
// src/commands/deploy/internal/minio.ts
|
|
5715
5931
|
import { statSync as statSync7 } from "node:fs";
|
|
5716
5932
|
import { readdir as readdir2, readFile as readFile2 } from "node:fs/promises";
|
|
5717
|
-
import
|
|
5933
|
+
import path10 from "node:path";
|
|
5718
5934
|
import * as Minio from "minio";
|
|
5719
5935
|
var DEFAULT_MAX_FILE_SIZE_MB = 50;
|
|
5720
5936
|
async function isDirectoryPath(dir) {
|
|
@@ -5744,7 +5960,7 @@ async function collectFiles(root) {
|
|
|
5744
5960
|
if (name === "." || name === "..") {
|
|
5745
5961
|
continue;
|
|
5746
5962
|
}
|
|
5747
|
-
const abs =
|
|
5963
|
+
const abs = path10.join(dir, name);
|
|
5748
5964
|
const rel = prefix ? `${prefix}/${name}` : name;
|
|
5749
5965
|
if (e.isDirectory()) {
|
|
5750
5966
|
await walk(abs, rel);
|
|
@@ -5787,7 +6003,7 @@ var MIME = {
|
|
|
5787
6003
|
".map": "application/json"
|
|
5788
6004
|
};
|
|
5789
6005
|
function detectMimeType(filePath) {
|
|
5790
|
-
const ext =
|
|
6006
|
+
const ext = path10.extname(filePath).toLowerCase();
|
|
5791
6007
|
return MIME[ext] ?? "";
|
|
5792
6008
|
}
|
|
5793
6009
|
var MinioClient = class {
|
|
@@ -5875,7 +6091,7 @@ function artifactObjectKey(namePrefix, branchSegment, relativePath) {
|
|
|
5875
6091
|
return `${base}/${branchSegment}/dist/${rel}`;
|
|
5876
6092
|
}
|
|
5877
6093
|
async function ensureArtifactRootIndexHtml(root) {
|
|
5878
|
-
const indexHtmlPath =
|
|
6094
|
+
const indexHtmlPath = path11.join(root, "index.html");
|
|
5879
6095
|
try {
|
|
5880
6096
|
const st = await stat(indexHtmlPath);
|
|
5881
6097
|
if (st.isFile()) {
|
|
@@ -5892,7 +6108,7 @@ async function ensureArtifactRootIndexHtml(root) {
|
|
|
5892
6108
|
}
|
|
5893
6109
|
const dirNames = entries.filter((e) => e.isDirectory()).map((e) => String(e.name)).sort();
|
|
5894
6110
|
for (const name of dirNames) {
|
|
5895
|
-
const candidate =
|
|
6111
|
+
const candidate = path11.join(root, name, "index.html");
|
|
5896
6112
|
try {
|
|
5897
6113
|
const st = await stat(candidate);
|
|
5898
6114
|
if (!st.isFile()) {
|
|
@@ -5903,7 +6119,7 @@ async function ensureArtifactRootIndexHtml(root) {
|
|
|
5903
6119
|
}
|
|
5904
6120
|
await copyFile(candidate, indexHtmlPath);
|
|
5905
6121
|
console.error(
|
|
5906
|
-
`\u4EA7\u7269\u534F\u8BAE\uFF1A\u5DF2\u5C06 ${
|
|
6122
|
+
`\u4EA7\u7269\u534F\u8BAE\uFF1A\u5DF2\u5C06 ${path11.join(name, "index.html")} \u590D\u5236\u4E3A\u6839\u76EE\u5F55 index.html`
|
|
5907
6123
|
);
|
|
5908
6124
|
return;
|
|
5909
6125
|
}
|
|
@@ -5939,7 +6155,7 @@ function registerDeployFrontendCommands(program) {
|
|
|
5939
6155
|
secretKey: settings.secretKey
|
|
5940
6156
|
});
|
|
5941
6157
|
const bucket = settings.bucket;
|
|
5942
|
-
const root =
|
|
6158
|
+
const root = path11.resolve(process.cwd(), opts.dir || "apps/web/dist");
|
|
5943
6159
|
if (!await isDirectoryPath(root)) {
|
|
5944
6160
|
console.error(`\u4EA7\u7269\u76EE\u5F55\u4E0D\u5B58\u5728\uFF1A${root}`);
|
|
5945
6161
|
process.exit(1);
|
|
@@ -6008,7 +6224,7 @@ function registerDeployFrontendCommands(program) {
|
|
|
6008
6224
|
}
|
|
6009
6225
|
|
|
6010
6226
|
// src/commands/deploy/sftp.ts
|
|
6011
|
-
import
|
|
6227
|
+
import path12 from "node:path";
|
|
6012
6228
|
function registerDeploySftpCommands(program) {
|
|
6013
6229
|
program.command("deploy-sftp").description(
|
|
6014
6230
|
"\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"
|
|
@@ -6023,7 +6239,7 @@ function registerDeploySftpCommands(program) {
|
|
|
6023
6239
|
async (opts) => {
|
|
6024
6240
|
const cfg = loadApmConfig({ configPath: opts.config });
|
|
6025
6241
|
const settings = resolveWisdomDeployFromApmConfig(cfg);
|
|
6026
|
-
const root =
|
|
6242
|
+
const root = path12.resolve(process.cwd(), opts.dir || "apps/web/dist");
|
|
6027
6243
|
if (!await isDirectoryPath(root)) {
|
|
6028
6244
|
console.error(`\u4EA7\u7269\u76EE\u5F55\u4E0D\u5B58\u5728\uFF1A${root}`);
|
|
6029
6245
|
process.exit(1);
|
package/package.json
CHANGED
|
@@ -1,8 +1,16 @@
|
|
|
1
|
+
# apm-deploy:自动化部署
|
|
2
|
+
|
|
1
3
|
## 工作流程
|
|
2
4
|
|
|
3
|
-
在项目根目录执行 `apm deploy
|
|
5
|
+
在项目根目录执行 `apm deploy <环境名称> --session <sessionId>`,**以命令执行结果为准**。
|
|
6
|
+
|
|
7
|
+
**sessionId**:从当前工作项目录 `.apm/sessions/<sessionId>/` 或 `session.yaml` 获取;必须传入 `--session`,平台才会记录部署。
|
|
8
|
+
|
|
9
|
+
- **成功**:部署完成,在回信中说明测试环境地址或部署结果。
|
|
10
|
+
- **失败且输出含「未配置自动化部署」或「可跳过部署」**:本项目不支持自动化部署,属正常情况;放弃部署,在回信说明已跳过即可,无需修复配置或重试。
|
|
11
|
+
- **其他失败**:按输出排查并修复后重试。
|
|
4
12
|
|
|
5
13
|
## 示例
|
|
6
14
|
|
|
7
|
-
1. 部署测试环境:`apm deploy test
|
|
8
|
-
2.
|
|
15
|
+
1. 部署测试环境:`apm deploy test --session <sessionId>`
|
|
16
|
+
2. 部署正式环境:`apm deploy online --session <sessionId>`
|
|
@@ -86,7 +86,7 @@ ALTER TABLE inspection_class ADD COLUMN is_project_add VARCHAR(1) DEFAULT '0';
|
|
|
86
86
|
开发完成的定义是以下三项**全部满足**,缺一不可:
|
|
87
87
|
|
|
88
88
|
1. **构建通过**:执行本仓库的构建/检查命令(见 AGENTS.md 或部署文档),失败必须修复后重试。
|
|
89
|
-
2. **发布测试环境**:**Read** `.apm/skills/apm-deploy/SKILL.md`
|
|
89
|
+
2. **发布测试环境**:**Read** `.apm/skills/apm-deploy/SKILL.md` 并按其流程执行 `apm deploy`(以命令结果判断是否跳过);**后端**涉及 SQL 变更时,须在回复中引用 `docs/SQL.md`,并写明待执行的 SQL 文件名或执行顺序。
|
|
90
90
|
3. **白名单对账**:在回复中逐文件列出本次改动与计划白名单的对应关系。
|
|
91
91
|
|
|
92
92
|
**注意:不做联调。** 前后端各自按 `API.md` 交付,接口对不上属于契约或实现问题,由 diff 评审与人工验收暴露后打回修复;禁止自行发起「联调」「接口实测」类的开放式动作。
|