@enspirit/emb 0.4.1 → 0.4.2

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 CHANGED
@@ -14,7 +14,7 @@ $ npm install -g @enspirit/emb
14
14
  $ emb COMMAND
15
15
  running command...
16
16
  $ emb (--version)
17
- @enspirit/emb/0.4.1 darwin-x64 node-v22.18.0
17
+ @enspirit/emb/0.4.2 darwin-x64 node-v22.18.0
18
18
  $ emb --help [COMMAND]
19
19
  USAGE
20
20
  $ emb COMMAND
@@ -20,9 +20,6 @@ export default class UpCommand extends FlavoredCommand {
20
20
  if (flags.force) {
21
21
  buildFlags.push('--force');
22
22
  }
23
- if (flags.flavor) {
24
- buildFlags.push('--flavor', flags.flavor);
25
- }
26
23
  await this.config.runCommand('resources:build', buildFlags);
27
24
  await monorepo.run(new ComposeUpOperation(), {
28
25
  forceRecreate: flags.force,
@@ -17,4 +17,9 @@ export declare class BuildImageOperation extends AbstractOperation<typeof BuildI
17
17
  private out?;
18
18
  constructor(out?: Writable | undefined);
19
19
  protected _run(input: z.input<typeof BuildImageOperationInputSchema>): Promise<void>;
20
+ protected _buildWithDockerCLI(input: z.input<typeof BuildImageOperationInputSchema>): Promise<void>;
21
+ /**
22
+ * Experimental with dockerode and the docker API directly
23
+ */
24
+ protected _buildWithDockerode(input: z.input<typeof BuildImageOperationInputSchema>): Promise<void>;
20
25
  }
@@ -1,4 +1,7 @@
1
- import { Transform } from 'node:stream';
1
+ import { CommandExecError } from '../../../index.js';
2
+ import { spawn } from 'node:child_process';
3
+ import { join } from 'node:path';
4
+ import { PassThrough } from 'node:stream';
2
5
  import * as z from 'zod';
3
6
  import { decodeBuildkitStatusResponse } from '../../index.js';
4
7
  import { AbstractOperation } from '../../../operations/index.js';
@@ -37,28 +40,61 @@ export class BuildImageOperation extends AbstractOperation {
37
40
  this.out = out;
38
41
  }
39
42
  async _run(input) {
43
+ return this._buildWithDockerCLI(input);
44
+ }
45
+ async _buildWithDockerCLI(input) {
46
+ const labels = Object.entries(input.labels || {})
47
+ .reduce((arr, [key, value]) => {
48
+ arr.push(`${key.trim()}=${value.trim()}`);
49
+ return arr;
50
+ }, [])
51
+ .join(',');
52
+ const args = [
53
+ 'build',
54
+ input.context,
55
+ '-f',
56
+ join(input.context, input.dockerfile || 'Dockerfile'),
57
+ '--label',
58
+ labels,
59
+ ];
60
+ if (input.tag) {
61
+ args.push('--tag', input.tag);
62
+ }
63
+ if (input.target) {
64
+ args.push('--target', input.target);
65
+ }
66
+ Object.entries(input.buildArgs || []).forEach(([key, value]) => {
67
+ args.push('--build-arg', `${key.trim()}=${value.trim()}`);
68
+ });
40
69
  const logFile = await this.context.monorepo.store.createWriteStream(`logs/docker/build/${input.tag}.log`);
41
- const decodeBuildkit = new Transform({
42
- transform: async (chunk, encoding, callback) => {
43
- try {
44
- try {
45
- const { aux } = JSON.parse(chunk);
46
- const { vertexes } = await decodeBuildkitStatusResponse(aux);
47
- vertexes.forEach((v) => {
48
- logFile.write(`${JSON.stringify(v)}\n`);
49
- this.out?.write(`${v.name}\n`);
50
- });
51
- }
52
- catch {
53
- //
54
- }
55
- callback();
56
- }
57
- catch (error) {
58
- console.error('__OOPS', error);
70
+ const tee = new PassThrough();
71
+ tee.pipe(logFile);
72
+ if (this.out) {
73
+ tee.pipe(this.out);
74
+ }
75
+ tee.write('Building image with opts: ' + JSON.stringify(args));
76
+ const child = await spawn('docker', args);
77
+ child.stderr.pipe(tee);
78
+ child.stdout.pipe(tee);
79
+ return new Promise((resolve, reject) => {
80
+ child.on('close', () => {
81
+ resolve();
82
+ });
83
+ child.on('exit', (code, signal) => {
84
+ if (code !== 0) {
85
+ reject(new CommandExecError('Docker build failed', code || -1, signal));
59
86
  }
60
- },
87
+ });
88
+ child.on('error', (err) => {
89
+ reject(err);
90
+ });
61
91
  });
92
+ }
93
+ /**
94
+ * Experimental with dockerode and the docker API directly
95
+ */
96
+ async _buildWithDockerode(input) {
97
+ const logFile = await this.context.monorepo.store.createWriteStream(`logs/docker/build/${input.tag}.log`);
62
98
  const stream = await this.context.docker.buildImage({
63
99
  context: input.context,
64
100
  src: [...input.src],
@@ -71,9 +107,28 @@ export class BuildImageOperation extends AbstractOperation {
71
107
  version: '2',
72
108
  });
73
109
  return new Promise((resolve, reject) => {
74
- stream.pipe(decodeBuildkit);
75
- stream.on('close', () => resolve());
76
- stream.on('error', (error) => reject(error));
110
+ this.context.docker.modem.followProgress(stream, (err, _traces) => {
111
+ return err ? reject(err) : resolve();
112
+ }, async (trace) => {
113
+ if (trace.error) {
114
+ logFile.write(trace.error + '\n');
115
+ this.out?.write(trace.error + '\n');
116
+ reject(trace.error);
117
+ }
118
+ else {
119
+ try {
120
+ const { vertexes } = await decodeBuildkitStatusResponse(trace.aux);
121
+ vertexes.forEach((v) => {
122
+ // logStream.write(JSON.stringify(v) + '\n');
123
+ logFile.write(v.name + '\n');
124
+ this.out?.write(v.name + '\n');
125
+ });
126
+ }
127
+ catch (error) {
128
+ console.error(error);
129
+ }
130
+ }
131
+ });
77
132
  });
78
133
  }
79
134
  }
@@ -72,6 +72,11 @@ export declare class MultipleContainersFoundError extends EMBError {
72
72
  component: string;
73
73
  constructor(msg: string, component: string);
74
74
  }
75
+ export declare class CommandExecError extends EMBError {
76
+ exitCode: number;
77
+ signal?: (NodeJS.Signals | null) | undefined;
78
+ constructor(msg: string, exitCode: number, signal?: (NodeJS.Signals | null) | undefined);
79
+ }
75
80
  export declare class ComposeExecError extends EMBError {
76
81
  exitCode: number;
77
82
  signal?: (NodeJS.Signals | null) | undefined;
@@ -95,6 +95,15 @@ export class MultipleContainersFoundError extends EMBError {
95
95
  this.component = component;
96
96
  }
97
97
  }
98
+ export class CommandExecError extends EMBError {
99
+ exitCode;
100
+ signal;
101
+ constructor(msg, exitCode, signal) {
102
+ super('COMMAND_EXEC_ERR', msg);
103
+ this.exitCode = exitCode;
104
+ this.signal = signal;
105
+ }
106
+ }
98
107
  export class ComposeExecError extends EMBError {
99
108
  exitCode;
100
109
  signal;
@@ -105,6 +105,7 @@ export class BuildResourcesOperation extends AbstractOperation {
105
105
  },
106
106
  },
107
107
  {
108
+ rendererOptions: { persistentOutput: true },
108
109
  title: `Build ${resource.id}`,
109
110
  task: async (ctx, task) => {
110
111
  const skip = (prefix) => {
@@ -10,8 +10,8 @@ declare const schema: z.ZodObject<{
10
10
  workingDir: z.ZodOptional<z.ZodString>;
11
11
  }, z.core.$strip>;
12
12
  export declare class ExecuteLocalCommandOperation extends AbstractOperation<typeof schema, Readable> {
13
- protected out: Writable;
14
- constructor(out: Writable);
13
+ protected out?: Writable | undefined;
14
+ constructor(out?: Writable | undefined);
15
15
  protected _run(input: z.input<typeof schema>): Promise<Readable>;
16
16
  }
17
17
  export {};
@@ -27,7 +27,9 @@ export class ExecuteLocalCommandOperation extends AbstractOperation {
27
27
  cwd: input.workingDir,
28
28
  shell: true,
29
29
  });
30
- process.all.pipe(this.out);
30
+ if (this.out) {
31
+ process.all.pipe(this.out);
32
+ }
31
33
  return process.all;
32
34
  }
33
35
  }
@@ -29,7 +29,6 @@ export class RunTasksOperation {
29
29
  if (!task.script) {
30
30
  return;
31
31
  }
32
- console.log('YES WE DO', task.component);
33
32
  const executor = params.executor ??
34
33
  (task.component ? ExecutorType.container : ExecutorType.local);
35
34
  if (executor === ExecutorType.container && !task.component) {
@@ -268,10 +268,12 @@
268
268
  "shell.js"
269
269
  ]
270
270
  },
271
- "config:print": {
272
- "aliases": [],
271
+ "containers": {
272
+ "aliases": [
273
+ "ps"
274
+ ],
273
275
  "args": {},
274
- "description": "Print the current config.",
276
+ "description": "List docker containers.",
275
277
  "examples": [
276
278
  "<%= config.bin %> <%= command.id %>"
277
279
  ],
@@ -283,21 +285,22 @@
283
285
  "allowNo": false,
284
286
  "type": "boolean"
285
287
  },
286
- "flavor": {
287
- "description": "Specify the flavor to use.",
288
- "name": "flavor",
288
+ "all": {
289
+ "char": "a",
290
+ "description": "Retun all containers. By default, only running containers are shown",
291
+ "name": "all",
289
292
  "required": false,
290
- "hasDynamicHelp": false,
291
- "multiple": false,
292
- "type": "option"
293
+ "allowNo": false,
294
+ "type": "boolean"
293
295
  }
294
296
  },
295
297
  "hasDynamicHelp": false,
296
298
  "hiddenAliases": [],
297
- "id": "config:print",
299
+ "id": "containers",
298
300
  "pluginAlias": "@enspirit/emb",
299
301
  "pluginName": "@enspirit/emb",
300
302
  "pluginType": "core",
303
+ "strict": true,
301
304
  "enableJsonFlag": true,
302
305
  "isESM": true,
303
306
  "relativePath": [
@@ -305,16 +308,14 @@
305
308
  "src",
306
309
  "cli",
307
310
  "commands",
308
- "config",
309
- "print.js"
311
+ "containers",
312
+ "index.js"
310
313
  ]
311
314
  },
312
- "containers": {
313
- "aliases": [
314
- "ps"
315
- ],
315
+ "containers:prune": {
316
+ "aliases": [],
316
317
  "args": {},
317
- "description": "List docker containers.",
318
+ "description": "Prune containers.",
318
319
  "examples": [
319
320
  "<%= config.bin %> <%= command.id %>"
320
321
  ],
@@ -325,19 +326,11 @@
325
326
  "name": "json",
326
327
  "allowNo": false,
327
328
  "type": "boolean"
328
- },
329
- "all": {
330
- "char": "a",
331
- "description": "Retun all containers. By default, only running containers are shown",
332
- "name": "all",
333
- "required": false,
334
- "allowNo": false,
335
- "type": "boolean"
336
329
  }
337
330
  },
338
331
  "hasDynamicHelp": false,
339
332
  "hiddenAliases": [],
340
- "id": "containers",
333
+ "id": "containers:prune",
341
334
  "pluginAlias": "@enspirit/emb",
342
335
  "pluginName": "@enspirit/emb",
343
336
  "pluginType": "core",
@@ -350,13 +343,13 @@
350
343
  "cli",
351
344
  "commands",
352
345
  "containers",
353
- "index.js"
346
+ "prune.js"
354
347
  ]
355
348
  },
356
- "containers:prune": {
349
+ "config:print": {
357
350
  "aliases": [],
358
351
  "args": {},
359
- "description": "Prune containers.",
352
+ "description": "Print the current config.",
360
353
  "examples": [
361
354
  "<%= config.bin %> <%= command.id %>"
362
355
  ],
@@ -367,15 +360,22 @@
367
360
  "name": "json",
368
361
  "allowNo": false,
369
362
  "type": "boolean"
363
+ },
364
+ "flavor": {
365
+ "description": "Specify the flavor to use.",
366
+ "name": "flavor",
367
+ "required": false,
368
+ "hasDynamicHelp": false,
369
+ "multiple": false,
370
+ "type": "option"
370
371
  }
371
372
  },
372
373
  "hasDynamicHelp": false,
373
374
  "hiddenAliases": [],
374
- "id": "containers:prune",
375
+ "id": "config:print",
375
376
  "pluginAlias": "@enspirit/emb",
376
377
  "pluginName": "@enspirit/emb",
377
378
  "pluginType": "core",
378
- "strict": true,
379
379
  "enableJsonFlag": true,
380
380
  "isESM": true,
381
381
  "relativePath": [
@@ -383,8 +383,8 @@
383
383
  "src",
384
384
  "cli",
385
385
  "commands",
386
- "containers",
387
- "prune.js"
386
+ "config",
387
+ "print.js"
388
388
  ]
389
389
  },
390
390
  "images:delete": {
@@ -718,5 +718,5 @@
718
718
  ]
719
719
  }
720
720
  },
721
- "version": "0.4.1"
721
+ "version": "0.4.2"
722
722
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@enspirit/emb",
3
3
  "type": "module",
4
- "version": "0.4.1",
4
+ "version": "0.4.2",
5
5
  "keywords": [
6
6
  "monorepo",
7
7
  "docker",