@cloudbase/cli 2.9.4 → 2.9.6
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/cloudbase-cli-2.7.8.tgz +0 -0
- package/lib/commands/cloudrun/base.js +30 -25
- package/lib/utils/template-manager.js +78 -10
- package/package.json +2 -2
- package/types/utils/template-manager.d.ts +2 -0
- package/dist/standalone/ccr.js +0 -78668
- package/dist/standalone/cli.js +0 -625713
|
Binary file
|
|
@@ -79,6 +79,10 @@ const AccessType = {
|
|
|
79
79
|
MINIAPP: 'MINIAPP',
|
|
80
80
|
VPC: 'VPC'
|
|
81
81
|
};
|
|
82
|
+
const ResourceTitle = {
|
|
83
|
+
container: '容器型云托管',
|
|
84
|
+
function: '函数型云托管'
|
|
85
|
+
};
|
|
82
86
|
function getCloudrunService(envId) {
|
|
83
87
|
return __awaiter(this, void 0, void 0, function* () {
|
|
84
88
|
const region = yield (0, toolbox_1.getRegion)();
|
|
@@ -598,12 +602,17 @@ let CloudRunDeployCommand = class CloudRunDeployCommand extends common_1.Command
|
|
|
598
602
|
}
|
|
599
603
|
serviceName = yield _inputServiceName(defaultName);
|
|
600
604
|
}
|
|
605
|
+
const containerConfigFile = 'container.config.json';
|
|
606
|
+
const containerConfigPath = path_1.default.join(targetDir, containerConfigFile);
|
|
607
|
+
if (yield fs_extra_1.default.pathExists(containerConfigPath)) {
|
|
608
|
+
log.warn(`CLI 中 ${containerConfigFile} 文件将不会生效,请通过命令行参数进行配置!`);
|
|
609
|
+
}
|
|
601
610
|
if (!force) {
|
|
602
611
|
const answers = yield inquirer_1.default.prompt([
|
|
603
612
|
{
|
|
604
613
|
type: 'confirm',
|
|
605
614
|
name: 'confirm',
|
|
606
|
-
message:
|
|
615
|
+
message: '即将开始部署,是否确认继续?',
|
|
607
616
|
default: true
|
|
608
617
|
}
|
|
609
618
|
]);
|
|
@@ -643,29 +652,25 @@ let CloudRunDeployCommand = class CloudRunDeployCommand extends common_1.Command
|
|
|
643
652
|
function _runDeploy() {
|
|
644
653
|
return __awaiter(this, void 0, void 0, function* () {
|
|
645
654
|
try {
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
})
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
}, function (message) {
|
|
660
|
-
(0, utils_2.trackCallback)(message, log);
|
|
661
|
-
});
|
|
655
|
+
utils_2.trackCallback === null || utils_2.trackCallback === void 0 ? void 0 : (0, utils_2.trackCallback)({
|
|
656
|
+
details: `正在提交${ResourceTitle[serverType]} ${serviceName} 中,请稍候...`,
|
|
657
|
+
status: 'progress'
|
|
658
|
+
}, log);
|
|
659
|
+
yield cloudrunService.deploy({
|
|
660
|
+
serverName: serviceName,
|
|
661
|
+
targetPath: targetDir,
|
|
662
|
+
serverConfig: Object.assign({}, (port ? { Port: Number(port) } : {}))
|
|
663
|
+
});
|
|
664
|
+
utils_2.trackCallback === null || utils_2.trackCallback === void 0 ? void 0 : (0, utils_2.trackCallback)({
|
|
665
|
+
details: `提交${ResourceTitle[serverType]} ${serviceName} 已完成!`,
|
|
666
|
+
status: 'done'
|
|
667
|
+
}, log);
|
|
662
668
|
yield (0, utils_2.upsertCloudbaserc)(targetDir, {
|
|
663
669
|
envId,
|
|
664
670
|
cloudrun: { name: serviceName }
|
|
665
671
|
});
|
|
666
|
-
const { envId: _envId, name, resourceType: _resourceType } = res === null || res === void 0 ? void 0 : res.data;
|
|
667
672
|
(0, utils_2.trackCallback)({
|
|
668
|
-
details: `请打开链接查看部署状态: https://tcb.cloud.tencent.com/dev?envId=${
|
|
673
|
+
details: `请打开链接查看部署状态: https://tcb.cloud.tencent.com/dev?envId=${envId}#/platform-run/service/detail?serverName=${serviceName}&tabId=deploy&envId=${envId}`
|
|
669
674
|
}, log);
|
|
670
675
|
}
|
|
671
676
|
catch (e) {
|
|
@@ -675,7 +680,7 @@ let CloudRunDeployCommand = class CloudRunDeployCommand extends common_1.Command
|
|
|
675
680
|
{
|
|
676
681
|
type: 'confirm',
|
|
677
682
|
name: 'confirm',
|
|
678
|
-
message:
|
|
683
|
+
message: '平台当前有部署发布任务正在运行中。确认继续部署,正在执行的部署任务将被取消,并立即部署最新的代码',
|
|
679
684
|
default: true
|
|
680
685
|
}
|
|
681
686
|
])
|
|
@@ -743,11 +748,11 @@ let CloudRunRunCommand = class CloudRunRunCommand extends common_1.Command {
|
|
|
743
748
|
options: [
|
|
744
749
|
{
|
|
745
750
|
flags: '--runMode <runMode>',
|
|
746
|
-
desc:
|
|
751
|
+
desc: '运行模式,可选值: normal(普通函数) | agent(函数式 Agent),默认值: normal'
|
|
747
752
|
},
|
|
748
753
|
{
|
|
749
754
|
flags: '--agentId <agentId>',
|
|
750
|
-
desc:
|
|
755
|
+
desc: '在 agent 模式下需要提供 Agent ID 进行调试'
|
|
751
756
|
},
|
|
752
757
|
{
|
|
753
758
|
flags: '-e, --envId <envId>',
|
|
@@ -793,7 +798,7 @@ let CloudRunRunCommand = class CloudRunRunCommand extends common_1.Command {
|
|
|
793
798
|
},
|
|
794
799
|
{
|
|
795
800
|
flags: '--open-debug-panel <openDebugPanel>',
|
|
796
|
-
desc:
|
|
801
|
+
desc: '是否打开调试面板,默认为 \'true\''
|
|
797
802
|
}
|
|
798
803
|
],
|
|
799
804
|
requiredEnvId: false,
|
|
@@ -828,7 +833,7 @@ let CloudRunRunCommand = class CloudRunRunCommand extends common_1.Command {
|
|
|
828
833
|
{
|
|
829
834
|
type: 'input',
|
|
830
835
|
name: 'agentId',
|
|
831
|
-
message:
|
|
836
|
+
message: '请输入 Agent ID(如没有请填写任意值):',
|
|
832
837
|
validate: (val) => {
|
|
833
838
|
return val.trim() ? true : 'Agent ID 不能为空';
|
|
834
839
|
}
|
|
@@ -895,7 +900,7 @@ let CloudRunRunCommand = class CloudRunRunCommand extends common_1.Command {
|
|
|
895
900
|
logger.info(`[nodemon ${e.type}] ${e.message}`);
|
|
896
901
|
})
|
|
897
902
|
.on('crash', () => {
|
|
898
|
-
logger.error(
|
|
903
|
+
logger.error('Server crashed.');
|
|
899
904
|
process.exit(1);
|
|
900
905
|
})
|
|
901
906
|
.on('exit', (e) => {
|
|
@@ -124,6 +124,19 @@ class TemplateManager {
|
|
|
124
124
|
subpath: giteeMatch[4]
|
|
125
125
|
};
|
|
126
126
|
}
|
|
127
|
+
const cnbMatchWithDash = url.match(/https?:\/\/cnb\.cool\/(.+?)\/-\/tree\/([^\/]+)\/(.+)$/);
|
|
128
|
+
if (cnbMatchWithDash) {
|
|
129
|
+
const pathParts = cnbMatchWithDash[1].split('/').filter(p => p.length > 0);
|
|
130
|
+
if (pathParts.length >= 2) {
|
|
131
|
+
return {
|
|
132
|
+
platform: 'cnb',
|
|
133
|
+
owner: pathParts[0],
|
|
134
|
+
repo: pathParts.slice(1).join('/'),
|
|
135
|
+
branch: cnbMatchWithDash[2] || 'main',
|
|
136
|
+
subpath: cnbMatchWithDash[3]
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
}
|
|
127
140
|
const cnbMatch = url.match(/https?:\/\/cnb\.cool\/(.+?)(?:\/tree\/([^\/]+)\/(.+))?$/);
|
|
128
141
|
if (cnbMatch) {
|
|
129
142
|
const pathParts = cnbMatch[1].split('/').filter(p => p.length > 0);
|
|
@@ -160,6 +173,38 @@ class TemplateManager {
|
|
|
160
173
|
}
|
|
161
174
|
throw new error_1.CloudBaseError(`不支持的 Git 平台: ${gitInfo.platform}`);
|
|
162
175
|
}
|
|
176
|
+
cloneWithSubpathOptimized(gitUrl, tempDir, gitInfo, log) {
|
|
177
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
178
|
+
try {
|
|
179
|
+
yield this.git.clone(gitUrl, tempDir, [
|
|
180
|
+
'--depth', '1',
|
|
181
|
+
'--single-branch',
|
|
182
|
+
'--branch', gitInfo.branch,
|
|
183
|
+
'--filter=blob:none'
|
|
184
|
+
]);
|
|
185
|
+
const subpathFull = path_1.default.join(tempDir, gitInfo.subpath);
|
|
186
|
+
if (!(yield fs_extra_1.default.pathExists(subpathFull))) {
|
|
187
|
+
throw new error_1.CloudBaseError(`子目录不存在: ${gitInfo.subpath}`);
|
|
188
|
+
}
|
|
189
|
+
const tempContentDir = path_1.default.join(tempDir, '.temp-content-' + Date.now());
|
|
190
|
+
yield fs_extra_1.default.move(subpathFull, tempContentDir);
|
|
191
|
+
const tempFiles = yield fs_extra_1.default.readdir(tempDir);
|
|
192
|
+
for (const file of tempFiles) {
|
|
193
|
+
if (file !== path_1.default.basename(tempContentDir)) {
|
|
194
|
+
yield fs_extra_1.default.remove(path_1.default.join(tempDir, file));
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
const contentFiles = yield fs_extra_1.default.readdir(tempContentDir);
|
|
198
|
+
for (const file of contentFiles) {
|
|
199
|
+
yield fs_extra_1.default.move(path_1.default.join(tempContentDir, file), path_1.default.join(tempDir, file));
|
|
200
|
+
}
|
|
201
|
+
yield fs_extra_1.default.remove(tempContentDir);
|
|
202
|
+
}
|
|
203
|
+
catch (error) {
|
|
204
|
+
throw new error_1.CloudBaseError(`克隆子目录失败: ${error.message}`, { original: error });
|
|
205
|
+
}
|
|
206
|
+
});
|
|
207
|
+
}
|
|
163
208
|
cloneWithSubpath(gitUrl, tempDir, gitInfo, log) {
|
|
164
209
|
return __awaiter(this, void 0, void 0, function* () {
|
|
165
210
|
try {
|
|
@@ -212,10 +257,10 @@ class TemplateManager {
|
|
|
212
257
|
log.info(`📦 正在从 ${gitInfo.platform} 下载模板到临时目录...`);
|
|
213
258
|
try {
|
|
214
259
|
if (gitInfo.subpath) {
|
|
215
|
-
yield this.
|
|
260
|
+
yield this.cloneWithSubpathOptimized(gitUrl, tempDir, gitInfo, log);
|
|
216
261
|
}
|
|
217
262
|
else {
|
|
218
|
-
yield this.git.clone(gitUrl, tempDir);
|
|
263
|
+
yield this.git.clone(gitUrl, tempDir, ['--depth', '1', '--single-branch', '--branch', gitInfo.branch]);
|
|
219
264
|
}
|
|
220
265
|
log.info(`✅ Git 模板下载完成到临时目录`);
|
|
221
266
|
}
|
|
@@ -271,10 +316,14 @@ class TemplateManager {
|
|
|
271
316
|
if (stat.isDirectory()) {
|
|
272
317
|
yield fs_extra_1.default.ensureDir(destPath);
|
|
273
318
|
const entries = yield fs_extra_1.default.readdir(srcPath, { withFileTypes: true });
|
|
274
|
-
|
|
319
|
+
const copyPromises = entries.map(entry => {
|
|
275
320
|
const entrySrcPath = path_1.default.join(srcPath, entry.name);
|
|
276
321
|
const entryDestPath = path_1.default.join(destPath, entry.name);
|
|
277
|
-
|
|
322
|
+
return copyFile(entrySrcPath, entryDestPath);
|
|
323
|
+
});
|
|
324
|
+
const chunks = this.chunkArray(copyPromises, 10);
|
|
325
|
+
for (const chunk of chunks) {
|
|
326
|
+
yield Promise.all(chunk);
|
|
278
327
|
}
|
|
279
328
|
}
|
|
280
329
|
else {
|
|
@@ -295,10 +344,14 @@ class TemplateManager {
|
|
|
295
344
|
}
|
|
296
345
|
});
|
|
297
346
|
const entries = yield fs_extra_1.default.readdir(sourceDir, { withFileTypes: true });
|
|
298
|
-
|
|
347
|
+
const copyPromises = entries.map(entry => {
|
|
299
348
|
const srcPath = path_1.default.join(sourceDir, entry.name);
|
|
300
349
|
const destPath = path_1.default.join(targetDir, entry.name);
|
|
301
|
-
|
|
350
|
+
return copyFile(srcPath, destPath);
|
|
351
|
+
});
|
|
352
|
+
const chunks = this.chunkArray(copyPromises, 5);
|
|
353
|
+
for (const chunk of chunks) {
|
|
354
|
+
yield Promise.all(chunk);
|
|
302
355
|
}
|
|
303
356
|
log.info(`📊 复制统计: ${copiedCount} 个新文件复制, ${overwrittenCount} 个文件覆盖`);
|
|
304
357
|
});
|
|
@@ -313,10 +366,14 @@ class TemplateManager {
|
|
|
313
366
|
if (stat.isDirectory()) {
|
|
314
367
|
yield fs_extra_1.default.ensureDir(destPath);
|
|
315
368
|
const entries = yield fs_extra_1.default.readdir(srcPath, { withFileTypes: true });
|
|
316
|
-
|
|
369
|
+
const copyPromises = entries.map(entry => {
|
|
317
370
|
const entrySrcPath = path_1.default.join(srcPath, entry.name);
|
|
318
371
|
const entryDestPath = path_1.default.join(destPath, entry.name);
|
|
319
|
-
|
|
372
|
+
return copyFile(entrySrcPath, entryDestPath);
|
|
373
|
+
});
|
|
374
|
+
const chunks = this.chunkArray(copyPromises, 10);
|
|
375
|
+
for (const chunk of chunks) {
|
|
376
|
+
yield Promise.all(chunk);
|
|
320
377
|
}
|
|
321
378
|
}
|
|
322
379
|
else {
|
|
@@ -337,14 +394,25 @@ class TemplateManager {
|
|
|
337
394
|
}
|
|
338
395
|
});
|
|
339
396
|
const entries = yield fs_extra_1.default.readdir(sourceDir, { withFileTypes: true });
|
|
340
|
-
|
|
397
|
+
const copyPromises = entries.map(entry => {
|
|
341
398
|
const srcPath = path_1.default.join(sourceDir, entry.name);
|
|
342
399
|
const destPath = path_1.default.join(targetDir, entry.name);
|
|
343
|
-
|
|
400
|
+
return copyFile(srcPath, destPath);
|
|
401
|
+
});
|
|
402
|
+
const chunks = this.chunkArray(copyPromises, 5);
|
|
403
|
+
for (const chunk of chunks) {
|
|
404
|
+
yield Promise.all(chunk);
|
|
344
405
|
}
|
|
345
406
|
log.info(`📊 复制统计: ${copiedCount} 个文件复制完成, ${skippedCount} 个文件跳过`);
|
|
346
407
|
});
|
|
347
408
|
}
|
|
409
|
+
chunkArray(array, chunkSize) {
|
|
410
|
+
const chunks = [];
|
|
411
|
+
for (let i = 0; i < array.length; i += chunkSize) {
|
|
412
|
+
chunks.push(array.slice(i, i + chunkSize));
|
|
413
|
+
}
|
|
414
|
+
return chunks;
|
|
415
|
+
}
|
|
348
416
|
getBuiltinTemplates() {
|
|
349
417
|
const templates = {};
|
|
350
418
|
for (const [key, template] of Object.entries(BUILTIN_TEMPLATES)) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cloudbase/cli",
|
|
3
|
-
"version": "2.9.
|
|
3
|
+
"version": "2.9.6",
|
|
4
4
|
"description": "cli tool for cloudbase",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
"@cloudbase/functions-framework": "1.16.0",
|
|
54
54
|
"@cloudbase/iac-core": "0.0.3-alpha.11",
|
|
55
55
|
"@cloudbase/lowcode-cli": "^0.22.2",
|
|
56
|
-
"@cloudbase/manager-node": "4.6.
|
|
56
|
+
"@cloudbase/manager-node": "4.6.3",
|
|
57
57
|
"@cloudbase/toolbox": "^0.7.9",
|
|
58
58
|
"@dotenvx/dotenvx": "^1.48.3",
|
|
59
59
|
"@musistudio/claude-code-router": "1.0.36",
|
|
@@ -12,12 +12,14 @@ export declare class TemplateManager {
|
|
|
12
12
|
private isGitUrl;
|
|
13
13
|
private parseGitUrl;
|
|
14
14
|
private buildGitUrl;
|
|
15
|
+
private cloneWithSubpathOptimized;
|
|
15
16
|
private cloneWithSubpath;
|
|
16
17
|
private downloadBuiltinTemplateToTemp;
|
|
17
18
|
private downloadGitTemplateToTemp;
|
|
18
19
|
private copyFromTempToTarget;
|
|
19
20
|
private copyFilesWithOverwrite;
|
|
20
21
|
private copyFilesSkipExisting;
|
|
22
|
+
private chunkArray;
|
|
21
23
|
getBuiltinTemplates(): Record<string, string>;
|
|
22
24
|
}
|
|
23
25
|
export {};
|