@qmuse/qmuse-cli 1.0.12 → 1.0.13-dev.1
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/app/release.js +12 -27
- package/dist/cli.js +22 -4
- package/package.json +1 -1
package/dist/app/release.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* 发布域(C10):POST /api/deploy/create
|
|
2
|
+
* 发布域(C10):POST /api/deploy/create,GET /api/deploy/query | list | last。
|
|
3
3
|
* 部署单状态机:INIT → INITED(安全检查通过)→ DEPLOYING → DEPLOYED / DEPLOY_FAILED / CANCEL。
|
|
4
4
|
* query 返回 content(infosec/mosec/域名发布状态/发布地址),供 release status 汇总。
|
|
5
5
|
*/
|
|
@@ -18,10 +18,6 @@ export function parseDeployTicketContent(ticket) {
|
|
|
18
18
|
export function createDeployTicket(appId, versionId, cfg) {
|
|
19
19
|
return apiCall('POST', '/api/deploy/create', { appId, versionId }, cfg);
|
|
20
20
|
}
|
|
21
|
-
/** 触发已就绪(INITED)部署单执行发布;服务端异步执行 DEPLOYING → 终态。 */
|
|
22
|
-
export function triggerDeployTicket(deployId, cfg) {
|
|
23
|
-
return apiCall('POST', '/api/deploy/update', { id: deployId }, cfg);
|
|
24
|
-
}
|
|
25
21
|
/** C10.03 查询发布结果:同一查询返回任务详情、产物/安全检查、地址与失败原因。 */
|
|
26
22
|
export function queryDeployTicket(deployId, cfg) {
|
|
27
23
|
return apiCall('GET', `/api/deploy/query?id=${encodeURIComponent(deployId)}`, undefined, cfg);
|
|
@@ -38,7 +34,7 @@ export function sleep(ms) {
|
|
|
38
34
|
return new Promise(resolve => setTimeout(resolve, ms));
|
|
39
35
|
}
|
|
40
36
|
/**
|
|
41
|
-
* 发布等待循环:CREATE 后轮询 query
|
|
37
|
+
* 发布等待循环:CREATE 后轮询 query;服务端 query 将 INITED 推进为 DEPLOYING 并执行发布;
|
|
42
38
|
* 终态、--no-wait 受理(DEPLOYING)或超时返回最近一次 ticket。
|
|
43
39
|
* 温和退避(5s→15s 封顶)降低轮询请求量;连续网络错误快速失败。
|
|
44
40
|
*/
|
|
@@ -47,7 +43,6 @@ export async function waitDeployResult(deployId, cfg, options = {}) {
|
|
|
47
43
|
const timeoutMs = options.timeoutMs ?? (noWait ? 5 * 60 * 1000 : 8 * 60 * 1000);
|
|
48
44
|
const baseIntervalMs = options.intervalMs ?? 5000;
|
|
49
45
|
const startedAt = Date.now();
|
|
50
|
-
let triggered = false;
|
|
51
46
|
let lastError;
|
|
52
47
|
let polls = 0;
|
|
53
48
|
let netErrors = 0;
|
|
@@ -59,7 +54,7 @@ export async function waitDeployResult(deployId, cfg, options = {}) {
|
|
|
59
54
|
netErrors += 1;
|
|
60
55
|
if (netErrors >= 3) {
|
|
61
56
|
lastError = `连续 ${netErrors} 次网络错误:${r.errorMessage ?? 'network'}`;
|
|
62
|
-
return { ticket: undefined,
|
|
57
|
+
return { ticket: undefined, timedOut: false, lastError };
|
|
63
58
|
}
|
|
64
59
|
}
|
|
65
60
|
else {
|
|
@@ -67,37 +62,27 @@ export async function waitDeployResult(deployId, cfg, options = {}) {
|
|
|
67
62
|
}
|
|
68
63
|
const ticket = r.ok ? r.data : undefined;
|
|
69
64
|
const status = typeof ticket?.['status'] === 'string' ? ticket['status'] : undefined;
|
|
70
|
-
if (
|
|
65
|
+
if (r.ok) {
|
|
66
|
+
lastError = undefined;
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
71
69
|
lastError = r.errorMessage ?? r.errorCode ?? `HTTP ${r.status}`;
|
|
72
70
|
// 快速失败:单据不存在/无权限时继续轮询没有意义(避免长达数分钟的空转)。
|
|
73
71
|
const notFound = r.status === 404
|
|
74
72
|
|| r.errorCode === 'NOT_FOUND'
|
|
75
73
|
|| /not found|不存在|无权限|forbidden/iu.test(String(lastError));
|
|
76
74
|
if (notFound) {
|
|
77
|
-
return { ticket: ticket ?? undefined,
|
|
75
|
+
return { ticket: ticket ?? undefined, timedOut: false, lastError };
|
|
78
76
|
}
|
|
79
77
|
}
|
|
80
78
|
if (status && APP_DEPLOY_TERMINAL_STATUSES.has(status)) {
|
|
81
|
-
return { ticket: ticket ?? undefined,
|
|
82
|
-
}
|
|
83
|
-
if (status === 'INITED' && !triggered) {
|
|
84
|
-
// 安全门禁通过:触发现有发布流程(INITED → DEPLOYING,服务端异步执行)。
|
|
85
|
-
const up = await triggerDeployTicket(deployId, cfg);
|
|
86
|
-
triggered = true;
|
|
87
|
-
if (!up.ok)
|
|
88
|
-
lastError = up.errorMessage ?? up.errorCode ?? `HTTP ${up.status}`; // 触发失败语义保留(不重触发)
|
|
89
|
-
const updated = up.ok ? up.data : undefined;
|
|
90
|
-
const next = typeof updated?.['status'] === 'string' ? updated['status'] : undefined;
|
|
91
|
-
if (next && APP_DEPLOY_TERMINAL_STATUSES.has(next))
|
|
92
|
-
return { ticket: updated, triggered, timedOut: false };
|
|
93
|
-
if (updated && noWait)
|
|
94
|
-
return { ticket: updated, triggered, timedOut: false };
|
|
79
|
+
return { ticket: ticket ?? undefined, timedOut: false, lastError };
|
|
95
80
|
}
|
|
96
|
-
if (noWait &&
|
|
97
|
-
return { ticket: ticket ?? undefined,
|
|
81
|
+
if (noWait && status === 'DEPLOYING') {
|
|
82
|
+
return { ticket: ticket ?? undefined, timedOut: false, lastError };
|
|
98
83
|
}
|
|
99
84
|
if (Date.now() - startedAt > timeoutMs)
|
|
100
|
-
return { ticket: ticket ?? undefined,
|
|
85
|
+
return { ticket: ticket ?? undefined, timedOut: true, lastError };
|
|
101
86
|
// 温和退避:每 4 轮 ×1.6,封顶 15s(8 分钟窗口轮询请求减半以上)。
|
|
102
87
|
const intervalMs = Math.min(baseIntervalMs * Math.pow(1.6, Math.floor(polls / 4)), 15000);
|
|
103
88
|
await sleep(Math.round(intervalMs));
|
package/dist/cli.js
CHANGED
|
@@ -876,6 +876,22 @@ function summarizeDeployTicket(ticket) {
|
|
|
876
876
|
updatedAt: ticket.updatedAt ?? ticket.gmtModified ?? undefined,
|
|
877
877
|
};
|
|
878
878
|
}
|
|
879
|
+
/** 同一应用的发布结果共用一次详情查询,补齐发布单未携带的正式访问地址。 */
|
|
880
|
+
async function summarizeDeployTickets(tickets, cfg) {
|
|
881
|
+
const summaries = tickets.map(summarizeDeployTicket);
|
|
882
|
+
const published = summaries.find(item => item.status === 'DEPLOYED' && !item.publishUrl);
|
|
883
|
+
if (typeof published?.appId === 'string') {
|
|
884
|
+
const app = await queryAppInfo(published.appId, cfg);
|
|
885
|
+
if (app.ok && app.data) {
|
|
886
|
+
const publishUrl = app.data.domain ? `https://${app.data.domain}` : app.data.url;
|
|
887
|
+
for (const summary of summaries) {
|
|
888
|
+
if (summary.status === 'DEPLOYED' && !summary.publishUrl)
|
|
889
|
+
summary.publishUrl = publishUrl;
|
|
890
|
+
}
|
|
891
|
+
}
|
|
892
|
+
}
|
|
893
|
+
return summaries;
|
|
894
|
+
}
|
|
879
895
|
async function cmdDeploy(command, flags) {
|
|
880
896
|
const cfg = resolveCfg(flags);
|
|
881
897
|
requireAuth(cfg);
|
|
@@ -900,6 +916,7 @@ async function cmdDeploy(command, flags) {
|
|
|
900
916
|
const success = !wait.timedOut && !!wait.ticket
|
|
901
917
|
&& wait.ticket.status !== 'DEPLOY_FAILED' && wait.ticket.status !== 'CANCEL'
|
|
902
918
|
&& (!wait.lastError || wait.ticket.status === 'DEPLOYED');
|
|
919
|
+
const [summary] = await summarizeDeployTickets([wait.ticket ?? seed], cfg);
|
|
903
920
|
const payload = {
|
|
904
921
|
success,
|
|
905
922
|
appId,
|
|
@@ -907,7 +924,7 @@ async function cmdDeploy(command, flags) {
|
|
|
907
924
|
deployId: deployId || undefined,
|
|
908
925
|
timedOut: wait.timedOut || undefined,
|
|
909
926
|
error: wait.lastError,
|
|
910
|
-
...
|
|
927
|
+
...summary,
|
|
911
928
|
};
|
|
912
929
|
if (flags['--json'] === true) {
|
|
913
930
|
output(payload, flags);
|
|
@@ -939,7 +956,7 @@ async function cmdRelease(command, flags) {
|
|
|
939
956
|
if (!releaseId)
|
|
940
957
|
fail('用法: qmuse release status <releaseId> [--wait] 或 qmuse release status --last --app-id <appId>');
|
|
941
958
|
const wait = await waitDeployResult(releaseId, cfg, { noWait: flags['--wait'] !== true });
|
|
942
|
-
const summary =
|
|
959
|
+
const [summary] = await summarizeDeployTickets([wait.ticket], cfg);
|
|
943
960
|
const lookupFailed = !wait.ticket;
|
|
944
961
|
const success = !wait.timedOut && !lookupFailed
|
|
945
962
|
&& summary.status !== 'DEPLOY_FAILED' && summary.status !== 'CANCEL'
|
|
@@ -962,7 +979,8 @@ async function cmdRelease(command, flags) {
|
|
|
962
979
|
const r = await lastDeployTicket(appId, cfg);
|
|
963
980
|
if (!r.ok)
|
|
964
981
|
failApi(r, `查询最近发布失败`);
|
|
965
|
-
|
|
982
|
+
const [summary] = await summarizeDeployTickets([r.data], cfg);
|
|
983
|
+
output(summary, flags);
|
|
966
984
|
return;
|
|
967
985
|
}
|
|
968
986
|
const r = await listDeployTickets(appId, cfg);
|
|
@@ -971,7 +989,7 @@ async function cmdRelease(command, flags) {
|
|
|
971
989
|
// 防御性兼容:老网关可能返回包装对象而非数组,运行时仍做数组判定。
|
|
972
990
|
const payload = r.data;
|
|
973
991
|
const list = Array.isArray(payload)
|
|
974
|
-
? payload
|
|
992
|
+
? await summarizeDeployTickets(payload, cfg)
|
|
975
993
|
: payload;
|
|
976
994
|
output({ appId, releases: list }, flags);
|
|
977
995
|
return;
|