@lazycatcloud/lzc-cli 1.1.12 → 1.2.0

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.
Files changed (39) hide show
  1. package/lib/app/index.js +52 -33
  2. package/lib/app/lpk_build.js +1 -5
  3. package/lib/app/lpk_create.js +9 -3
  4. package/lib/app/lpk_debug_bridge.js +101 -0
  5. package/lib/app/lpk_devshell.js +59 -129
  6. package/lib/app/lpk_installer.js +43 -50
  7. package/lib/appstore/publish.js +18 -8
  8. package/lib/box/index.js +2 -86
  9. package/lib/env.js +18 -178
  10. package/lib/lzc_sdk.js +75 -17
  11. package/lib/shellapi.js +95 -0
  12. package/lib/shellapi.proto +301 -0
  13. package/lib/utils.js +7 -103
  14. package/package.json +3 -21
  15. package/scripts/cli.js +6 -6
  16. package/template/_lpk/busybox-1.35.0 +0 -0
  17. package/template/_lpk/exec.sh +1 -10
  18. package/template/_lpk/init_debug_bridge.sh +24 -0
  19. package/template/_lpk/vue.lzc-build.yml.in +0 -16
  20. package/template/golang/lzc-build.yml +0 -15
  21. package/template/ionic_vue3/lzc-build.yml +0 -16
  22. package/template/ionic_vue3/package-lock.json +8100 -0
  23. package/template/lite/lzc-build.yml +0 -28
  24. package/lib/api.js +0 -155
  25. package/lib/app/lpk_devshell_docker.js +0 -211
  26. package/lib/app/lpk_log.js +0 -68
  27. package/lib/app/lpk_status.js +0 -18
  28. package/lib/app/lpk_uninstall.js +0 -19
  29. package/lib/box/api/clientapi.js +0 -1322
  30. package/lib/box/api/empty.js +0 -35
  31. package/lib/box/check_qemu.js +0 -51
  32. package/lib/box/qemu_vm_mgr.js +0 -608
  33. package/lib/box/schemes/vm_box_system_debian.json +0 -47
  34. package/lib/docker/promise.js +0 -91
  35. package/lib/docker-compose.js +0 -50
  36. package/lib/git/git-commit.sh +0 -7
  37. package/lib/git/git-reset.sh +0 -15
  38. package/lib/key.js +0 -102
  39. package/lib/sdk.js +0 -135
package/lib/app/index.js CHANGED
@@ -3,9 +3,10 @@ import lpkCreate from "./lpk_create.js";
3
3
  import { LpkBuild } from "./lpk_build.js";
4
4
  import { AppDevShell } from "./lpk_devshell.js";
5
5
  import { LpkInstaller } from "./lpk_installer.js";
6
- import { LpkUninstaller } from "./lpk_uninstall.js";
7
- import { LpkStatuser } from "./lpk_status.js";
8
- import { LpkLogger } from "./lpk_log.js";
6
+ import logger from "loglevel";
7
+ import { sleep } from "../utils.js";
8
+ import { DebugBridge } from "./lpk_debug_bridge.js";
9
+ import shellApi from "../shellapi.js";
9
10
 
10
11
  export function lpkProjectCommand(program) {
11
12
  let subCommands = [
@@ -13,6 +14,8 @@ export function lpkProjectCommand(program) {
13
14
  command: "create <name>",
14
15
  desc: "创建懒猫云应用",
15
16
  handler: async ({ name }) => {
17
+ await shellApi.init();
18
+
16
19
  await lpkCreate(name);
17
20
  },
18
21
  },
@@ -32,6 +35,8 @@ export function lpkProjectCommand(program) {
32
35
  });
33
36
  },
34
37
  handler: async ({ context, output, file }) => {
38
+ await shellApi.init();
39
+
35
40
  const lpk = await new LpkBuild(context, file).init();
36
41
  // 正常的打包逻辑不需要 devshell
37
42
  lpk.onBeforeBuildPackage(async (options) => {
@@ -49,18 +54,6 @@ export function lpkProjectCommand(program) {
49
54
  command: "devshell [context]",
50
55
  desc: "进入盒子的开发环境",
51
56
  builder: (args) => {
52
- args.option("r", {
53
- alias: "rsync",
54
- deprecate: true,
55
- type: "boolean",
56
- default: true,
57
- });
58
- args.option("s", {
59
- alias: "shell",
60
- describe: "指定你最喜欢的shell",
61
- type: "string",
62
- default: "bash",
63
- });
64
57
  args.option("f", {
65
58
  alias: "force",
66
59
  describe: "强制重新构建",
@@ -72,12 +65,32 @@ export function lpkProjectCommand(program) {
72
65
  type: "string",
73
66
  default: "lzc-build.yml",
74
67
  });
68
+ args.option("contentdir", {
69
+ describe: "同时打包 lzc-build.yml 中指定的 contentdir 目录",
70
+ type: "boolean",
71
+ });
75
72
  },
76
- handler: async ({ context, shell, force, config }) => {
77
- const app = new AppDevShell(context, config, force);
73
+ handler: async ({ context, force, config, contentdir }) => {
74
+ await shellApi.init();
75
+
76
+ const cwd = context ? path.resolve(context) : process.cwd();
77
+ const lpkBuild = await new LpkBuild(cwd, config).init();
78
+ lpkBuild.onBeforeBuildPackage(async (options) => {
79
+ // devshell 正常情况下,不需要执行 buildscript 和 contentdir 字段
80
+ logger.debug("devshell delete 'buildscript' field");
81
+ delete options["buildscript"];
82
+
83
+ if (!contentdir) {
84
+ logger.debug("devshell delete 'contentdir' field");
85
+ delete options["contentdir"];
86
+ }
87
+ return options;
88
+ });
89
+ const app = new AppDevShell(cwd, lpkBuild, force);
78
90
  await app.init();
79
91
  await app.build();
80
- await app.rsyncShell(shell);
92
+ await sleep(2000);
93
+ await app.rsyncShell();
81
94
  },
82
95
  },
83
96
  ];
@@ -93,30 +106,36 @@ export function lpkProjectCommand(program) {
93
106
  export function lpkAppCommand(program) {
94
107
  let subCommands = [
95
108
  {
96
- command: "install <pkgUrl>",
97
- desc: "部署应用至设备, pkgUrl 可以为路径,或者https://,http://请求地址",
98
- handler: async ({ pkgUrl }) => {
109
+ command: "install [pkgPath]",
110
+ desc: "部署应用至设备, pkgPath 可以为路径,或者https://,http://请求地址, 如果不填写,将默认为当前目录下的lpk",
111
+ handler: async ({ pkgPath }) => {
112
+ await shellApi.init();
113
+
114
+ pkgPath = pkgPath ?? process.cwd();
99
115
  const installer = new LpkInstaller();
100
116
  await installer.init();
101
- await installer.install(pkgUrl);
117
+ await installer.install(pkgPath);
102
118
  },
103
119
  },
104
120
  {
105
121
  command: "uninstall <pkgId>",
106
122
  desc: "从设备中卸载某一个应用",
107
123
  handler: async ({ pkgId }) => {
108
- const uninstaller = new LpkUninstaller();
109
- await uninstaller.init();
110
- await uninstaller.uninstall(pkgId);
124
+ await shellApi.init();
125
+
126
+ const bridge = new DebugBridge();
127
+ await bridge.uninstall(pkgId);
111
128
  },
112
129
  },
113
130
  {
114
131
  command: "status <pkgId>",
115
132
  desc: "获取某一个应用的状态",
116
133
  handler: async ({ pkgId }) => {
117
- const statuser = new LpkStatuser();
118
- await statuser.init();
119
- await statuser.status(pkgId);
134
+ await shellApi.init();
135
+
136
+ const bridge = new DebugBridge();
137
+ const status = await bridge.status(pkgId);
138
+ console.log(status);
120
139
  },
121
140
  },
122
141
  {
@@ -130,17 +149,17 @@ export function lpkAppCommand(program) {
130
149
  default: false,
131
150
  });
132
151
  },
133
- handler: async ({ pkgId, follow }) => {
134
- const log = new LpkLogger();
135
- await log.init();
136
- await log.start(pkgId, follow);
152
+ handler: async () => {
153
+ await shellApi.init();
154
+
155
+ throw "还没有实现";
137
156
  },
138
157
  },
139
158
  ];
140
159
  program.command({
141
160
  command: "app",
142
161
  desc: "应用管理",
143
- builder: (args) => {
162
+ builder: async (args) => {
144
163
  args.command(subCommands);
145
164
  },
146
165
  });
@@ -8,6 +8,7 @@ import {
8
8
  isFileExist,
9
9
  dumpToYaml,
10
10
  envTemplateFile,
11
+ isValidPackageName,
11
12
  } from "../utils.js";
12
13
  import { spawnSync } from "child_process";
13
14
  import { LpkManifest } from "./lpk_create.js";
@@ -130,11 +131,6 @@ function convenientEnv() {
130
131
  );
131
132
  }
132
133
 
133
- function isValidPackageName(packageName) {
134
- const regex = /^([a-zA-Z_][a-zA-Z0-9_]*\.)*[a-zA-Z_][a-zA-Z0-9_]*$/;
135
- return regex.test(packageName);
136
- }
137
-
138
134
  export class LpkBuild {
139
135
  constructor(cwd, lzcBuild = "lzc-build.yml") {
140
136
  this.pwd = cwd ?? process.cwd();
@@ -7,6 +7,7 @@ import {
7
7
  ensureDir,
8
8
  dumpToYaml,
9
9
  isFileExist,
10
+ isValidPackageName,
10
11
  } from "../utils.js";
11
12
  import path from "node:path";
12
13
  import { TemplateConfig } from "./lpk_create_generator.js";
@@ -74,9 +75,14 @@ export class LpkManifest {
74
75
  {
75
76
  type: "input",
76
77
  name: "package",
77
- message: "请输入应用ID",
78
- default: this.defaultAppID,
79
- validate: noEmpty,
78
+ message: "请输入应用ID, 如 cloud.lazycat.app.video",
79
+ validate: (input) => {
80
+ if (isValidPackageName(input)) {
81
+ return true;
82
+ } else {
83
+ return "应用ID错误,请输入正确的格式, 如 cloud.lazycat.app.video";
84
+ }
85
+ },
80
86
  },
81
87
  {
82
88
  type: "input",
@@ -0,0 +1,101 @@
1
+ import { spawn, spawnSync } from "child_process";
2
+ import fs from "node:fs";
3
+ import shellApi from "../shellapi.js";
4
+ import inquirer from "inquirer";
5
+
6
+ export class DebugBridge {
7
+ constructor() {
8
+ this.uid = shellApi.uid;
9
+ this.boxname = shellApi.boxname;
10
+ this.sshCmd = `ssh -p 22222 box@dev.${this.boxname}.heiyu.space`;
11
+ }
12
+
13
+ common(cmd, args) {
14
+ const ssh = spawnSync(cmd, args, {
15
+ shell: true,
16
+ encoding: "utf-8",
17
+ stdio: "pipe",
18
+ });
19
+ return new Promise((resolve, reject) => {
20
+ ssh.status == 0 ? resolve(ssh.stdout) : reject(ssh.stderr);
21
+ });
22
+ }
23
+
24
+ async install(lpkPath) {
25
+ if (!(await this.canPublicKey())) {
26
+ await this.sshCopyId();
27
+ }
28
+
29
+ const stream = fs.createReadStream(lpkPath);
30
+ const ssh = spawn(this.sshCmd, [`install --uid ${this.uid}`], {
31
+ shell: true,
32
+ stdio: ["pipe", "inherit", "inherit"],
33
+ });
34
+ stream.pipe(ssh.stdin);
35
+ return new Promise((resolve, reject) => {
36
+ ssh.on("close", (code) => {
37
+ code == 0 ? resolve() : reject("install 失败");
38
+ });
39
+ });
40
+ }
41
+
42
+ async canPublicKey() {
43
+ try {
44
+ await this.common(this.sshCmd, [`-o PasswordAuthentication=no`]);
45
+ return true;
46
+ } catch {
47
+ return false;
48
+ }
49
+ }
50
+
51
+ async sshCopyId() {
52
+ const questions = [
53
+ {
54
+ name: "upload",
55
+ type: "input",
56
+ default: "y",
57
+ message:
58
+ "检测到你目前使用的密码帐号登录,是否使用 ssh-copy-id 上传密钥 (y/n): ",
59
+ },
60
+ ];
61
+ const answers = await inquirer.prompt(questions);
62
+ if (answers.upload.toLowerCase() == "y") {
63
+ return this.common(`ssh-copy-id`, [
64
+ `-f -p 22222 box@dev.${this.boxname}.heiyu.space`,
65
+ ]);
66
+ }
67
+ }
68
+
69
+ async status(appId) {
70
+ return this.common(this.sshCmd, [`status --uid ${this.uid}`, appId]);
71
+ }
72
+
73
+ async isDevshell(appId) {
74
+ const stdout = await this.common(this.sshCmd, [`isDevshell`, appId]);
75
+ return stdout == "true";
76
+ }
77
+
78
+ async resume(appId) {
79
+ return this.common(this.sshCmd, [`resume --uid ${this.uid}`, appId]);
80
+ }
81
+
82
+ async uninstall(appId) {
83
+ return this.common(this.sshCmd, [`uninstall --uid ${this.uid}`, appId]);
84
+ }
85
+
86
+ async devshell(appId) {
87
+ const stream = spawn(
88
+ this.sshCmd,
89
+ ["-t", "devshell", appId, "/lzcapp/pkg/content/devshell/exec.sh"],
90
+ {
91
+ shell: true,
92
+ stdio: "inherit",
93
+ }
94
+ );
95
+ return new Promise((resolve, reject) => {
96
+ stream.on("close", (code) => {
97
+ code == 0 ? resolve() : reject();
98
+ });
99
+ });
100
+ }
101
+ }
@@ -3,7 +3,6 @@ import path from "node:path";
3
3
  import fs from "node:fs";
4
4
  import logger from "loglevel";
5
5
  import { execSync } from "node:child_process";
6
- import { LpkBuild } from "./lpk_build.js";
7
6
  import { LpkInstaller } from "./lpk_installer.js";
8
7
  import debounce from "lodash.debounce";
9
8
  import {
@@ -12,32 +11,18 @@ import {
12
11
  ensureDir,
13
12
  isFileExist,
14
13
  GitIgnore,
15
- sleep,
16
14
  md5String,
17
15
  md5File,
18
- createTemplateFileCommon,
19
16
  loadFromYaml,
20
17
  FileLocker,
21
18
  } from "../utils.js";
22
- import Key from "../key.js";
23
19
  import os from "node:os";
24
- import { sdkEnv } from "../env.js";
25
20
  import commandExists from "command-exists";
26
21
  import chokidar from "chokidar";
27
22
  import _ from "lodash";
28
- import BoxAPI from "../api.js";
29
- import { SdkDocker } from "./lpk_devshell_docker.js";
30
23
  import { getUidByManifest } from "../lzc_sdk.js";
31
-
32
- function sdkSSHHost() {
33
- const sdkUrl = sdkEnv.sdkUrl;
34
- let url = new URL(sdkUrl);
35
- return `box@${url.hostname}`;
36
- }
37
-
38
- function sdkSSHPort() {
39
- return 2222;
40
- }
24
+ import { DebugBridge } from "./lpk_debug_bridge.js";
25
+ import shellApi from "../shellapi.js";
41
26
 
42
27
  // 判断是否需要重新构建
43
28
  // - 先判断 lzc-build.yml 是否发生改变
@@ -46,11 +31,9 @@ function sdkSSHPort() {
46
31
  // - 根据 backend api 判断一个 appid 是否属于 running
47
32
  // - 根据在 backend api 中判断同步的目录下是否存在文件 判断当前运行的 app 是否已经有一个挂载的实例,避免重复挂载
48
33
  class AppDevShellMonitor {
49
- constructor(cwd, pkgId, uid = "") {
34
+ constructor(cwd, pkgId) {
50
35
  this.pwd = cwd ? path.resolve(cwd) : process.cwd();
51
-
52
36
  this.pkgId = pkgId;
53
- this.boxapi = new BoxAPI(pkgId, sdkEnv.sdkUrl, uid);
54
37
 
55
38
  this.optionsFilePath = path.join(this.pwd, "lzc-build.yml");
56
39
  this.options = loadFromYaml(this.optionsFilePath);
@@ -66,6 +49,7 @@ class AppDevShellMonitor {
66
49
  this.cacheFilePath = undefined;
67
50
  this.oldHash = undefined;
68
51
  this.newHash = undefined;
52
+ this.bridge = new DebugBridge();
69
53
  }
70
54
 
71
55
  async init() {
@@ -85,7 +69,9 @@ class AppDevShellMonitor {
85
69
 
86
70
  async shouldBuild() {
87
71
  return (
88
- this.change() || (await this.notRunning()) || (await this.noDevshell())
72
+ this.change() ||
73
+ (await this.bridge.status(this.pkgId)) === "NotInstalled" ||
74
+ !(await this.bridge.isDevshell(this.pkgId))
89
75
  );
90
76
  }
91
77
 
@@ -113,35 +99,17 @@ class AppDevShellMonitor {
113
99
  fs.writeFileSync(this.cacheFilePath, JSON.stringify(this.newHash));
114
100
  }
115
101
  }
116
-
117
- async notRunning() {
118
- try {
119
- const { status } = await this.boxapi.status();
120
- return status !== "running";
121
- } catch {
122
- return true;
123
- }
124
- }
125
-
126
- async noDevshell() {
127
- return !(await this.boxapi.isDevshell());
128
- }
129
102
  }
130
103
 
131
104
  export class AppDevShell {
132
- constructor(cwd, config, forceBuild = false) {
133
- this.cwd = cwd ? path.resolve(cwd) : process.cwd();
134
- this.lpkBuild = undefined;
105
+ constructor(cwd, lpkBuild, forceBuild = false) {
106
+ this.cwd = cwd;
107
+ this.lpkBuild = lpkBuild;
135
108
  this.monitor = undefined;
136
109
  this.forceBuild = forceBuild;
137
- this.lpkBuildConfig = config;
138
110
  }
139
111
 
140
112
  async init() {
141
- if (!this.lpkBuild) {
142
- this.lpkBuild = new LpkBuild(this.cwd, this.lpkBuildConfig);
143
- await this.lpkBuild.init();
144
- }
145
113
  const manifest = await this.lpkBuild.getManifest();
146
114
  const uid = await getUidByManifest(manifest);
147
115
  this.monitor = await new AppDevShellMonitor(
@@ -160,18 +128,7 @@ export class AppDevShell {
160
128
  }
161
129
 
162
130
  async devshellBuild() {
163
- // 确保 sdk key ,并上传到 sdk
164
- const k = new Key();
165
- await k.ensure(sdkEnv.sdkUrl);
166
- const pairs = await k.getKeyPair();
167
-
168
- // devshell 不需要执行 buildscript 和 contentdir 也不需要
169
131
  this.lpkBuild.onBeforeBuildPackage(async (options) => {
170
- logger.debug("devshell delete 'buildscript' field");
171
- logger.debug("devshell delete 'contentdir' field");
172
- delete options["buildscript"];
173
- delete options["contentdir"];
174
-
175
132
  const devshell = options["devshell"];
176
133
  if (!devshell) {
177
134
  throw "devshell 模式下,devshell 字段必须要指定";
@@ -185,6 +142,30 @@ export class AppDevShell {
185
142
  return options;
186
143
  });
187
144
 
145
+ // 复制 busybox 到 devshell 中去
146
+ this.lpkBuild.onBeforeTarContent(async (contentdir) => {
147
+ const busyboxPath = path.join(
148
+ contextDirname(import.meta.url),
149
+ "../../template/_lpk/busybox-1.35.0"
150
+ );
151
+ let dest = path.join(contentdir, "devshell", "busybox");
152
+ ensureDir(dest);
153
+ fs.copyFileSync(busyboxPath, dest);
154
+ fs.chmodSync(dest, 0o775);
155
+ });
156
+
157
+ // 复制 init_debug_bridge.sh 到 devshell 中去
158
+ this.lpkBuild.onBeforeTarContent(async (contentdir) => {
159
+ const initPath = path.join(
160
+ contextDirname(import.meta.url),
161
+ "../../template/_lpk/init_debug_bridge.sh"
162
+ );
163
+ let dest = path.join(contentdir, "devshell", "init_debug_bridge.sh");
164
+ ensureDir(dest);
165
+ fs.copyFileSync(initPath, dest);
166
+ fs.chmodSync(dest, 0o775);
167
+ });
168
+
188
169
  // 复制 exec.sh 到 devshell 中去
189
170
  this.lpkBuild.onBeforeTarContent(async (contentdir) => {
190
171
  const execScriptPath = path.join(
@@ -197,15 +178,6 @@ export class AppDevShell {
197
178
  fs.chmodSync(dest, 0o775);
198
179
  });
199
180
 
200
- // 用 sdk ssh key 并复制到 contentdir 目录
201
- // docker 中 sshd 的配置中已改成 /lzcapp/pkg/content/devshell/authorized_keys
202
- this.lpkBuild.onBeforeTarContent(async (contentdir) => {
203
- let publicKey = pairs["public"];
204
- let dest = path.join(contentdir, "devshell", "authorized_keys");
205
- ensureDir(dest);
206
- fs.copyFileSync(publicKey, dest);
207
- });
208
-
209
181
  // 复制 setupscript 脚本
210
182
  this.lpkBuild.onBeforeTarContent(async (contentdir, options) => {
211
183
  const devshell = options["devshell"];
@@ -238,6 +210,13 @@ export class AppDevShell {
238
210
  const routes = devshell["routes"];
239
211
  logger.debug("options devshell delete 'routes' field");
240
212
  delete options["devshell"]["routes"];
213
+
214
+ // 添加 devshell 必要路由
215
+ routes.push(
216
+ "/__debug.bridge=exec://22222,/lzcapp/pkg/content/devshell/init_debug_bridge.sh"
217
+ );
218
+ routes.push("/__isdevshell=file:///lzcapp/pkg/devshell");
219
+
241
220
  // 如果 devshell 中的 router 和 manifest 中的 prefix 出现冲突
242
221
  // 优先使用 devshell 中的。
243
222
  routes.forEach((r) => {
@@ -285,32 +264,7 @@ export class AppDevShell {
285
264
  return manifest;
286
265
  }
287
266
 
288
- const depsStr = deps.sort().join(" ");
289
- logger.debug("开始创建 Dockerfile 文件");
290
- const tag = `${await md5String(depsStr)}:latest`;
291
-
292
- const tempDir = fs.mkdtempSync(".lzc-cli-build-dependencies");
293
- try {
294
- const dockerfilePath = path.join(
295
- contextDirname(import.meta.url),
296
- "../../template/_lpk/Dockerfile.in"
297
- );
298
- await createTemplateFileCommon(
299
- dockerfilePath,
300
- path.join(tempDir, "Dockerfile"),
301
- { dependencies: depsStr }
302
- );
303
-
304
- logger.debug(`开始在盒子中构建 ${tag} 镜像 from ${tempDir}`);
305
- const sdk = new SdkDocker();
306
- await sdk.buildImage(tag, tempDir, tempDir);
307
- } finally {
308
- fs.rmSync(tempDir, { recursive: true });
309
- }
310
-
311
- delete manifest["application"]["devshell"];
312
- manifest["application"]["image"] = tag;
313
- return manifest;
267
+ throw "lzc-cli 不支持在盒子中构建 docker 镜像,请从其他地方构建,然后指定image字段";
314
268
  });
315
269
 
316
270
  // 如果 services 中有 devshell 的字段,需要检测是否需要提前构建
@@ -325,16 +279,7 @@ export class AppDevShell {
325
279
  return manifest;
326
280
  }
327
281
 
328
- const tag = `${manifest["package"]}-devshell:${manifest["version"]}`;
329
-
330
- logger.debug(`开始在盒子中构建 ${tag} 镜像`);
331
-
332
- const sdk = new SdkDocker();
333
- await sdk.buildImage(tag, config["build"], process.cwd());
334
-
335
- delete manifest["application"]["devshell"];
336
- manifest["application"]["image"] = tag;
337
- return manifest;
282
+ throw "lzc-cli 不支持在盒子中构建 docker 镜像,请从其他地方构建,然后指定image字段";
338
283
  });
339
284
 
340
285
  // 如果 devshell 中指定了 image 字段将使用 image 字段
@@ -371,14 +316,10 @@ export class AppDevShell {
371
316
  // 在构建生成 lpk 包后,调用 deploy 进行部署
372
317
  let installer = new LpkInstaller();
373
318
  await installer.init();
374
- await installer.deploy(this.lpkBuild);
375
-
376
- await sleep(2000);
319
+ await installer.deploy(this.lpkBuild, true);
377
320
  }
378
321
 
379
- async rsyncShell(runShell) {
380
- const k = new Key();
381
- const pairs = await k.getKeyPair();
322
+ async rsyncShell() {
382
323
  const manifest = await this.lpkBuild.getManifest();
383
324
  const pkgId = manifest["package"];
384
325
 
@@ -397,7 +338,7 @@ export class AppDevShell {
397
338
  }
398
339
 
399
340
  const uid = await getUidByManifest(manifest);
400
- const devshell = new DevShell(pairs["private"], pkgId, runShell, uid);
341
+ const devshell = new DevShell(pkgId, uid);
401
342
  if (isSync) {
402
343
  await devshell.shell();
403
344
  } else {
@@ -411,29 +352,22 @@ export class AppDevShell {
411
352
  }
412
353
 
413
354
  class DevShell {
414
- constructor(keyFile, appId, runShell = "sh", uid = "") {
415
- logger.debug("keyFile", keyFile);
416
- logger.debug("appid", appId);
417
-
418
- this.keyFile = keyFile;
355
+ constructor(appId, uid = "") {
419
356
  this.appId = appId;
420
357
  this.uid = uid;
421
- this.runShell = runShell;
422
358
  }
423
359
 
424
- async syncProject(keyFile, appId) {
425
- const host = sdkSSHHost();
426
- const port = sdkSSHPort();
360
+ async syncProject(appId) {
427
361
  // prettier-ignore
428
362
  let rsh = [
429
363
  "ssh",
430
- "-p", `${port}`,
364
+ "-J", `box@dev.${shellApi.boxname}.heiyu.space:22222`,
365
+ "-p", `22222`,
431
366
  "-o", `"StrictHostKeyChecking=no"`,
432
367
  "-o", `"UserKnownHostsFile=/dev/null"`,
433
368
  "-o", `"ConnectionAttempts=3"`,
434
369
  "-o", `"ConnectTimeout=30"`,
435
370
  "-o", `"LogLevel=ERROR"`,
436
- "-i", keyFile,
437
371
  ].join(" ");
438
372
  // 检查rsync工具是否存在:提示用户
439
373
  const rsyncExisted = commandExists.sync("rsync");
@@ -442,13 +376,11 @@ class DevShell {
442
376
  process.exit(1);
443
377
  }
444
378
 
445
- let rsyncDebug = process.env.RSYNCDEBUG ? "-P" : "";
446
- const userId = this.uid ? `/${this.uid}` : "";
447
- let storePath = `/run/lzc_boot/data/cache/${appId}${userId}/devshell`;
448
- // FIXME: 下方执行命令不确定是否有兼容性问题
379
+ const rsyncDebug = process.env.RSYNCDEBUG ? "-P" : "";
380
+ const dest = `root@app.${appId}.lzcapp:/lzcapp/cache/devshell`;
449
381
  try {
450
382
  execSync(
451
- `rsync ${rsyncDebug} --rsh='${rsh}' --recursive --relative --perms --update . ${host}:${storePath} --filter=':- .gitignore' --exclude='node_modules' --exclude='.git' --ignore-errors --usermap=:nobody --groupmap=*:nobody`,
383
+ `rsync ${rsyncDebug} --rsh='${rsh}' --recursive --relative --perms --update --filter=':- .gitignore' --ignore-errors --usermap=:nobody --groupmap=*:nobody . ${dest}`,
452
384
  { stdio: ["ignore", "inherit", "inherit"] }
453
385
  );
454
386
  } catch (err) {
@@ -498,7 +430,7 @@ class DevShell {
498
430
 
499
431
  // 监听非.gitignore文件
500
432
  // TODO: 目前仅仅监听process.cwd()以下的文件
501
- async watchFile(keyFile, appId) {
433
+ async watchFile(appId) {
502
434
  const ignore = new GitIgnore(process.cwd());
503
435
  await ignore.collect();
504
436
  chokidar
@@ -513,29 +445,27 @@ class DevShell {
513
445
  .on(
514
446
  "all",
515
447
  debounce(() => {
516
- this.syncProject(keyFile, appId);
448
+ this.syncProject(appId);
517
449
  }),
518
450
  1000
519
451
  );
520
452
  }
521
453
  async shell() {
522
- let keyFile = this.keyFile;
523
454
  try {
524
455
  // 当进入shell的时候,都同步一次
525
- await this.syncProject(keyFile, this.appId);
456
+ await this.syncProject(this.appId);
526
457
  // 注册watch函数
527
- await this.watchFile(keyFile, this.appId);
458
+ await this.watchFile(this.appId);
528
459
 
529
460
  await this.connectShell();
530
461
  } catch (e) {
531
462
  console.log(e);
532
- // this.reset();
533
463
  return Promise.reject(e);
534
464
  }
535
465
  }
536
466
 
537
467
  async connectShell() {
538
- const sdk = new SdkDocker();
539
- await sdk.interactiveShell(this.appId, this.runShell, this.uid);
468
+ const bridge = new DebugBridge();
469
+ await bridge.devshell(this.appId);
540
470
  }
541
471
  }