@enspirit/emb 0.5.2 → 0.5.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 +61 -3
- package/dist/src/cli/commands/components/logs.js +4 -3
- package/dist/src/cli/commands/restart.d.ts +14 -0
- package/dist/src/cli/commands/restart.js +38 -0
- package/dist/src/cli/commands/stop.js +2 -2
- package/dist/src/cli/commands/tasks/index.js +1 -1
- package/dist/src/cli/commands/tasks/run.d.ts +1 -0
- package/dist/src/cli/commands/tasks/run.js +1 -0
- package/dist/src/config/schema.d.ts +6 -0
- package/dist/src/config/schema.json +7 -0
- package/dist/src/docker/compose/operations/ComposeExecOperation.d.ts +1 -0
- package/dist/src/docker/compose/operations/ComposeExecOperation.js +12 -1
- package/dist/src/docker/compose/operations/ComposeRestartOperation.d.ts +14 -0
- package/dist/src/docker/compose/operations/ComposeRestartOperation.js +46 -0
- package/dist/src/docker/compose/operations/index.d.ts +1 -0
- package/dist/src/docker/compose/operations/index.js +1 -0
- package/dist/src/docker/operations/containers/ContainerExecOperation.d.ts +0 -3
- package/dist/src/docker/operations/containers/ContainerExecOperation.js +3 -19
- package/dist/src/monorepo/config.js +1 -1
- package/dist/src/monorepo/operations/resources/BuildResourcesOperation.js +0 -1
- package/dist/src/monorepo/operations/shell/ExecuteLocalCommandOperation.js +1 -0
- package/dist/src/monorepo/operations/tasks/RunTasksOperation.d.ts +5 -1
- package/dist/src/monorepo/operations/tasks/RunTasksOperation.js +20 -4
- package/dist/src/monorepo/types.d.ts +6 -1
- package/dist/src/monorepo/utils/EMBCollection.d.ts +0 -3
- package/dist/src/monorepo/utils/EMBCollection.js +0 -14
- package/dist/src/monorepo/utils/index.d.ts +7 -4
- package/dist/src/monorepo/utils/index.js +14 -8
- package/oclif.manifest.json +83 -36
- package/package.json +1 -1
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.5.
|
|
17
|
+
@enspirit/emb/0.5.3 darwin-x64 node-v22.18.0
|
|
18
18
|
$ emb --help [COMMAND]
|
|
19
19
|
USAGE
|
|
20
20
|
$ emb COMMAND
|
|
@@ -40,6 +40,8 @@ USAGE
|
|
|
40
40
|
* [`emb ps`](#emb-ps)
|
|
41
41
|
* [`emb resources`](#emb-resources)
|
|
42
42
|
* [`emb resources build [COMPONENT]`](#emb-resources-build-component)
|
|
43
|
+
* [`emb restart [COMPONENT]`](#emb-restart-component)
|
|
44
|
+
* [`emb run TASK`](#emb-run-task)
|
|
43
45
|
* [`emb shell COMPONENT`](#emb-shell-component)
|
|
44
46
|
* [`emb stop`](#emb-stop)
|
|
45
47
|
* [`emb tasks`](#emb-tasks)
|
|
@@ -132,7 +134,7 @@ ARGUMENTS
|
|
|
132
134
|
COMPONENT The component you want to see the logs of
|
|
133
135
|
|
|
134
136
|
FLAGS
|
|
135
|
-
-f, --follow Follow log output
|
|
137
|
+
-f, --[no-]follow Follow log output
|
|
136
138
|
|
|
137
139
|
DESCRIPTION
|
|
138
140
|
Get components logs.
|
|
@@ -348,7 +350,7 @@ ARGUMENTS
|
|
|
348
350
|
COMPONENT The component you want to see the logs of
|
|
349
351
|
|
|
350
352
|
FLAGS
|
|
351
|
-
-f, --follow Follow log output
|
|
353
|
+
-f, --[no-]follow Follow log output
|
|
352
354
|
|
|
353
355
|
DESCRIPTION
|
|
354
356
|
Get components logs.
|
|
@@ -431,6 +433,59 @@ EXAMPLES
|
|
|
431
433
|
$ emb resources build build --flavor development
|
|
432
434
|
```
|
|
433
435
|
|
|
436
|
+
## `emb restart [COMPONENT]`
|
|
437
|
+
|
|
438
|
+
Restart the whole project.
|
|
439
|
+
|
|
440
|
+
```
|
|
441
|
+
USAGE
|
|
442
|
+
$ emb restart [COMPONENT...] [--json] [-f]
|
|
443
|
+
|
|
444
|
+
ARGUMENTS
|
|
445
|
+
COMPONENT... The component(s) to restart
|
|
446
|
+
|
|
447
|
+
FLAGS
|
|
448
|
+
-f, --no-deps Don't restart depdendent components
|
|
449
|
+
|
|
450
|
+
GLOBAL FLAGS
|
|
451
|
+
--json Format output as json.
|
|
452
|
+
|
|
453
|
+
DESCRIPTION
|
|
454
|
+
Restart the whole project.
|
|
455
|
+
|
|
456
|
+
EXAMPLES
|
|
457
|
+
$ emb restart
|
|
458
|
+
```
|
|
459
|
+
|
|
460
|
+
## `emb run TASK`
|
|
461
|
+
|
|
462
|
+
Run tasks.
|
|
463
|
+
|
|
464
|
+
```
|
|
465
|
+
USAGE
|
|
466
|
+
$ emb run TASK... [--json] [-x container|local] [-a]
|
|
467
|
+
|
|
468
|
+
ARGUMENTS
|
|
469
|
+
TASK... List of tasks to run. You can provide either ids or names (eg: component:task or task)
|
|
470
|
+
|
|
471
|
+
FLAGS
|
|
472
|
+
-a, --all-matching Run all tasks matching (when multiple matches)
|
|
473
|
+
-x, --executor=<option> Where to run the task. (experimental!)
|
|
474
|
+
<options: container|local>
|
|
475
|
+
|
|
476
|
+
GLOBAL FLAGS
|
|
477
|
+
--json Format output as json.
|
|
478
|
+
|
|
479
|
+
DESCRIPTION
|
|
480
|
+
Run tasks.
|
|
481
|
+
|
|
482
|
+
ALIASES
|
|
483
|
+
$ emb run
|
|
484
|
+
|
|
485
|
+
EXAMPLES
|
|
486
|
+
$ emb run
|
|
487
|
+
```
|
|
488
|
+
|
|
434
489
|
## `emb shell COMPONENT`
|
|
435
490
|
|
|
436
491
|
Get a shell on a running component.
|
|
@@ -516,6 +571,9 @@ GLOBAL FLAGS
|
|
|
516
571
|
DESCRIPTION
|
|
517
572
|
Run tasks.
|
|
518
573
|
|
|
574
|
+
ALIASES
|
|
575
|
+
$ emb run
|
|
576
|
+
|
|
519
577
|
EXAMPLES
|
|
520
578
|
$ emb tasks run
|
|
521
579
|
```
|
|
@@ -10,8 +10,9 @@ export default class ComponentsLogs extends BaseCommand {
|
|
|
10
10
|
follow: Flags.boolean({
|
|
11
11
|
name: 'follow',
|
|
12
12
|
char: 'f',
|
|
13
|
+
allowNo: true,
|
|
13
14
|
description: 'Follow log output',
|
|
14
|
-
default:
|
|
15
|
+
default: true,
|
|
15
16
|
}),
|
|
16
17
|
};
|
|
17
18
|
static args = {
|
|
@@ -26,11 +27,11 @@ export default class ComponentsLogs extends BaseCommand {
|
|
|
26
27
|
const { monorepo, docker } = await getContext();
|
|
27
28
|
const component = monorepo.component(args.component);
|
|
28
29
|
const containers = await monorepo.run(new ListContainersOperation(), {
|
|
30
|
+
all: true,
|
|
29
31
|
filters: {
|
|
30
32
|
label: [
|
|
31
33
|
`emb/project=${monorepo.name}`,
|
|
32
34
|
`emb/component=${component.name}`,
|
|
33
|
-
`emb/flavor=${monorepo.currentFlavor}`,
|
|
34
35
|
],
|
|
35
36
|
},
|
|
36
37
|
});
|
|
@@ -47,7 +48,7 @@ export default class ComponentsLogs extends BaseCommand {
|
|
|
47
48
|
stderr: true,
|
|
48
49
|
stdout: true,
|
|
49
50
|
});
|
|
50
|
-
|
|
51
|
+
docker.modem.demuxStream(stream, process.stdout, process.stderr);
|
|
51
52
|
}
|
|
52
53
|
else {
|
|
53
54
|
const res = await container.logs({
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { BaseCommand } from '../index.js';
|
|
2
|
+
export default class RestartComand extends BaseCommand {
|
|
3
|
+
static description: string;
|
|
4
|
+
static enableJsonFlag: boolean;
|
|
5
|
+
static examples: string[];
|
|
6
|
+
static flags: {
|
|
7
|
+
'no-deps': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
8
|
+
};
|
|
9
|
+
static args: {
|
|
10
|
+
component: import("@oclif/core/interfaces").Arg<string | undefined, Record<string, unknown>>;
|
|
11
|
+
};
|
|
12
|
+
static strict: boolean;
|
|
13
|
+
run(): Promise<void>;
|
|
14
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { Args, Flags } from '@oclif/core';
|
|
2
|
+
import { BaseCommand, getContext } from '../index.js';
|
|
3
|
+
import { ComposeRestartOperation } from '../../docker/index.js';
|
|
4
|
+
export default class RestartComand extends BaseCommand {
|
|
5
|
+
static description = 'Restart the whole project.';
|
|
6
|
+
static enableJsonFlag = true;
|
|
7
|
+
static examples = ['<%= config.bin %> <%= command.id %>'];
|
|
8
|
+
static flags = {
|
|
9
|
+
'no-deps': Flags.boolean({
|
|
10
|
+
char: 'f',
|
|
11
|
+
default: false,
|
|
12
|
+
description: "Don't restart depdendent components",
|
|
13
|
+
name: 'no-deps',
|
|
14
|
+
}),
|
|
15
|
+
};
|
|
16
|
+
static args = {
|
|
17
|
+
component: Args.string({
|
|
18
|
+
name: 'component',
|
|
19
|
+
description: 'The component(s) to restart',
|
|
20
|
+
}),
|
|
21
|
+
};
|
|
22
|
+
static strict = false;
|
|
23
|
+
async run() {
|
|
24
|
+
const { flags, argv } = await this.parse(RestartComand);
|
|
25
|
+
const { monorepo } = getContext();
|
|
26
|
+
let components;
|
|
27
|
+
if (argv.length > 0) {
|
|
28
|
+
components =
|
|
29
|
+
argv.length > 0
|
|
30
|
+
? argv.map((name) => monorepo.component(name))
|
|
31
|
+
: monorepo.components;
|
|
32
|
+
}
|
|
33
|
+
await monorepo.run(new ComposeRestartOperation(), {
|
|
34
|
+
noDeps: flags['no-deps'],
|
|
35
|
+
services: components?.map((c) => c.name),
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Listr } from 'listr2';
|
|
2
2
|
import { FlavoredCommand, getContext } from '../index.js';
|
|
3
|
-
import {
|
|
3
|
+
import { ComposeStopOperation } from '../../docker/index.js';
|
|
4
4
|
export default class StopCommand extends FlavoredCommand {
|
|
5
5
|
static description = 'Stop the whole project.';
|
|
6
6
|
static enableJsonFlag = true;
|
|
@@ -12,7 +12,7 @@ export default class StopCommand extends FlavoredCommand {
|
|
|
12
12
|
{
|
|
13
13
|
rendererOptions: { persistentOutput: true },
|
|
14
14
|
async task(ctx, task) {
|
|
15
|
-
return monorepo.run(new
|
|
15
|
+
return monorepo.run(new ComposeStopOperation(task.stdout()), {});
|
|
16
16
|
},
|
|
17
17
|
title: 'Stopping project',
|
|
18
18
|
},
|
|
@@ -20,7 +20,7 @@ export default class TasksIndex extends BaseCommand {
|
|
|
20
20
|
return 1;
|
|
21
21
|
}
|
|
22
22
|
// Compare components (if both not null)
|
|
23
|
-
if (Boolean(ac) && Boolean(bc)) {
|
|
23
|
+
if (ac && bc && Boolean(ac) && Boolean(bc)) {
|
|
24
24
|
const cmp = ac.localeCompare(bc);
|
|
25
25
|
if (cmp !== 0) {
|
|
26
26
|
return cmp;
|
|
@@ -3,6 +3,7 @@ import { Args, Flags } from '@oclif/core';
|
|
|
3
3
|
import { BaseCommand } from '../../index.js';
|
|
4
4
|
import { ExecutorType, RunTasksOperation } from '../../../monorepo/index.js';
|
|
5
5
|
export default class RunTask extends BaseCommand {
|
|
6
|
+
static aliases = ['run'];
|
|
6
7
|
static args = {
|
|
7
8
|
task: Args.string({
|
|
8
9
|
description: 'List of tasks to run. You can provide either ids or names (eg: component:task or task)',
|
|
@@ -136,6 +136,13 @@
|
|
|
136
136
|
"items": {
|
|
137
137
|
"$ref": "#/definitions/Identifier"
|
|
138
138
|
}
|
|
139
|
+
},
|
|
140
|
+
"vars": {
|
|
141
|
+
"type": "object",
|
|
142
|
+
"description": "Variables to pass onto the task",
|
|
143
|
+
"additionalProperties": {
|
|
144
|
+
"type": "string"
|
|
145
|
+
}
|
|
139
146
|
}
|
|
140
147
|
},
|
|
141
148
|
"additionalProperties": false
|
|
@@ -3,6 +3,7 @@ import * as z from 'zod';
|
|
|
3
3
|
import { AbstractOperation } from '../../../operations/index.js';
|
|
4
4
|
declare const schema: z.ZodObject<{
|
|
5
5
|
command: z.ZodString;
|
|
6
|
+
env: z.ZodOptional<z.ZodObject<{}, z.core.$catchall<z.ZodString>>>;
|
|
6
7
|
service: z.ZodString;
|
|
7
8
|
}, z.core.$strip>;
|
|
8
9
|
export declare class ComposeExecOperation extends AbstractOperation<typeof schema, void> {
|
|
@@ -4,6 +4,11 @@ import { ComposeExecError } from '../../../errors.js';
|
|
|
4
4
|
import { AbstractOperation } from '../../../operations/index.js';
|
|
5
5
|
const schema = z.object({
|
|
6
6
|
command: z.string().describe('The command to execute on the service'),
|
|
7
|
+
env: z
|
|
8
|
+
.object()
|
|
9
|
+
.catchall(z.string())
|
|
10
|
+
.describe('Environment variables to pass to the execution')
|
|
11
|
+
.optional(),
|
|
7
12
|
service: z
|
|
8
13
|
.string()
|
|
9
14
|
.describe('The name of the compose service to exec a shell'),
|
|
@@ -17,7 +22,13 @@ export class ComposeExecOperation extends AbstractOperation {
|
|
|
17
22
|
async _run(input) {
|
|
18
23
|
const { monorepo } = this.context;
|
|
19
24
|
const cmd = 'docker';
|
|
20
|
-
const args = ['compose', 'exec'
|
|
25
|
+
const args = ['compose', 'exec'];
|
|
26
|
+
// Add any env vars
|
|
27
|
+
Object.entries(input.env || {}).forEach(([key, value]) => {
|
|
28
|
+
args.push('-e', `${key.trim()}=${value.trim()}`);
|
|
29
|
+
});
|
|
30
|
+
// add component and script
|
|
31
|
+
args.push(input.service, input.command);
|
|
21
32
|
const child = spawn(cmd, args, {
|
|
22
33
|
stdio: 'pipe',
|
|
23
34
|
shell: true,
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import * as z from 'zod';
|
|
2
|
+
import { AbstractOperation } from '../../../operations/index.js';
|
|
3
|
+
/**
|
|
4
|
+
* https://docs.docker.com/reference/cli/docker/compose/restart/
|
|
5
|
+
*/
|
|
6
|
+
declare const schema: z.ZodOptional<z.ZodObject<{
|
|
7
|
+
services: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
8
|
+
noDeps: z.ZodOptional<z.ZodBoolean>;
|
|
9
|
+
}, z.core.$strip>>;
|
|
10
|
+
export declare class ComposeRestartOperation extends AbstractOperation<typeof schema, void> {
|
|
11
|
+
constructor();
|
|
12
|
+
protected _run(input: z.input<typeof schema>): Promise<void>;
|
|
13
|
+
}
|
|
14
|
+
export {};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { getContext } from '../../../index.js';
|
|
2
|
+
import * as z from 'zod';
|
|
3
|
+
import { ExecuteLocalCommandOperation, taskManagerFactory } from '../../../monorepo/index.js';
|
|
4
|
+
import { AbstractOperation } from '../../../operations/index.js';
|
|
5
|
+
/**
|
|
6
|
+
* https://docs.docker.com/reference/cli/docker/compose/restart/
|
|
7
|
+
*/
|
|
8
|
+
const schema = z
|
|
9
|
+
.object({
|
|
10
|
+
services: z
|
|
11
|
+
.array(z.string())
|
|
12
|
+
.optional()
|
|
13
|
+
.describe('The list of service to restart'),
|
|
14
|
+
noDeps: z.boolean().optional().describe("Don't restart dependent services"),
|
|
15
|
+
})
|
|
16
|
+
.optional();
|
|
17
|
+
export class ComposeRestartOperation extends AbstractOperation {
|
|
18
|
+
constructor() {
|
|
19
|
+
super(schema);
|
|
20
|
+
}
|
|
21
|
+
async _run(input) {
|
|
22
|
+
const { monorepo } = getContext();
|
|
23
|
+
const manager = taskManagerFactory();
|
|
24
|
+
const command = ['docker', 'compose', 'restart'];
|
|
25
|
+
if (input?.services) {
|
|
26
|
+
command.push(...input.services);
|
|
27
|
+
}
|
|
28
|
+
if (input?.noDeps) {
|
|
29
|
+
command.push('--no-deps');
|
|
30
|
+
}
|
|
31
|
+
manager.add([
|
|
32
|
+
{
|
|
33
|
+
async task(ctx, task) {
|
|
34
|
+
return monorepo.run(new ExecuteLocalCommandOperation(task.stdout()), {
|
|
35
|
+
script: command.join(' '),
|
|
36
|
+
workingDir: monorepo.rootDir,
|
|
37
|
+
});
|
|
38
|
+
},
|
|
39
|
+
title: input?.services
|
|
40
|
+
? `Restarting ${input.services.join(', ')}`
|
|
41
|
+
: 'Restarting project',
|
|
42
|
+
},
|
|
43
|
+
]);
|
|
44
|
+
await manager.runAll();
|
|
45
|
+
}
|
|
46
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export * from './ComposeDownOperation.js';
|
|
2
2
|
export * from './ComposeExecOperation.js';
|
|
3
3
|
export * from './ComposeExecShellOperation.js';
|
|
4
|
+
export * from './ComposeRestartOperation.js';
|
|
4
5
|
export * from './ComposeStopOperation.js';
|
|
5
6
|
export * from './ComposeUpOperation.js';
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export * from './ComposeDownOperation.js';
|
|
2
2
|
export * from './ComposeExecOperation.js';
|
|
3
3
|
export * from './ComposeExecShellOperation.js';
|
|
4
|
+
export * from './ComposeRestartOperation.js';
|
|
4
5
|
export * from './ComposeStopOperation.js';
|
|
5
6
|
export * from './ComposeUpOperation.js';
|
|
@@ -5,9 +5,6 @@ import { AbstractOperation } from '../../../operations/index.js';
|
|
|
5
5
|
* https://docs.docker.com/reference/api/engine/version/v1.37/#tag/Exec/operation/ContainerExec
|
|
6
6
|
*/
|
|
7
7
|
declare const schema: z.ZodObject<{
|
|
8
|
-
attachStderr: z.ZodOptional<z.ZodDefault<z.ZodBoolean>>;
|
|
9
|
-
attachStdin: z.ZodOptional<z.ZodDefault<z.ZodBoolean>>;
|
|
10
|
-
attachStdout: z.ZodOptional<z.ZodDefault<z.ZodBoolean>>;
|
|
11
8
|
container: z.ZodString;
|
|
12
9
|
env: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
13
10
|
script: z.ZodString;
|
|
@@ -4,21 +4,6 @@ import { AbstractOperation } from '../../../operations/index.js';
|
|
|
4
4
|
* https://docs.docker.com/reference/api/engine/version/v1.37/#tag/Exec/operation/ContainerExec
|
|
5
5
|
*/
|
|
6
6
|
const schema = z.object({
|
|
7
|
-
attachStderr: z
|
|
8
|
-
.boolean()
|
|
9
|
-
.default(false)
|
|
10
|
-
.optional()
|
|
11
|
-
.describe('Attach to `stderr` of the exec command.'),
|
|
12
|
-
attachStdin: z
|
|
13
|
-
.boolean()
|
|
14
|
-
.default(false)
|
|
15
|
-
.optional()
|
|
16
|
-
.describe('Attach to `stdin` of the exec command.'),
|
|
17
|
-
attachStdout: z
|
|
18
|
-
.boolean()
|
|
19
|
-
.default(false)
|
|
20
|
-
.optional()
|
|
21
|
-
.describe('Attach to `stdout` of the exec command.'),
|
|
22
7
|
container: z.string().describe('ID or name of the container'),
|
|
23
8
|
env: z
|
|
24
9
|
.record(z.string(), z.string())
|
|
@@ -43,9 +28,8 @@ export class ContainerExecOperation extends AbstractOperation {
|
|
|
43
28
|
return [...arr, `${key}=${value}`];
|
|
44
29
|
}, []);
|
|
45
30
|
const options = {
|
|
46
|
-
AttachStderr:
|
|
47
|
-
|
|
48
|
-
AttachStdout: input.attachStdout,
|
|
31
|
+
AttachStderr: true,
|
|
32
|
+
AttachStdout: true,
|
|
49
33
|
Cmd: ['bash', '-eu', '-o', 'pipefail', '-c', input.script],
|
|
50
34
|
Env: envVars,
|
|
51
35
|
Tty: input.tty,
|
|
@@ -53,7 +37,7 @@ export class ContainerExecOperation extends AbstractOperation {
|
|
|
53
37
|
};
|
|
54
38
|
const exec = await container.exec(options);
|
|
55
39
|
const stream = await exec.start({});
|
|
56
|
-
|
|
40
|
+
exec.modem.demuxStream(stream, this.out || process.stdout, this.out || process.stderr);
|
|
57
41
|
await new Promise((resolve, reject) => {
|
|
58
42
|
const onError = (err) => reject(err);
|
|
59
43
|
const onEnd = async () => {
|
|
@@ -16,7 +16,7 @@ export class MonorepoConfig {
|
|
|
16
16
|
this.flavors = config.flavors || {};
|
|
17
17
|
this.env = config.env || {};
|
|
18
18
|
this.plugins = config.plugins || [];
|
|
19
|
-
this.tasks = toIdentifedHash(config.tasks || {}
|
|
19
|
+
this.tasks = toIdentifedHash(config.tasks || {});
|
|
20
20
|
this.components = config.components || {};
|
|
21
21
|
}
|
|
22
22
|
component(id) {
|
|
@@ -34,7 +34,6 @@ export class BuildResourcesOperation extends AbstractOperation {
|
|
|
34
34
|
const collection = new EMBCollection(monorepo.resources, {
|
|
35
35
|
idField: 'id',
|
|
36
36
|
depField: 'dependencies',
|
|
37
|
-
forbidIdNameCollision: true,
|
|
38
37
|
});
|
|
39
38
|
const ordered = findRunOrder(input.resources || [], collection);
|
|
40
39
|
const tasks = ordered.map((resource) => {
|
|
@@ -13,8 +13,12 @@ export type RunTasksOperationParams = {
|
|
|
13
13
|
export type TaskWithScript = TaskInfo & {
|
|
14
14
|
script: string;
|
|
15
15
|
};
|
|
16
|
+
export type TaskWithScriptAndComponent = TaskInfo & {
|
|
17
|
+
script: string;
|
|
18
|
+
component: string;
|
|
19
|
+
};
|
|
16
20
|
export declare class RunTasksOperation implements IOperation<RunTasksOperationParams, Array<TaskInfo>> {
|
|
17
21
|
run(params: RunTasksOperationParams): Promise<Array<TaskInfo>>;
|
|
18
|
-
protected runDocker(task:
|
|
22
|
+
protected runDocker(task: TaskWithScriptAndComponent, out?: Writable): Promise<void>;
|
|
19
23
|
protected runLocal(task: TaskWithScript, out: Writable): Promise<import("stream").Readable>;
|
|
20
24
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { getContext } from '../../../index.js';
|
|
2
2
|
import { PassThrough } from 'node:stream';
|
|
3
|
-
import {
|
|
3
|
+
import { ContainerExecOperation, ListContainersOperation } from '../../../docker/index.js';
|
|
4
4
|
import { EMBCollection, findRunOrder, taskManagerFactory, } from '../../index.js';
|
|
5
5
|
import { ExecuteLocalCommandOperation } from '../index.js';
|
|
6
6
|
export var ExecutorType;
|
|
@@ -58,9 +58,24 @@ export class RunTasksOperation {
|
|
|
58
58
|
}
|
|
59
59
|
async runDocker(task, out) {
|
|
60
60
|
const { monorepo } = getContext();
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
61
|
+
const containers = await monorepo.run(new ListContainersOperation(), {
|
|
62
|
+
filters: {
|
|
63
|
+
label: [
|
|
64
|
+
`emb/project=${monorepo.name}`,
|
|
65
|
+
`emb/component=${task.component}`,
|
|
66
|
+
],
|
|
67
|
+
},
|
|
68
|
+
});
|
|
69
|
+
if (containers.length === 0) {
|
|
70
|
+
throw new Error(`No container found for component \`${task.component}\``);
|
|
71
|
+
}
|
|
72
|
+
if (containers.length > 1) {
|
|
73
|
+
throw new Error(`More than one container found for component \`${task.component}\``);
|
|
74
|
+
}
|
|
75
|
+
return monorepo.run(new ContainerExecOperation(out), {
|
|
76
|
+
container: containers[0].Id,
|
|
77
|
+
script: task.script,
|
|
78
|
+
env: await monorepo.expand(task.vars || {}),
|
|
64
79
|
});
|
|
65
80
|
}
|
|
66
81
|
async runLocal(task, out) {
|
|
@@ -71,6 +86,7 @@ export class RunTasksOperation {
|
|
|
71
86
|
return monorepo.run(new ExecuteLocalCommandOperation(out), {
|
|
72
87
|
script: task.script,
|
|
73
88
|
workingDir: cwd,
|
|
89
|
+
env: await monorepo.expand(task.vars || {}),
|
|
74
90
|
});
|
|
75
91
|
}
|
|
76
92
|
}
|
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
import { ComponentFlavorConfig, IResourceConfig, ProjectFlavorConfig, TaskConfig } from '../config/types.js';
|
|
2
|
+
export type MaybeComponentIdentifiable<T> = T & {
|
|
3
|
+
id: string;
|
|
4
|
+
name: string;
|
|
5
|
+
component?: string;
|
|
6
|
+
};
|
|
2
7
|
export type ComponentIdentifiable<T> = T & {
|
|
3
8
|
id: string;
|
|
4
9
|
name: string;
|
|
@@ -17,7 +22,7 @@ export type ComponentFlavorInfo = ComponentIdentifiable<ComponentFlavorConfig>;
|
|
|
17
22
|
export type ComponentFlavors = {
|
|
18
23
|
[k: string]: ComponentFlavorInfo;
|
|
19
24
|
};
|
|
20
|
-
export type TaskInfo =
|
|
25
|
+
export type TaskInfo = MaybeComponentIdentifiable<TaskConfig>;
|
|
21
26
|
export type Tasks = {
|
|
22
27
|
[k: string]: TaskInfo;
|
|
23
28
|
};
|
|
@@ -2,8 +2,6 @@ import { DepList } from './types.js';
|
|
|
2
2
|
export type CollectionConfig<IDK extends PropertyKey, DPK extends PropertyKey> = {
|
|
3
3
|
idField: IDK;
|
|
4
4
|
depField: DPK;
|
|
5
|
-
/** If true, throw when an item's id equals some other item's name (or vice versa). */
|
|
6
|
-
forbidIdNameCollision?: boolean;
|
|
7
5
|
};
|
|
8
6
|
export declare class EMBCollection<T extends Partial<Record<DPK, DepList>> & Record<IDK, string> & {
|
|
9
7
|
name: string;
|
|
@@ -11,7 +9,6 @@ export declare class EMBCollection<T extends Partial<Record<DPK, DepList>> & Rec
|
|
|
11
9
|
private items;
|
|
12
10
|
readonly idField: IDK;
|
|
13
11
|
readonly depField: DPK;
|
|
14
|
-
readonly forbidIdNameCollision: boolean;
|
|
15
12
|
private byId;
|
|
16
13
|
private byName;
|
|
17
14
|
constructor(items: Iterable<T>, cfg: CollectionConfig<IDK, DPK>);
|
|
@@ -3,7 +3,6 @@ export class EMBCollection {
|
|
|
3
3
|
items;
|
|
4
4
|
idField;
|
|
5
5
|
depField;
|
|
6
|
-
forbidIdNameCollision;
|
|
7
6
|
//
|
|
8
7
|
byId;
|
|
9
8
|
byName;
|
|
@@ -11,7 +10,6 @@ export class EMBCollection {
|
|
|
11
10
|
this.items = [];
|
|
12
11
|
this.idField = cfg.idField;
|
|
13
12
|
this.depField = cfg.depField;
|
|
14
|
-
this.forbidIdNameCollision = cfg.forbidIdNameCollision ?? true;
|
|
15
13
|
this.byId = new Map();
|
|
16
14
|
this.byName = new Map();
|
|
17
15
|
// single-pass validation state
|
|
@@ -32,18 +30,6 @@ export class EMBCollection {
|
|
|
32
30
|
this.byId.set(id, t);
|
|
33
31
|
seenIds.add(id);
|
|
34
32
|
}
|
|
35
|
-
// --- Optional validation: forbid id <-> name collisions ---
|
|
36
|
-
if (this.forbidIdNameCollision) {
|
|
37
|
-
if (seenNames.has(id)) {
|
|
38
|
-
const nameOwners = this.byName.get(id) ?? [];
|
|
39
|
-
const ownerIds = nameOwners.map((o) => o[this.idField]).join(', ');
|
|
40
|
-
collisions.push(`value \`${id}\` is an id of \`${name}\` and also a name of item(s) with id(s): [${ownerIds}]`);
|
|
41
|
-
}
|
|
42
|
-
if (seenIds.has(name)) {
|
|
43
|
-
const idOwner = this.byId.get(name);
|
|
44
|
-
collisions.push(`value \`${name}\` is a name of \`${t.name}\` and also an id of \`${idOwner.name}\``);
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
33
|
// byName index
|
|
48
34
|
const list = this.byName.get(name);
|
|
49
35
|
if (list) {
|
|
@@ -1,7 +1,10 @@
|
|
|
1
|
-
import { ComponentIdentifiable } from '../../index.js';
|
|
1
|
+
import { ComponentIdentifiable, MaybeComponentIdentifiable } from '../../index.js';
|
|
2
2
|
export * from './EMBCollection.js';
|
|
3
3
|
export * from './graph.js';
|
|
4
4
|
export * from './types.js';
|
|
5
|
-
export declare
|
|
6
|
-
[
|
|
7
|
-
}
|
|
5
|
+
export declare function toIdentifedHash<V, T extends Record<string, V>>(hash: T, parentName: string): {
|
|
6
|
+
[K in keyof T]: ComponentIdentifiable<T[K]>;
|
|
7
|
+
};
|
|
8
|
+
export declare function toIdentifedHash<V, T extends Record<string, V>>(hash: T, parentName?: undefined): {
|
|
9
|
+
[K in keyof T]: MaybeComponentIdentifiable<T[K]>;
|
|
10
|
+
};
|
|
@@ -1,14 +1,20 @@
|
|
|
1
1
|
export * from './EMBCollection.js';
|
|
2
2
|
export * from './graph.js';
|
|
3
3
|
export * from './types.js';
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
// implementation
|
|
5
|
+
export function toIdentifedHash(hash, parentName) {
|
|
6
|
+
const out = {};
|
|
7
|
+
for (const key in hash) {
|
|
8
|
+
if (!Object.hasOwn(hash, key)) {
|
|
9
|
+
continue;
|
|
10
|
+
}
|
|
11
|
+
const value = hash[key];
|
|
12
|
+
out[key] = {
|
|
7
13
|
...value,
|
|
8
|
-
id: `${parentName}:${key}
|
|
14
|
+
id: parentName ? `${parentName}:${key}` : key,
|
|
9
15
|
name: key,
|
|
10
|
-
component: parentName,
|
|
16
|
+
...(parentName ? { component: parentName } : {}),
|
|
11
17
|
};
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
}
|
|
18
|
+
}
|
|
19
|
+
return out;
|
|
20
|
+
}
|
package/oclif.manifest.json
CHANGED
|
@@ -80,6 +80,51 @@
|
|
|
80
80
|
"down.js"
|
|
81
81
|
]
|
|
82
82
|
},
|
|
83
|
+
"restart": {
|
|
84
|
+
"aliases": [],
|
|
85
|
+
"args": {
|
|
86
|
+
"component": {
|
|
87
|
+
"description": "The component(s) to restart",
|
|
88
|
+
"name": "component"
|
|
89
|
+
}
|
|
90
|
+
},
|
|
91
|
+
"description": "Restart the whole project.",
|
|
92
|
+
"examples": [
|
|
93
|
+
"<%= config.bin %> <%= command.id %>"
|
|
94
|
+
],
|
|
95
|
+
"flags": {
|
|
96
|
+
"json": {
|
|
97
|
+
"description": "Format output as json.",
|
|
98
|
+
"helpGroup": "GLOBAL",
|
|
99
|
+
"name": "json",
|
|
100
|
+
"allowNo": false,
|
|
101
|
+
"type": "boolean"
|
|
102
|
+
},
|
|
103
|
+
"no-deps": {
|
|
104
|
+
"char": "f",
|
|
105
|
+
"description": "Don't restart depdendent components",
|
|
106
|
+
"name": "no-deps",
|
|
107
|
+
"allowNo": false,
|
|
108
|
+
"type": "boolean"
|
|
109
|
+
}
|
|
110
|
+
},
|
|
111
|
+
"hasDynamicHelp": false,
|
|
112
|
+
"hiddenAliases": [],
|
|
113
|
+
"id": "restart",
|
|
114
|
+
"pluginAlias": "@enspirit/emb",
|
|
115
|
+
"pluginName": "@enspirit/emb",
|
|
116
|
+
"pluginType": "core",
|
|
117
|
+
"strict": false,
|
|
118
|
+
"enableJsonFlag": true,
|
|
119
|
+
"isESM": true,
|
|
120
|
+
"relativePath": [
|
|
121
|
+
"dist",
|
|
122
|
+
"src",
|
|
123
|
+
"cli",
|
|
124
|
+
"commands",
|
|
125
|
+
"restart.js"
|
|
126
|
+
]
|
|
127
|
+
},
|
|
83
128
|
"stop": {
|
|
84
129
|
"aliases": [],
|
|
85
130
|
"args": {},
|
|
@@ -234,7 +279,7 @@
|
|
|
234
279
|
"char": "f",
|
|
235
280
|
"description": "Follow log output",
|
|
236
281
|
"name": "follow",
|
|
237
|
-
"allowNo":
|
|
282
|
+
"allowNo": true,
|
|
238
283
|
"type": "boolean"
|
|
239
284
|
}
|
|
240
285
|
},
|
|
@@ -300,12 +345,10 @@
|
|
|
300
345
|
"shell.js"
|
|
301
346
|
]
|
|
302
347
|
},
|
|
303
|
-
"
|
|
304
|
-
"aliases": [
|
|
305
|
-
"ps"
|
|
306
|
-
],
|
|
348
|
+
"config:print": {
|
|
349
|
+
"aliases": [],
|
|
307
350
|
"args": {},
|
|
308
|
-
"description": "
|
|
351
|
+
"description": "Print the current config.",
|
|
309
352
|
"examples": [
|
|
310
353
|
"<%= config.bin %> <%= command.id %>"
|
|
311
354
|
],
|
|
@@ -317,22 +360,21 @@
|
|
|
317
360
|
"allowNo": false,
|
|
318
361
|
"type": "boolean"
|
|
319
362
|
},
|
|
320
|
-
"
|
|
321
|
-
"
|
|
322
|
-
"
|
|
323
|
-
"name": "all",
|
|
363
|
+
"flavor": {
|
|
364
|
+
"description": "Specify the flavor to use.",
|
|
365
|
+
"name": "flavor",
|
|
324
366
|
"required": false,
|
|
325
|
-
"
|
|
326
|
-
"
|
|
367
|
+
"hasDynamicHelp": false,
|
|
368
|
+
"multiple": false,
|
|
369
|
+
"type": "option"
|
|
327
370
|
}
|
|
328
371
|
},
|
|
329
372
|
"hasDynamicHelp": false,
|
|
330
373
|
"hiddenAliases": [],
|
|
331
|
-
"id": "
|
|
374
|
+
"id": "config:print",
|
|
332
375
|
"pluginAlias": "@enspirit/emb",
|
|
333
376
|
"pluginName": "@enspirit/emb",
|
|
334
377
|
"pluginType": "core",
|
|
335
|
-
"strict": true,
|
|
336
378
|
"enableJsonFlag": true,
|
|
337
379
|
"isESM": true,
|
|
338
380
|
"relativePath": [
|
|
@@ -340,14 +382,16 @@
|
|
|
340
382
|
"src",
|
|
341
383
|
"cli",
|
|
342
384
|
"commands",
|
|
343
|
-
"
|
|
344
|
-
"
|
|
385
|
+
"config",
|
|
386
|
+
"print.js"
|
|
345
387
|
]
|
|
346
388
|
},
|
|
347
|
-
"containers
|
|
348
|
-
"aliases": [
|
|
389
|
+
"containers": {
|
|
390
|
+
"aliases": [
|
|
391
|
+
"ps"
|
|
392
|
+
],
|
|
349
393
|
"args": {},
|
|
350
|
-
"description": "
|
|
394
|
+
"description": "List docker containers.",
|
|
351
395
|
"examples": [
|
|
352
396
|
"<%= config.bin %> <%= command.id %>"
|
|
353
397
|
],
|
|
@@ -358,11 +402,19 @@
|
|
|
358
402
|
"name": "json",
|
|
359
403
|
"allowNo": false,
|
|
360
404
|
"type": "boolean"
|
|
405
|
+
},
|
|
406
|
+
"all": {
|
|
407
|
+
"char": "a",
|
|
408
|
+
"description": "Retun all containers. By default, only running containers are shown",
|
|
409
|
+
"name": "all",
|
|
410
|
+
"required": false,
|
|
411
|
+
"allowNo": false,
|
|
412
|
+
"type": "boolean"
|
|
361
413
|
}
|
|
362
414
|
},
|
|
363
415
|
"hasDynamicHelp": false,
|
|
364
416
|
"hiddenAliases": [],
|
|
365
|
-
"id": "containers
|
|
417
|
+
"id": "containers",
|
|
366
418
|
"pluginAlias": "@enspirit/emb",
|
|
367
419
|
"pluginName": "@enspirit/emb",
|
|
368
420
|
"pluginType": "core",
|
|
@@ -375,13 +427,13 @@
|
|
|
375
427
|
"cli",
|
|
376
428
|
"commands",
|
|
377
429
|
"containers",
|
|
378
|
-
"
|
|
430
|
+
"index.js"
|
|
379
431
|
]
|
|
380
432
|
},
|
|
381
|
-
"
|
|
433
|
+
"containers:prune": {
|
|
382
434
|
"aliases": [],
|
|
383
435
|
"args": {},
|
|
384
|
-
"description": "
|
|
436
|
+
"description": "Prune containers.",
|
|
385
437
|
"examples": [
|
|
386
438
|
"<%= config.bin %> <%= command.id %>"
|
|
387
439
|
],
|
|
@@ -392,22 +444,15 @@
|
|
|
392
444
|
"name": "json",
|
|
393
445
|
"allowNo": false,
|
|
394
446
|
"type": "boolean"
|
|
395
|
-
},
|
|
396
|
-
"flavor": {
|
|
397
|
-
"description": "Specify the flavor to use.",
|
|
398
|
-
"name": "flavor",
|
|
399
|
-
"required": false,
|
|
400
|
-
"hasDynamicHelp": false,
|
|
401
|
-
"multiple": false,
|
|
402
|
-
"type": "option"
|
|
403
447
|
}
|
|
404
448
|
},
|
|
405
449
|
"hasDynamicHelp": false,
|
|
406
450
|
"hiddenAliases": [],
|
|
407
|
-
"id": "
|
|
451
|
+
"id": "containers:prune",
|
|
408
452
|
"pluginAlias": "@enspirit/emb",
|
|
409
453
|
"pluginName": "@enspirit/emb",
|
|
410
454
|
"pluginType": "core",
|
|
455
|
+
"strict": true,
|
|
411
456
|
"enableJsonFlag": true,
|
|
412
457
|
"isESM": true,
|
|
413
458
|
"relativePath": [
|
|
@@ -415,8 +460,8 @@
|
|
|
415
460
|
"src",
|
|
416
461
|
"cli",
|
|
417
462
|
"commands",
|
|
418
|
-
"
|
|
419
|
-
"
|
|
463
|
+
"containers",
|
|
464
|
+
"prune.js"
|
|
420
465
|
]
|
|
421
466
|
},
|
|
422
467
|
"images:delete": {
|
|
@@ -691,7 +736,9 @@
|
|
|
691
736
|
]
|
|
692
737
|
},
|
|
693
738
|
"tasks:run": {
|
|
694
|
-
"aliases": [
|
|
739
|
+
"aliases": [
|
|
740
|
+
"run"
|
|
741
|
+
],
|
|
695
742
|
"args": {
|
|
696
743
|
"task": {
|
|
697
744
|
"description": "List of tasks to run. You can provide either ids or names (eg: component:task or task)",
|
|
@@ -750,5 +797,5 @@
|
|
|
750
797
|
]
|
|
751
798
|
}
|
|
752
799
|
},
|
|
753
|
-
"version": "0.5.
|
|
800
|
+
"version": "0.5.3"
|
|
754
801
|
}
|