@lark-apaas/miaoda-cli 0.1.2 → 0.1.3-alpha.4bf312e
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/README.md +8 -7
- package/dist/api/app/api.js +25 -0
- package/dist/api/app/index.js +15 -0
- package/dist/api/app/schemas.js +79 -0
- package/dist/api/app/types.js +58 -0
- package/dist/api/db/api.js +317 -6
- package/dist/api/db/client.js +36 -0
- package/dist/api/db/index.js +11 -1
- package/dist/api/deploy/api.js +60 -0
- package/dist/api/deploy/index.js +16 -0
- package/dist/api/deploy/schemas.js +105 -0
- package/dist/api/deploy/types.js +22 -0
- package/dist/api/file/api.js +15 -0
- package/dist/api/file/index.js +2 -1
- package/dist/api/index.js +7 -1
- package/dist/api/observability/api.js +52 -0
- package/dist/api/observability/index.js +16 -0
- package/dist/api/observability/schemas.js +60 -0
- package/dist/api/observability/types.js +27 -0
- package/dist/cli/commands/app/index.js +62 -0
- package/dist/cli/commands/db/index.js +440 -5
- package/dist/cli/commands/deploy/index.js +155 -0
- package/dist/cli/commands/file/index.js +13 -5
- package/dist/cli/commands/index.js +10 -6
- package/dist/cli/commands/observability/index.js +240 -0
- package/dist/cli/commands/shared.js +83 -7
- package/dist/cli/handlers/app/get.js +47 -0
- package/dist/cli/handlers/app/index.js +7 -0
- package/dist/cli/handlers/app/update.js +59 -0
- package/dist/cli/handlers/db/audit.js +285 -0
- package/dist/cli/handlers/db/changelog.js +117 -0
- package/dist/cli/handlers/db/data.js +3 -4
- package/dist/cli/handlers/db/index.js +17 -1
- package/dist/cli/handlers/db/migration.js +235 -0
- package/dist/cli/handlers/db/quota.js +68 -0
- package/dist/cli/handlers/db/recovery.js +328 -0
- package/dist/cli/handlers/db/schema.js +2 -3
- package/dist/cli/handlers/db/sql.js +1 -2
- package/dist/cli/handlers/deploy/deploy.js +84 -0
- package/dist/cli/handlers/deploy/error-log.js +60 -0
- package/dist/cli/handlers/deploy/format.js +39 -0
- package/dist/cli/handlers/deploy/get.js +71 -0
- package/dist/cli/handlers/deploy/helpers.js +41 -0
- package/dist/cli/handlers/deploy/history.js +70 -0
- package/dist/cli/handlers/deploy/index.js +14 -0
- package/dist/cli/handlers/deploy/polling.js +162 -0
- package/dist/cli/handlers/file/cp.js +1 -2
- package/dist/cli/handlers/file/index.js +3 -1
- package/dist/cli/handlers/file/ls.js +1 -2
- package/dist/cli/handlers/file/quota.js +66 -0
- package/dist/cli/handlers/file/rm.js +1 -2
- package/dist/cli/handlers/file/sign.js +1 -2
- package/dist/cli/handlers/file/stat.js +1 -2
- package/dist/cli/handlers/observability/analytics.js +212 -0
- package/dist/cli/handlers/observability/helpers.js +66 -0
- package/dist/cli/handlers/observability/index.js +12 -0
- package/dist/cli/handlers/observability/log.js +94 -0
- package/dist/cli/handlers/observability/metric.js +208 -0
- package/dist/cli/handlers/observability/trace.js +102 -0
- package/dist/main.js +6 -2
- package/dist/utils/args.js +8 -0
- package/dist/utils/devops-error.js +28 -0
- package/dist/utils/git.js +29 -0
- package/dist/utils/http.js +118 -0
- package/dist/utils/index.js +15 -1
- package/dist/utils/output.js +360 -7
- package/dist/utils/poll.js +27 -0
- package/dist/utils/time.js +203 -0
- package/package.json +7 -5
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.handleDeploy = handleDeploy;
|
|
37
|
+
const api = __importStar(require("../../../api/index"));
|
|
38
|
+
const output_1 = require("../../../utils/output");
|
|
39
|
+
const index_1 = require("../../../api/deploy/index");
|
|
40
|
+
const polling_1 = require("./polling");
|
|
41
|
+
const format_1 = require("./format");
|
|
42
|
+
/** miaoda deploy [--branch ...] [--wait] [--timeout 300] */
|
|
43
|
+
async function handleDeploy(opts) {
|
|
44
|
+
const appID = opts.appId;
|
|
45
|
+
const resp = await api.deploy.createRelease({ appID, branch: opts.branch });
|
|
46
|
+
const pipelineTaskID = resp.pipelineTaskID ?? "";
|
|
47
|
+
if (!opts.wait) {
|
|
48
|
+
if (!(0, output_1.isJsonMode)()) {
|
|
49
|
+
process.stdout.write(`✓ Deployment triggered. (deploy-id: ${pipelineTaskID})\n`);
|
|
50
|
+
process.stdout.write(` hint: No terminal status yet. Poll every 2s with \`miaoda deploy get ${pipelineTaskID} --json\`; if no deploy-id is visible, first get it from \`miaoda deploy history --limit 1 --json\`.\n`);
|
|
51
|
+
}
|
|
52
|
+
(0, output_1.emit)({
|
|
53
|
+
data: { pipelineTaskID },
|
|
54
|
+
next_cursor: null,
|
|
55
|
+
has_more: false,
|
|
56
|
+
});
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
if (!(0, output_1.isJsonMode)()) {
|
|
60
|
+
process.stdout.write(`Waiting for deployment to complete... (deploy-id: ${pipelineTaskID})\n`);
|
|
61
|
+
}
|
|
62
|
+
const detail = await (0, polling_1.waitForPipeline)({
|
|
63
|
+
appID,
|
|
64
|
+
pipelineTaskID,
|
|
65
|
+
timeoutSec: opts.timeout ?? 300,
|
|
66
|
+
});
|
|
67
|
+
if (!(0, output_1.isJsonMode)()) {
|
|
68
|
+
if (detail.status === index_1.NodeStatus.SUCCESS) {
|
|
69
|
+
process.stdout.write("✓ 发布成功\n");
|
|
70
|
+
}
|
|
71
|
+
else if (detail.status === index_1.NodeStatus.FAILED) {
|
|
72
|
+
process.stdout.write("✗ 发布失败\n");
|
|
73
|
+
process.stdout.write(` hint: Run \`miaoda deploy error-log ${pipelineTaskID}\` to view error logs\n`);
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
process.stdout.write("• 发布已取消\n");
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
(0, output_1.emit)({
|
|
80
|
+
data: { pipelineTaskID, detail: (0, format_1.formatPipelineInstance)(detail) },
|
|
81
|
+
next_cursor: null,
|
|
82
|
+
has_more: false,
|
|
83
|
+
});
|
|
84
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.handleDeployErrorLog = handleDeployErrorLog;
|
|
37
|
+
const api = __importStar(require("../../../api/index"));
|
|
38
|
+
const output_1 = require("../../../utils/output");
|
|
39
|
+
const args_1 = require("../../../utils/args");
|
|
40
|
+
const index_1 = require("../../../api/deploy/index");
|
|
41
|
+
const helpers_1 = require("./helpers");
|
|
42
|
+
/** miaoda deploy error-log <deploy-id> */
|
|
43
|
+
async function handleDeployErrorLog(opts) {
|
|
44
|
+
if (!opts.deployId)
|
|
45
|
+
(0, args_1.failArgs)("<deploy-id> 必填");
|
|
46
|
+
const appID = opts.appId;
|
|
47
|
+
(0, helpers_1.parseDeployId)(opts.deployId); // 仅校验数字形式;URL 直接用原字符串
|
|
48
|
+
const instanceID = opts.deployId;
|
|
49
|
+
const resp = await api.deploy.getErrorLog({ appID, instanceID });
|
|
50
|
+
(0, output_1.emit)({
|
|
51
|
+
data: resp.errorJobs,
|
|
52
|
+
next_cursor: null,
|
|
53
|
+
has_more: false,
|
|
54
|
+
}, index_1.errorJobSchema);
|
|
55
|
+
// pretty 模式额外打一行整体状态。
|
|
56
|
+
if (!process.stdout.isTTY)
|
|
57
|
+
return;
|
|
58
|
+
const statusText = (0, index_1.nodeStatusText)(resp.status) ?? String(resp.status);
|
|
59
|
+
process.stdout.write(`\n— pipeline status: ${statusText}\n`);
|
|
60
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.formatStatusMetadata = formatStatusMetadata;
|
|
4
|
+
exports.formatSimpleInstance = formatSimpleInstance;
|
|
5
|
+
exports.formatPipelineInstance = formatPipelineInstance;
|
|
6
|
+
const index_1 = require("../../../api/deploy/index");
|
|
7
|
+
function formatStatusMetadata(statusCode) {
|
|
8
|
+
return {
|
|
9
|
+
status: (0, index_1.nodeStatusText)(statusCode) ?? `unknown(${String(statusCode)})`,
|
|
10
|
+
status_code: statusCode,
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
function formatSimpleInstance(instance) {
|
|
14
|
+
if (instance.status === undefined)
|
|
15
|
+
return { ...instance };
|
|
16
|
+
return {
|
|
17
|
+
...instance,
|
|
18
|
+
...formatStatusMetadata(instance.status),
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
function formatPipelineInstance(detail) {
|
|
22
|
+
const stages = Array.isArray(detail.stages) ? detail.stages : [];
|
|
23
|
+
return {
|
|
24
|
+
...detail,
|
|
25
|
+
...formatStatusMetadata(detail.status),
|
|
26
|
+
stages: stages.map((stage) => ({
|
|
27
|
+
...stage,
|
|
28
|
+
...formatStatusMetadata(stage.status),
|
|
29
|
+
jobs: stage.jobs.map((group) => group.map((job) => ({
|
|
30
|
+
...job,
|
|
31
|
+
...formatStatusMetadata(job.status),
|
|
32
|
+
steps: job.steps?.map((step) => ({
|
|
33
|
+
...step,
|
|
34
|
+
...formatStatusMetadata(step.status),
|
|
35
|
+
})),
|
|
36
|
+
}))),
|
|
37
|
+
})),
|
|
38
|
+
};
|
|
39
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.handleDeployGet = handleDeployGet;
|
|
37
|
+
const api = __importStar(require("../../../api/index"));
|
|
38
|
+
const output_1 = require("../../../utils/output");
|
|
39
|
+
const args_1 = require("../../../utils/args");
|
|
40
|
+
const error_1 = require("../../../utils/error");
|
|
41
|
+
const index_1 = require("../../../api/deploy/index");
|
|
42
|
+
const helpers_1 = require("./helpers");
|
|
43
|
+
const format_1 = require("./format");
|
|
44
|
+
/**
|
|
45
|
+
* 单页拉取上限:BAM listPipelineInstances 限制 1~500,取 500 让 deploy get
|
|
46
|
+
* 在最近 500 条记录里按 ID 命中。
|
|
47
|
+
*/
|
|
48
|
+
const DEPLOY_GET_LOOKUP_LIMIT = 500;
|
|
49
|
+
/**
|
|
50
|
+
* miaoda deploy get <deploy-id>
|
|
51
|
+
*
|
|
52
|
+
* BAM 没有 by-ID 的查询接口,复用 listPipelineInstances 在最近窗口里按 ID 筛一条。
|
|
53
|
+
* 命中失败时抛 DEPLOY_NOT_FOUND,提示用户用 history 查窗口。
|
|
54
|
+
*/
|
|
55
|
+
async function handleDeployGet(opts) {
|
|
56
|
+
if (!opts.deployId)
|
|
57
|
+
(0, args_1.failArgs)("<deploy-id> 必填");
|
|
58
|
+
const appID = opts.appId;
|
|
59
|
+
const deployId = (0, helpers_1.parseDeployId)(opts.deployId);
|
|
60
|
+
const resp = await api.deploy.listPipelineInstances({
|
|
61
|
+
appID,
|
|
62
|
+
limit: DEPLOY_GET_LOOKUP_LIMIT,
|
|
63
|
+
});
|
|
64
|
+
const instance = resp.instances?.find((it) => Number(it.ID) === deployId);
|
|
65
|
+
if (!instance) {
|
|
66
|
+
throw new error_1.AppError("DEPLOY_NOT_FOUND", `未在最近 ${String(DEPLOY_GET_LOOKUP_LIMIT)} 条记录中找到 deploy-id=${opts.deployId}`, {
|
|
67
|
+
next_actions: ["运行 `miaoda deploy history` 确认 deploy-id 是否在最近窗口内"],
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
(0, output_1.emit)({ data: (0, format_1.formatSimpleInstance)(instance), next_cursor: null, has_more: false }, index_1.deployGetSchema);
|
|
71
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseStatusFlag = parseStatusFlag;
|
|
4
|
+
exports.validateLimit = validateLimit;
|
|
5
|
+
exports.parseDeployId = parseDeployId;
|
|
6
|
+
const args_1 = require("../../../utils/args");
|
|
7
|
+
const index_1 = require("../../../api/deploy/index");
|
|
8
|
+
/**
|
|
9
|
+
* 把 CLI --status 字符串映射成 BAM NodeStatus 数字;非法值抛 ARGS_INVALID。
|
|
10
|
+
*
|
|
11
|
+
* 历史接口(CliListPipelineInstances)返回 SimpleInstance,状态语义是 pipeline 节点状态,
|
|
12
|
+
* 取值 todo / running / success / failed / canceled / hold_on。
|
|
13
|
+
*/
|
|
14
|
+
function parseStatusFlag(text) {
|
|
15
|
+
const value = (0, index_1.nodeStatusFromText)(text);
|
|
16
|
+
if (value === undefined) {
|
|
17
|
+
(0, args_1.failArgs)(`--status 无效:'${text}'。可选值:todo | running | success | failed | canceled | hold_on`);
|
|
18
|
+
}
|
|
19
|
+
return value;
|
|
20
|
+
}
|
|
21
|
+
/** limit/pageSize 校验(API 限制 1~100) */
|
|
22
|
+
function validateLimit(limit, defaultLimit = 50) {
|
|
23
|
+
const n = Number.isFinite(limit) ? limit : defaultLimit;
|
|
24
|
+
if (n <= 0 || n > 100) {
|
|
25
|
+
(0, args_1.failArgs)(`--limit 必须在 1~100 之间,收到 ${String(n)}`);
|
|
26
|
+
}
|
|
27
|
+
return n;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* 把 CLI <deploy-id> 字符串转成 i64 number。
|
|
31
|
+
*
|
|
32
|
+
* 语义上 deploy-id 即 pipelineTaskID(pipeline 实例 ID);BAM CLIGetReleaseLogs
|
|
33
|
+
* IDL 历史命名为 releaseID,但传入的就是这同一个值。
|
|
34
|
+
*/
|
|
35
|
+
function parseDeployId(text) {
|
|
36
|
+
const n = Number(text);
|
|
37
|
+
if (!Number.isFinite(n) || !/^\d+$/.test(text)) {
|
|
38
|
+
(0, args_1.failArgs)(`<deploy-id> 必须是数字 ID,收到 '${text}'`);
|
|
39
|
+
}
|
|
40
|
+
return n;
|
|
41
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.handleDeployHistory = handleDeployHistory;
|
|
37
|
+
const api = __importStar(require("../../../api/index"));
|
|
38
|
+
const output_1 = require("../../../utils/output");
|
|
39
|
+
const time_1 = require("../../../utils/time");
|
|
40
|
+
const index_1 = require("../../../api/deploy/index");
|
|
41
|
+
const helpers_1 = require("./helpers");
|
|
42
|
+
const format_1 = require("./format");
|
|
43
|
+
/** miaoda deploy history */
|
|
44
|
+
async function handleDeployHistory(opts) {
|
|
45
|
+
const appID = opts.appId;
|
|
46
|
+
const limit = (0, helpers_1.validateLimit)(opts.limit ?? 50);
|
|
47
|
+
const req = {
|
|
48
|
+
appID,
|
|
49
|
+
limit,
|
|
50
|
+
pageToken: opts.cursor,
|
|
51
|
+
};
|
|
52
|
+
if (opts.status)
|
|
53
|
+
req.status = [(0, helpers_1.parseStatusFlag)(opts.status)];
|
|
54
|
+
// BAM startTimestamp / endTimestamp 单位是秒(IDL desc:单位:秒)
|
|
55
|
+
if (opts.since !== undefined)
|
|
56
|
+
req.startTimestamp = msToSec((0, time_1.parseToMs)(opts.since));
|
|
57
|
+
if (opts.until !== undefined)
|
|
58
|
+
req.endTimestamp = msToSec((0, time_1.parseToMs)(opts.until));
|
|
59
|
+
const resp = await api.deploy.listPipelineInstances(req);
|
|
60
|
+
(0, output_1.emit)({
|
|
61
|
+
data: (resp.instances ?? []).map(format_1.formatSimpleInstance),
|
|
62
|
+
next_cursor: resp.hasMore ? (resp.nextPageToken ?? null) : null,
|
|
63
|
+
has_more: resp.hasMore ?? false,
|
|
64
|
+
}, index_1.deployHistorySchema);
|
|
65
|
+
}
|
|
66
|
+
function msToSec(ms) {
|
|
67
|
+
if (ms === undefined)
|
|
68
|
+
return undefined;
|
|
69
|
+
return Math.floor(ms / 1000);
|
|
70
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DEFAULT_POLL_INTERVAL_MS = exports.waitForPipeline = exports.handleDeployErrorLog = exports.handleDeployHistory = exports.handleDeployGet = exports.handleDeploy = void 0;
|
|
4
|
+
var deploy_1 = require("./deploy");
|
|
5
|
+
Object.defineProperty(exports, "handleDeploy", { enumerable: true, get: function () { return deploy_1.handleDeploy; } });
|
|
6
|
+
var get_1 = require("./get");
|
|
7
|
+
Object.defineProperty(exports, "handleDeployGet", { enumerable: true, get: function () { return get_1.handleDeployGet; } });
|
|
8
|
+
var history_1 = require("./history");
|
|
9
|
+
Object.defineProperty(exports, "handleDeployHistory", { enumerable: true, get: function () { return history_1.handleDeployHistory; } });
|
|
10
|
+
var error_log_1 = require("./error-log");
|
|
11
|
+
Object.defineProperty(exports, "handleDeployErrorLog", { enumerable: true, get: function () { return error_log_1.handleDeployErrorLog; } });
|
|
12
|
+
var polling_1 = require("./polling");
|
|
13
|
+
Object.defineProperty(exports, "waitForPipeline", { enumerable: true, get: function () { return polling_1.waitForPipeline; } });
|
|
14
|
+
Object.defineProperty(exports, "DEFAULT_POLL_INTERVAL_MS", { enumerable: true, get: function () { return polling_1.DEFAULT_POLL_INTERVAL_MS; } });
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.DEFAULT_POLL_INTERVAL_MS = void 0;
|
|
40
|
+
exports.waitForPipeline = waitForPipeline;
|
|
41
|
+
const ora_1 = __importDefault(require("ora"));
|
|
42
|
+
const api = __importStar(require("../../../api/index"));
|
|
43
|
+
const error_1 = require("../../../utils/error");
|
|
44
|
+
const output_1 = require("../../../utils/output");
|
|
45
|
+
const index_1 = require("../../../api/deploy/index");
|
|
46
|
+
/** 默认轮询间隔(毫秒) */
|
|
47
|
+
exports.DEFAULT_POLL_INTERVAL_MS = 2_000;
|
|
48
|
+
const TERMINAL_STATUSES = [
|
|
49
|
+
index_1.NodeStatus.SUCCESS,
|
|
50
|
+
index_1.NodeStatus.FAILED,
|
|
51
|
+
index_1.NodeStatus.CANCELED,
|
|
52
|
+
];
|
|
53
|
+
function defaultSleep(ms) {
|
|
54
|
+
return new Promise((res) => setTimeout(res, ms));
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* 轮询 pipeline 状态直到终态或超时。
|
|
58
|
+
*
|
|
59
|
+
* - JSON 模式:轮询期间静默;终态后由 caller 输出最终信封。
|
|
60
|
+
* - Pretty 非 TTY:同 JSON。
|
|
61
|
+
* - Pretty TTY:底部行用 braille spinner 显示当前正在跑的 stage(每 80ms 跳一帧),
|
|
62
|
+
* stage 转终态时把 ✓ stage(12.3s) 打到 spinner 上方然后清掉 spinner 行。
|
|
63
|
+
*
|
|
64
|
+
* 终态返回最终 PipelineInstance,调用方再决定怎么 emit。
|
|
65
|
+
*/
|
|
66
|
+
async function waitForPipeline(opts) {
|
|
67
|
+
const interval = opts.intervalMs ?? exports.DEFAULT_POLL_INTERVAL_MS;
|
|
68
|
+
const timeoutMs = opts.timeoutSec * 1000;
|
|
69
|
+
const sleep = opts.sleep ?? defaultSleep;
|
|
70
|
+
const now = opts.now ?? Date.now;
|
|
71
|
+
const start = now();
|
|
72
|
+
// ora 自身在非 TTY 下会降级为不动画,但我们额外加 isJsonMode 闸门:JSON / 字段选择
|
|
73
|
+
// 模式下完全静默。
|
|
74
|
+
const showProgress = !(0, output_1.isJsonMode)() && process.stdout.isTTY;
|
|
75
|
+
const printedStages = new Set();
|
|
76
|
+
const spinner = showProgress
|
|
77
|
+
? (0, ora_1.default)({ text: "等待调度", spinner: "dots", stream: process.stdout }).start()
|
|
78
|
+
: null;
|
|
79
|
+
try {
|
|
80
|
+
for (;;) {
|
|
81
|
+
const resp = await api.deploy.queryPipelineInstance({
|
|
82
|
+
appID: opts.appID,
|
|
83
|
+
instanceID: opts.pipelineTaskID,
|
|
84
|
+
});
|
|
85
|
+
const detail = normalizePipelineInstance(resp);
|
|
86
|
+
if (spinner)
|
|
87
|
+
advanceProgress(detail, printedStages, spinner);
|
|
88
|
+
if (TERMINAL_STATUSES.includes(detail.status)) {
|
|
89
|
+
return detail;
|
|
90
|
+
}
|
|
91
|
+
if (now() - start >= timeoutMs) {
|
|
92
|
+
throw new error_1.AppError("DEPLOY_TIMEOUT", `轮询发布状态超时(${String(opts.timeoutSec)}s)`, {
|
|
93
|
+
retryable: true,
|
|
94
|
+
next_actions: [
|
|
95
|
+
`Run \`miaoda deploy get <deploy-id>\` 查看最新状态`,
|
|
96
|
+
`加大 --timeout 后重试`,
|
|
97
|
+
],
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
await sleep(interval);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
finally {
|
|
104
|
+
spinner?.stop();
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* 每轮 poll 的进度推进:刚转终态的 stage 用 stopAndPersist 落定为永久行,
|
|
109
|
+
* 再把 spinner 文本切到当前 running stage;没有 running 时显示"等待调度"。
|
|
110
|
+
*/
|
|
111
|
+
function advanceProgress(detail, printed, spinner) {
|
|
112
|
+
const stages = Array.isArray(detail.stages) ? detail.stages : [];
|
|
113
|
+
for (const stage of stages) {
|
|
114
|
+
if (printed.has(stage.id))
|
|
115
|
+
continue;
|
|
116
|
+
if (!TERMINAL_STATUSES.includes(stage.status))
|
|
117
|
+
continue;
|
|
118
|
+
spinner.stopAndPersist({
|
|
119
|
+
symbol: stageSymbol(stage),
|
|
120
|
+
text: formatStageBody(stage),
|
|
121
|
+
});
|
|
122
|
+
printed.add(stage.id);
|
|
123
|
+
}
|
|
124
|
+
const running = stages.find((s) => s.status === index_1.NodeStatus.RUNNING);
|
|
125
|
+
const text = running ? `${running.name} 执行中` : "等待调度";
|
|
126
|
+
if (spinner.isSpinning) {
|
|
127
|
+
spinner.text = text;
|
|
128
|
+
}
|
|
129
|
+
else {
|
|
130
|
+
spinner.start(text);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
function normalizePipelineInstance(resp) {
|
|
134
|
+
const keyedDetail = readPipelineDetail(resp, "pipelineInstanceDetail") ?? readPipelineDetail(resp, "detail");
|
|
135
|
+
if (keyedDetail)
|
|
136
|
+
return keyedDetail;
|
|
137
|
+
if (isPipelineInstance(resp))
|
|
138
|
+
return resp;
|
|
139
|
+
throw new error_1.AppError("DEPLOY_RESPONSE_INVALID", "发布状态响应缺少 pipeline detail", {
|
|
140
|
+
next_actions: ["使用 --verbose 重试以查看请求 logid,并联系平台排查响应结构"],
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
function readPipelineDetail(resp, key) {
|
|
144
|
+
if (!(key in resp))
|
|
145
|
+
return undefined;
|
|
146
|
+
const detail = resp[key];
|
|
147
|
+
return isPipelineInstance(detail) ? detail : undefined;
|
|
148
|
+
}
|
|
149
|
+
function isPipelineInstance(value) {
|
|
150
|
+
if (typeof value !== "object" || value === null)
|
|
151
|
+
return false;
|
|
152
|
+
const item = value;
|
|
153
|
+
return typeof item.status === "number";
|
|
154
|
+
}
|
|
155
|
+
function stageSymbol(stage) {
|
|
156
|
+
return stage.status === index_1.NodeStatus.SUCCESS ? "✓" : stage.status === index_1.NodeStatus.FAILED ? "✗" : "•";
|
|
157
|
+
}
|
|
158
|
+
function formatStageBody(stage) {
|
|
159
|
+
const cost = stage.costTime >= 0 ? `(${(stage.costTime / 1000).toFixed(1)}s)` : "";
|
|
160
|
+
const status = (0, index_1.nodeStatusText)(stage.status) ?? String(stage.status);
|
|
161
|
+
return `${stage.name}${cost ? ` ${cost}` : ""} ${status}`.trim();
|
|
162
|
+
}
|
|
@@ -44,7 +44,6 @@ const api = __importStar(require("../../../api/index"));
|
|
|
44
44
|
const output_1 = require("../../../utils/output");
|
|
45
45
|
const render_1 = require("../../../utils/render");
|
|
46
46
|
const error_1 = require("../../../utils/error");
|
|
47
|
-
const shared_1 = require("../../../cli/commands/shared");
|
|
48
47
|
const colors_1 = require("../../../utils/colors");
|
|
49
48
|
const MAX_UPLOAD_BYTES = 100 * 1024 * 1024;
|
|
50
49
|
/**
|
|
@@ -233,7 +232,7 @@ async function handleDownload(appId, remoteRaw, localRaw) {
|
|
|
233
232
|
}
|
|
234
233
|
}
|
|
235
234
|
async function handleFileCp(src, dst, opts) {
|
|
236
|
-
const appId =
|
|
235
|
+
const appId = opts.appId;
|
|
237
236
|
// src 本地存在 → upload;其他情况(file_ref / `/path` / 裸文件名)→ download
|
|
238
237
|
if (isLocalSrc(src)) {
|
|
239
238
|
return handleUpload(appId, src, dst, opts.rename);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.handleFileSign = exports.handleFileRm = exports.handleFileCp = exports.handleFileStat = exports.handleFileLs = void 0;
|
|
3
|
+
exports.handleFileQuota = exports.handleFileSign = exports.handleFileRm = exports.handleFileCp = exports.handleFileStat = exports.handleFileLs = void 0;
|
|
4
4
|
var ls_1 = require("./ls");
|
|
5
5
|
Object.defineProperty(exports, "handleFileLs", { enumerable: true, get: function () { return ls_1.handleFileLs; } });
|
|
6
6
|
var stat_1 = require("./stat");
|
|
@@ -11,3 +11,5 @@ var rm_1 = require("./rm");
|
|
|
11
11
|
Object.defineProperty(exports, "handleFileRm", { enumerable: true, get: function () { return rm_1.handleFileRm; } });
|
|
12
12
|
var sign_1 = require("./sign");
|
|
13
13
|
Object.defineProperty(exports, "handleFileSign", { enumerable: true, get: function () { return sign_1.handleFileSign; } });
|
|
14
|
+
var quota_1 = require("./quota");
|
|
15
|
+
Object.defineProperty(exports, "handleFileQuota", { enumerable: true, get: function () { return quota_1.handleFileQuota; } });
|
|
@@ -38,7 +38,6 @@ const api = __importStar(require("../../../api/index"));
|
|
|
38
38
|
const output_1 = require("../../../utils/output");
|
|
39
39
|
const render_1 = require("../../../utils/render");
|
|
40
40
|
const error_1 = require("../../../utils/error");
|
|
41
|
-
const shared_1 = require("../../../cli/commands/shared");
|
|
42
41
|
const index_1 = require("../../../api/file/index");
|
|
43
42
|
/**
|
|
44
43
|
* 把位置参数 `query` 路由到 `--path` 或 `--name`:
|
|
@@ -65,7 +64,7 @@ function resolveQueryRouting(opts) {
|
|
|
65
64
|
return { name: opts.query };
|
|
66
65
|
}
|
|
67
66
|
async function handleFileLs(opts) {
|
|
68
|
-
const appId =
|
|
67
|
+
const appId = opts.appId;
|
|
69
68
|
// commander 已经把 --limit 解析为 number;保留 ?? undefined 兼容老调用
|
|
70
69
|
const limit = opts.limit;
|
|
71
70
|
const sizeGt = opts.sizeGt ? (0, render_1.parseSize)(opts.sizeGt) : undefined;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.handleFileQuota = handleFileQuota;
|
|
37
|
+
const api = __importStar(require("../../../api/index"));
|
|
38
|
+
const shared_1 = require("../../../cli/commands/shared");
|
|
39
|
+
const output_1 = require("../../../utils/output");
|
|
40
|
+
const render_1 = require("../../../utils/render");
|
|
41
|
+
async function handleFileQuota(opts) {
|
|
42
|
+
const appId = (0, shared_1.resolveAppId)(opts);
|
|
43
|
+
const data = await api.file.getStorageQuota({ appId });
|
|
44
|
+
if ((0, output_1.isJsonMode)()) {
|
|
45
|
+
// 配额未对接(storageQuotaBytes=0)时,quota / usage_percent 字段都不输出
|
|
46
|
+
const out = {
|
|
47
|
+
storageUsedBytes: data.storageUsedBytes,
|
|
48
|
+
files: data.files,
|
|
49
|
+
};
|
|
50
|
+
if (data.storageQuotaBytes > 0) {
|
|
51
|
+
out.storageQuotaBytes = data.storageQuotaBytes;
|
|
52
|
+
out.usagePercent = data.usagePercent;
|
|
53
|
+
}
|
|
54
|
+
(0, output_1.emitOk)((0, output_1.snakeCaseKeys)(out));
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
// PRD:单行 "Storage: 150 MB / 1 GB (15%)";配额未对接时只显示 used
|
|
58
|
+
const tty = (0, render_1.isStdoutTty)();
|
|
59
|
+
const storageLine = data.storageQuotaBytes > 0
|
|
60
|
+
? `${(0, render_1.formatSize)(data.storageUsedBytes)} / ${(0, render_1.formatSize)(data.storageQuotaBytes)} (${data.usagePercent.toFixed(1)}%)`
|
|
61
|
+
: (0, render_1.formatSize)(data.storageUsedBytes);
|
|
62
|
+
(0, output_1.emit)((0, render_1.renderKeyValue)([
|
|
63
|
+
["Storage", storageLine],
|
|
64
|
+
["Files", String(data.files)],
|
|
65
|
+
], tty));
|
|
66
|
+
}
|