@lark-apaas/miaoda-cli 0.1.2 → 0.1.3
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/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/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 +6 -5
- package/dist/cli/commands/deploy/index.js +155 -0
- package/dist/cli/commands/file/index.js +6 -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/data.js +2 -3
- 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/ls.js +1 -2
- 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 +13 -1
- package/dist/utils/output.js +338 -7
- package/dist/utils/time.js +203 -0
- package/package.json +7 -5
|
@@ -1,11 +1,26 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.failArgs = void 0;
|
|
4
|
+
exports.appIdOption = appIdOption;
|
|
5
|
+
exports.branchOption = branchOption;
|
|
3
6
|
exports.softRequiredOption = softRequiredOption;
|
|
4
7
|
exports.resolveAppId = resolveAppId;
|
|
5
8
|
exports.withHelp = withHelp;
|
|
6
|
-
exports.
|
|
9
|
+
exports.caseInsensitiveChoice = caseInsensitiveChoice;
|
|
10
|
+
exports.validateTimeOptions = validateTimeOptions;
|
|
11
|
+
exports.rejectCliOverride = rejectCliOverride;
|
|
7
12
|
const commander_1 = require("commander");
|
|
8
13
|
const error_1 = require("../../utils/error");
|
|
14
|
+
const time_1 = require("../../utils/time");
|
|
15
|
+
const args_1 = require("../../utils/args");
|
|
16
|
+
Object.defineProperty(exports, "failArgs", { enumerable: true, get: function () { return args_1.failArgs; } });
|
|
17
|
+
/** --app-id option,需要应用上下文的命令自行 .addOption(appIdOption()) */
|
|
18
|
+
function appIdOption() {
|
|
19
|
+
return new commander_1.Option("--app-id <id>", "指定目标应用").env("MIAODA_APP_ID");
|
|
20
|
+
}
|
|
21
|
+
function branchOption() {
|
|
22
|
+
return new commander_1.Option("--branch <branch>", "分支(优先级:--branch > 当前仓库 HEAD 分支;非 git 目录回退应用默认分支)").env("LOCAL_MOCK_MIAODA_DEPLOY_BRANCH");
|
|
23
|
+
}
|
|
9
24
|
/**
|
|
10
25
|
* soft-required: Commander 类型上 optional,runtime 校验必填。
|
|
11
26
|
*/
|
|
@@ -27,11 +42,15 @@ function resolveAppId(opts) {
|
|
|
27
42
|
}
|
|
28
43
|
return id;
|
|
29
44
|
}
|
|
30
|
-
/**
|
|
45
|
+
/**
|
|
46
|
+
* 包裹 handler,缺 soft-required 参数 / 自定义校验失败时打 help 并退出。
|
|
47
|
+
*
|
|
48
|
+
* 兼容带位置参数的 action 签名(如 `(arg1: string, opts) => ...`)。
|
|
49
|
+
*/
|
|
31
50
|
function withHelp(cmd, handler) {
|
|
32
|
-
return async (
|
|
51
|
+
return async (...args) => {
|
|
33
52
|
try {
|
|
34
|
-
await handler(
|
|
53
|
+
await handler(...args);
|
|
35
54
|
}
|
|
36
55
|
catch (err) {
|
|
37
56
|
if (err instanceof error_1.AppError && err.code === "ARGS_INVALID") {
|
|
@@ -44,7 +63,64 @@ function withHelp(cmd, handler) {
|
|
|
44
63
|
}
|
|
45
64
|
};
|
|
46
65
|
}
|
|
47
|
-
/**
|
|
48
|
-
|
|
49
|
-
|
|
66
|
+
/**
|
|
67
|
+
* 大小写不敏感的 choice argParser:把用户输入按 lowerCase 匹配回 canonical 数组里
|
|
68
|
+
* 的同名值(保留 canonical 大小写),未命中抛 Commander 的 InvalidArgumentError
|
|
69
|
+
* (exit code 1,自带友好错误)。
|
|
70
|
+
*
|
|
71
|
+
* 必须先 .choices(canonical)、再 .argParser()——Commander 内部 .choices() 会
|
|
72
|
+
* 重置 parseArg,反过来调会让 argParser 失效。.choices() 仅留给 help 渲染
|
|
73
|
+
* "choices: A, B, C",实际白名单校验由 argParser 接管。
|
|
74
|
+
*
|
|
75
|
+
* new Option("--level <level>", "日志级别(不区分大小写)")
|
|
76
|
+
* .choices(["DEBUG", "INFO", "WARN", "ERROR"])
|
|
77
|
+
* .argParser(caseInsensitiveChoice(["DEBUG", "INFO", "WARN", "ERROR"]));
|
|
78
|
+
*/
|
|
79
|
+
function caseInsensitiveChoice(canonical) {
|
|
80
|
+
const map = new Map(canonical.map((v) => [v.toLowerCase(), v]));
|
|
81
|
+
return (raw) => {
|
|
82
|
+
const hit = map.get(raw.toLowerCase());
|
|
83
|
+
if (hit === undefined) {
|
|
84
|
+
throw new commander_1.InvalidArgumentError(`Allowed choices are ${canonical.join(", ")} (case-insensitive).`);
|
|
85
|
+
}
|
|
86
|
+
return hit;
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* --since / --until 等时间参数的 action 阶段校验。
|
|
91
|
+
*
|
|
92
|
+
* Commander 的 argParser 会在 action 前直接按 parser error 退出(exit 1),
|
|
93
|
+
* 绕过 withHelp 的 ARGS_INVALID → exit 2 路径;所以时间参数在 action 内先
|
|
94
|
+
* 校验一遍,再把原始字符串交给 handler 解析成接口需要的单位。
|
|
95
|
+
*/
|
|
96
|
+
function validateTimeOptions(opts, ...names) {
|
|
97
|
+
for (const name of names) {
|
|
98
|
+
const value = opts[name];
|
|
99
|
+
if (value === undefined)
|
|
100
|
+
continue;
|
|
101
|
+
if (typeof value !== "string") {
|
|
102
|
+
(0, args_1.failArgs)(`--${name.replace(/([A-Z])/g, "-$1").toLowerCase()} 必须是时间字符串`);
|
|
103
|
+
}
|
|
104
|
+
(0, time_1.parseTimeToMs)(value);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* 拒绝 CLI 显式覆盖:用于 hideHelp() + .env() 的"沙箱注入参数"(如 --app-id / --branch)。
|
|
109
|
+
*
|
|
110
|
+
* Commander 的 getOptionValueSource() 区分来源(cli / env / default / config / undefined);
|
|
111
|
+
* 用户在 CLI 上显式传时 source === "cli",此时抛 ARGS_INVALID(exit 2 + help)。
|
|
112
|
+
*
|
|
113
|
+
* 用法:在 action 头部一行调用——
|
|
114
|
+
* cmd.action(withHelp(cmd, async (rawOpts) => {
|
|
115
|
+
* rejectCliOverride(cmd, "appId", "branch");
|
|
116
|
+
* ...
|
|
117
|
+
* }));
|
|
118
|
+
*/
|
|
119
|
+
function rejectCliOverride(cmd, ...optNames) {
|
|
120
|
+
for (const name of optNames) {
|
|
121
|
+
if (cmd.getOptionValueSource(name) === "cli") {
|
|
122
|
+
const flag = "--" + name.replace(/([A-Z])/g, "-$1").toLowerCase();
|
|
123
|
+
(0, args_1.failArgs)(`${flag} 由沙箱/本地配置注入,不允许显式传递`);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
50
126
|
}
|
|
@@ -0,0 +1,47 @@
|
|
|
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.handleAppGet = handleAppGet;
|
|
37
|
+
const api = __importStar(require("../../../api/index"));
|
|
38
|
+
const output_1 = require("../../../utils/output");
|
|
39
|
+
const index_1 = require("../../../api/app/index");
|
|
40
|
+
/** miaoda app get [--app-id <id>] */
|
|
41
|
+
async function handleAppGet(opts) {
|
|
42
|
+
const appID = opts.appId;
|
|
43
|
+
const resp = await api.app.getAppInfo(appID);
|
|
44
|
+
// BAM 在 status_code=0 时 data 字段含 appInfo;不存在则 fallback 空对象
|
|
45
|
+
const meta = resp.appInfo?.appMeta ?? {};
|
|
46
|
+
(0, output_1.emit)({ data: meta }, index_1.appMetaSchema);
|
|
47
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.handleAppUpdate = exports.handleAppGet = void 0;
|
|
4
|
+
var get_1 = require("./get");
|
|
5
|
+
Object.defineProperty(exports, "handleAppGet", { enumerable: true, get: function () { return get_1.handleAppGet; } });
|
|
6
|
+
var update_1 = require("./update");
|
|
7
|
+
Object.defineProperty(exports, "handleAppUpdate", { enumerable: true, get: function () { return update_1.handleAppUpdate; } });
|
|
@@ -0,0 +1,59 @@
|
|
|
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.handleAppUpdate = handleAppUpdate;
|
|
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/app/index");
|
|
41
|
+
/** miaoda app update [--app-id <id>] [--name <n>] [--description <d>] */
|
|
42
|
+
async function handleAppUpdate(opts) {
|
|
43
|
+
if (opts.name === undefined && opts.description === undefined) {
|
|
44
|
+
(0, args_1.failArgs)("至少需要 --name 或 --description 中的一个");
|
|
45
|
+
}
|
|
46
|
+
const appID = opts.appId;
|
|
47
|
+
await api.app.updateAppMeta({
|
|
48
|
+
appID,
|
|
49
|
+
name: opts.name,
|
|
50
|
+
description: opts.description,
|
|
51
|
+
});
|
|
52
|
+
// 服务端不回写新 meta,本地再 fetch 一次拿最新值给用户
|
|
53
|
+
const resp = await api.app.getAppInfo(appID);
|
|
54
|
+
const meta = resp.appInfo?.appMeta ?? {};
|
|
55
|
+
if (!(0, output_1.isJsonMode)()) {
|
|
56
|
+
process.stdout.write("✓ App updated successfully\n");
|
|
57
|
+
}
|
|
58
|
+
(0, output_1.emit)({ data: meta }, index_1.appMetaSchema);
|
|
59
|
+
}
|
|
@@ -40,13 +40,12 @@ const path = __importStar(require("node:path"));
|
|
|
40
40
|
const api = __importStar(require("../../../api/index"));
|
|
41
41
|
const error_1 = require("../../../utils/error");
|
|
42
42
|
const output_1 = require("../../../utils/output");
|
|
43
|
-
const shared_1 = require("../../../cli/commands/shared");
|
|
44
43
|
const render_1 = require("../../../utils/render");
|
|
45
44
|
// P0 规格(对齐技术方案关键决策 2)
|
|
46
45
|
const MAX_SIZE_BYTES = 1 * 1024 * 1024; // 1 MB
|
|
47
46
|
const MAX_ROWS = 5000;
|
|
48
47
|
async function handleDbDataImport(file, opts) {
|
|
49
|
-
const appId =
|
|
48
|
+
const appId = opts.appId;
|
|
50
49
|
const ext = path.extname(file).toLowerCase();
|
|
51
50
|
const format = resolveFormat(opts.format, ext, "import");
|
|
52
51
|
let body;
|
|
@@ -95,7 +94,7 @@ async function handleDbDataImport(file, opts) {
|
|
|
95
94
|
: `OK Imported ${file} -> table '${result.tableName}' (${String(result.recordCount)} rows)`);
|
|
96
95
|
}
|
|
97
96
|
async function handleDbDataExport(table, opts) {
|
|
98
|
-
const appId =
|
|
97
|
+
const appId = opts.appId;
|
|
99
98
|
const format = resolveFormat(opts.format, undefined, "export", "csv");
|
|
100
99
|
const outputPath = opts.file ?? `${table}.${format}`;
|
|
101
100
|
const limit = opts.limit ? Number(opts.limit) : MAX_ROWS;
|
|
@@ -39,12 +39,11 @@ const api = __importStar(require("../../../api/index"));
|
|
|
39
39
|
const error_1 = require("../../../utils/error");
|
|
40
40
|
const output_1 = require("../../../utils/output");
|
|
41
41
|
const render_1 = require("../../../utils/render");
|
|
42
|
-
const shared_1 = require("../../../cli/commands/shared");
|
|
43
42
|
const colors_1 = require("../../../utils/colors");
|
|
44
43
|
const index_1 = require("../../../api/db/index");
|
|
45
44
|
// ── schema list ──
|
|
46
45
|
async function handleDbSchemaList(opts) {
|
|
47
|
-
const appId =
|
|
46
|
+
const appId = opts.appId;
|
|
48
47
|
const resp = await api.db.getSchema({
|
|
49
48
|
appId,
|
|
50
49
|
format: "schema",
|
|
@@ -80,7 +79,7 @@ async function handleDbSchemaList(opts) {
|
|
|
80
79
|
(0, output_1.emit)(tty ? (0, render_1.renderAlignedTable)(headers, rows) : (0, render_1.renderTsv)(headers, rows));
|
|
81
80
|
}
|
|
82
81
|
async function handleDbSchemaGet(table, opts) {
|
|
83
|
-
const appId =
|
|
82
|
+
const appId = opts.appId;
|
|
84
83
|
const tty = (0, render_1.isStdoutTty)();
|
|
85
84
|
const forceDdl = Boolean(opts.ddl);
|
|
86
85
|
const wantsStructured = (0, output_1.isJsonMode)() || (tty && !forceDdl);
|
|
@@ -42,7 +42,6 @@ const error_1 = require("../../../utils/error");
|
|
|
42
42
|
const output_1 = require("../../../utils/output");
|
|
43
43
|
const config_1 = require("../../../utils/config");
|
|
44
44
|
const logger_1 = require("../../../utils/logger");
|
|
45
|
-
const shared_1 = require("../../../cli/commands/shared");
|
|
46
45
|
const render_1 = require("../../../utils/render");
|
|
47
46
|
const colors_1 = require("../../../utils/colors");
|
|
48
47
|
const fuzzy_match_1 = require("../../../utils/fuzzy-match");
|
|
@@ -62,7 +61,7 @@ const node_path_1 = __importDefault(require("node:path"));
|
|
|
62
61
|
* 末尾汇总,--json 输出 data 数组。
|
|
63
62
|
*/
|
|
64
63
|
async function handleDbSql(query, opts) {
|
|
65
|
-
const appId =
|
|
64
|
+
const appId = opts.appId;
|
|
66
65
|
const sql = await readSql(query);
|
|
67
66
|
if (!sql.trim()) {
|
|
68
67
|
throw new error_1.AppError("ARGS_INVALID", "Empty SQL (no inline query and stdin is empty)");
|
|
@@ -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
|
+
}
|